| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * GPIO driver for the ACCES 104-IDIO-16 family |
|---|
| 3 | 4 | * Copyright (C) 2015 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 | 5 | * |
|---|
| 14 | 6 | * This driver supports the following ACCES devices: 104-IDIO-16, |
|---|
| 15 | 7 | * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8. |
|---|
| .. | .. |
|---|
| 59 | 51 | static int idio_16_gpio_get_direction(struct gpio_chip *chip, unsigned offset) |
|---|
| 60 | 52 | { |
|---|
| 61 | 53 | if (offset > 15) |
|---|
| 62 | | - return 1; |
|---|
| 54 | + return GPIO_LINE_DIRECTION_IN; |
|---|
| 63 | 55 | |
|---|
| 64 | | - return 0; |
|---|
| 56 | + return GPIO_LINE_DIRECTION_OUT; |
|---|
| 65 | 57 | } |
|---|
| 66 | 58 | |
|---|
| 67 | 59 | static int idio_16_gpio_direction_input(struct gpio_chip *chip, unsigned offset) |
|---|
| .. | .. |
|---|
| 232 | 224 | "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15" |
|---|
| 233 | 225 | }; |
|---|
| 234 | 226 | |
|---|
| 227 | +static int idio_16_irq_init_hw(struct gpio_chip *gc) |
|---|
| 228 | +{ |
|---|
| 229 | + struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc); |
|---|
| 230 | + |
|---|
| 231 | + /* Disable IRQ by default */ |
|---|
| 232 | + outb(0, idio16gpio->base + 2); |
|---|
| 233 | + outb(0, idio16gpio->base + 1); |
|---|
| 234 | + |
|---|
| 235 | + return 0; |
|---|
| 236 | +} |
|---|
| 237 | + |
|---|
| 235 | 238 | static int idio_16_probe(struct device *dev, unsigned int id) |
|---|
| 236 | 239 | { |
|---|
| 237 | 240 | struct idio_16_gpio *idio16gpio; |
|---|
| 238 | 241 | const char *const name = dev_name(dev); |
|---|
| 242 | + struct gpio_irq_chip *girq; |
|---|
| 239 | 243 | int err; |
|---|
| 240 | 244 | |
|---|
| 241 | 245 | idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 264 | 268 | idio16gpio->base = base[id]; |
|---|
| 265 | 269 | idio16gpio->out_state = 0xFFFF; |
|---|
| 266 | 270 | |
|---|
| 271 | + girq = &idio16gpio->chip.irq; |
|---|
| 272 | + girq->chip = &idio_16_irqchip; |
|---|
| 273 | + /* This will let us handle the parent IRQ in the driver */ |
|---|
| 274 | + girq->parent_handler = NULL; |
|---|
| 275 | + girq->num_parents = 0; |
|---|
| 276 | + girq->parents = NULL; |
|---|
| 277 | + girq->default_type = IRQ_TYPE_NONE; |
|---|
| 278 | + girq->handler = handle_edge_irq; |
|---|
| 279 | + girq->init_hw = idio_16_irq_init_hw; |
|---|
| 280 | + |
|---|
| 267 | 281 | raw_spin_lock_init(&idio16gpio->lock); |
|---|
| 268 | 282 | |
|---|
| 269 | 283 | err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); |
|---|
| 270 | 284 | if (err) { |
|---|
| 271 | 285 | dev_err(dev, "GPIO registering failed (%d)\n", err); |
|---|
| 272 | | - return err; |
|---|
| 273 | | - } |
|---|
| 274 | | - |
|---|
| 275 | | - /* Disable IRQ by default */ |
|---|
| 276 | | - outb(0, base[id] + 2); |
|---|
| 277 | | - outb(0, base[id] + 1); |
|---|
| 278 | | - |
|---|
| 279 | | - err = gpiochip_irqchip_add(&idio16gpio->chip, &idio_16_irqchip, 0, |
|---|
| 280 | | - handle_edge_irq, IRQ_TYPE_NONE); |
|---|
| 281 | | - if (err) { |
|---|
| 282 | | - dev_err(dev, "Could not add irqchip (%d)\n", err); |
|---|
| 283 | 286 | return err; |
|---|
| 284 | 287 | } |
|---|
| 285 | 288 | |
|---|