1#include <linux/kernel.h> 2#include <linux/init.h> 3#include <linux/gpio.h> 4#include <linux/gpio/driver.h> 5#include <linux/of_gpio.h> 6#include <linux/io.h> 7#include <linux/interrupt.h> 8#include <linux/platform_device.h> 9#include <linux/basic_mmio_gpio.h> 10 11#define ETRAX_FS_rw_pa_dout 0 12#define ETRAX_FS_r_pa_din 4 13#define ETRAX_FS_rw_pa_oe 8 14#define ETRAX_FS_rw_intr_cfg 12 15#define ETRAX_FS_rw_intr_mask 16 16#define ETRAX_FS_rw_ack_intr 20 17#define ETRAX_FS_r_intr 24 18#define ETRAX_FS_r_masked_intr 28 19#define ETRAX_FS_rw_pb_dout 32 20#define ETRAX_FS_r_pb_din 36 21#define ETRAX_FS_rw_pb_oe 40 22#define ETRAX_FS_rw_pc_dout 48 23#define ETRAX_FS_r_pc_din 52 24#define ETRAX_FS_rw_pc_oe 56 25#define ETRAX_FS_rw_pd_dout 64 26#define ETRAX_FS_r_pd_din 68 27#define ETRAX_FS_rw_pd_oe 72 28#define ETRAX_FS_rw_pe_dout 80 29#define ETRAX_FS_r_pe_din 84 30#define ETRAX_FS_rw_pe_oe 88 31 32#define ARTPEC3_r_pa_din 0 33#define ARTPEC3_rw_pa_dout 4 34#define ARTPEC3_rw_pa_oe 8 35#define ARTPEC3_r_pb_din 44 36#define ARTPEC3_rw_pb_dout 48 37#define ARTPEC3_rw_pb_oe 52 38#define ARTPEC3_r_pc_din 88 39#define ARTPEC3_rw_pc_dout 92 40#define ARTPEC3_rw_pc_oe 96 41#define ARTPEC3_r_pd_din 116 42#define ARTPEC3_rw_intr_cfg 120 43#define ARTPEC3_rw_intr_pins 124 44#define ARTPEC3_rw_intr_mask 128 45#define ARTPEC3_rw_ack_intr 132 46#define ARTPEC3_r_masked_intr 140 47 48#define GIO_CFG_OFF 0 49#define GIO_CFG_HI 1 50#define GIO_CFG_LO 2 51#define GIO_CFG_SET 3 52#define GIO_CFG_POSEDGE 5 53#define GIO_CFG_NEGEDGE 6 54#define GIO_CFG_ANYEDGE 7 55 56struct etraxfs_gpio_info; 57 58struct etraxfs_gpio_block { 59 spinlock_t lock; 60 u32 mask; 61 u32 cfg; 62 u32 pins; 63 unsigned int group[8]; 64 65 void __iomem *regs; 66 const struct etraxfs_gpio_info *info; 67}; 68 69struct etraxfs_gpio_chip { 70 struct bgpio_chip bgc; 71 struct etraxfs_gpio_block *block; 72}; 73 74struct etraxfs_gpio_port { 75 const char *label; 76 unsigned int oe; 77 unsigned int dout; 78 unsigned int din; 79 unsigned int ngpio; 80}; 81 82struct etraxfs_gpio_info { 83 unsigned int num_ports; 84 const struct etraxfs_gpio_port *ports; 85 86 unsigned int rw_ack_intr; 87 unsigned int rw_intr_mask; 88 unsigned int rw_intr_cfg; 89 unsigned int rw_intr_pins; 90 unsigned int r_masked_intr; 91}; 92 93static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = { 94 { 95 .label = "A", 96 .ngpio = 8, 97 .oe = ETRAX_FS_rw_pa_oe, 98 .dout = ETRAX_FS_rw_pa_dout, 99 .din = ETRAX_FS_r_pa_din, 100 }, 101 { 102 .label = "B", 103 .ngpio = 18, 104 .oe = ETRAX_FS_rw_pb_oe, 105 .dout = ETRAX_FS_rw_pb_dout, 106 .din = ETRAX_FS_r_pb_din, 107 }, 108 { 109 .label = "C", 110 .ngpio = 18, 111 .oe = ETRAX_FS_rw_pc_oe, 112 .dout = ETRAX_FS_rw_pc_dout, 113 .din = ETRAX_FS_r_pc_din, 114 }, 115 { 116 .label = "D", 117 .ngpio = 18, 118 .oe = ETRAX_FS_rw_pd_oe, 119 .dout = ETRAX_FS_rw_pd_dout, 120 .din = ETRAX_FS_r_pd_din, 121 }, 122 { 123 .label = "E", 124 .ngpio = 18, 125 .oe = ETRAX_FS_rw_pe_oe, 126 .dout = ETRAX_FS_rw_pe_dout, 127 .din = ETRAX_FS_r_pe_din, 128 }, 129}; 130 131static const struct etraxfs_gpio_info etraxfs_gpio_etraxfs = { 132 .num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports), 133 .ports = etraxfs_gpio_etraxfs_ports, 134 .rw_ack_intr = ETRAX_FS_rw_ack_intr, 135 .rw_intr_mask = ETRAX_FS_rw_intr_mask, 136 .rw_intr_cfg = ETRAX_FS_rw_intr_cfg, 137 .r_masked_intr = ETRAX_FS_r_masked_intr, 138}; 139 140static const struct etraxfs_gpio_port etraxfs_gpio_artpec3_ports[] = { 141 { 142 .label = "A", 143 .ngpio = 32, 144 .oe = ARTPEC3_rw_pa_oe, 145 .dout = ARTPEC3_rw_pa_dout, 146 .din = ARTPEC3_r_pa_din, 147 }, 148 { 149 .label = "B", 150 .ngpio = 32, 151 .oe = ARTPEC3_rw_pb_oe, 152 .dout = ARTPEC3_rw_pb_dout, 153 .din = ARTPEC3_r_pb_din, 154 }, 155 { 156 .label = "C", 157 .ngpio = 16, 158 .oe = ARTPEC3_rw_pc_oe, 159 .dout = ARTPEC3_rw_pc_dout, 160 .din = ARTPEC3_r_pc_din, 161 }, 162 { 163 .label = "D", 164 .ngpio = 32, 165 .din = ARTPEC3_r_pd_din, 166 }, 167}; 168 169static const struct etraxfs_gpio_info etraxfs_gpio_artpec3 = { 170 .num_ports = ARRAY_SIZE(etraxfs_gpio_artpec3_ports), 171 .ports = etraxfs_gpio_artpec3_ports, 172 .rw_ack_intr = ARTPEC3_rw_ack_intr, 173 .rw_intr_mask = ARTPEC3_rw_intr_mask, 174 .rw_intr_cfg = ARTPEC3_rw_intr_cfg, 175 .r_masked_intr = ARTPEC3_r_masked_intr, 176 .rw_intr_pins = ARTPEC3_rw_intr_pins, 177}; 178 179static struct etraxfs_gpio_chip *to_etraxfs(struct gpio_chip *gc) 180{ 181 return container_of(gc, struct etraxfs_gpio_chip, bgc.gc); 182} 183 184static unsigned int etraxfs_gpio_chip_to_port(struct gpio_chip *gc) 185{ 186 return gc->label[0] - 'A'; 187} 188 189static int etraxfs_gpio_of_xlate(struct gpio_chip *gc, 190 const struct of_phandle_args *gpiospec, 191 u32 *flags) 192{ 193 /* 194 * Port numbers are A to E, and the properties are integers, so we 195 * specify them as 0xA - 0xE. 196 */ 197 if (etraxfs_gpio_chip_to_port(gc) + 0xA != gpiospec->args[2]) 198 return -EINVAL; 199 200 return of_gpio_simple_xlate(gc, gpiospec, flags); 201} 202 203static const struct of_device_id etraxfs_gpio_of_table[] = { 204 { 205 .compatible = "axis,etraxfs-gio", 206 .data = &etraxfs_gpio_etraxfs, 207 }, 208 { 209 .compatible = "axis,artpec3-gio", 210 .data = &etraxfs_gpio_artpec3, 211 }, 212 {}, 213}; 214 215static unsigned int etraxfs_gpio_to_group_irq(unsigned int gpio) 216{ 217 return gpio % 8; 218} 219 220static unsigned int etraxfs_gpio_to_group_pin(struct etraxfs_gpio_chip *chip, 221 unsigned int gpio) 222{ 223 return 4 * etraxfs_gpio_chip_to_port(&chip->bgc.gc) + gpio / 8; 224} 225 226static void etraxfs_gpio_irq_ack(struct irq_data *d) 227{ 228 struct etraxfs_gpio_chip *chip = 229 to_etraxfs(irq_data_get_irq_chip_data(d)); 230 struct etraxfs_gpio_block *block = chip->block; 231 unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); 232 233 writel(BIT(grpirq), block->regs + block->info->rw_ack_intr); 234} 235 236static void etraxfs_gpio_irq_mask(struct irq_data *d) 237{ 238 struct etraxfs_gpio_chip *chip = 239 to_etraxfs(irq_data_get_irq_chip_data(d)); 240 struct etraxfs_gpio_block *block = chip->block; 241 unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); 242 243 spin_lock(&block->lock); 244 block->mask &= ~BIT(grpirq); 245 writel(block->mask, block->regs + block->info->rw_intr_mask); 246 spin_unlock(&block->lock); 247} 248 249static void etraxfs_gpio_irq_unmask(struct irq_data *d) 250{ 251 struct etraxfs_gpio_chip *chip = 252 to_etraxfs(irq_data_get_irq_chip_data(d)); 253 struct etraxfs_gpio_block *block = chip->block; 254 unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); 255 256 spin_lock(&block->lock); 257 block->mask |= BIT(grpirq); 258 writel(block->mask, block->regs + block->info->rw_intr_mask); 259 spin_unlock(&block->lock); 260} 261 262static int etraxfs_gpio_irq_set_type(struct irq_data *d, u32 type) 263{ 264 struct etraxfs_gpio_chip *chip = 265 to_etraxfs(irq_data_get_irq_chip_data(d)); 266 struct etraxfs_gpio_block *block = chip->block; 267 unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); 268 u32 cfg; 269 270 switch (type) { 271 case IRQ_TYPE_EDGE_RISING: 272 cfg = GIO_CFG_POSEDGE; 273 break; 274 case IRQ_TYPE_EDGE_FALLING: 275 cfg = GIO_CFG_NEGEDGE; 276 break; 277 case IRQ_TYPE_EDGE_BOTH: 278 cfg = GIO_CFG_ANYEDGE; 279 break; 280 case IRQ_TYPE_LEVEL_LOW: 281 cfg = GIO_CFG_LO; 282 break; 283 case IRQ_TYPE_LEVEL_HIGH: 284 cfg = GIO_CFG_HI; 285 break; 286 default: 287 return -EINVAL; 288 } 289 290 spin_lock(&block->lock); 291 block->cfg &= ~(0x7 << (grpirq * 3)); 292 block->cfg |= (cfg << (grpirq * 3)); 293 writel(block->cfg, block->regs + block->info->rw_intr_cfg); 294 spin_unlock(&block->lock); 295 296 return 0; 297} 298 299static int etraxfs_gpio_irq_request_resources(struct irq_data *d) 300{ 301 struct etraxfs_gpio_chip *chip = 302 to_etraxfs(irq_data_get_irq_chip_data(d)); 303 struct etraxfs_gpio_block *block = chip->block; 304 unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); 305 int ret = -EBUSY; 306 307 spin_lock(&block->lock); 308 if (block->group[grpirq]) 309 goto out; 310 311 ret = gpiochip_lock_as_irq(&chip->bgc.gc, d->hwirq); 312 if (ret) 313 goto out; 314 315 block->group[grpirq] = d->irq; 316 if (block->info->rw_intr_pins) { 317 unsigned int pin = etraxfs_gpio_to_group_pin(chip, d->hwirq); 318 319 block->pins &= ~(0xf << (grpirq * 4)); 320 block->pins |= (pin << (grpirq * 4)); 321 322 writel(block->pins, block->regs + block->info->rw_intr_pins); 323 } 324 325out: 326 spin_unlock(&block->lock); 327 return ret; 328} 329 330static void etraxfs_gpio_irq_release_resources(struct irq_data *d) 331{ 332 struct etraxfs_gpio_chip *chip = 333 to_etraxfs(irq_data_get_irq_chip_data(d)); 334 struct etraxfs_gpio_block *block = chip->block; 335 unsigned int grpirq = etraxfs_gpio_to_group_irq(d->hwirq); 336 337 spin_lock(&block->lock); 338 block->group[grpirq] = 0; 339 gpiochip_unlock_as_irq(&chip->bgc.gc, d->hwirq); 340 spin_unlock(&block->lock); 341} 342 343static struct irq_chip etraxfs_gpio_irq_chip = { 344 .name = "gpio-etraxfs", 345 .irq_ack = etraxfs_gpio_irq_ack, 346 .irq_mask = etraxfs_gpio_irq_mask, 347 .irq_unmask = etraxfs_gpio_irq_unmask, 348 .irq_set_type = etraxfs_gpio_irq_set_type, 349 .irq_request_resources = etraxfs_gpio_irq_request_resources, 350 .irq_release_resources = etraxfs_gpio_irq_release_resources, 351}; 352 353static irqreturn_t etraxfs_gpio_interrupt(int irq, void *dev_id) 354{ 355 struct etraxfs_gpio_block *block = dev_id; 356 unsigned long intr = readl(block->regs + block->info->r_masked_intr); 357 int bit; 358 359 for_each_set_bit(bit, &intr, 8) 360 generic_handle_irq(block->group[bit]); 361 362 return IRQ_RETVAL(intr & 0xff); 363} 364 365static int etraxfs_gpio_probe(struct platform_device *pdev) 366{ 367 struct device *dev = &pdev->dev; 368 const struct etraxfs_gpio_info *info; 369 const struct of_device_id *match; 370 struct etraxfs_gpio_block *block; 371 struct etraxfs_gpio_chip *chips; 372 struct resource *res, *irq; 373 bool allportsirq = false; 374 void __iomem *regs; 375 int ret; 376 int i; 377 378 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 379 regs = devm_ioremap_resource(dev, res); 380 if (IS_ERR(regs)) 381 return PTR_ERR(regs); 382 383 match = of_match_node(etraxfs_gpio_of_table, dev->of_node); 384 if (!match) 385 return -EINVAL; 386 387 info = match->data; 388 389 chips = devm_kzalloc(dev, sizeof(*chips) * info->num_ports, GFP_KERNEL); 390 if (!chips) 391 return -ENOMEM; 392 393 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 394 if (!irq) 395 return -EINVAL; 396 397 block = devm_kzalloc(dev, sizeof(*block), GFP_KERNEL); 398 if (!block) 399 return -ENOMEM; 400 401 spin_lock_init(&block->lock); 402 403 block->regs = regs; 404 block->info = info; 405 406 writel(0, block->regs + info->rw_intr_mask); 407 writel(0, block->regs + info->rw_intr_cfg); 408 if (info->rw_intr_pins) { 409 allportsirq = true; 410 writel(0, block->regs + info->rw_intr_pins); 411 } 412 413 ret = devm_request_irq(dev, irq->start, etraxfs_gpio_interrupt, 414 IRQF_SHARED, dev_name(dev), block); 415 if (ret) { 416 dev_err(dev, "Unable to request irq %d\n", ret); 417 return ret; 418 } 419 420 for (i = 0; i < info->num_ports; i++) { 421 struct etraxfs_gpio_chip *chip = &chips[i]; 422 struct bgpio_chip *bgc = &chip->bgc; 423 const struct etraxfs_gpio_port *port = &info->ports[i]; 424 unsigned long flags = BGPIOF_READ_OUTPUT_REG_SET; 425 void __iomem *dat = regs + port->din; 426 void __iomem *set = regs + port->dout; 427 void __iomem *dirout = regs + port->oe; 428 429 chip->block = block; 430 431 if (dirout == set) { 432 dirout = set = NULL; 433 flags = BGPIOF_NO_OUTPUT; 434 } 435 436 ret = bgpio_init(bgc, dev, 4, 437 dat, set, NULL, dirout, NULL, 438 flags); 439 if (ret) { 440 dev_err(dev, "Unable to init port %s\n", 441 port->label); 442 continue; 443 } 444 445 bgc->gc.ngpio = port->ngpio; 446 bgc->gc.label = port->label; 447 448 bgc->gc.of_node = dev->of_node; 449 bgc->gc.of_gpio_n_cells = 3; 450 bgc->gc.of_xlate = etraxfs_gpio_of_xlate; 451 452 ret = gpiochip_add(&bgc->gc); 453 if (ret) { 454 dev_err(dev, "Unable to register port %s\n", 455 bgc->gc.label); 456 continue; 457 } 458 459 if (i > 0 && !allportsirq) 460 continue; 461 462 ret = gpiochip_irqchip_add(&bgc->gc, &etraxfs_gpio_irq_chip, 0, 463 handle_level_irq, IRQ_TYPE_NONE); 464 if (ret) { 465 dev_err(dev, "Unable to add irqchip to port %s\n", 466 bgc->gc.label); 467 } 468 } 469 470 return 0; 471} 472 473static struct platform_driver etraxfs_gpio_driver = { 474 .driver = { 475 .name = "etraxfs-gpio", 476 .of_match_table = of_match_ptr(etraxfs_gpio_of_table), 477 }, 478 .probe = etraxfs_gpio_probe, 479}; 480 481static int __init etraxfs_gpio_init(void) 482{ 483 return platform_driver_register(&etraxfs_gpio_driver); 484} 485 486device_initcall(etraxfs_gpio_init); 487