1 /* 2 * GPIO driver for the WinSystems WS16C48 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 #include <linux/bitops.h> 15 #include <linux/device.h> 16 #include <linux/errno.h> 17 #include <linux/gpio/driver.h> 18 #include <linux/io.h> 19 #include <linux/ioport.h> 20 #include <linux/interrupt.h> 21 #include <linux/irqdesc.h> 22 #include <linux/isa.h> 23 #include <linux/kernel.h> 24 #include <linux/module.h> 25 #include <linux/moduleparam.h> 26 #include <linux/spinlock.h> 27 28 #define WS16C48_EXTENT 16 29 #define MAX_NUM_WS16C48 max_num_isa_dev(WS16C48_EXTENT) 30 31 static unsigned int base[MAX_NUM_WS16C48]; 32 static unsigned int num_ws16c48; 33 module_param_array(base, uint, &num_ws16c48, 0); 34 MODULE_PARM_DESC(base, "WinSystems WS16C48 base addresses"); 35 36 static unsigned int irq[MAX_NUM_WS16C48]; 37 module_param_array(irq, uint, NULL, 0); 38 MODULE_PARM_DESC(irq, "WinSystems WS16C48 interrupt line numbers"); 39 40 /** 41 * struct ws16c48_gpio - GPIO device private data structure 42 * @chip: instance of the gpio_chip 43 * @io_state: bit I/O state (whether bit is set to input or output) 44 * @out_state: output bits state 45 * @lock: synchronization lock to prevent I/O race conditions 46 * @irq_mask: I/O bits affected by interrupts 47 * @flow_mask: IRQ flow type mask for the respective I/O bits 48 * @base: base port address of the GPIO device 49 * @irq: Interrupt line number 50 */ 51 struct ws16c48_gpio { 52 struct gpio_chip chip; 53 unsigned char io_state[6]; 54 unsigned char out_state[6]; 55 spinlock_t lock; 56 unsigned long irq_mask; 57 unsigned long flow_mask; 58 unsigned base; 59 unsigned irq; 60 }; 61 62 static int ws16c48_gpio_get_direction(struct gpio_chip *chip, unsigned offset) 63 { 64 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); 65 const unsigned port = offset / 8; 66 const unsigned mask = BIT(offset % 8); 67 68 return !!(ws16c48gpio->io_state[port] & mask); 69 } 70 71 static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 72 { 73 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); 74 const unsigned port = offset / 8; 75 const unsigned mask = BIT(offset % 8); 76 unsigned long flags; 77 78 spin_lock_irqsave(&ws16c48gpio->lock, flags); 79 80 ws16c48gpio->io_state[port] |= mask; 81 ws16c48gpio->out_state[port] &= ~mask; 82 outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); 83 84 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 85 86 return 0; 87 } 88 89 static int ws16c48_gpio_direction_output(struct gpio_chip *chip, 90 unsigned offset, int value) 91 { 92 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); 93 const unsigned port = offset / 8; 94 const unsigned mask = BIT(offset % 8); 95 unsigned long flags; 96 97 spin_lock_irqsave(&ws16c48gpio->lock, flags); 98 99 ws16c48gpio->io_state[port] &= ~mask; 100 if (value) 101 ws16c48gpio->out_state[port] |= mask; 102 else 103 ws16c48gpio->out_state[port] &= ~mask; 104 outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); 105 106 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 107 108 return 0; 109 } 110 111 static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset) 112 { 113 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); 114 const unsigned port = offset / 8; 115 const unsigned mask = BIT(offset % 8); 116 unsigned long flags; 117 unsigned port_state; 118 119 spin_lock_irqsave(&ws16c48gpio->lock, flags); 120 121 /* ensure that GPIO is set for input */ 122 if (!(ws16c48gpio->io_state[port] & mask)) { 123 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 124 return -EINVAL; 125 } 126 127 port_state = inb(ws16c48gpio->base + port); 128 129 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 130 131 return !!(port_state & mask); 132 } 133 134 static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 135 { 136 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); 137 const unsigned port = offset / 8; 138 const unsigned mask = BIT(offset % 8); 139 unsigned long flags; 140 141 spin_lock_irqsave(&ws16c48gpio->lock, flags); 142 143 /* ensure that GPIO is set for output */ 144 if (ws16c48gpio->io_state[port] & mask) { 145 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 146 return; 147 } 148 149 if (value) 150 ws16c48gpio->out_state[port] |= mask; 151 else 152 ws16c48gpio->out_state[port] &= ~mask; 153 outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); 154 155 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 156 } 157 158 static void ws16c48_irq_ack(struct irq_data *data) 159 { 160 struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 161 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); 162 const unsigned long offset = irqd_to_hwirq(data); 163 const unsigned port = offset / 8; 164 const unsigned mask = BIT(offset % 8); 165 unsigned long flags; 166 unsigned port_state; 167 168 /* only the first 3 ports support interrupts */ 169 if (port > 2) 170 return; 171 172 spin_lock_irqsave(&ws16c48gpio->lock, flags); 173 174 port_state = ws16c48gpio->irq_mask >> (8*port); 175 176 outb(0x80, ws16c48gpio->base + 7); 177 outb(port_state & ~mask, ws16c48gpio->base + 8 + port); 178 outb(port_state | mask, ws16c48gpio->base + 8 + port); 179 outb(0xC0, ws16c48gpio->base + 7); 180 181 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 182 } 183 184 static void ws16c48_irq_mask(struct irq_data *data) 185 { 186 struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 187 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); 188 const unsigned long offset = irqd_to_hwirq(data); 189 const unsigned long mask = BIT(offset); 190 const unsigned port = offset / 8; 191 unsigned long flags; 192 193 /* only the first 3 ports support interrupts */ 194 if (port > 2) 195 return; 196 197 spin_lock_irqsave(&ws16c48gpio->lock, flags); 198 199 ws16c48gpio->irq_mask &= ~mask; 200 201 outb(0x80, ws16c48gpio->base + 7); 202 outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); 203 outb(0xC0, ws16c48gpio->base + 7); 204 205 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 206 } 207 208 static void ws16c48_irq_unmask(struct irq_data *data) 209 { 210 struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 211 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); 212 const unsigned long offset = irqd_to_hwirq(data); 213 const unsigned long mask = BIT(offset); 214 const unsigned port = offset / 8; 215 unsigned long flags; 216 217 /* only the first 3 ports support interrupts */ 218 if (port > 2) 219 return; 220 221 spin_lock_irqsave(&ws16c48gpio->lock, flags); 222 223 ws16c48gpio->irq_mask |= mask; 224 225 outb(0x80, ws16c48gpio->base + 7); 226 outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); 227 outb(0xC0, ws16c48gpio->base + 7); 228 229 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 230 } 231 232 static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type) 233 { 234 struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 235 struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); 236 const unsigned long offset = irqd_to_hwirq(data); 237 const unsigned long mask = BIT(offset); 238 const unsigned port = offset / 8; 239 unsigned long flags; 240 241 /* only the first 3 ports support interrupts */ 242 if (port > 2) 243 return -EINVAL; 244 245 spin_lock_irqsave(&ws16c48gpio->lock, flags); 246 247 switch (flow_type) { 248 case IRQ_TYPE_NONE: 249 break; 250 case IRQ_TYPE_EDGE_RISING: 251 ws16c48gpio->flow_mask |= mask; 252 break; 253 case IRQ_TYPE_EDGE_FALLING: 254 ws16c48gpio->flow_mask &= ~mask; 255 break; 256 default: 257 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 258 return -EINVAL; 259 } 260 261 outb(0x40, ws16c48gpio->base + 7); 262 outb(ws16c48gpio->flow_mask >> (8*port), ws16c48gpio->base + 8 + port); 263 outb(0xC0, ws16c48gpio->base + 7); 264 265 spin_unlock_irqrestore(&ws16c48gpio->lock, flags); 266 267 return 0; 268 } 269 270 static struct irq_chip ws16c48_irqchip = { 271 .name = "ws16c48", 272 .irq_ack = ws16c48_irq_ack, 273 .irq_mask = ws16c48_irq_mask, 274 .irq_unmask = ws16c48_irq_unmask, 275 .irq_set_type = ws16c48_irq_set_type 276 }; 277 278 static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id) 279 { 280 struct ws16c48_gpio *const ws16c48gpio = dev_id; 281 struct gpio_chip *const chip = &ws16c48gpio->chip; 282 unsigned long int_pending; 283 unsigned long port; 284 unsigned long int_id; 285 unsigned long gpio; 286 287 int_pending = inb(ws16c48gpio->base + 6) & 0x7; 288 if (!int_pending) 289 return IRQ_NONE; 290 291 /* loop until all pending interrupts are handled */ 292 do { 293 for_each_set_bit(port, &int_pending, 3) { 294 int_id = inb(ws16c48gpio->base + 8 + port); 295 for_each_set_bit(gpio, &int_id, 8) 296 generic_handle_irq(irq_find_mapping( 297 chip->irqdomain, gpio + 8*port)); 298 } 299 300 int_pending = inb(ws16c48gpio->base + 6) & 0x7; 301 } while (int_pending); 302 303 return IRQ_HANDLED; 304 } 305 306 static int ws16c48_probe(struct device *dev, unsigned int id) 307 { 308 struct ws16c48_gpio *ws16c48gpio; 309 const char *const name = dev_name(dev); 310 int err; 311 312 ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL); 313 if (!ws16c48gpio) 314 return -ENOMEM; 315 316 if (!devm_request_region(dev, base[id], WS16C48_EXTENT, name)) { 317 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", 318 base[id], base[id] + WS16C48_EXTENT); 319 return -EBUSY; 320 } 321 322 ws16c48gpio->chip.label = name; 323 ws16c48gpio->chip.parent = dev; 324 ws16c48gpio->chip.owner = THIS_MODULE; 325 ws16c48gpio->chip.base = -1; 326 ws16c48gpio->chip.ngpio = 48; 327 ws16c48gpio->chip.get_direction = ws16c48_gpio_get_direction; 328 ws16c48gpio->chip.direction_input = ws16c48_gpio_direction_input; 329 ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output; 330 ws16c48gpio->chip.get = ws16c48_gpio_get; 331 ws16c48gpio->chip.set = ws16c48_gpio_set; 332 ws16c48gpio->base = base[id]; 333 ws16c48gpio->irq = irq[id]; 334 335 spin_lock_init(&ws16c48gpio->lock); 336 337 dev_set_drvdata(dev, ws16c48gpio); 338 339 err = gpiochip_add_data(&ws16c48gpio->chip, ws16c48gpio); 340 if (err) { 341 dev_err(dev, "GPIO registering failed (%d)\n", err); 342 return err; 343 } 344 345 /* Disable IRQ by default */ 346 outb(0x80, base[id] + 7); 347 outb(0, base[id] + 8); 348 outb(0, base[id] + 9); 349 outb(0, base[id] + 10); 350 outb(0xC0, base[id] + 7); 351 352 err = gpiochip_irqchip_add(&ws16c48gpio->chip, &ws16c48_irqchip, 0, 353 handle_edge_irq, IRQ_TYPE_NONE); 354 if (err) { 355 dev_err(dev, "Could not add irqchip (%d)\n", err); 356 goto err_gpiochip_remove; 357 } 358 359 err = request_irq(irq[id], ws16c48_irq_handler, IRQF_SHARED, name, 360 ws16c48gpio); 361 if (err) { 362 dev_err(dev, "IRQ handler registering failed (%d)\n", err); 363 goto err_gpiochip_remove; 364 } 365 366 return 0; 367 368 err_gpiochip_remove: 369 gpiochip_remove(&ws16c48gpio->chip); 370 return err; 371 } 372 373 static int ws16c48_remove(struct device *dev, unsigned int id) 374 { 375 struct ws16c48_gpio *const ws16c48gpio = dev_get_drvdata(dev); 376 377 free_irq(ws16c48gpio->irq, ws16c48gpio); 378 gpiochip_remove(&ws16c48gpio->chip); 379 380 return 0; 381 } 382 383 static struct isa_driver ws16c48_driver = { 384 .probe = ws16c48_probe, 385 .driver = { 386 .name = "ws16c48" 387 }, 388 .remove = ws16c48_remove 389 }; 390 391 module_isa_driver(ws16c48_driver, num_ws16c48); 392 393 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); 394 MODULE_DESCRIPTION("WinSystems WS16C48 GPIO driver"); 395 MODULE_LICENSE("GPL v2"); 396