diff options
| author | Minghuan Lian <Minghuan.Lian@nxp.com> | 2017-07-05 02:59:02 -0400 |
|---|---|---|
| committer | Marc Zyngier <marc.zyngier@arm.com> | 2017-08-31 11:19:39 -0400 |
| commit | fd100dab63ef634e1e0e8b5d9d6d4ba7df9be93f (patch) | |
| tree | f928d82b8007a5403c9a7ccbff2fcba7ebd4c288 | |
| parent | 4dd5da65a39d9a0405304fdef0804afffece044b (diff) | |
irqchip/ls-scfg-msi: Add LS1043a v1.1 MSI support
A MSI controller of LS1043a v1.0 only includes one MSIR and
is assigned one GIC interrupt. In order to support affinity,
LS1043a v1.1 MSI is assigned 4 MSIRs and 4 GIC interrupts.
But the MSIR has the different offset and only supports 8 MSIs.
The bits between variable bit_start and bit_end in structure
ls_scfg_msir are used to show 8 MSI interrupts. msir_irqs and
msir_base are added to describe the difference of MSI between
LS1043a v1.1 and other SoCs.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Minghuan Lian <Minghuan.Lian@nxp.com>
Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
| -rw-r--r-- | Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt | 1 | ||||
| -rw-r--r-- | drivers/irqchip/irq-ls-scfg-msi.c | 45 |
2 files changed, 40 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt index dde455289c16..49ccabbfa6f3 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/fsl,ls-scfg-msi.txt | |||
| @@ -7,6 +7,7 @@ Required properties: | |||
| 7 | "fsl,ls1021a-msi" | 7 | "fsl,ls1021a-msi" |
| 8 | "fsl,ls1043a-msi" | 8 | "fsl,ls1043a-msi" |
| 9 | "fsl,ls1046a-msi" | 9 | "fsl,ls1046a-msi" |
| 10 | "fsl,ls1043a-v1.1-msi" | ||
| 10 | - msi-controller: indicates that this is a PCIe MSI controller node | 11 | - msi-controller: indicates that this is a PCIe MSI controller node |
| 11 | - reg: physical base address of the controller and length of memory mapped. | 12 | - reg: physical base address of the controller and length of memory mapped. |
| 12 | - interrupts: an interrupt to the parent interrupt controller. | 13 | - interrupts: an interrupt to the parent interrupt controller. |
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c index 0b1f34ddab00..8d57a599c0fb 100644 --- a/drivers/irqchip/irq-ls-scfg-msi.c +++ b/drivers/irqchip/irq-ls-scfg-msi.c | |||
| @@ -25,14 +25,21 @@ | |||
| 25 | #define MSI_IRQS_PER_MSIR 32 | 25 | #define MSI_IRQS_PER_MSIR 32 |
| 26 | #define MSI_MSIR_OFFSET 4 | 26 | #define MSI_MSIR_OFFSET 4 |
| 27 | 27 | ||
| 28 | #define MSI_LS1043V1_1_IRQS_PER_MSIR 8 | ||
| 29 | #define MSI_LS1043V1_1_MSIR_OFFSET 0x10 | ||
| 30 | |||
| 28 | struct ls_scfg_msi_cfg { | 31 | struct ls_scfg_msi_cfg { |
| 29 | u32 ibs_shift; /* Shift of interrupt bit select */ | 32 | u32 ibs_shift; /* Shift of interrupt bit select */ |
| 33 | u32 msir_irqs; /* The irq number per MSIR */ | ||
| 34 | u32 msir_base; /* The base address of MSIR */ | ||
| 30 | }; | 35 | }; |
| 31 | 36 | ||
| 32 | struct ls_scfg_msir { | 37 | struct ls_scfg_msir { |
| 33 | struct ls_scfg_msi *msi_data; | 38 | struct ls_scfg_msi *msi_data; |
| 34 | unsigned int index; | 39 | unsigned int index; |
| 35 | unsigned int gic_irq; | 40 | unsigned int gic_irq; |
| 41 | unsigned int bit_start; | ||
| 42 | unsigned int bit_end; | ||
| 36 | void __iomem *reg; | 43 | void __iomem *reg; |
| 37 | }; | 44 | }; |
| 38 | 45 | ||
| @@ -140,13 +147,18 @@ static void ls_scfg_msi_irq_handler(struct irq_desc *desc) | |||
| 140 | struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc); | 147 | struct ls_scfg_msir *msir = irq_desc_get_handler_data(desc); |
| 141 | struct ls_scfg_msi *msi_data = msir->msi_data; | 148 | struct ls_scfg_msi *msi_data = msir->msi_data; |
| 142 | unsigned long val; | 149 | unsigned long val; |
| 143 | int pos, virq, hwirq; | 150 | int pos, size, virq, hwirq; |
| 144 | 151 | ||
| 145 | chained_irq_enter(irq_desc_get_chip(desc), desc); | 152 | chained_irq_enter(irq_desc_get_chip(desc), desc); |
| 146 | 153 | ||
| 147 | val = ioread32be(msir->reg); | 154 | val = ioread32be(msir->reg); |
| 148 | for_each_set_bit(pos, &val, MSI_IRQS_PER_MSIR) { | 155 | |
| 149 | hwirq = ((31 - pos) << msi_data->cfg->ibs_shift) | msir->index; | 156 | pos = msir->bit_start; |
| 157 | size = msir->bit_end + 1; | ||
| 158 | |||
| 159 | for_each_set_bit_from(pos, &val, size) { | ||
| 160 | hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) | | ||
| 161 | msir->index; | ||
| 150 | virq = irq_find_mapping(msi_data->parent, hwirq); | 162 | virq = irq_find_mapping(msi_data->parent, hwirq); |
| 151 | if (virq) | 163 | if (virq) |
| 152 | generic_handle_irq(virq); | 164 | generic_handle_irq(virq); |
| @@ -193,14 +205,24 @@ static int ls_scfg_msi_setup_hwirq(struct ls_scfg_msi *msi_data, int index) | |||
| 193 | msir->index = index; | 205 | msir->index = index; |
| 194 | msir->msi_data = msi_data; | 206 | msir->msi_data = msi_data; |
| 195 | msir->gic_irq = virq; | 207 | msir->gic_irq = virq; |
| 196 | msir->reg = msi_data->regs + MSI_MSIR_OFFSET + 4 * index; | 208 | msir->reg = msi_data->regs + msi_data->cfg->msir_base + 4 * index; |
| 209 | |||
| 210 | if (msi_data->cfg->msir_irqs == MSI_LS1043V1_1_IRQS_PER_MSIR) { | ||
| 211 | msir->bit_start = 32 - ((msir->index + 1) * | ||
| 212 | MSI_LS1043V1_1_IRQS_PER_MSIR); | ||
| 213 | msir->bit_end = msir->bit_start + | ||
| 214 | MSI_LS1043V1_1_IRQS_PER_MSIR - 1; | ||
| 215 | } else { | ||
| 216 | msir->bit_start = 0; | ||
| 217 | msir->bit_end = msi_data->cfg->msir_irqs - 1; | ||
| 218 | } | ||
| 197 | 219 | ||
| 198 | irq_set_chained_handler_and_data(msir->gic_irq, | 220 | irq_set_chained_handler_and_data(msir->gic_irq, |
| 199 | ls_scfg_msi_irq_handler, | 221 | ls_scfg_msi_irq_handler, |
| 200 | msir); | 222 | msir); |
| 201 | 223 | ||
| 202 | /* Release the hwirqs corresponding to this MSIR */ | 224 | /* Release the hwirqs corresponding to this MSIR */ |
| 203 | for (i = 0; i < MSI_IRQS_PER_MSIR; i++) { | 225 | for (i = 0; i < msi_data->cfg->msir_irqs; i++) { |
| 204 | hwirq = i << msi_data->cfg->ibs_shift | msir->index; | 226 | hwirq = i << msi_data->cfg->ibs_shift | msir->index; |
| 205 | bitmap_clear(msi_data->used, hwirq, 1); | 227 | bitmap_clear(msi_data->used, hwirq, 1); |
| 206 | } | 228 | } |
| @@ -216,7 +238,7 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir) | |||
| 216 | if (msir->gic_irq > 0) | 238 | if (msir->gic_irq > 0) |
| 217 | irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL); | 239 | irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL); |
| 218 | 240 | ||
| 219 | for (i = 0; i < MSI_IRQS_PER_MSIR; i++) { | 241 | for (i = 0; i < msi_data->cfg->msir_irqs; i++) { |
| 220 | hwirq = i << msi_data->cfg->ibs_shift | msir->index; | 242 | hwirq = i << msi_data->cfg->ibs_shift | msir->index; |
| 221 | bitmap_set(msi_data->used, hwirq, 1); | 243 | bitmap_set(msi_data->used, hwirq, 1); |
| 222 | } | 244 | } |
| @@ -226,10 +248,20 @@ static int ls_scfg_msi_teardown_hwirq(struct ls_scfg_msir *msir) | |||
| 226 | 248 | ||
| 227 | static struct ls_scfg_msi_cfg ls1021_msi_cfg = { | 249 | static struct ls_scfg_msi_cfg ls1021_msi_cfg = { |
| 228 | .ibs_shift = 3, | 250 | .ibs_shift = 3, |
| 251 | .msir_irqs = MSI_IRQS_PER_MSIR, | ||
| 252 | .msir_base = MSI_MSIR_OFFSET, | ||
| 229 | }; | 253 | }; |
| 230 | 254 | ||
| 231 | static struct ls_scfg_msi_cfg ls1046_msi_cfg = { | 255 | static struct ls_scfg_msi_cfg ls1046_msi_cfg = { |
| 232 | .ibs_shift = 2, | 256 | .ibs_shift = 2, |
| 257 | .msir_irqs = MSI_IRQS_PER_MSIR, | ||
| 258 | .msir_base = MSI_MSIR_OFFSET, | ||
| 259 | }; | ||
| 260 | |||
| 261 | static struct ls_scfg_msi_cfg ls1043_v1_1_msi_cfg = { | ||
| 262 | .ibs_shift = 2, | ||
| 263 | .msir_irqs = MSI_LS1043V1_1_IRQS_PER_MSIR, | ||
| 264 | .msir_base = MSI_LS1043V1_1_MSIR_OFFSET, | ||
| 233 | }; | 265 | }; |
| 234 | 266 | ||
| 235 | static const struct of_device_id ls_scfg_msi_id[] = { | 267 | static const struct of_device_id ls_scfg_msi_id[] = { |
| @@ -239,6 +271,7 @@ static const struct of_device_id ls_scfg_msi_id[] = { | |||
| 239 | 271 | ||
| 240 | { .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg }, | 272 | { .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg }, |
| 241 | { .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg }, | 273 | { .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg }, |
| 274 | { .compatible = "fsl,ls1043a-v1.1-msi", .data = &ls1043_v1_1_msi_cfg }, | ||
| 242 | { .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg }, | 275 | { .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg }, |
| 243 | {}, | 276 | {}, |
| 244 | }; | 277 | }; |
