1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Toshiba Visconti GPIO Support 4 * 5 * (C) Copyright 2020 Toshiba Electronic Devices & Storage Corporation 6 * (C) Copyright 2020 TOSHIBA CORPORATION 7 * 8 * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> 9 */ 10 11 #include <linux/gpio/driver.h> 12 #include <linux/init.h> 13 #include <linux/interrupt.h> 14 #include <linux/module.h> 15 #include <linux/io.h> 16 #include <linux/of_irq.h> 17 #include <linux/platform_device.h> 18 #include <linux/bitops.h> 19 20 /* register offset */ 21 #define GPIO_DIR 0x00 22 #define GPIO_IDATA 0x08 23 #define GPIO_ODATA 0x10 24 #define GPIO_OSET 0x18 25 #define GPIO_OCLR 0x20 26 #define GPIO_INTMODE 0x30 27 28 #define BASE_HW_IRQ 24 29 30 struct visconti_gpio { 31 void __iomem *base; 32 spinlock_t lock; /* protect gpio register */ 33 struct gpio_chip gpio_chip; 34 struct irq_chip irq_chip; 35 }; 36 37 static int visconti_gpio_irq_set_type(struct irq_data *d, unsigned int type) 38 { 39 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 40 struct visconti_gpio *priv = gpiochip_get_data(gc); 41 u32 offset = irqd_to_hwirq(d); 42 u32 bit = BIT(offset); 43 u32 intc_type = IRQ_TYPE_EDGE_RISING; 44 u32 intmode, odata; 45 int ret = 0; 46 unsigned long flags; 47 48 spin_lock_irqsave(&priv->lock, flags); 49 50 odata = readl(priv->base + GPIO_ODATA); 51 intmode = readl(priv->base + GPIO_INTMODE); 52 53 switch (type) { 54 case IRQ_TYPE_EDGE_RISING: 55 odata &= ~bit; 56 intmode &= ~bit; 57 break; 58 case IRQ_TYPE_EDGE_FALLING: 59 odata |= bit; 60 intmode &= ~bit; 61 break; 62 case IRQ_TYPE_EDGE_BOTH: 63 intmode |= bit; 64 break; 65 case IRQ_TYPE_LEVEL_HIGH: 66 intc_type = IRQ_TYPE_LEVEL_HIGH; 67 odata &= ~bit; 68 intmode &= ~bit; 69 break; 70 case IRQ_TYPE_LEVEL_LOW: 71 intc_type = IRQ_TYPE_LEVEL_HIGH; 72 odata |= bit; 73 intmode &= ~bit; 74 break; 75 default: 76 ret = -EINVAL; 77 goto err; 78 } 79 80 writel(odata, priv->base + GPIO_ODATA); 81 writel(intmode, priv->base + GPIO_INTMODE); 82 irq_set_irq_type(offset, intc_type); 83 84 ret = irq_chip_set_type_parent(d, type); 85 err: 86 spin_unlock_irqrestore(&priv->lock, flags); 87 return ret; 88 } 89 90 static int visconti_gpio_child_to_parent_hwirq(struct gpio_chip *gc, 91 unsigned int child, 92 unsigned int child_type, 93 unsigned int *parent, 94 unsigned int *parent_type) 95 { 96 /* Interrupts 0..15 mapped to interrupts 24..39 on the GIC */ 97 if (child < 16) { 98 /* All these interrupts are level high in the CPU */ 99 *parent_type = IRQ_TYPE_LEVEL_HIGH; 100 *parent = child + BASE_HW_IRQ; 101 return 0; 102 } 103 return -EINVAL; 104 } 105 106 static void *visconti_gpio_populate_parent_fwspec(struct gpio_chip *chip, 107 unsigned int parent_hwirq, 108 unsigned int parent_type) 109 { 110 struct irq_fwspec *fwspec; 111 112 fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); 113 if (!fwspec) 114 return NULL; 115 116 fwspec->fwnode = chip->irq.parent_domain->fwnode; 117 fwspec->param_count = 3; 118 fwspec->param[0] = 0; 119 fwspec->param[1] = parent_hwirq; 120 fwspec->param[2] = parent_type; 121 122 return fwspec; 123 } 124 125 static int visconti_gpio_probe(struct platform_device *pdev) 126 { 127 struct device *dev = &pdev->dev; 128 struct visconti_gpio *priv; 129 struct irq_chip *irq_chip; 130 struct gpio_irq_chip *girq; 131 struct irq_domain *parent; 132 struct device_node *irq_parent; 133 struct fwnode_handle *fwnode; 134 int ret; 135 136 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 137 if (!priv) 138 return -ENOMEM; 139 140 spin_lock_init(&priv->lock); 141 142 priv->base = devm_platform_ioremap_resource(pdev, 0); 143 if (IS_ERR(priv->base)) 144 return PTR_ERR(priv->base); 145 146 irq_parent = of_irq_find_parent(dev->of_node); 147 if (!irq_parent) { 148 dev_err(dev, "No IRQ parent node\n"); 149 return -ENODEV; 150 } 151 152 parent = irq_find_host(irq_parent); 153 if (!parent) { 154 dev_err(dev, "No IRQ parent domain\n"); 155 return -ENODEV; 156 } 157 158 fwnode = of_node_to_fwnode(irq_parent); 159 of_node_put(irq_parent); 160 161 ret = bgpio_init(&priv->gpio_chip, dev, 4, 162 priv->base + GPIO_IDATA, 163 priv->base + GPIO_OSET, 164 priv->base + GPIO_OCLR, 165 priv->base + GPIO_DIR, 166 NULL, 167 0); 168 if (ret) { 169 dev_err(dev, "unable to init generic GPIO\n"); 170 return ret; 171 } 172 173 irq_chip = &priv->irq_chip; 174 irq_chip->name = dev_name(dev); 175 irq_chip->irq_mask = irq_chip_mask_parent; 176 irq_chip->irq_unmask = irq_chip_unmask_parent; 177 irq_chip->irq_eoi = irq_chip_eoi_parent; 178 irq_chip->irq_set_type = visconti_gpio_irq_set_type; 179 irq_chip->flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND; 180 181 girq = &priv->gpio_chip.irq; 182 girq->chip = irq_chip; 183 girq->fwnode = fwnode; 184 girq->parent_domain = parent; 185 girq->child_to_parent_hwirq = visconti_gpio_child_to_parent_hwirq; 186 girq->populate_parent_alloc_arg = visconti_gpio_populate_parent_fwspec; 187 girq->default_type = IRQ_TYPE_NONE; 188 girq->handler = handle_level_irq; 189 190 ret = devm_gpiochip_add_data(dev, &priv->gpio_chip, priv); 191 if (ret) { 192 dev_err(dev, "failed to add GPIO chip\n"); 193 return ret; 194 } 195 196 platform_set_drvdata(pdev, priv); 197 198 return ret; 199 } 200 201 static const struct of_device_id visconti_gpio_of_match[] = { 202 { .compatible = "toshiba,gpio-tmpv7708", }, 203 { /* end of table */ } 204 }; 205 MODULE_DEVICE_TABLE(of, visconti_gpio_of_match); 206 207 static struct platform_driver visconti_gpio_driver = { 208 .probe = visconti_gpio_probe, 209 .driver = { 210 .name = "visconti_gpio", 211 .of_match_table = of_match_ptr(visconti_gpio_of_match), 212 } 213 }; 214 module_platform_driver(visconti_gpio_driver); 215 216 MODULE_AUTHOR("Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>"); 217 MODULE_DESCRIPTION("Toshiba Visconti GPIO Driver"); 218 MODULE_LICENSE("GPL v2"); 219