layerscape: add LS1043A Rev1.1 support
[openwrt/staging/yousong.git] / target / linux / layerscape / patches-4.4 / 8240-irqchip-ls-scfg-msi-add-LS1043a-v1.1-MSI-support.patch
1 From ab9d5c5c767c17bf9526f84beb5667f2a50e1a4d Mon Sep 17 00:00:00 2001
2 From: Minghuan Lian <Minghuan.Lian@nxp.com>
3 Date: Tue, 17 Jan 2017 17:32:42 +0800
4 Subject: [PATCH] irqchip/ls-scfg-msi: add LS1043a v1.1 MSI support
5
6 Cherry-pick patchwork patch with context adjustment.
7
8 A MSI controller of LS1043a v1.0 only includes one MSIR and
9 is assigned one GIC interrupt. In order to support affinity,
10 LS1043a v1.1 MSI is assigned 4 MSIRs and 4 GIC interrupts.
11 But the MSIR has the different offset and only supports 8 MSIs.
12 The bits between variable bit_start and bit_end in structure
13 ls_scfg_msir are used to show 8 MSI interrupts. msir_irqs and
14 msir_base are added to describe the difference of MSI between
15 LS1043a v1.1 and other SoCs.
16
17 Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
18 Acked-by: Rob Herring <robh@kernel.org>
19 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
20 ---
21 drivers/irqchip/irq-ls-scfg-msi.c | 45 +++++++++++++++++++++++++++++++++------
22 1 file changed, 39 insertions(+), 6 deletions(-)
23
24 diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
25 index 6586076..71a2050 100644
26 --- a/drivers/irqchip/irq-ls-scfg-msi.c
27 +++ b/drivers/irqchip/irq-ls-scfg-msi.c
28 @@ -25,14 +25,21 @@
29 #define MSI_IRQS_PER_MSIR 32
30 #define MSI_MSIR_OFFSET 4
31
32 +#define MSI_LS1043V1_1_IRQS_PER_MSIR 8
33 +#define MSI_LS1043V1_1_MSIR_OFFSET 0x10
34 +
35 struct ls_scfg_msi_cfg {
36 u32 ibs_shift; /* Shift of interrupt bit select */
37 + u32 msir_irqs; /* The irq number per MSIR */
38 + u32 msir_base; /* The base address of MSIR */
39 };
40
41 struct ls_scfg_msir {
42 struct ls_scfg_msi *msi_data;
43 unsigned int index;
44 unsigned int gic_irq;
45 + unsigned int bit_start;
46 + unsigned int bit_end;
47 void __iomem *reg;
48 };
49
50 @@ -140,13 +147,18 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc)
51 struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc);
52 struct ls_scfg_msi *msi_data = msir->msi_data;
53 unsigned long val;
54 - int pos, virq, hwirq;
55 + int pos, size, virq, hwirq;
56
57 chained_irq_enter(irq_desc_get_chip(desc), desc);
58
59 val = ioread32be(msir->reg);
60 - for_each_set_bit(pos, &val, MSI_IRQS_PER_MSIR) {
61 - hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index;
62 +
63 + pos = msir->bit_start;
64 + size = msir->bit_end + 1;
65 +
66 + for_each_set_bit_from(pos, &val, size) {
67 + hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) |
68 + msir->index;
69 virq = irq_find_mapping(msi_data->parent, hwirq);
70 if (virq)
71 generic_handle_irq(virq);
72 @@ -193,14 +205,24 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index)
73 msir->index = index;
74 msir->msi_data = msi_data;
75 msir->gic_irq = virq;
76 - msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index;
77 + msir->reg = msi_data->regs + msi_data->cfg->msir_base + 4 * index;
78 +
79 + if (msi_data->cfg->msir_irqs == MSI_LS1043V1_1_IRQS_PER_MSIR) {
80 + msir->bit_start = 32 - ((msir->index + 1) *
81 + MSI_LS1043V1_1_IRQS_PER_MSIR);
82 + msir->bit_end = msir->bit_start +
83 + MSI_LS1043V1_1_IRQS_PER_MSIR - 1;
84 + } else {
85 + msir->bit_start = 0;
86 + msir->bit_end = msi_data->cfg->msir_irqs - 1;
87 + }
88
89 irq_set_chained_handler_and_data(msir->gic_irq,
90 ls_scfg_msi_irq_handler,
91 msir);
92
93 /* Release the hwirqs corresponding to this MSIR */
94 - for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
95 + for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
96 hwirq = i << msi_data->cfg->ibs_shift | msir->index;
97 bitmap_clear(msi_data->used, hwirq, 1);
98 }
99 @@ -216,7 +238,7 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
100 if (msir->gic_irq > 0)
101 irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL);
102
103 - for (i = 0; i < MSI_IRQS_PER_MSIR; i++) {
104 + for (i = 0; i < msi_data->cfg->msir_irqs; i++) {
105 hwirq = i << msi_data->cfg->ibs_shift | msir->index;
106 bitmap_set(msi_data->used, hwirq, 1);
107 }
108 @@ -226,10 +248,20 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir)
109
110 static struct ls_scfg_msi_cfg ls1021_msi_cfg = {
111 .ibs_shift = 3,
112 + .msir_irqs = MSI_IRQS_PER_MSIR,
113 + .msir_base = MSI_MSIR_OFFSET,
114 };
115
116 static struct ls_scfg_msi_cfg ls1046_msi_cfg = {
117 .ibs_shift = 2,
118 + .msir_irqs = MSI_IRQS_PER_MSIR,
119 + .msir_base = MSI_MSIR_OFFSET,
120 +};
121 +
122 +static struct ls_scfg_msi_cfg ls1043_v1_1_msi_cfg = {
123 + .ibs_shift = 2,
124 + .msir_irqs = MSI_LS1043V1_1_IRQS_PER_MSIR,
125 + .msir_base = MSI_LS1043V1_1_MSIR_OFFSET,
126 };
127
128 static const struct of_device_id ls_scfg_msi_id[] = {
129 @@ -240,6 +272,7 @@ static const struct of_device_id ls_scfg_msi_id[] = {
130 { .compatible = "fsl,ls1012a-msi", .data = &ls1021_msi_cfg },
131 { .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg },
132 { .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg },
133 + { .compatible = "fsl,ls1043a-v1.1-msi", .data = &ls1043_v1_1_msi_cfg },
134 { .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg },
135 {},
136 };
137 --
138 2.1.0.27.g96db324
139