Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Driver for IDT/Renesas 79RC3243x Interrupt Controller  */
0003 
0004 #include <linux/bitops.h>
0005 #include <linux/gpio/driver.h>
0006 #include <linux/irq.h>
0007 #include <linux/module.h>
0008 #include <linux/mod_devicetable.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/spinlock.h>
0011 
0012 #define IDT_PIC_IRQ_PEND    0x00
0013 #define IDT_PIC_IRQ_MASK    0x08
0014 
0015 #define IDT_GPIO_DIR        0x00
0016 #define IDT_GPIO_DATA       0x04
0017 #define IDT_GPIO_ILEVEL     0x08
0018 #define IDT_GPIO_ISTAT      0x0C
0019 
0020 struct idt_gpio_ctrl {
0021     struct gpio_chip gc;
0022     void __iomem *pic;
0023     void __iomem *gpio;
0024     u32 mask_cache;
0025 };
0026 
0027 static void idt_gpio_dispatch(struct irq_desc *desc)
0028 {
0029     struct gpio_chip *gc = irq_desc_get_handler_data(desc);
0030     struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc);
0031     struct irq_chip *host_chip = irq_desc_get_chip(desc);
0032     unsigned int bit, virq;
0033     unsigned long pending;
0034 
0035     chained_irq_enter(host_chip, desc);
0036 
0037     pending = readl(ctrl->pic + IDT_PIC_IRQ_PEND);
0038     pending &= ~ctrl->mask_cache;
0039     for_each_set_bit(bit, &pending, gc->ngpio) {
0040         virq = irq_linear_revmap(gc->irq.domain, bit);
0041         if (virq)
0042             generic_handle_irq(virq);
0043     }
0044 
0045     chained_irq_exit(host_chip, desc);
0046 }
0047 
0048 static int idt_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
0049 {
0050     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0051     struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc);
0052     unsigned int sense = flow_type & IRQ_TYPE_SENSE_MASK;
0053     unsigned long flags;
0054     u32 ilevel;
0055 
0056     /* hardware only supports level triggered */
0057     if (sense == IRQ_TYPE_NONE || (sense & IRQ_TYPE_EDGE_BOTH))
0058         return -EINVAL;
0059 
0060     raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
0061 
0062     ilevel = readl(ctrl->gpio + IDT_GPIO_ILEVEL);
0063     if (sense & IRQ_TYPE_LEVEL_HIGH)
0064         ilevel |= BIT(d->hwirq);
0065     else if (sense & IRQ_TYPE_LEVEL_LOW)
0066         ilevel &= ~BIT(d->hwirq);
0067 
0068     writel(ilevel, ctrl->gpio + IDT_GPIO_ILEVEL);
0069     irq_set_handler_locked(d, handle_level_irq);
0070 
0071     raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
0072     return 0;
0073 }
0074 
0075 static void idt_gpio_ack(struct irq_data *d)
0076 {
0077     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0078     struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc);
0079 
0080     writel(~BIT(d->hwirq), ctrl->gpio + IDT_GPIO_ISTAT);
0081 }
0082 
0083 static void idt_gpio_mask(struct irq_data *d)
0084 {
0085     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0086     struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc);
0087     unsigned long flags;
0088 
0089     raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
0090 
0091     ctrl->mask_cache |= BIT(d->hwirq);
0092     writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK);
0093 
0094     raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
0095 }
0096 
0097 static void idt_gpio_unmask(struct irq_data *d)
0098 {
0099     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0100     struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc);
0101     unsigned long flags;
0102 
0103     raw_spin_lock_irqsave(&gc->bgpio_lock, flags);
0104 
0105     ctrl->mask_cache &= ~BIT(d->hwirq);
0106     writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK);
0107 
0108     raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
0109 }
0110 
0111 static int idt_gpio_irq_init_hw(struct gpio_chip *gc)
0112 {
0113     struct idt_gpio_ctrl *ctrl = gpiochip_get_data(gc);
0114 
0115     /* Mask interrupts. */
0116     ctrl->mask_cache = 0xffffffff;
0117     writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK);
0118 
0119     return 0;
0120 }
0121 
0122 static struct irq_chip idt_gpio_irqchip = {
0123     .name = "IDTGPIO",
0124     .irq_mask = idt_gpio_mask,
0125     .irq_ack = idt_gpio_ack,
0126     .irq_unmask = idt_gpio_unmask,
0127     .irq_set_type = idt_gpio_irq_set_type
0128 };
0129 
0130 static int idt_gpio_probe(struct platform_device *pdev)
0131 {
0132     struct device *dev = &pdev->dev;
0133     struct gpio_irq_chip *girq;
0134     struct idt_gpio_ctrl *ctrl;
0135     int parent_irq;
0136     int ngpios;
0137     int ret;
0138 
0139 
0140     ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
0141     if (!ctrl)
0142         return -ENOMEM;
0143 
0144     ctrl->gpio = devm_platform_ioremap_resource_byname(pdev, "gpio");
0145     if (IS_ERR(ctrl->gpio))
0146         return PTR_ERR(ctrl->gpio);
0147 
0148     ctrl->gc.parent = dev;
0149 
0150     ret = bgpio_init(&ctrl->gc, &pdev->dev, 4, ctrl->gpio + IDT_GPIO_DATA,
0151              NULL, NULL, ctrl->gpio + IDT_GPIO_DIR, NULL, 0);
0152     if (ret) {
0153         dev_err(dev, "bgpio_init failed\n");
0154         return ret;
0155     }
0156 
0157     ret = device_property_read_u32(dev, "ngpios", &ngpios);
0158     if (!ret)
0159         ctrl->gc.ngpio = ngpios;
0160 
0161     if (device_property_read_bool(dev, "interrupt-controller")) {
0162         ctrl->pic = devm_platform_ioremap_resource_byname(pdev, "pic");
0163         if (IS_ERR(ctrl->pic))
0164             return PTR_ERR(ctrl->pic);
0165 
0166         parent_irq = platform_get_irq(pdev, 0);
0167         if (parent_irq < 0)
0168             return parent_irq;
0169 
0170         girq = &ctrl->gc.irq;
0171         girq->chip = &idt_gpio_irqchip;
0172         girq->init_hw = idt_gpio_irq_init_hw;
0173         girq->parent_handler = idt_gpio_dispatch;
0174         girq->num_parents = 1;
0175         girq->parents = devm_kcalloc(dev, girq->num_parents,
0176                          sizeof(*girq->parents),
0177                          GFP_KERNEL);
0178         if (!girq->parents)
0179             return -ENOMEM;
0180 
0181         girq->parents[0] = parent_irq;
0182         girq->default_type = IRQ_TYPE_NONE;
0183         girq->handler = handle_bad_irq;
0184     }
0185 
0186     return devm_gpiochip_add_data(&pdev->dev, &ctrl->gc, ctrl);
0187 }
0188 
0189 static const struct of_device_id idt_gpio_of_match[] = {
0190     { .compatible = "idt,32434-gpio" },
0191     { }
0192 };
0193 MODULE_DEVICE_TABLE(of, idt_gpio_of_match);
0194 
0195 static struct platform_driver idt_gpio_driver = {
0196     .probe = idt_gpio_probe,
0197     .driver = {
0198         .name = "idt3243x-gpio",
0199         .of_match_table = idt_gpio_of_match,
0200     },
0201 };
0202 module_platform_driver(idt_gpio_driver);
0203 
0204 MODULE_DESCRIPTION("IDT 79RC3243x GPIO/PIC Driver");
0205 MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
0206 MODULE_LICENSE("GPL");