1 /* 2 * GPIO driver for the Diamond Systems GPIO-MM 3 * Copyright (C) 2016 William Breathitt Gray 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License, version 2, as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * This driver supports the following Diamond Systems devices: GPIO-MM and 15 * GPIO-MM-12. 16 */ 17 #include <linux/bitops.h> 18 #include <linux/device.h> 19 #include <linux/errno.h> 20 #include <linux/gpio/driver.h> 21 #include <linux/io.h> 22 #include <linux/ioport.h> 23 #include <linux/isa.h> 24 #include <linux/kernel.h> 25 #include <linux/module.h> 26 #include <linux/moduleparam.h> 27 #include <linux/spinlock.h> 28 29 #define GPIOMM_EXTENT 8 30 #define MAX_NUM_GPIOMM max_num_isa_dev(GPIOMM_EXTENT) 31 32 static unsigned int base[MAX_NUM_GPIOMM]; 33 static unsigned int num_gpiomm; 34 module_param_array(base, uint, &num_gpiomm, 0); 35 MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addresses"); 36 37 /** 38 * struct gpiomm_gpio - GPIO device private data structure 39 * @chip: instance of the gpio_chip 40 * @io_state: bit I/O state (whether bit is set to input or output) 41 * @out_state: output bits state 42 * @control: Control registers state 43 * @lock: synchronization lock to prevent I/O race conditions 44 * @base: base port address of the GPIO device 45 */ 46 struct gpiomm_gpio { 47 struct gpio_chip chip; 48 unsigned char io_state[6]; 49 unsigned char out_state[6]; 50 unsigned char control[2]; 51 spinlock_t lock; 52 unsigned int base; 53 }; 54 55 static int gpiomm_gpio_get_direction(struct gpio_chip *chip, 56 unsigned int offset) 57 { 58 struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 59 const unsigned int port = offset / 8; 60 const unsigned int mask = BIT(offset % 8); 61 62 return !!(gpiommgpio->io_state[port] & mask); 63 } 64 65 static int gpiomm_gpio_direction_input(struct gpio_chip *chip, 66 unsigned int offset) 67 { 68 struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 69 const unsigned int io_port = offset / 8; 70 const unsigned int control_port = io_port / 3; 71 const unsigned int control_addr = gpiommgpio->base + 3 + control_port*4; 72 unsigned long flags; 73 unsigned int control; 74 75 spin_lock_irqsave(&gpiommgpio->lock, flags); 76 77 /* Check if configuring Port C */ 78 if (io_port == 2 || io_port == 5) { 79 /* Port C can be configured by nibble */ 80 if (offset % 8 > 3) { 81 gpiommgpio->io_state[io_port] |= 0xF0; 82 gpiommgpio->control[control_port] |= BIT(3); 83 } else { 84 gpiommgpio->io_state[io_port] |= 0x0F; 85 gpiommgpio->control[control_port] |= BIT(0); 86 } 87 } else { 88 gpiommgpio->io_state[io_port] |= 0xFF; 89 if (io_port == 0 || io_port == 3) 90 gpiommgpio->control[control_port] |= BIT(4); 91 else 92 gpiommgpio->control[control_port] |= BIT(1); 93 } 94 95 control = BIT(7) | gpiommgpio->control[control_port]; 96 outb(control, control_addr); 97 98 spin_unlock_irqrestore(&gpiommgpio->lock, flags); 99 100 return 0; 101 } 102 103 static int gpiomm_gpio_direction_output(struct gpio_chip *chip, 104 unsigned int offset, int value) 105 { 106 struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 107 const unsigned int io_port = offset / 8; 108 const unsigned int control_port = io_port / 3; 109 const unsigned int mask = BIT(offset % 8); 110 const unsigned int control_addr = gpiommgpio->base + 3 + control_port*4; 111 const unsigned int out_port = (io_port > 2) ? io_port + 1 : io_port; 112 unsigned long flags; 113 unsigned int control; 114 115 spin_lock_irqsave(&gpiommgpio->lock, flags); 116 117 /* Check if configuring Port C */ 118 if (io_port == 2 || io_port == 5) { 119 /* Port C can be configured by nibble */ 120 if (offset % 8 > 3) { 121 gpiommgpio->io_state[io_port] &= 0x0F; 122 gpiommgpio->control[control_port] &= ~BIT(3); 123 } else { 124 gpiommgpio->io_state[io_port] &= 0xF0; 125 gpiommgpio->control[control_port] &= ~BIT(0); 126 } 127 } else { 128 gpiommgpio->io_state[io_port] &= 0x00; 129 if (io_port == 0 || io_port == 3) 130 gpiommgpio->control[control_port] &= ~BIT(4); 131 else 132 gpiommgpio->control[control_port] &= ~BIT(1); 133 } 134 135 if (value) 136 gpiommgpio->out_state[io_port] |= mask; 137 else 138 gpiommgpio->out_state[io_port] &= ~mask; 139 140 control = BIT(7) | gpiommgpio->control[control_port]; 141 outb(control, control_addr); 142 143 outb(gpiommgpio->out_state[io_port], gpiommgpio->base + out_port); 144 145 spin_unlock_irqrestore(&gpiommgpio->lock, flags); 146 147 return 0; 148 } 149 150 static int gpiomm_gpio_get(struct gpio_chip *chip, unsigned int offset) 151 { 152 struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 153 const unsigned int port = offset / 8; 154 const unsigned int mask = BIT(offset % 8); 155 const unsigned int in_port = (port > 2) ? port + 1 : port; 156 unsigned long flags; 157 unsigned int port_state; 158 159 spin_lock_irqsave(&gpiommgpio->lock, flags); 160 161 /* ensure that GPIO is set for input */ 162 if (!(gpiommgpio->io_state[port] & mask)) { 163 spin_unlock_irqrestore(&gpiommgpio->lock, flags); 164 return -EINVAL; 165 } 166 167 port_state = inb(gpiommgpio->base + in_port); 168 169 spin_unlock_irqrestore(&gpiommgpio->lock, flags); 170 171 return !!(port_state & mask); 172 } 173 174 static void gpiomm_gpio_set(struct gpio_chip *chip, unsigned int offset, 175 int value) 176 { 177 struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 178 const unsigned int port = offset / 8; 179 const unsigned int mask = BIT(offset % 8); 180 const unsigned int out_port = (port > 2) ? port + 1 : port; 181 unsigned long flags; 182 183 spin_lock_irqsave(&gpiommgpio->lock, flags); 184 185 if (value) 186 gpiommgpio->out_state[port] |= mask; 187 else 188 gpiommgpio->out_state[port] &= ~mask; 189 190 outb(gpiommgpio->out_state[port], gpiommgpio->base + out_port); 191 192 spin_unlock_irqrestore(&gpiommgpio->lock, flags); 193 } 194 195 static void gpiomm_gpio_set_multiple(struct gpio_chip *chip, 196 unsigned long *mask, unsigned long *bits) 197 { 198 struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip); 199 unsigned int i; 200 const unsigned int gpio_reg_size = 8; 201 unsigned int port; 202 unsigned int out_port; 203 unsigned int bitmask; 204 unsigned long flags; 205 206 /* set bits are evaluated a gpio register size at a time */ 207 for (i = 0; i < chip->ngpio; i += gpio_reg_size) { 208 /* no more set bits in this mask word; skip to the next word */ 209 if (!mask[BIT_WORD(i)]) { 210 i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size; 211 continue; 212 } 213 214 port = i / gpio_reg_size; 215 out_port = (port > 2) ? port + 1 : port; 216 bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)]; 217 218 spin_lock_irqsave(&gpiommgpio->lock, flags); 219 220 /* update output state data and set device gpio register */ 221 gpiommgpio->out_state[port] &= ~mask[BIT_WORD(i)]; 222 gpiommgpio->out_state[port] |= bitmask; 223 outb(gpiommgpio->out_state[port], gpiommgpio->base + out_port); 224 225 spin_unlock_irqrestore(&gpiommgpio->lock, flags); 226 227 /* prepare for next gpio register set */ 228 mask[BIT_WORD(i)] >>= gpio_reg_size; 229 bits[BIT_WORD(i)] >>= gpio_reg_size; 230 } 231 } 232 233 #define GPIOMM_NGPIO 48 234 static const char *gpiomm_names[GPIOMM_NGPIO] = { 235 "Port 1A0", "Port 1A1", "Port 1A2", "Port 1A3", "Port 1A4", "Port 1A5", 236 "Port 1A6", "Port 1A7", "Port 1B0", "Port 1B1", "Port 1B2", "Port 1B3", 237 "Port 1B4", "Port 1B5", "Port 1B6", "Port 1B7", "Port 1C0", "Port 1C1", 238 "Port 1C2", "Port 1C3", "Port 1C4", "Port 1C5", "Port 1C6", "Port 1C7", 239 "Port 2A0", "Port 2A1", "Port 2A2", "Port 2A3", "Port 2A4", "Port 2A5", 240 "Port 2A6", "Port 2A7", "Port 2B0", "Port 2B1", "Port 2B2", "Port 2B3", 241 "Port 2B4", "Port 2B5", "Port 2B6", "Port 2B7", "Port 2C0", "Port 2C1", 242 "Port 2C2", "Port 2C3", "Port 2C4", "Port 2C5", "Port 2C6", "Port 2C7", 243 }; 244 245 static int gpiomm_probe(struct device *dev, unsigned int id) 246 { 247 struct gpiomm_gpio *gpiommgpio; 248 const char *const name = dev_name(dev); 249 int err; 250 251 gpiommgpio = devm_kzalloc(dev, sizeof(*gpiommgpio), GFP_KERNEL); 252 if (!gpiommgpio) 253 return -ENOMEM; 254 255 if (!devm_request_region(dev, base[id], GPIOMM_EXTENT, name)) { 256 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", 257 base[id], base[id] + GPIOMM_EXTENT); 258 return -EBUSY; 259 } 260 261 gpiommgpio->chip.label = name; 262 gpiommgpio->chip.parent = dev; 263 gpiommgpio->chip.owner = THIS_MODULE; 264 gpiommgpio->chip.base = -1; 265 gpiommgpio->chip.ngpio = GPIOMM_NGPIO; 266 gpiommgpio->chip.names = gpiomm_names; 267 gpiommgpio->chip.get_direction = gpiomm_gpio_get_direction; 268 gpiommgpio->chip.direction_input = gpiomm_gpio_direction_input; 269 gpiommgpio->chip.direction_output = gpiomm_gpio_direction_output; 270 gpiommgpio->chip.get = gpiomm_gpio_get; 271 gpiommgpio->chip.set = gpiomm_gpio_set; 272 gpiommgpio->chip.set_multiple = gpiomm_gpio_set_multiple; 273 gpiommgpio->base = base[id]; 274 275 spin_lock_init(&gpiommgpio->lock); 276 277 err = devm_gpiochip_add_data(dev, &gpiommgpio->chip, gpiommgpio); 278 if (err) { 279 dev_err(dev, "GPIO registering failed (%d)\n", err); 280 return err; 281 } 282 283 /* initialize all GPIO as output */ 284 outb(0x80, base[id] + 3); 285 outb(0x00, base[id]); 286 outb(0x00, base[id] + 1); 287 outb(0x00, base[id] + 2); 288 outb(0x80, base[id] + 7); 289 outb(0x00, base[id] + 4); 290 outb(0x00, base[id] + 5); 291 outb(0x00, base[id] + 6); 292 293 return 0; 294 } 295 296 static struct isa_driver gpiomm_driver = { 297 .probe = gpiomm_probe, 298 .driver = { 299 .name = "gpio-mm" 300 }, 301 }; 302 303 module_isa_driver(gpiomm_driver, num_gpiomm); 304 305 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 306 MODULE_DESCRIPTION("Diamond Systems GPIO-MM GPIO driver"); 307 MODULE_LICENSE("GPL v2"); 308