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