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