Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Toshiba Visconti GPIO Support
0004  *
0005  * (C) Copyright 2020 Toshiba Electronic Devices & Storage Corporation
0006  * (C) Copyright 2020 TOSHIBA CORPORATION
0007  *
0008  * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
0009  */
0010 
0011 #include <linux/gpio/driver.h>
0012 #include <linux/init.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/module.h>
0015 #include <linux/io.h>
0016 #include <linux/of_irq.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/bitops.h>
0019 
0020 /* register offset */
0021 #define GPIO_DIR    0x00
0022 #define GPIO_IDATA  0x08
0023 #define GPIO_ODATA  0x10
0024 #define GPIO_OSET   0x18
0025 #define GPIO_OCLR   0x20
0026 #define GPIO_INTMODE    0x30
0027 
0028 #define BASE_HW_IRQ 24
0029 
0030 struct visconti_gpio {
0031     void __iomem *base;
0032     spinlock_t lock; /* protect gpio register */
0033     struct gpio_chip gpio_chip;
0034     struct irq_chip irq_chip;
0035 };
0036 
0037 static int visconti_gpio_irq_set_type(struct irq_data *d, unsigned int type)
0038 {
0039     struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
0040     struct visconti_gpio *priv = gpiochip_get_data(gc);
0041     u32 offset = irqd_to_hwirq(d);
0042     u32 bit = BIT(offset);
0043     u32 intc_type = IRQ_TYPE_EDGE_RISING;
0044     u32 intmode, odata;
0045     int ret = 0;
0046     unsigned long flags;
0047 
0048     spin_lock_irqsave(&priv->lock, flags);
0049 
0050     odata = readl(priv->base + GPIO_ODATA);
0051     intmode = readl(priv->base + GPIO_INTMODE);
0052 
0053     switch (type) {
0054     case IRQ_TYPE_EDGE_RISING:
0055         odata &= ~bit;
0056         intmode &= ~bit;
0057         break;
0058     case IRQ_TYPE_EDGE_FALLING:
0059         odata |= bit;
0060         intmode &= ~bit;
0061         break;
0062     case IRQ_TYPE_EDGE_BOTH:
0063         intmode |= bit;
0064         break;
0065     case IRQ_TYPE_LEVEL_HIGH:
0066         intc_type = IRQ_TYPE_LEVEL_HIGH;
0067         odata &= ~bit;
0068         intmode &= ~bit;
0069         break;
0070     case IRQ_TYPE_LEVEL_LOW:
0071         intc_type = IRQ_TYPE_LEVEL_HIGH;
0072         odata |= bit;
0073         intmode &= ~bit;
0074         break;
0075     default:
0076         ret = -EINVAL;
0077         goto err;
0078     }
0079 
0080     writel(odata, priv->base + GPIO_ODATA);
0081     writel(intmode, priv->base + GPIO_INTMODE);
0082     irq_set_irq_type(offset, intc_type);
0083 
0084     ret = irq_chip_set_type_parent(d, type);
0085 err:
0086     spin_unlock_irqrestore(&priv->lock, flags);
0087     return ret;
0088 }
0089 
0090 static int visconti_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
0091                            unsigned int child,
0092                            unsigned int child_type,
0093                            unsigned int *parent,
0094                            unsigned int *parent_type)
0095 {
0096     /* Interrupts 0..15 mapped to interrupts 24..39 on the GIC */
0097     if (child < 16) {
0098         /* All these interrupts are level high in the CPU */
0099         *parent_type = IRQ_TYPE_LEVEL_HIGH;
0100         *parent = child + BASE_HW_IRQ;
0101         return 0;
0102     }
0103     return -EINVAL;
0104 }
0105 
0106 static int visconti_gpio_populate_parent_fwspec(struct gpio_chip *chip,
0107                         union gpio_irq_fwspec *gfwspec,
0108                         unsigned int parent_hwirq,
0109                         unsigned int parent_type)
0110 {
0111     struct irq_fwspec *fwspec = &gfwspec->fwspec;
0112 
0113     fwspec->fwnode = chip->irq.parent_domain->fwnode;
0114     fwspec->param_count = 3;
0115     fwspec->param[0] = 0;
0116     fwspec->param[1] = parent_hwirq;
0117     fwspec->param[2] = parent_type;
0118 
0119     return 0;
0120 }
0121 
0122 static int visconti_gpio_probe(struct platform_device *pdev)
0123 {
0124     struct device *dev = &pdev->dev;
0125     struct visconti_gpio *priv;
0126     struct irq_chip *irq_chip;
0127     struct gpio_irq_chip *girq;
0128     struct irq_domain *parent;
0129     struct device_node *irq_parent;
0130     int ret;
0131 
0132     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0133     if (!priv)
0134         return -ENOMEM;
0135 
0136     spin_lock_init(&priv->lock);
0137 
0138     priv->base = devm_platform_ioremap_resource(pdev, 0);
0139     if (IS_ERR(priv->base))
0140         return PTR_ERR(priv->base);
0141 
0142     irq_parent = of_irq_find_parent(dev->of_node);
0143     if (!irq_parent) {
0144         dev_err(dev, "No IRQ parent node\n");
0145         return -ENODEV;
0146     }
0147 
0148     parent = irq_find_host(irq_parent);
0149     of_node_put(irq_parent);
0150     if (!parent) {
0151         dev_err(dev, "No IRQ parent domain\n");
0152         return -ENODEV;
0153     }
0154 
0155     ret = bgpio_init(&priv->gpio_chip, dev, 4,
0156              priv->base + GPIO_IDATA,
0157              priv->base + GPIO_OSET,
0158              priv->base + GPIO_OCLR,
0159              priv->base + GPIO_DIR,
0160              NULL,
0161              0);
0162     if (ret) {
0163         dev_err(dev, "unable to init generic GPIO\n");
0164         return ret;
0165     }
0166 
0167     irq_chip = &priv->irq_chip;
0168     irq_chip->name = dev_name(dev);
0169     irq_chip->irq_mask = irq_chip_mask_parent;
0170     irq_chip->irq_unmask = irq_chip_unmask_parent;
0171     irq_chip->irq_eoi = irq_chip_eoi_parent;
0172     irq_chip->irq_set_type = visconti_gpio_irq_set_type;
0173     irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
0174 
0175     girq = &priv->gpio_chip.irq;
0176     girq->chip = irq_chip;
0177     girq->fwnode = of_node_to_fwnode(dev->of_node);
0178     girq->parent_domain = parent;
0179     girq->child_to_parent_hwirq = visconti_gpio_child_to_parent_hwirq;
0180     girq->populate_parent_alloc_arg = visconti_gpio_populate_parent_fwspec;
0181     girq->default_type = IRQ_TYPE_NONE;
0182     girq->handler = handle_level_irq;
0183 
0184     return devm_gpiochip_add_data(dev, &priv->gpio_chip, priv);
0185 }
0186 
0187 static const struct of_device_id visconti_gpio_of_match[] = {
0188     { .compatible = "toshiba,gpio-tmpv7708", },
0189     { /* end of table */ }
0190 };
0191 MODULE_DEVICE_TABLE(of, visconti_gpio_of_match);
0192 
0193 static struct platform_driver visconti_gpio_driver = {
0194     .probe      = visconti_gpio_probe,
0195     .driver     = {
0196         .name   = "visconti_gpio",
0197         .of_match_table = of_match_ptr(visconti_gpio_of_match),
0198     }
0199 };
0200 module_platform_driver(visconti_gpio_driver);
0201 
0202 MODULE_AUTHOR("Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>");
0203 MODULE_DESCRIPTION("Toshiba Visconti GPIO Driver");
0204 MODULE_LICENSE("GPL v2");