11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 26ea5dcdfSWilliam Breathitt Gray /* 36ea5dcdfSWilliam Breathitt Gray * GPIO driver for the Diamond Systems GPIO-MM 46ea5dcdfSWilliam Breathitt Gray * Copyright (C) 2016 William Breathitt Gray 56ea5dcdfSWilliam Breathitt Gray * 66ea5dcdfSWilliam Breathitt Gray * This driver supports the following Diamond Systems devices: GPIO-MM and 76ea5dcdfSWilliam Breathitt Gray * GPIO-MM-12. 86ea5dcdfSWilliam Breathitt Gray */ 941b25131SWilliam Breathitt Gray #include <linux/bitmap.h> 106ea5dcdfSWilliam Breathitt Gray #include <linux/bitops.h> 116ea5dcdfSWilliam Breathitt Gray #include <linux/device.h> 126ea5dcdfSWilliam Breathitt Gray #include <linux/errno.h> 136ea5dcdfSWilliam Breathitt Gray #include <linux/gpio/driver.h> 146ea5dcdfSWilliam Breathitt Gray #include <linux/io.h> 156ea5dcdfSWilliam Breathitt Gray #include <linux/ioport.h> 166ea5dcdfSWilliam Breathitt Gray #include <linux/isa.h> 176ea5dcdfSWilliam Breathitt Gray #include <linux/kernel.h> 186ea5dcdfSWilliam Breathitt Gray #include <linux/module.h> 196ea5dcdfSWilliam Breathitt Gray #include <linux/moduleparam.h> 206ea5dcdfSWilliam Breathitt Gray #include <linux/spinlock.h> 216ea5dcdfSWilliam Breathitt Gray 226ea5dcdfSWilliam Breathitt Gray #define GPIOMM_EXTENT 8 236ea5dcdfSWilliam Breathitt Gray #define MAX_NUM_GPIOMM max_num_isa_dev(GPIOMM_EXTENT) 246ea5dcdfSWilliam Breathitt Gray 256ea5dcdfSWilliam Breathitt Gray static unsigned int base[MAX_NUM_GPIOMM]; 266ea5dcdfSWilliam Breathitt Gray static unsigned int num_gpiomm; 27d759f906SDavid Howells module_param_hw_array(base, uint, ioport, &num_gpiomm, 0); 286ea5dcdfSWilliam Breathitt Gray MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addresses"); 296ea5dcdfSWilliam Breathitt Gray 306ea5dcdfSWilliam Breathitt Gray /** 316ea5dcdfSWilliam Breathitt Gray * struct gpiomm_gpio - GPIO device private data structure 326ea5dcdfSWilliam Breathitt Gray * @chip: instance of the gpio_chip 336ea5dcdfSWilliam Breathitt Gray * @io_state: bit I/O state (whether bit is set to input or output) 346ea5dcdfSWilliam Breathitt Gray * @out_state: output bits state 356ea5dcdfSWilliam Breathitt Gray * @control: Control registers state 366ea5dcdfSWilliam Breathitt Gray * @lock: synchronization lock to prevent I/O race conditions 376ea5dcdfSWilliam Breathitt Gray * @base: base port address of the GPIO device 386ea5dcdfSWilliam Breathitt Gray */ 396ea5dcdfSWilliam Breathitt Gray struct gpiomm_gpio { 406ea5dcdfSWilliam Breathitt Gray struct gpio_chip chip; 416ea5dcdfSWilliam Breathitt Gray unsigned char io_state[6]; 426ea5dcdfSWilliam Breathitt Gray unsigned char out_state[6]; 436ea5dcdfSWilliam Breathitt Gray unsigned char control[2]; 446ea5dcdfSWilliam Breathitt Gray spinlock_t lock; 45*54c8e251SWilliam Breathitt Gray void __iomem *base; 466ea5dcdfSWilliam Breathitt Gray }; 476ea5dcdfSWilliam Breathitt Gray 486ea5dcdfSWilliam Breathitt Gray static int gpiomm_gpio_get_direction(struct gpio_chip *chip, 496ea5dcdfSWilliam Breathitt Gray unsigned int offset) 506ea5dcdfSWilliam Breathitt Gray { 516ea5dcdfSWilliam Breathitt Gray struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 526ea5dcdfSWilliam Breathitt Gray const unsigned int port = offset / 8; 536ea5dcdfSWilliam Breathitt Gray const unsigned int mask = BIT(offset % 8); 546ea5dcdfSWilliam Breathitt Gray 55e42615ecSMatti Vaittinen if (gpiommgpio->io_state[port] & mask) 56e42615ecSMatti Vaittinen return GPIO_LINE_DIRECTION_IN; 57e42615ecSMatti Vaittinen 58e42615ecSMatti Vaittinen return GPIO_LINE_DIRECTION_OUT; 596ea5dcdfSWilliam Breathitt Gray } 606ea5dcdfSWilliam Breathitt Gray 616ea5dcdfSWilliam Breathitt Gray static int gpiomm_gpio_direction_input(struct gpio_chip *chip, 626ea5dcdfSWilliam Breathitt Gray unsigned int offset) 636ea5dcdfSWilliam Breathitt Gray { 646ea5dcdfSWilliam Breathitt Gray struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 656ea5dcdfSWilliam Breathitt Gray const unsigned int io_port = offset / 8; 666ea5dcdfSWilliam Breathitt Gray const unsigned int control_port = io_port / 3; 676ea5dcdfSWilliam Breathitt Gray unsigned long flags; 686ea5dcdfSWilliam Breathitt Gray unsigned int control; 696ea5dcdfSWilliam Breathitt Gray 706ea5dcdfSWilliam Breathitt Gray spin_lock_irqsave(&gpiommgpio->lock, flags); 716ea5dcdfSWilliam Breathitt Gray 726ea5dcdfSWilliam Breathitt Gray /* Check if configuring Port C */ 736ea5dcdfSWilliam Breathitt Gray if (io_port == 2 || io_port == 5) { 746ea5dcdfSWilliam Breathitt Gray /* Port C can be configured by nibble */ 756ea5dcdfSWilliam Breathitt Gray if (offset % 8 > 3) { 766ea5dcdfSWilliam Breathitt Gray gpiommgpio->io_state[io_port] |= 0xF0; 776ea5dcdfSWilliam Breathitt Gray gpiommgpio->control[control_port] |= BIT(3); 786ea5dcdfSWilliam Breathitt Gray } else { 796ea5dcdfSWilliam Breathitt Gray gpiommgpio->io_state[io_port] |= 0x0F; 806ea5dcdfSWilliam Breathitt Gray gpiommgpio->control[control_port] |= BIT(0); 816ea5dcdfSWilliam Breathitt Gray } 826ea5dcdfSWilliam Breathitt Gray } else { 836ea5dcdfSWilliam Breathitt Gray gpiommgpio->io_state[io_port] |= 0xFF; 846ea5dcdfSWilliam Breathitt Gray if (io_port == 0 || io_port == 3) 856ea5dcdfSWilliam Breathitt Gray gpiommgpio->control[control_port] |= BIT(4); 866ea5dcdfSWilliam Breathitt Gray else 876ea5dcdfSWilliam Breathitt Gray gpiommgpio->control[control_port] |= BIT(1); 886ea5dcdfSWilliam Breathitt Gray } 896ea5dcdfSWilliam Breathitt Gray 906ea5dcdfSWilliam Breathitt Gray control = BIT(7) | gpiommgpio->control[control_port]; 91*54c8e251SWilliam Breathitt Gray iowrite8(control, gpiommgpio->base + 3 + control_port*4); 926ea5dcdfSWilliam Breathitt Gray 936ea5dcdfSWilliam Breathitt Gray spin_unlock_irqrestore(&gpiommgpio->lock, flags); 946ea5dcdfSWilliam Breathitt Gray 956ea5dcdfSWilliam Breathitt Gray return 0; 966ea5dcdfSWilliam Breathitt Gray } 976ea5dcdfSWilliam Breathitt Gray 986ea5dcdfSWilliam Breathitt Gray static int gpiomm_gpio_direction_output(struct gpio_chip *chip, 996ea5dcdfSWilliam Breathitt Gray unsigned int offset, int value) 1006ea5dcdfSWilliam Breathitt Gray { 1016ea5dcdfSWilliam Breathitt Gray struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 1026ea5dcdfSWilliam Breathitt Gray const unsigned int io_port = offset / 8; 1036ea5dcdfSWilliam Breathitt Gray const unsigned int control_port = io_port / 3; 1046ea5dcdfSWilliam Breathitt Gray const unsigned int mask = BIT(offset % 8); 1056ea5dcdfSWilliam Breathitt Gray const unsigned int out_port = (io_port > 2) ? io_port + 1 : io_port; 1066ea5dcdfSWilliam Breathitt Gray unsigned long flags; 1076ea5dcdfSWilliam Breathitt Gray unsigned int control; 1086ea5dcdfSWilliam Breathitt Gray 1096ea5dcdfSWilliam Breathitt Gray spin_lock_irqsave(&gpiommgpio->lock, flags); 1106ea5dcdfSWilliam Breathitt Gray 1116ea5dcdfSWilliam Breathitt Gray /* Check if configuring Port C */ 1126ea5dcdfSWilliam Breathitt Gray if (io_port == 2 || io_port == 5) { 1136ea5dcdfSWilliam Breathitt Gray /* Port C can be configured by nibble */ 1146ea5dcdfSWilliam Breathitt Gray if (offset % 8 > 3) { 1156ea5dcdfSWilliam Breathitt Gray gpiommgpio->io_state[io_port] &= 0x0F; 1166ea5dcdfSWilliam Breathitt Gray gpiommgpio->control[control_port] &= ~BIT(3); 1176ea5dcdfSWilliam Breathitt Gray } else { 1186ea5dcdfSWilliam Breathitt Gray gpiommgpio->io_state[io_port] &= 0xF0; 1196ea5dcdfSWilliam Breathitt Gray gpiommgpio->control[control_port] &= ~BIT(0); 1206ea5dcdfSWilliam Breathitt Gray } 1216ea5dcdfSWilliam Breathitt Gray } else { 1226ea5dcdfSWilliam Breathitt Gray gpiommgpio->io_state[io_port] &= 0x00; 1236ea5dcdfSWilliam Breathitt Gray if (io_port == 0 || io_port == 3) 1246ea5dcdfSWilliam Breathitt Gray gpiommgpio->control[control_port] &= ~BIT(4); 1256ea5dcdfSWilliam Breathitt Gray else 1266ea5dcdfSWilliam Breathitt Gray gpiommgpio->control[control_port] &= ~BIT(1); 1276ea5dcdfSWilliam Breathitt Gray } 1286ea5dcdfSWilliam Breathitt Gray 1296ea5dcdfSWilliam Breathitt Gray if (value) 1306ea5dcdfSWilliam Breathitt Gray gpiommgpio->out_state[io_port] |= mask; 1316ea5dcdfSWilliam Breathitt Gray else 1326ea5dcdfSWilliam Breathitt Gray gpiommgpio->out_state[io_port] &= ~mask; 1336ea5dcdfSWilliam Breathitt Gray 1346ea5dcdfSWilliam Breathitt Gray control = BIT(7) | gpiommgpio->control[control_port]; 135*54c8e251SWilliam Breathitt Gray iowrite8(control, gpiommgpio->base + 3 + control_port*4); 1366ea5dcdfSWilliam Breathitt Gray 137*54c8e251SWilliam Breathitt Gray iowrite8(gpiommgpio->out_state[io_port], gpiommgpio->base + out_port); 1386ea5dcdfSWilliam Breathitt Gray 1396ea5dcdfSWilliam Breathitt Gray spin_unlock_irqrestore(&gpiommgpio->lock, flags); 1406ea5dcdfSWilliam Breathitt Gray 1416ea5dcdfSWilliam Breathitt Gray return 0; 1426ea5dcdfSWilliam Breathitt Gray } 1436ea5dcdfSWilliam Breathitt Gray 1446ea5dcdfSWilliam Breathitt Gray static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset) 1456ea5dcdfSWilliam Breathitt Gray { 1466ea5dcdfSWilliam Breathitt Gray struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 1476ea5dcdfSWilliam Breathitt Gray const unsigned int port = offset / 8; 1486ea5dcdfSWilliam Breathitt Gray const unsigned int mask = BIT(offset % 8); 1496ea5dcdfSWilliam Breathitt Gray const unsigned int in_port = (port > 2) ? port + 1 : port; 1506ea5dcdfSWilliam Breathitt Gray unsigned long flags; 1516ea5dcdfSWilliam Breathitt Gray unsigned int port_state; 1526ea5dcdfSWilliam Breathitt Gray 1536ea5dcdfSWilliam Breathitt Gray spin_lock_irqsave(&gpiommgpio->lock, flags); 1546ea5dcdfSWilliam Breathitt Gray 1556ea5dcdfSWilliam Breathitt Gray /* ensure that GPIO is set for input */ 1566ea5dcdfSWilliam Breathitt Gray if (!(gpiommgpio->io_state[port] & mask)) { 1576ea5dcdfSWilliam Breathitt Gray spin_unlock_irqrestore(&gpiommgpio->lock, flags); 1586ea5dcdfSWilliam Breathitt Gray return -EINVAL; 1596ea5dcdfSWilliam Breathitt Gray } 1606ea5dcdfSWilliam Breathitt Gray 161*54c8e251SWilliam Breathitt Gray port_state = ioread8(gpiommgpio->base + in_port); 1626ea5dcdfSWilliam Breathitt Gray 1636ea5dcdfSWilliam Breathitt Gray spin_unlock_irqrestore(&gpiommgpio->lock, flags); 1646ea5dcdfSWilliam Breathitt Gray 1656ea5dcdfSWilliam Breathitt Gray return !!(port_state & mask); 1666ea5dcdfSWilliam Breathitt Gray } 1676ea5dcdfSWilliam Breathitt Gray 168b0f49e9bSWilliam Breathitt Gray static const size_t ports[] = { 0, 1, 2, 4, 5, 6 }; 169b0f49e9bSWilliam Breathitt Gray 17041b25131SWilliam Breathitt Gray static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, 17141b25131SWilliam Breathitt Gray unsigned long *bits) 17241b25131SWilliam Breathitt Gray { 17341b25131SWilliam Breathitt Gray struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 174b0f49e9bSWilliam Breathitt Gray unsigned long offset; 175b0f49e9bSWilliam Breathitt Gray unsigned long gpio_mask; 176*54c8e251SWilliam Breathitt Gray void __iomem *port_addr; 17741b25131SWilliam Breathitt Gray unsigned long port_state; 17841b25131SWilliam Breathitt Gray 17941b25131SWilliam Breathitt Gray /* clear bits array to a clean slate */ 18041b25131SWilliam Breathitt Gray bitmap_zero(bits, chip->ngpio); 18141b25131SWilliam Breathitt Gray 182b0f49e9bSWilliam Breathitt Gray for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { 183b0f49e9bSWilliam Breathitt Gray port_addr = gpiommgpio->base + ports[offset / 8]; 184*54c8e251SWilliam Breathitt Gray port_state = ioread8(port_addr) & gpio_mask; 18541b25131SWilliam Breathitt Gray 186b0f49e9bSWilliam Breathitt Gray bitmap_set_value8(bits, port_state, offset); 18741b25131SWilliam Breathitt Gray } 18841b25131SWilliam Breathitt Gray 18941b25131SWilliam Breathitt Gray return 0; 19041b25131SWilliam Breathitt Gray } 19141b25131SWilliam Breathitt Gray 1926ea5dcdfSWilliam Breathitt Gray static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset, 1936ea5dcdfSWilliam Breathitt Gray int value) 1946ea5dcdfSWilliam Breathitt Gray { 1956ea5dcdfSWilliam Breathitt Gray struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 1966ea5dcdfSWilliam Breathitt Gray const unsigned int port = offset / 8; 1976ea5dcdfSWilliam Breathitt Gray const unsigned int mask = BIT(offset % 8); 1986ea5dcdfSWilliam Breathitt Gray const unsigned int out_port = (port > 2) ? port + 1 : port; 1996ea5dcdfSWilliam Breathitt Gray unsigned long flags; 2006ea5dcdfSWilliam Breathitt Gray 2016ea5dcdfSWilliam Breathitt Gray spin_lock_irqsave(&gpiommgpio->lock, flags); 2026ea5dcdfSWilliam Breathitt Gray 2036ea5dcdfSWilliam Breathitt Gray if (value) 2046ea5dcdfSWilliam Breathitt Gray gpiommgpio->out_state[port] |= mask; 2056ea5dcdfSWilliam Breathitt Gray else 2066ea5dcdfSWilliam Breathitt Gray gpiommgpio->out_state[port] &= ~mask; 2076ea5dcdfSWilliam Breathitt Gray 208*54c8e251SWilliam Breathitt Gray iowrite8(gpiommgpio->out_state[port], gpiommgpio->base + out_port); 2096ea5dcdfSWilliam Breathitt Gray 2106ea5dcdfSWilliam Breathitt Gray spin_unlock_irqrestore(&gpiommgpio->lock, flags); 2116ea5dcdfSWilliam Breathitt Gray } 2126ea5dcdfSWilliam Breathitt Gray 21365502a12SWilliam Breathitt Gray static void gpiomm_gpio_set_multiple(struct gpio_chip *chip, 21465502a12SWilliam Breathitt Gray unsigned long *mask, unsigned long *bits) 21565502a12SWilliam Breathitt Gray { 21665502a12SWilliam Breathitt Gray struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 217b0f49e9bSWilliam Breathitt Gray unsigned long offset; 218b0f49e9bSWilliam Breathitt Gray unsigned long gpio_mask; 219b0f49e9bSWilliam Breathitt Gray size_t index; 220*54c8e251SWilliam Breathitt Gray void __iomem *port_addr; 221b0f49e9bSWilliam Breathitt Gray unsigned long bitmask; 22265502a12SWilliam Breathitt Gray unsigned long flags; 22365502a12SWilliam Breathitt Gray 224b0f49e9bSWilliam Breathitt Gray for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { 225b0f49e9bSWilliam Breathitt Gray index = offset / 8; 226b0f49e9bSWilliam Breathitt Gray port_addr = gpiommgpio->base + ports[index]; 22765502a12SWilliam Breathitt Gray 228b0f49e9bSWilliam Breathitt Gray bitmask = bitmap_get_value8(bits, offset) & gpio_mask; 22965502a12SWilliam Breathitt Gray 23065502a12SWilliam Breathitt Gray spin_lock_irqsave(&gpiommgpio->lock, flags); 23165502a12SWilliam Breathitt Gray 23265502a12SWilliam Breathitt Gray /* update output state data and set device gpio register */ 233b0f49e9bSWilliam Breathitt Gray gpiommgpio->out_state[index] &= ~gpio_mask; 234b0f49e9bSWilliam Breathitt Gray gpiommgpio->out_state[index] |= bitmask; 235*54c8e251SWilliam Breathitt Gray iowrite8(gpiommgpio->out_state[index], port_addr); 23665502a12SWilliam Breathitt Gray 23765502a12SWilliam Breathitt Gray spin_unlock_irqrestore(&gpiommgpio->lock, flags); 23865502a12SWilliam Breathitt Gray } 23965502a12SWilliam Breathitt Gray } 24065502a12SWilliam Breathitt Gray 241210b4bdeSWilliam Breathitt Gray #define GPIOMM_NGPIO 48 242210b4bdeSWilliam Breathitt Gray static const char *gpiomm_names[GPIOMM_NGPIO] = { 243210b4bdeSWilliam Breathitt Gray "Port 1A0", "Port 1A1", "Port 1A2", "Port 1A3", "Port 1A4", "Port 1A5", 244210b4bdeSWilliam Breathitt Gray "Port 1A6", "Port 1A7", "Port 1B0", "Port 1B1", "Port 1B2", "Port 1B3", 245210b4bdeSWilliam Breathitt Gray "Port 1B4", "Port 1B5", "Port 1B6", "Port 1B7", "Port 1C0", "Port 1C1", 246210b4bdeSWilliam Breathitt Gray "Port 1C2", "Port 1C3", "Port 1C4", "Port 1C5", "Port 1C6", "Port 1C7", 247210b4bdeSWilliam Breathitt Gray "Port 2A0", "Port 2A1", "Port 2A2", "Port 2A3", "Port 2A4", "Port 2A5", 248210b4bdeSWilliam Breathitt Gray "Port 2A6", "Port 2A7", "Port 2B0", "Port 2B1", "Port 2B2", "Port 2B3", 249210b4bdeSWilliam Breathitt Gray "Port 2B4", "Port 2B5", "Port 2B6", "Port 2B7", "Port 2C0", "Port 2C1", 250210b4bdeSWilliam Breathitt Gray "Port 2C2", "Port 2C3", "Port 2C4", "Port 2C5", "Port 2C6", "Port 2C7", 251210b4bdeSWilliam Breathitt Gray }; 252210b4bdeSWilliam Breathitt Gray 2536ea5dcdfSWilliam Breathitt Gray static int gpiomm_probe(struct device *dev, unsigned int id) 2546ea5dcdfSWilliam Breathitt Gray { 2556ea5dcdfSWilliam Breathitt Gray struct gpiomm_gpio *gpiommgpio; 2566ea5dcdfSWilliam Breathitt Gray const char *const name = dev_name(dev); 2576ea5dcdfSWilliam Breathitt Gray int err; 2586ea5dcdfSWilliam Breathitt Gray 2596ea5dcdfSWilliam Breathitt Gray gpiommgpio = devm_kzalloc(dev, sizeof(*gpiommgpio), GFP_KERNEL); 2606ea5dcdfSWilliam Breathitt Gray if (!gpiommgpio) 2616ea5dcdfSWilliam Breathitt Gray return -ENOMEM; 2626ea5dcdfSWilliam Breathitt Gray 2636ea5dcdfSWilliam Breathitt Gray if (!devm_request_region(dev, base[id], GPIOMM_EXTENT, name)) { 2646ea5dcdfSWilliam Breathitt Gray dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", 2656ea5dcdfSWilliam Breathitt Gray base[id], base[id] + GPIOMM_EXTENT); 2666ea5dcdfSWilliam Breathitt Gray return -EBUSY; 2676ea5dcdfSWilliam Breathitt Gray } 2686ea5dcdfSWilliam Breathitt Gray 269*54c8e251SWilliam Breathitt Gray gpiommgpio->base = devm_ioport_map(dev, base[id], GPIOMM_EXTENT); 270*54c8e251SWilliam Breathitt Gray if (!gpiommgpio->base) 271*54c8e251SWilliam Breathitt Gray return -ENOMEM; 272*54c8e251SWilliam Breathitt Gray 2736ea5dcdfSWilliam Breathitt Gray gpiommgpio->chip.label = name; 2746ea5dcdfSWilliam Breathitt Gray gpiommgpio->chip.parent = dev; 2756ea5dcdfSWilliam Breathitt Gray gpiommgpio->chip.owner = THIS_MODULE; 2766ea5dcdfSWilliam Breathitt Gray gpiommgpio->chip.base = -1; 277210b4bdeSWilliam Breathitt Gray gpiommgpio->chip.ngpio = GPIOMM_NGPIO; 278210b4bdeSWilliam Breathitt Gray gpiommgpio->chip.names = gpiomm_names; 2796ea5dcdfSWilliam Breathitt Gray gpiommgpio->chip.get_direction = gpiomm_gpio_get_direction; 2806ea5dcdfSWilliam Breathitt Gray gpiommgpio->chip.direction_input = gpiomm_gpio_direction_input; 2816ea5dcdfSWilliam Breathitt Gray gpiommgpio->chip.direction_output = gpiomm_gpio_direction_output; 2826ea5dcdfSWilliam Breathitt Gray gpiommgpio->chip.get = gpiomm_gpio_get; 28341b25131SWilliam Breathitt Gray gpiommgpio->chip.get_multiple = gpiomm_gpio_get_multiple; 2846ea5dcdfSWilliam Breathitt Gray gpiommgpio->chip.set = gpiomm_gpio_set; 28565502a12SWilliam Breathitt Gray gpiommgpio->chip.set_multiple = gpiomm_gpio_set_multiple; 2866ea5dcdfSWilliam Breathitt Gray 2876ea5dcdfSWilliam Breathitt Gray spin_lock_init(&gpiommgpio->lock); 2886ea5dcdfSWilliam Breathitt Gray 2892141b0a1SWilliam Breathitt Gray err = devm_gpiochip_add_data(dev, &gpiommgpio->chip, gpiommgpio); 2906ea5dcdfSWilliam Breathitt Gray if (err) { 2916ea5dcdfSWilliam Breathitt Gray dev_err(dev, "GPIO registering failed (%d)\n", err); 2926ea5dcdfSWilliam Breathitt Gray return err; 2936ea5dcdfSWilliam Breathitt Gray } 2946ea5dcdfSWilliam Breathitt Gray 2956ea5dcdfSWilliam Breathitt Gray /* initialize all GPIO as output */ 296*54c8e251SWilliam Breathitt Gray iowrite8(0x80, gpiommgpio->base + 3); 297*54c8e251SWilliam Breathitt Gray iowrite8(0x00, gpiommgpio->base); 298*54c8e251SWilliam Breathitt Gray iowrite8(0x00, gpiommgpio->base + 1); 299*54c8e251SWilliam Breathitt Gray iowrite8(0x00, gpiommgpio->base + 2); 300*54c8e251SWilliam Breathitt Gray iowrite8(0x80, gpiommgpio->base + 7); 301*54c8e251SWilliam Breathitt Gray iowrite8(0x00, gpiommgpio->base + 4); 302*54c8e251SWilliam Breathitt Gray iowrite8(0x00, gpiommgpio->base + 5); 303*54c8e251SWilliam Breathitt Gray iowrite8(0x00, gpiommgpio->base + 6); 3046ea5dcdfSWilliam Breathitt Gray 3056ea5dcdfSWilliam Breathitt Gray return 0; 3066ea5dcdfSWilliam Breathitt Gray } 3076ea5dcdfSWilliam Breathitt Gray 3086ea5dcdfSWilliam Breathitt Gray static struct isa_driver gpiomm_driver = { 3096ea5dcdfSWilliam Breathitt Gray .probe = gpiomm_probe, 3106ea5dcdfSWilliam Breathitt Gray .driver = { 3116ea5dcdfSWilliam Breathitt Gray .name = "gpio-mm" 3126ea5dcdfSWilliam Breathitt Gray }, 3136ea5dcdfSWilliam Breathitt Gray }; 3146ea5dcdfSWilliam Breathitt Gray 3156ea5dcdfSWilliam Breathitt Gray module_isa_driver(gpiomm_driver, num_gpiomm); 3166ea5dcdfSWilliam Breathitt Gray 3176ea5dcdfSWilliam Breathitt Gray MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 3186ea5dcdfSWilliam Breathitt Gray MODULE_DESCRIPTION("Diamond Systems GPIO-MM GPIO driver"); 3196ea5dcdfSWilliam Breathitt Gray MODULE_LICENSE("GPL v2"); 320