Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Renesas IRQC Driver
0004  *
0005  *  Copyright (C) 2013 Magnus Damm
0006  */
0007 
0008 #include <linux/init.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/ioport.h>
0012 #include <linux/io.h>
0013 #include <linux/irq.h>
0014 #include <linux/irqdomain.h>
0015 #include <linux/err.h>
0016 #include <linux/slab.h>
0017 #include <linux/module.h>
0018 #include <linux/pm_runtime.h>
0019 
0020 #define IRQC_IRQ_MAX    32  /* maximum 32 interrupts per driver instance */
0021 
0022 #define IRQC_REQ_STS    0x00    /* Interrupt Request Status Register */
0023 #define IRQC_EN_STS 0x04    /* Interrupt Enable Status Register */
0024 #define IRQC_EN_SET 0x08    /* Interrupt Enable Set Register */
0025 #define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10))
0026                 /* SYS-CPU vs. RT-CPU */
0027 #define DETECT_STATUS   0x100   /* IRQn Detect Status Register */
0028 #define MONITOR     0x104   /* IRQn Signal Level Monitor Register */
0029 #define HLVL_STS    0x108   /* IRQn High Level Detect Status Register */
0030 #define LLVL_STS    0x10c   /* IRQn Low Level Detect Status Register */
0031 #define S_R_EDGE_STS    0x110   /* IRQn Sync Rising Edge Detect Status Reg. */
0032 #define S_F_EDGE_STS    0x114   /* IRQn Sync Falling Edge Detect Status Reg. */
0033 #define A_R_EDGE_STS    0x118   /* IRQn Async Rising Edge Detect Status Reg. */
0034 #define A_F_EDGE_STS    0x11c   /* IRQn Async Falling Edge Detect Status Reg. */
0035 #define CHTEN_STS   0x120   /* Chattering Reduction Status Register */
0036 #define IRQC_CONFIG(n) (0x180 + ((n) * 0x04))
0037                 /* IRQn Configuration Register */
0038 
0039 struct irqc_irq {
0040     int hw_irq;
0041     int requested_irq;
0042     struct irqc_priv *p;
0043 };
0044 
0045 struct irqc_priv {
0046     void __iomem *iomem;
0047     void __iomem *cpu_int_base;
0048     struct irqc_irq irq[IRQC_IRQ_MAX];
0049     unsigned int number_of_irqs;
0050     struct device *dev;
0051     struct irq_chip_generic *gc;
0052     struct irq_domain *irq_domain;
0053     atomic_t wakeup_path;
0054 };
0055 
0056 static struct irqc_priv *irq_data_to_priv(struct irq_data *data)
0057 {
0058     return data->domain->host_data;
0059 }
0060 
0061 static void irqc_dbg(struct irqc_irq *i, char *str)
0062 {
0063     dev_dbg(i->p->dev, "%s (%d:%d)\n", str, i->requested_irq, i->hw_irq);
0064 }
0065 
0066 static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = {
0067     [IRQ_TYPE_LEVEL_LOW]    = 0x01,
0068     [IRQ_TYPE_LEVEL_HIGH]   = 0x02,
0069     [IRQ_TYPE_EDGE_FALLING] = 0x04, /* Synchronous */
0070     [IRQ_TYPE_EDGE_RISING]  = 0x08, /* Synchronous */
0071     [IRQ_TYPE_EDGE_BOTH]    = 0x0c, /* Synchronous */
0072 };
0073 
0074 static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
0075 {
0076     struct irqc_priv *p = irq_data_to_priv(d);
0077     int hw_irq = irqd_to_hwirq(d);
0078     unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK];
0079     u32 tmp;
0080 
0081     irqc_dbg(&p->irq[hw_irq], "sense");
0082 
0083     if (!value)
0084         return -EINVAL;
0085 
0086     tmp = ioread32(p->iomem + IRQC_CONFIG(hw_irq));
0087     tmp &= ~0x3f;
0088     tmp |= value;
0089     iowrite32(tmp, p->iomem + IRQC_CONFIG(hw_irq));
0090     return 0;
0091 }
0092 
0093 static int irqc_irq_set_wake(struct irq_data *d, unsigned int on)
0094 {
0095     struct irqc_priv *p = irq_data_to_priv(d);
0096     int hw_irq = irqd_to_hwirq(d);
0097 
0098     irq_set_irq_wake(p->irq[hw_irq].requested_irq, on);
0099     if (on)
0100         atomic_inc(&p->wakeup_path);
0101     else
0102         atomic_dec(&p->wakeup_path);
0103 
0104     return 0;
0105 }
0106 
0107 static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
0108 {
0109     struct irqc_irq *i = dev_id;
0110     struct irqc_priv *p = i->p;
0111     u32 bit = BIT(i->hw_irq);
0112 
0113     irqc_dbg(i, "demux1");
0114 
0115     if (ioread32(p->iomem + DETECT_STATUS) & bit) {
0116         iowrite32(bit, p->iomem + DETECT_STATUS);
0117         irqc_dbg(i, "demux2");
0118         generic_handle_domain_irq(p->irq_domain, i->hw_irq);
0119         return IRQ_HANDLED;
0120     }
0121     return IRQ_NONE;
0122 }
0123 
0124 static int irqc_probe(struct platform_device *pdev)
0125 {
0126     struct device *dev = &pdev->dev;
0127     const char *name = dev_name(dev);
0128     struct irqc_priv *p;
0129     int ret;
0130     int k;
0131 
0132     p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
0133     if (!p)
0134         return -ENOMEM;
0135 
0136     p->dev = dev;
0137     platform_set_drvdata(pdev, p);
0138 
0139     pm_runtime_enable(dev);
0140     pm_runtime_get_sync(dev);
0141 
0142     /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */
0143     for (k = 0; k < IRQC_IRQ_MAX; k++) {
0144         ret = platform_get_irq_optional(pdev, k);
0145         if (ret == -ENXIO)
0146             break;
0147         if (ret < 0)
0148             goto err_runtime_pm_disable;
0149 
0150         p->irq[k].p = p;
0151         p->irq[k].hw_irq = k;
0152         p->irq[k].requested_irq = ret;
0153     }
0154 
0155     p->number_of_irqs = k;
0156     if (p->number_of_irqs < 1) {
0157         dev_err(dev, "not enough IRQ resources\n");
0158         ret = -EINVAL;
0159         goto err_runtime_pm_disable;
0160     }
0161 
0162     /* ioremap IOMEM and setup read/write callbacks */
0163     p->iomem = devm_platform_ioremap_resource(pdev, 0);
0164     if (IS_ERR(p->iomem)) {
0165         ret = PTR_ERR(p->iomem);
0166         goto err_runtime_pm_disable;
0167     }
0168 
0169     p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */
0170 
0171     p->irq_domain = irq_domain_add_linear(dev->of_node, p->number_of_irqs,
0172                           &irq_generic_chip_ops, p);
0173     if (!p->irq_domain) {
0174         ret = -ENXIO;
0175         dev_err(dev, "cannot initialize irq domain\n");
0176         goto err_runtime_pm_disable;
0177     }
0178 
0179     ret = irq_alloc_domain_generic_chips(p->irq_domain, p->number_of_irqs,
0180                          1, "irqc", handle_level_irq,
0181                          0, 0, IRQ_GC_INIT_NESTED_LOCK);
0182     if (ret) {
0183         dev_err(dev, "cannot allocate generic chip\n");
0184         goto err_remove_domain;
0185     }
0186 
0187     p->gc = irq_get_domain_generic_chip(p->irq_domain, 0);
0188     p->gc->reg_base = p->cpu_int_base;
0189     p->gc->chip_types[0].regs.enable = IRQC_EN_SET;
0190     p->gc->chip_types[0].regs.disable = IRQC_EN_STS;
0191     p->gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
0192     p->gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
0193     p->gc->chip_types[0].chip.irq_set_type  = irqc_irq_set_type;
0194     p->gc->chip_types[0].chip.irq_set_wake  = irqc_irq_set_wake;
0195     p->gc->chip_types[0].chip.flags = IRQCHIP_MASK_ON_SUSPEND;
0196 
0197     irq_domain_set_pm_device(p->irq_domain, dev);
0198 
0199     /* request interrupts one by one */
0200     for (k = 0; k < p->number_of_irqs; k++) {
0201         if (devm_request_irq(dev, p->irq[k].requested_irq,
0202                      irqc_irq_handler, 0, name, &p->irq[k])) {
0203             dev_err(dev, "failed to request IRQ\n");
0204             ret = -ENOENT;
0205             goto err_remove_domain;
0206         }
0207     }
0208 
0209     dev_info(dev, "driving %d irqs\n", p->number_of_irqs);
0210 
0211     return 0;
0212 
0213 err_remove_domain:
0214     irq_domain_remove(p->irq_domain);
0215 err_runtime_pm_disable:
0216     pm_runtime_put(dev);
0217     pm_runtime_disable(dev);
0218     return ret;
0219 }
0220 
0221 static int irqc_remove(struct platform_device *pdev)
0222 {
0223     struct irqc_priv *p = platform_get_drvdata(pdev);
0224 
0225     irq_domain_remove(p->irq_domain);
0226     pm_runtime_put(&pdev->dev);
0227     pm_runtime_disable(&pdev->dev);
0228     return 0;
0229 }
0230 
0231 static int __maybe_unused irqc_suspend(struct device *dev)
0232 {
0233     struct irqc_priv *p = dev_get_drvdata(dev);
0234 
0235     if (atomic_read(&p->wakeup_path))
0236         device_set_wakeup_path(dev);
0237 
0238     return 0;
0239 }
0240 
0241 static SIMPLE_DEV_PM_OPS(irqc_pm_ops, irqc_suspend, NULL);
0242 
0243 static const struct of_device_id irqc_dt_ids[] = {
0244     { .compatible = "renesas,irqc", },
0245     {},
0246 };
0247 MODULE_DEVICE_TABLE(of, irqc_dt_ids);
0248 
0249 static struct platform_driver irqc_device_driver = {
0250     .probe      = irqc_probe,
0251     .remove     = irqc_remove,
0252     .driver     = {
0253         .name   = "renesas_irqc",
0254         .of_match_table = irqc_dt_ids,
0255         .pm = &irqc_pm_ops,
0256     }
0257 };
0258 
0259 static int __init irqc_init(void)
0260 {
0261     return platform_driver_register(&irqc_device_driver);
0262 }
0263 postcore_initcall(irqc_init);
0264 
0265 static void __exit irqc_exit(void)
0266 {
0267     platform_driver_unregister(&irqc_device_driver);
0268 }
0269 module_exit(irqc_exit);
0270 
0271 MODULE_AUTHOR("Magnus Damm");
0272 MODULE_DESCRIPTION("Renesas IRQC Driver");
0273 MODULE_LICENSE("GPL v2");