Lines Matching +full:msi +full:- +full:base +full:- +full:spi
5 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
18 #include <linux/msi.h>
23 #include <dt-bindings/interrupt-controller/mvebu-icu.h>
53 void __iomem *base; member
75 const struct mvebu_icu_subset_data *subset = msi_data->subset_data; in mvebu_icu_init()
77 if (atomic_cmpxchg(&msi_data->initialized, false, true)) in mvebu_icu_init()
80 /* Set 'SET' ICU SPI message address in AP */ in mvebu_icu_init()
81 writel_relaxed(msg[0].address_hi, icu->base + subset->offset_set_ah); in mvebu_icu_init()
82 writel_relaxed(msg[0].address_lo, icu->base + subset->offset_set_al); in mvebu_icu_init()
84 if (subset->icu_group != ICU_GRP_NSR) in mvebu_icu_init()
87 /* Set 'CLEAR' ICU SPI message address in AP (level-MSI only) */ in mvebu_icu_init()
88 writel_relaxed(msg[1].address_hi, icu->base + subset->offset_clr_ah); in mvebu_icu_init()
89 writel_relaxed(msg[1].address_lo, icu->base + subset->offset_clr_al); in mvebu_icu_init()
94 struct irq_data *d = irq_get_irq_data(desc->irq); in mvebu_icu_write_msg()
95 struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d->domain); in mvebu_icu_write_msg()
96 struct mvebu_icu_irq_data *icu_irqd = d->chip_data; in mvebu_icu_write_msg()
97 struct mvebu_icu *icu = icu_irqd->icu; in mvebu_icu_write_msg()
100 if (msg->address_lo || msg->address_hi) { in mvebu_icu_write_msg()
104 icu_int = msg->data | ICU_INT_ENABLE; in mvebu_icu_write_msg()
105 if (icu_irqd->type & IRQ_TYPE_EDGE_RISING) in mvebu_icu_write_msg()
107 icu_int |= icu_irqd->icu_group << ICU_GROUP_SHIFT; in mvebu_icu_write_msg()
109 /* De-configure the ICU */ in mvebu_icu_write_msg()
113 writel_relaxed(icu_int, icu->base + ICU_INT_CFG(d->hwirq)); in mvebu_icu_write_msg()
124 if (d->hwirq == ICU_SATA0_ICU_ID || d->hwirq == ICU_SATA1_ICU_ID) { in mvebu_icu_write_msg()
126 icu->base + ICU_INT_CFG(ICU_SATA0_ICU_ID)); in mvebu_icu_write_msg()
128 icu->base + ICU_INT_CFG(ICU_SATA1_ICU_ID)); in mvebu_icu_write_msg()
133 .name = "ICU-NSR",
142 .name = "ICU-SEI",
159 if (WARN_ON(fwspec->param_count != param_count)) { in mvebu_icu_irq_domain_translate()
160 dev_err(icu->dev, "wrong ICU parameter count %d\n", in mvebu_icu_irq_domain_translate()
161 fwspec->param_count); in mvebu_icu_irq_domain_translate()
162 return -EINVAL; in mvebu_icu_irq_domain_translate()
166 *hwirq = fwspec->param[1]; in mvebu_icu_irq_domain_translate()
167 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; in mvebu_icu_irq_domain_translate()
168 if (fwspec->param[0] != ICU_GRP_NSR) { in mvebu_icu_irq_domain_translate()
169 dev_err(icu->dev, "wrong ICU group type %x\n", in mvebu_icu_irq_domain_translate()
170 fwspec->param[0]); in mvebu_icu_irq_domain_translate()
171 return -EINVAL; in mvebu_icu_irq_domain_translate()
174 *hwirq = fwspec->param[0]; in mvebu_icu_irq_domain_translate()
175 *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; in mvebu_icu_irq_domain_translate()
183 if (msi_data->subset_data->icu_group == ICU_GRP_SEI) in mvebu_icu_irq_domain_translate()
188 dev_err(icu->dev, "invalid interrupt number %ld\n", *hwirq); in mvebu_icu_irq_domain_translate()
189 return -EINVAL; in mvebu_icu_irq_domain_translate()
203 struct mvebu_icu *icu = msi_data->icu; in mvebu_icu_irq_domain_alloc()
209 return -ENOMEM; in mvebu_icu_irq_domain_alloc()
212 &icu_irqd->type); in mvebu_icu_irq_domain_alloc()
214 dev_err(icu->dev, "failed to translate ICU parameters\n"); in mvebu_icu_irq_domain_alloc()
219 icu_irqd->icu_group = fwspec->param[0]; in mvebu_icu_irq_domain_alloc()
221 icu_irqd->icu_group = msi_data->subset_data->icu_group; in mvebu_icu_irq_domain_alloc()
222 icu_irqd->icu = icu; in mvebu_icu_irq_domain_alloc()
226 dev_err(icu->dev, "failed to allocate ICU interrupt in parent domain\n"); in mvebu_icu_irq_domain_alloc()
235 if (icu_irqd->icu_group == ICU_GRP_SEI) in mvebu_icu_irq_domain_alloc()
241 dev_err(icu->dev, "failed to set the data to IRQ domain\n"); in mvebu_icu_irq_domain_alloc()
259 struct mvebu_icu_irq_data *icu_irqd = d->chip_data; in mvebu_icu_irq_domain_free()
288 .compatible = "marvell,cp110-icu-nsr",
292 .compatible = "marvell,cp110-icu-sei",
302 struct device *dev = &pdev->dev; in mvebu_icu_subset_probe()
307 return -ENOMEM; in mvebu_icu_subset_probe()
310 msi_data->icu = dev_get_drvdata(dev); in mvebu_icu_subset_probe()
311 msi_data->subset_data = &mvebu_icu_nsr_subset_data; in mvebu_icu_subset_probe()
313 msi_data->icu = dev_get_drvdata(dev->parent); in mvebu_icu_subset_probe()
314 msi_data->subset_data = of_device_get_match_data(dev); in mvebu_icu_subset_probe()
317 dev->msi_domain = of_msi_get_domain(dev, dev->of_node, in mvebu_icu_subset_probe()
319 if (!dev->msi_domain) in mvebu_icu_subset_probe()
320 return -EPROBE_DEFER; in mvebu_icu_subset_probe()
322 msi_parent_dn = irq_domain_get_of_node(dev->msi_domain); in mvebu_icu_subset_probe()
324 return -ENODEV; in mvebu_icu_subset_probe()
331 dev_err(dev, "Failed to create ICU MSI domain\n"); in mvebu_icu_subset_probe()
332 return -ENOMEM; in mvebu_icu_subset_probe()
341 .name = "mvebu-icu-subset",
353 icu = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_icu), in mvebu_icu_probe()
356 return -ENOMEM; in mvebu_icu_probe()
358 icu->dev = &pdev->dev; in mvebu_icu_probe()
361 icu->base = devm_ioremap_resource(&pdev->dev, res); in mvebu_icu_probe()
362 if (IS_ERR(icu->base)) { in mvebu_icu_probe()
363 dev_err(&pdev->dev, "Failed to map icu base address.\n"); in mvebu_icu_probe()
364 return PTR_ERR(icu->base); in mvebu_icu_probe()
368 * Legacy bindings: ICU is one node with one MSI parent: force manually in mvebu_icu_probe()
371 * having its own MSI parent: call platform_populate(). in mvebu_icu_probe()
374 if (!of_get_child_count(pdev->dev.of_node)) in mvebu_icu_probe()
379 * avoid unpredictable SPI assignments done by firmware. in mvebu_icu_probe()
384 icu_int = readl_relaxed(icu->base + ICU_INT_CFG(i)); in mvebu_icu_probe()
390 writel_relaxed(0x0, icu->base + ICU_INT_CFG(i)); in mvebu_icu_probe()
398 return devm_of_platform_populate(&pdev->dev); in mvebu_icu_probe()
402 { .compatible = "marvell,cp110-icu", },
409 .name = "mvebu-icu",