diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index c4e61843d9d9..b0b3a80f8cde 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -232,6 +232,7 @@ config QE_GPIO
bool "QE GPIO support"
depends on QUICC_ENGINE
select GPIOLIB
+ select GENERIC_IRQ_CHIP
help
Say Y here if you're going to use hardware that connects to the
QE GPIOs.
diff --git a/drivers/soc/fsl/qe/qe_ports_ic.c b/drivers/soc/fsl/qe/qe_ports_ic.c
index c8b73b0aa233..d022aa224f6d 100644
--- a/drivers/soc/fsl/qe/qe_ports_ic.c
+++ b/drivers/soc/fsl/qe/qe_ports_ic.c
@@ -20,63 +20,65 @@ struct qepic_data {
void __iomem *reg;
struct irq_domain *host;
int irq;
+ struct irq_chip_generic *gc;
};
static void qepic_mask(struct irq_data *d)
{
- struct qepic_data *data = irq_data_get_irq_chip_data(d);
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
- clrbits32(data->reg + CEPIMR, 1 << (31 - irqd_to_hwirq(d)));
+ clrbits32(gc->reg_base + ct->regs.mask, d->mask);
}
static void qepic_unmask(struct irq_data *d)
{
- struct qepic_data *data = irq_data_get_irq_chip_data(d);
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
- setbits32(data->reg + CEPIMR, 1 << (31 - irqd_to_hwirq(d)));
+ setbits32(gc->reg_base + ct->regs.mask, d->mask);
}
static void qepic_end(struct irq_data *d)
{
- struct qepic_data *data = irq_data_get_irq_chip_data(d);
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
- out_be32(data->reg + CEPIER, 1 << (31 - irqd_to_hwirq(d)));
+ out_be32(gc->reg_base + ct->regs.eoi, d->mask);
+}
+
+static void qepic_calc_mask(struct irq_data *d)
+{
+ d->mask = 1 << (31 - irqd_to_hwirq(d));
}
static int qepic_set_type(struct irq_data *d, unsigned int flow_type)
{
- struct qepic_data *data = irq_data_get_irq_chip_data(d);
- unsigned int vec = (unsigned int)irqd_to_hwirq(d);
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+ struct irq_chip_type *ct = irq_data_get_chip_type(d);
switch (flow_type & IRQ_TYPE_SENSE_MASK) {
case IRQ_TYPE_EDGE_FALLING:
- setbits32(data->reg + CEPICR, 1 << (31 - vec));
+ setbits32(gc->reg_base + ct->regs.type, d->mask);
return 0;
case IRQ_TYPE_EDGE_BOTH:
case IRQ_TYPE_NONE:
- clrbits32(data->reg + CEPICR, 1 << (31 - vec));
+ clrbits32(gc->reg_base + ct->regs.type, d->mask);
return 0;
}
return -EINVAL;
}
-static struct irq_chip qepic = {
- .name = "QEPIC",
- .irq_mask = qepic_mask,
- .irq_unmask = qepic_unmask,
- .irq_eoi = qepic_end,
- .irq_set_type = qepic_set_type,
-};
-
static void qepic_cascade(struct irq_desc *desc)
{
struct qepic_data *data = irq_desc_get_handler_data(desc);
+ struct irq_chip_type *ct = data->gc->chip_types;
struct irq_chip *chip = irq_desc_get_chip(desc);
unsigned long event, bit;
chained_irq_enter(chip, desc);
- event = in_be32(data->reg + CEPIER);
+ event = in_be32(data->gc->reg_base + ct->regs.eoi);
if (!event) {
handle_bad_irq(desc);
goto out;@@ -89,33 +91,64 @@ static void qepic_cascade(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
-static int qepic_host_map(struct irq_domain *h, unsigned int virq, irq_hw_number_t hw)
+static int qepic_chip_init(struct irq_chip_generic *gc)
{
- irq_set_chip_data(virq, h->host_data);
- irq_set_chip_and_handler(virq, &qepic, handle_fasteoi_irq);
+ struct irq_chip_type *ct = gc->chip_types;
+
+ ct->regs.mask = CEPIMR;
+ ct->chip.irq_mask = qepic_mask;
+ ct->chip.irq_unmask = qepic_unmask;
+ ct->regs.eoi = CEPIER;
+ ct->chip.irq_eoi = qepic_end;
+ ct->regs.type = CEPICR;
+ ct->chip.irq_set_type = qepic_set_type;
+ ct->chip.irq_calc_mask = qepic_calc_mask;
+
return 0;
}
-static const struct irq_domain_ops qepic_host_ops = {
- .map = qepic_host_map,
-};
+static int qepic_domain_init(struct irq_domain *d)
+{
+ struct qepic_data *data = d->host_data;
-static void qepic_remove(void *res)
+ irq_set_chained_handler_and_data(data->irq, qepic_cascade, data);
+
+ return 0;
+}
+
+static void qepic_domain_exit(struct irq_domain *d)
{
- struct qepic_data *data = res;
+ struct qepic_data *data = d->host_data;
irq_set_chained_handler_and_data(data->irq, NULL, NULL);
- irq_domain_remove(data->host);
}
static int qepic_probe(struct platform_device *pdev)
{
+ struct irq_domain_chip_generic_info dgc_info = {
+ .name = "QEPIC",
+ .handler = handle_fasteoi_irq,
+ .irqs_per_chip = 32,
+ .num_ct = 1,
+ .init = qepic_chip_init,
+ };
+ struct irq_domain_info d_info = {
+ .fwnode = of_fwnode_handle(pdev->dev.of_node),
+ .domain_flags = IRQ_DOMAIN_FLAG_DESTROY_GC,
+ .size = 32,
+ .hwirq_max = 32,
+ .ops = &irq_generic_chip_ops,
+ .dgc_info = &dgc_info,
+ .init = qepic_domain_init,
+ .exit = qepic_domain_exit,
+ };
struct device *dev = &pdev->dev;
struct qepic_data *data;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+ d_info.host_data = data;
data->reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->reg))@@ -125,14 +158,16 @@ static int qepic_probe(struct platform_device *pdev)
if (data->irq < 0)
return data->irq;
- data->host = irq_domain_create_linear(dev_fwnode(dev), 32, &qepic_host_ops, data);
- if (!data->host)
- return -ENODEV;
+ data->host = devm_irq_domain_instantiate(dev, &d_info);
+ if (IS_ERR(data->host))
+ return PTR_ERR(data->host);
- irq_set_chained_handler_and_data(data->irq, qepic_cascade, data);
-
- return devm_add_action_or_reset(dev, qepic_remove, data);
+ data->gc = irq_get_domain_generic_chip(data->host, 0);
+ if (!data->gc)
+ return -ENODEV;
+ data->gc->reg_base = data->reg;
+ return 0;
}
static const struct of_device_id qepic_match[] = {
--
2.55.0