1 /* 2 * Broadcom specific AMBA 3 * GPIO driver 4 * 5 * Copyright 2011, Broadcom Corporation 6 * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> 7 * 8 * Licensed under the GNU/GPL. See COPYING for details. 9 */ 10 11 #include <linux/gpio/driver.h> 12 #include <linux/interrupt.h> 13 #include <linux/export.h> 14 #include <linux/property.h> 15 16 #include <linux/bcma/bcma.h> 17 18 #include "bcma_private.h" 19 20 #define BCMA_GPIO_MAX_PINS 32 21 22 const struct software_node bcma_gpio_swnode = { 23 .name = "bcma-gpio", 24 }; 25 EXPORT_SYMBOL_GPL(bcma_gpio_swnode); 26 27 static int bcma_gpio_get_value(struct gpio_chip *chip, unsigned gpio) 28 { 29 struct bcma_drv_cc *cc = gpiochip_get_data(chip); 30 31 return !!bcma_chipco_gpio_in(cc, 1 << gpio); 32 } 33 34 static int bcma_gpio_set_value(struct gpio_chip *chip, unsigned int gpio, 35 int value) 36 { 37 struct bcma_drv_cc *cc = gpiochip_get_data(chip); 38 39 bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); 40 41 return 0; 42 } 43 44 static int bcma_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) 45 { 46 struct bcma_drv_cc *cc = gpiochip_get_data(chip); 47 48 bcma_chipco_gpio_outen(cc, 1 << gpio, 0); 49 return 0; 50 } 51 52 static int bcma_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, 53 int value) 54 { 55 struct bcma_drv_cc *cc = gpiochip_get_data(chip); 56 57 bcma_chipco_gpio_outen(cc, 1 << gpio, 1 << gpio); 58 bcma_chipco_gpio_out(cc, 1 << gpio, value ? 1 << gpio : 0); 59 return 0; 60 } 61 62 static int bcma_gpio_request(struct gpio_chip *chip, unsigned gpio) 63 { 64 struct bcma_drv_cc *cc = gpiochip_get_data(chip); 65 66 bcma_chipco_gpio_control(cc, 1 << gpio, 0); 67 /* clear pulldown */ 68 bcma_chipco_gpio_pulldown(cc, 1 << gpio, 0); 69 /* Set pullup */ 70 bcma_chipco_gpio_pullup(cc, 1 << gpio, 1 << gpio); 71 72 return 0; 73 } 74 75 static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio) 76 { 77 struct bcma_drv_cc *cc = gpiochip_get_data(chip); 78 79 /* clear pullup */ 80 bcma_chipco_gpio_pullup(cc, 1 << gpio, 0); 81 } 82 83 #if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X) 84 85 static void bcma_gpio_irq_unmask(struct irq_data *d) 86 { 87 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 88 struct bcma_drv_cc *cc = gpiochip_get_data(gc); 89 int gpio = irqd_to_hwirq(d); 90 u32 val = bcma_chipco_gpio_in(cc, BIT(gpio)); 91 92 gpiochip_enable_irq(gc, gpio); 93 bcma_chipco_gpio_polarity(cc, BIT(gpio), val); 94 bcma_chipco_gpio_intmask(cc, BIT(gpio), BIT(gpio)); 95 } 96 97 static void bcma_gpio_irq_mask(struct irq_data *d) 98 { 99 struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 100 struct bcma_drv_cc *cc = gpiochip_get_data(gc); 101 int gpio = irqd_to_hwirq(d); 102 103 bcma_chipco_gpio_intmask(cc, BIT(gpio), 0); 104 gpiochip_disable_irq(gc, gpio); 105 } 106 107 static const struct irq_chip bcma_gpio_irq_chip = { 108 .name = "BCMA-GPIO", 109 .irq_mask = bcma_gpio_irq_mask, 110 .irq_unmask = bcma_gpio_irq_unmask, 111 .flags = IRQCHIP_IMMUTABLE, 112 GPIOCHIP_IRQ_RESOURCE_HELPERS, 113 }; 114 115 static irqreturn_t bcma_gpio_irq_handler(int irq, void *dev_id) 116 { 117 struct bcma_drv_cc *cc = dev_id; 118 struct gpio_chip *gc = &cc->gpio; 119 u32 val = bcma_cc_read32(cc, BCMA_CC_GPIOIN); 120 u32 mask = bcma_cc_read32(cc, BCMA_CC_GPIOIRQ); 121 u32 pol = bcma_cc_read32(cc, BCMA_CC_GPIOPOL); 122 unsigned long irqs = (val ^ pol) & mask; 123 int gpio; 124 125 if (!irqs) 126 return IRQ_NONE; 127 128 for_each_set_bit(gpio, &irqs, gc->ngpio) 129 generic_handle_domain_irq_safe(gc->irq.domain, gpio); 130 bcma_chipco_gpio_polarity(cc, irqs, val & irqs); 131 132 return IRQ_HANDLED; 133 } 134 135 static int bcma_gpio_irq_init(struct bcma_drv_cc *cc) 136 { 137 struct gpio_chip *chip = &cc->gpio; 138 struct gpio_irq_chip *girq = &chip->irq; 139 int hwirq, err; 140 141 if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC) 142 return 0; 143 144 hwirq = bcma_core_irq(cc->core, 0); 145 err = request_irq(hwirq, bcma_gpio_irq_handler, IRQF_SHARED, "gpio", 146 cc); 147 if (err) 148 return err; 149 150 bcma_chipco_gpio_intmask(cc, ~0, 0); 151 bcma_cc_set32(cc, BCMA_CC_IRQMASK, BCMA_CC_IRQ_GPIO); 152 153 gpio_irq_chip_set_chip(girq, &bcma_gpio_irq_chip); 154 /* This will let us handle the parent IRQ in the driver */ 155 girq->parent_handler = NULL; 156 girq->num_parents = 0; 157 girq->parents = NULL; 158 girq->default_type = IRQ_TYPE_NONE; 159 girq->handler = handle_simple_irq; 160 161 return 0; 162 } 163 164 static void bcma_gpio_irq_exit(struct bcma_drv_cc *cc) 165 { 166 if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC) 167 return; 168 169 bcma_cc_mask32(cc, BCMA_CC_IRQMASK, ~BCMA_CC_IRQ_GPIO); 170 free_irq(bcma_core_irq(cc->core, 0), cc); 171 } 172 #else 173 static int bcma_gpio_irq_init(struct bcma_drv_cc *cc) 174 { 175 return 0; 176 } 177 178 static void bcma_gpio_irq_exit(struct bcma_drv_cc *cc) 179 { 180 } 181 #endif 182 183 int bcma_gpio_init(struct bcma_drv_cc *cc) 184 { 185 struct bcma_bus *bus = cc->core->bus; 186 struct gpio_chip *chip = &cc->gpio; 187 int err; 188 189 chip->label = "bcma_gpio"; 190 chip->owner = THIS_MODULE; 191 chip->request = bcma_gpio_request; 192 chip->free = bcma_gpio_free; 193 chip->get = bcma_gpio_get_value; 194 chip->set = bcma_gpio_set_value; 195 chip->direction_input = bcma_gpio_direction_input; 196 chip->direction_output = bcma_gpio_direction_output; 197 chip->parent = bus->dev; 198 199 /* 200 * Register software node only for the host SoC bus, unless there is 201 * already a firmware node assigned. There is only one SoC instance 202 * in the system, so there are no concerns with registration conflicts. 203 */ 204 if (bus->hosttype == BCMA_HOSTTYPE_SOC && !dev_fwnode(&cc->core->dev)) { 205 err = software_node_register(&bcma_gpio_swnode); 206 if (err) 207 return err; 208 chip->fwnode = software_node_fwnode(&bcma_gpio_swnode); 209 } else { 210 chip->fwnode = dev_fwnode(&cc->core->dev); 211 } 212 213 switch (bus->chipinfo.id) { 214 case BCMA_CHIP_ID_BCM4707: 215 case BCMA_CHIP_ID_BCM5357: 216 case BCMA_CHIP_ID_BCM53572: 217 case BCMA_CHIP_ID_BCM53573: 218 case BCMA_CHIP_ID_BCM47094: 219 chip->ngpio = 32; 220 break; 221 default: 222 chip->ngpio = 16; 223 } 224 225 /* 226 * Register SoC GPIO devices with absolute GPIO pin base. 227 * On MIPS, we don't have Device Tree and we can't use relative (per chip) 228 * GPIO numbers. 229 * On some ARM devices, user space may want to access some system GPIO 230 * pins directly, which is easier to do with a predictable GPIO base. 231 */ 232 if (IS_BUILTIN(CONFIG_BCM47XX) || 233 cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC) 234 chip->base = bus->num * BCMA_GPIO_MAX_PINS; 235 else 236 chip->base = -1; 237 238 err = bcma_gpio_irq_init(cc); 239 if (err) 240 goto err_unregister_swnode; 241 242 err = gpiochip_add_data(chip, cc); 243 if (err) 244 goto err_irq_exit; 245 246 return 0; 247 248 err_irq_exit: 249 bcma_gpio_irq_exit(cc); 250 err_unregister_swnode: 251 if (bus->hosttype == BCMA_HOSTTYPE_SOC && 252 chip->fwnode && is_software_node(chip->fwnode)) { 253 software_node_unregister(&bcma_gpio_swnode); 254 chip->fwnode = NULL; 255 } 256 return err; 257 } 258 259 int bcma_gpio_unregister(struct bcma_drv_cc *cc) 260 { 261 bcma_gpio_irq_exit(cc); 262 gpiochip_remove(&cc->gpio); 263 if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC && 264 cc->gpio.fwnode && is_software_node(cc->gpio.fwnode)) { 265 software_node_unregister(&bcma_gpio_swnode); 266 cc->gpio.fwnode = NULL; 267 } 268 return 0; 269 } 270