]> Git Repo - linux.git/blob - drivers/gpio/gpio-pci-idio-16.c
block: add a sanity check for non-write flush/fua bios
[linux.git] / drivers / gpio / gpio-pci-idio-16.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * GPIO driver for the ACCES PCI-IDIO-16
4  * Copyright (C) 2017 William Breathitt Gray
5  */
6 #include <linux/bits.h>
7 #include <linux/device.h>
8 #include <linux/errno.h>
9 #include <linux/gpio/driver.h>
10 #include <linux/interrupt.h>
11 #include <linux/irqdesc.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/pci.h>
15 #include <linux/spinlock.h>
16 #include <linux/types.h>
17
18 #include "gpio-idio-16.h"
19
20 /**
21  * struct idio_16_gpio - GPIO device private data structure
22  * @chip:       instance of the gpio_chip
23  * @lock:       synchronization lock to prevent I/O race conditions
24  * @reg:        I/O address offset for the GPIO device registers
25  * @state:      ACCES IDIO-16 device state
26  * @irq_mask:   I/O bits affected by interrupts
27  */
28 struct idio_16_gpio {
29         struct gpio_chip chip;
30         raw_spinlock_t lock;
31         struct idio_16 __iomem *reg;
32         struct idio_16_state state;
33         unsigned long irq_mask;
34 };
35
36 static int idio_16_gpio_get_direction(struct gpio_chip *chip,
37         unsigned int offset)
38 {
39         if (idio_16_get_direction(offset))
40                 return GPIO_LINE_DIRECTION_IN;
41
42         return GPIO_LINE_DIRECTION_OUT;
43 }
44
45 static int idio_16_gpio_direction_input(struct gpio_chip *chip,
46         unsigned int offset)
47 {
48         return 0;
49 }
50
51 static int idio_16_gpio_direction_output(struct gpio_chip *chip,
52         unsigned int offset, int value)
53 {
54         chip->set(chip, offset, value);
55         return 0;
56 }
57
58 static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset)
59 {
60         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
61
62         return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset);
63 }
64
65 static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
66         unsigned long *mask, unsigned long *bits)
67 {
68         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
69
70         idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
71         return 0;
72 }
73
74 static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset,
75         int value)
76 {
77         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
78
79         idio_16_set(idio16gpio->reg, &idio16gpio->state, offset, value);
80 }
81
82 static void idio_16_gpio_set_multiple(struct gpio_chip *chip,
83         unsigned long *mask, unsigned long *bits)
84 {
85         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
86
87         idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits);
88 }
89
90 static void idio_16_irq_ack(struct irq_data *data)
91 {
92 }
93
94 static void idio_16_irq_mask(struct irq_data *data)
95 {
96         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
97         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
98         const unsigned long mask = BIT(irqd_to_hwirq(data));
99         unsigned long flags;
100
101         idio16gpio->irq_mask &= ~mask;
102
103         if (!idio16gpio->irq_mask) {
104                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
105
106                 iowrite8(0, &idio16gpio->reg->irq_ctl);
107
108                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
109         }
110 }
111
112 static void idio_16_irq_unmask(struct irq_data *data)
113 {
114         struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
115         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
116         const unsigned long mask = BIT(irqd_to_hwirq(data));
117         const unsigned long prev_irq_mask = idio16gpio->irq_mask;
118         unsigned long flags;
119
120         idio16gpio->irq_mask |= mask;
121
122         if (!prev_irq_mask) {
123                 raw_spin_lock_irqsave(&idio16gpio->lock, flags);
124
125                 ioread8(&idio16gpio->reg->irq_ctl);
126
127                 raw_spin_unlock_irqrestore(&idio16gpio->lock, flags);
128         }
129 }
130
131 static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type)
132 {
133         /* The only valid irq types are none and both-edges */
134         if (flow_type != IRQ_TYPE_NONE &&
135                 (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH)
136                 return -EINVAL;
137
138         return 0;
139 }
140
141 static struct irq_chip idio_16_irqchip = {
142         .name = "pci-idio-16",
143         .irq_ack = idio_16_irq_ack,
144         .irq_mask = idio_16_irq_mask,
145         .irq_unmask = idio_16_irq_unmask,
146         .irq_set_type = idio_16_irq_set_type
147 };
148
149 static irqreturn_t idio_16_irq_handler(int irq, void *dev_id)
150 {
151         struct idio_16_gpio *const idio16gpio = dev_id;
152         unsigned int irq_status;
153         struct gpio_chip *const chip = &idio16gpio->chip;
154         int gpio;
155
156         raw_spin_lock(&idio16gpio->lock);
157
158         irq_status = ioread8(&idio16gpio->reg->irq_status);
159
160         raw_spin_unlock(&idio16gpio->lock);
161
162         /* Make sure our device generated IRQ */
163         if (!(irq_status & 0x3) || !(irq_status & 0x4))
164                 return IRQ_NONE;
165
166         for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio)
167                 generic_handle_domain_irq(chip->irq.domain, gpio);
168
169         raw_spin_lock(&idio16gpio->lock);
170
171         /* Clear interrupt */
172         iowrite8(0, &idio16gpio->reg->in0_7);
173
174         raw_spin_unlock(&idio16gpio->lock);
175
176         return IRQ_HANDLED;
177 }
178
179 #define IDIO_16_NGPIO 32
180 static const char *idio_16_names[IDIO_16_NGPIO] = {
181         "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
182         "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
183         "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
184         "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15"
185 };
186
187 static int idio_16_irq_init_hw(struct gpio_chip *gc)
188 {
189         struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc);
190
191         /* Disable IRQ by default and clear any pending interrupt */
192         iowrite8(0, &idio16gpio->reg->irq_ctl);
193         iowrite8(0, &idio16gpio->reg->in0_7);
194
195         return 0;
196 }
197
198 static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id)
199 {
200         struct device *const dev = &pdev->dev;
201         struct idio_16_gpio *idio16gpio;
202         int err;
203         const size_t pci_bar_index = 2;
204         const char *const name = pci_name(pdev);
205         struct gpio_irq_chip *girq;
206
207         idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL);
208         if (!idio16gpio)
209                 return -ENOMEM;
210
211         err = pcim_enable_device(pdev);
212         if (err) {
213                 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
214                 return err;
215         }
216
217         err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
218         if (err) {
219                 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
220                 return err;
221         }
222
223         idio16gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
224
225         /* Deactivate input filters */
226         iowrite8(0, &idio16gpio->reg->filter_ctl);
227
228         idio16gpio->chip.label = name;
229         idio16gpio->chip.parent = dev;
230         idio16gpio->chip.owner = THIS_MODULE;
231         idio16gpio->chip.base = -1;
232         idio16gpio->chip.ngpio = IDIO_16_NGPIO;
233         idio16gpio->chip.names = idio_16_names;
234         idio16gpio->chip.get_direction = idio_16_gpio_get_direction;
235         idio16gpio->chip.direction_input = idio_16_gpio_direction_input;
236         idio16gpio->chip.direction_output = idio_16_gpio_direction_output;
237         idio16gpio->chip.get = idio_16_gpio_get;
238         idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple;
239         idio16gpio->chip.set = idio_16_gpio_set;
240         idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple;
241
242         idio_16_state_init(&idio16gpio->state);
243
244         girq = &idio16gpio->chip.irq;
245         girq->chip = &idio_16_irqchip;
246         /* This will let us handle the parent IRQ in the driver */
247         girq->parent_handler = NULL;
248         girq->num_parents = 0;
249         girq->parents = NULL;
250         girq->default_type = IRQ_TYPE_NONE;
251         girq->handler = handle_edge_irq;
252         girq->init_hw = idio_16_irq_init_hw;
253
254         raw_spin_lock_init(&idio16gpio->lock);
255
256         err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio);
257         if (err) {
258                 dev_err(dev, "GPIO registering failed (%d)\n", err);
259                 return err;
260         }
261
262         err = devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED,
263                 name, idio16gpio);
264         if (err) {
265                 dev_err(dev, "IRQ handler registering failed (%d)\n", err);
266                 return err;
267         }
268
269         return 0;
270 }
271
272 static const struct pci_device_id idio_16_pci_dev_id[] = {
273         { PCI_DEVICE(0x494F, 0x0DC8) }, { 0 }
274 };
275 MODULE_DEVICE_TABLE(pci, idio_16_pci_dev_id);
276
277 static struct pci_driver idio_16_driver = {
278         .name = "pci-idio-16",
279         .id_table = idio_16_pci_dev_id,
280         .probe = idio_16_probe
281 };
282
283 module_pci_driver(idio_16_driver);
284
285 MODULE_AUTHOR("William Breathitt Gray <[email protected]>");
286 MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
287 MODULE_LICENSE("GPL v2");
288 MODULE_IMPORT_NS(GPIO_IDIO_16);
This page took 0.049543 seconds and 4 git commands to generate.