Merge tag 'vfs-6.10.rw' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[sfrench/cifs-2.6.git] / drivers / gpio / gpio-pcie-idio-24.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * GPIO driver for the ACCES PCIe-IDIO-24 family
4  * Copyright (C) 2018 William Breathitt Gray
5  *
6  * This driver supports the following ACCES devices: PCIe-IDIO-24,
7  * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12.
8  */
9 #include <linux/bits.h>
10 #include <linux/device.h>
11 #include <linux/err.h>
12 #include <linux/gpio/regmap.h>
13 #include <linux/irq.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/pci.h>
17 #include <linux/regmap.h>
18 #include <linux/spinlock.h>
19 #include <linux/types.h>
20
21 /*
22  * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status
23  *
24  * Bit: Description
25  *   0: Enable Interrupt Sources (Bit 0)
26  *   1: Enable Interrupt Sources (Bit 1)
27  *   2: Generate Internal PCI Bus Internal SERR# Interrupt
28  *   3: Mailbox Interrupt Enable
29  *   4: Power Management Interrupt Enable
30  *   5: Power Management Interrupt
31  *   6: Slave Read Local Data Parity Check Error Enable
32  *   7: Slave Read Local Data Parity Check Error Status
33  *   8: Internal PCI Wire Interrupt Enable
34  *   9: PCI Express Doorbell Interrupt Enable
35  *  10: PCI Abort Interrupt Enable
36  *  11: Local Interrupt Input Enable
37  *  12: Retry Abort Enable
38  *  13: PCI Express Doorbell Interrupt Active
39  *  14: PCI Abort Interrupt Active
40  *  15: Local Interrupt Input Active
41  *  16: Local Interrupt Output Enable
42  *  17: Local Doorbell Interrupt Enable
43  *  18: DMA Channel 0 Interrupt Enable
44  *  19: DMA Channel 1 Interrupt Enable
45  *  20: Local Doorbell Interrupt Active
46  *  21: DMA Channel 0 Interrupt Active
47  *  22: DMA Channel 1 Interrupt Active
48  *  23: Built-In Self-Test (BIST) Interrupt Active
49  *  24: Direct Master was the Bus Master during a Master or Target Abort
50  *  25: DMA Channel 0 was the Bus Master during a Master or Target Abort
51  *  26: DMA Channel 1 was the Bus Master during a Master or Target Abort
52  *  27: Target Abort after internal 256 consecutive Master Retrys
53  *  28: PCI Bus wrote data to LCS_MBOX0
54  *  29: PCI Bus wrote data to LCS_MBOX1
55  *  30: PCI Bus wrote data to LCS_MBOX2
56  *  31: PCI Bus wrote data to LCS_MBOX3
57  */
58 #define PLX_PEX8311_PCI_LCS_INTCSR  0x68
59 #define INTCSR_INTERNAL_PCI_WIRE    BIT(8)
60 #define INTCSR_LOCAL_INPUT          BIT(11)
61 #define IDIO_24_ENABLE_IRQ          (INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT)
62
63 #define IDIO_24_OUT_BASE 0x0
64 #define IDIO_24_TTLCMOS_OUT_REG 0x3
65 #define IDIO_24_IN_BASE 0x4
66 #define IDIO_24_TTLCMOS_IN_REG 0x7
67 #define IDIO_24_COS_STATUS_BASE 0x8
68 #define IDIO_24_CONTROL_REG 0xC
69 #define IDIO_24_COS_ENABLE 0xE
70 #define IDIO_24_SOFT_RESET 0xF
71
72 #define CONTROL_REG_OUT_MODE BIT(1)
73
74 #define COS_ENABLE_RISING BIT(1)
75 #define COS_ENABLE_FALLING BIT(4)
76 #define COS_ENABLE_BOTH (COS_ENABLE_RISING | COS_ENABLE_FALLING)
77
78 static const struct regmap_config pex8311_intcsr_regmap_config = {
79         .name = "pex8311_intcsr",
80         .reg_bits = 32,
81         .reg_stride = 1,
82         .reg_base = PLX_PEX8311_PCI_LCS_INTCSR,
83         .val_bits = 32,
84         .io_port = true,
85 };
86
87 static const struct regmap_range idio_24_wr_ranges[] = {
88         regmap_reg_range(0x0, 0x3), regmap_reg_range(0x8, 0xC),
89         regmap_reg_range(0xE, 0xF),
90 };
91 static const struct regmap_range idio_24_rd_ranges[] = {
92         regmap_reg_range(0x0, 0xC), regmap_reg_range(0xE, 0xF),
93 };
94 static const struct regmap_range idio_24_volatile_ranges[] = {
95         regmap_reg_range(0x4, 0xB), regmap_reg_range(0xF, 0xF),
96 };
97 static const struct regmap_access_table idio_24_wr_table = {
98         .yes_ranges = idio_24_wr_ranges,
99         .n_yes_ranges = ARRAY_SIZE(idio_24_wr_ranges),
100 };
101 static const struct regmap_access_table idio_24_rd_table = {
102         .yes_ranges = idio_24_rd_ranges,
103         .n_yes_ranges = ARRAY_SIZE(idio_24_rd_ranges),
104 };
105 static const struct regmap_access_table idio_24_volatile_table = {
106         .yes_ranges = idio_24_volatile_ranges,
107         .n_yes_ranges = ARRAY_SIZE(idio_24_volatile_ranges),
108 };
109
110 static const struct regmap_config idio_24_regmap_config = {
111         .reg_bits = 8,
112         .reg_stride = 1,
113         .val_bits = 8,
114         .io_port = true,
115         .wr_table = &idio_24_wr_table,
116         .rd_table = &idio_24_rd_table,
117         .volatile_table = &idio_24_volatile_table,
118         .cache_type = REGCACHE_FLAT,
119         .use_raw_spinlock = true,
120 };
121
122 #define IDIO_24_NGPIO_PER_REG 8
123 #define IDIO_24_REGMAP_IRQ(_id)                                         \
124         [24 + _id] = {                                                  \
125                 .reg_offset = (_id) / IDIO_24_NGPIO_PER_REG,            \
126                 .mask = BIT((_id) % IDIO_24_NGPIO_PER_REG),             \
127                 .type = { .types_supported = IRQ_TYPE_EDGE_BOTH },      \
128         }
129 #define IDIO_24_IIN_IRQ(_id) IDIO_24_REGMAP_IRQ(_id)
130 #define IDIO_24_TTL_IRQ(_id) IDIO_24_REGMAP_IRQ(24 + _id)
131
132 static const struct regmap_irq idio_24_regmap_irqs[] = {
133         IDIO_24_IIN_IRQ(0), IDIO_24_IIN_IRQ(1), IDIO_24_IIN_IRQ(2), /* IIN 0-2 */
134         IDIO_24_IIN_IRQ(3), IDIO_24_IIN_IRQ(4), IDIO_24_IIN_IRQ(5), /* IIN 3-5 */
135         IDIO_24_IIN_IRQ(6), IDIO_24_IIN_IRQ(7), IDIO_24_IIN_IRQ(8), /* IIN 6-8 */
136         IDIO_24_IIN_IRQ(9), IDIO_24_IIN_IRQ(10), IDIO_24_IIN_IRQ(11), /* IIN 9-11 */
137         IDIO_24_IIN_IRQ(12), IDIO_24_IIN_IRQ(13), IDIO_24_IIN_IRQ(14), /* IIN 12-14 */
138         IDIO_24_IIN_IRQ(15), IDIO_24_IIN_IRQ(16), IDIO_24_IIN_IRQ(17), /* IIN 15-17 */
139         IDIO_24_IIN_IRQ(18), IDIO_24_IIN_IRQ(19), IDIO_24_IIN_IRQ(20), /* IIN 18-20 */
140         IDIO_24_IIN_IRQ(21), IDIO_24_IIN_IRQ(22), IDIO_24_IIN_IRQ(23), /* IIN 21-23 */
141         IDIO_24_TTL_IRQ(0), IDIO_24_TTL_IRQ(1), IDIO_24_TTL_IRQ(2), /* TTL 0-2 */
142         IDIO_24_TTL_IRQ(3), IDIO_24_TTL_IRQ(4), IDIO_24_TTL_IRQ(5), /* TTL 3-5 */
143         IDIO_24_TTL_IRQ(6), IDIO_24_TTL_IRQ(7), /* TTL 6-7 */
144 };
145
146 /**
147  * struct idio_24_gpio - GPIO device private data structure
148  * @map:        regmap for the device
149  * @lock:       synchronization lock to prevent I/O race conditions
150  * @irq_type:   type configuration for IRQs
151  */
152 struct idio_24_gpio {
153         struct regmap *map;
154         raw_spinlock_t lock;
155         u8 irq_type;
156 };
157
158 static int idio_24_handle_mask_sync(const int index, const unsigned int mask_buf_def,
159                                     const unsigned int mask_buf, void *const irq_drv_data)
160 {
161         const unsigned int type_mask = COS_ENABLE_BOTH << index;
162         struct idio_24_gpio *const idio24gpio = irq_drv_data;
163         u8 type;
164         int ret;
165
166         raw_spin_lock(&idio24gpio->lock);
167
168         /* if all are masked, then disable interrupts, else set to type */
169         type = (mask_buf == mask_buf_def) ? ~type_mask : idio24gpio->irq_type;
170
171         ret = regmap_update_bits(idio24gpio->map, IDIO_24_COS_ENABLE, type_mask, type);
172
173         raw_spin_unlock(&idio24gpio->lock);
174
175         return ret;
176 }
177
178 static int idio_24_set_type_config(unsigned int **const buf, const unsigned int type,
179                                    const struct regmap_irq *const irq_data, const int idx,
180                                    void *const irq_drv_data)
181 {
182         const unsigned int offset = irq_data->reg_offset;
183         const unsigned int rising = COS_ENABLE_RISING << offset;
184         const unsigned int falling = COS_ENABLE_FALLING << offset;
185         const unsigned int mask = COS_ENABLE_BOTH << offset;
186         struct idio_24_gpio *const idio24gpio = irq_drv_data;
187         unsigned int new;
188         unsigned int cos_enable;
189         int ret;
190
191         switch (type) {
192         case IRQ_TYPE_EDGE_RISING:
193                 new = rising;
194                 break;
195         case IRQ_TYPE_EDGE_FALLING:
196                 new = falling;
197                 break;
198         case IRQ_TYPE_EDGE_BOTH:
199                 new = mask;
200                 break;
201         default:
202                 return -EINVAL;
203         }
204
205         raw_spin_lock(&idio24gpio->lock);
206
207         /* replace old bitmap with new bitmap */
208         idio24gpio->irq_type = (idio24gpio->irq_type & ~mask) | (new & mask);
209
210         ret = regmap_read(idio24gpio->map, IDIO_24_COS_ENABLE, &cos_enable);
211         if (ret)
212                 goto exit_unlock;
213
214         /* if COS is currently enabled then update the edge type */
215         if (cos_enable & mask) {
216                 ret = regmap_update_bits(idio24gpio->map, IDIO_24_COS_ENABLE, mask,
217                                          idio24gpio->irq_type);
218                 if (ret)
219                         goto exit_unlock;
220         }
221
222 exit_unlock:
223         raw_spin_unlock(&idio24gpio->lock);
224
225         return ret;
226 }
227
228 static int idio_24_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base,
229                                   const unsigned int offset, unsigned int *const reg,
230                                   unsigned int *const mask)
231 {
232         const unsigned int out_stride = offset / IDIO_24_NGPIO_PER_REG;
233         const unsigned int in_stride = (offset - 24) / IDIO_24_NGPIO_PER_REG;
234         struct regmap *const map = gpio_regmap_get_drvdata(gpio);
235         int err;
236         unsigned int ctrl_reg;
237
238         switch (base) {
239         case IDIO_24_OUT_BASE:
240                 *mask = BIT(offset % IDIO_24_NGPIO_PER_REG);
241
242                 /* FET Outputs */
243                 if (offset < 24) {
244                         *reg = IDIO_24_OUT_BASE + out_stride;
245                         return 0;
246                 }
247
248                 /* Isolated Inputs */
249                 if (offset < 48) {
250                         *reg = IDIO_24_IN_BASE + in_stride;
251                         return 0;
252                 }
253
254                 err = regmap_read(map, IDIO_24_CONTROL_REG, &ctrl_reg);
255                 if (err)
256                         return err;
257
258                 /* TTL/CMOS Outputs */
259                 if (ctrl_reg & CONTROL_REG_OUT_MODE) {
260                         *reg = IDIO_24_TTLCMOS_OUT_REG;
261                         return 0;
262                 }
263
264                 /* TTL/CMOS Inputs */
265                 *reg = IDIO_24_TTLCMOS_IN_REG;
266                 return 0;
267         case IDIO_24_CONTROL_REG:
268                 /* We can only set direction for TTL/CMOS lines */
269                 if (offset < 48)
270                         return -EOPNOTSUPP;
271
272                 *reg = IDIO_24_CONTROL_REG;
273                 *mask = CONTROL_REG_OUT_MODE;
274                 return 0;
275         default:
276                 /* Should never reach this path */
277                 return -EINVAL;
278         }
279 }
280
281 #define IDIO_24_NGPIO 56
282 static const char *idio_24_names[IDIO_24_NGPIO] = {
283         "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7",
284         "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15",
285         "OUT16", "OUT17", "OUT18", "OUT19", "OUT20", "OUT21", "OUT22", "OUT23",
286         "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7",
287         "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15",
288         "IIN16", "IIN17", "IIN18", "IIN19", "IIN20", "IIN21", "IIN22", "IIN23",
289         "TTL0", "TTL1", "TTL2", "TTL3", "TTL4", "TTL5", "TTL6", "TTL7"
290 };
291
292 static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id)
293 {
294         struct device *const dev = &pdev->dev;
295         struct idio_24_gpio *idio24gpio;
296         int err;
297         const size_t pci_plx_bar_index = 1;
298         const size_t pci_bar_index = 2;
299         const char *const name = pci_name(pdev);
300         struct gpio_regmap_config gpio_config = {};
301         void __iomem *pex8311_regs;
302         void __iomem *idio_24_regs;
303         struct regmap *intcsr_map;
304         struct regmap_irq_chip *chip;
305         struct regmap_irq_chip_data *chip_data;
306
307         err = pcim_enable_device(pdev);
308         if (err) {
309                 dev_err(dev, "Failed to enable PCI device (%d)\n", err);
310                 return err;
311         }
312
313         err = pcim_iomap_regions(pdev, BIT(pci_plx_bar_index) | BIT(pci_bar_index), name);
314         if (err) {
315                 dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
316                 return err;
317         }
318
319         pex8311_regs = pcim_iomap_table(pdev)[pci_plx_bar_index];
320         idio_24_regs = pcim_iomap_table(pdev)[pci_bar_index];
321
322         intcsr_map = devm_regmap_init_mmio(dev, pex8311_regs, &pex8311_intcsr_regmap_config);
323         if (IS_ERR(intcsr_map))
324                 return dev_err_probe(dev, PTR_ERR(intcsr_map),
325                                      "Unable to initialize PEX8311 register map\n");
326
327         idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL);
328         if (!idio24gpio)
329                 return -ENOMEM;
330
331         idio24gpio->map = devm_regmap_init_mmio(dev, idio_24_regs, &idio_24_regmap_config);
332         if (IS_ERR(idio24gpio->map))
333                 return dev_err_probe(dev, PTR_ERR(idio24gpio->map),
334                                      "Unable to initialize register map\n");
335
336         raw_spin_lock_init(&idio24gpio->lock);
337
338         /* Initialize all IRQ type configuration to IRQ_TYPE_EDGE_BOTH */
339         idio24gpio->irq_type = GENMASK(7, 0);
340
341         chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
342         if (!chip)
343                 return -ENOMEM;
344
345         chip->name = name;
346         chip->status_base = IDIO_24_COS_STATUS_BASE;
347         chip->mask_base = IDIO_24_COS_ENABLE;
348         chip->ack_base = IDIO_24_COS_STATUS_BASE;
349         chip->num_regs = 4;
350         chip->irqs = idio_24_regmap_irqs;
351         chip->num_irqs = ARRAY_SIZE(idio_24_regmap_irqs);
352         chip->handle_mask_sync = idio_24_handle_mask_sync;
353         chip->set_type_config = idio_24_set_type_config;
354         chip->irq_drv_data = idio24gpio;
355
356         /* Software board reset */
357         err = regmap_write(idio24gpio->map, IDIO_24_SOFT_RESET, 0);
358         if (err)
359                 return err;
360         /*
361          * enable PLX PEX8311 internal PCI wire interrupt and local interrupt
362          * input
363          */
364         err = regmap_update_bits(intcsr_map, 0x0, IDIO_24_ENABLE_IRQ, IDIO_24_ENABLE_IRQ);
365         if (err)
366                 return err;
367
368         err = devm_regmap_add_irq_chip(dev, idio24gpio->map, pdev->irq, 0, 0, chip, &chip_data);
369         if (err)
370                 return dev_err_probe(dev, err, "IRQ registration failed\n");
371
372         gpio_config.parent = dev;
373         gpio_config.regmap = idio24gpio->map;
374         gpio_config.ngpio = IDIO_24_NGPIO;
375         gpio_config.names = idio_24_names;
376         gpio_config.reg_dat_base = GPIO_REGMAP_ADDR(IDIO_24_OUT_BASE);
377         gpio_config.reg_set_base = GPIO_REGMAP_ADDR(IDIO_24_OUT_BASE);
378         gpio_config.reg_dir_out_base = GPIO_REGMAP_ADDR(IDIO_24_CONTROL_REG);
379         gpio_config.ngpio_per_reg = IDIO_24_NGPIO_PER_REG;
380         gpio_config.irq_domain = regmap_irq_get_domain(chip_data);
381         gpio_config.reg_mask_xlate = idio_24_reg_mask_xlate;
382         gpio_config.drvdata = idio24gpio->map;
383
384         return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
385 }
386
387 static const struct pci_device_id idio_24_pci_dev_id[] = {
388         { PCI_DEVICE(0x494F, 0x0FD0) }, { PCI_DEVICE(0x494F, 0x0BD0) },
389         { PCI_DEVICE(0x494F, 0x07D0) }, { PCI_DEVICE(0x494F, 0x0FC0) },
390         { 0 }
391 };
392 MODULE_DEVICE_TABLE(pci, idio_24_pci_dev_id);
393
394 static struct pci_driver idio_24_driver = {
395         .name = "pcie-idio-24",
396         .id_table = idio_24_pci_dev_id,
397         .probe = idio_24_probe
398 };
399
400 module_pci_driver(idio_24_driver);
401
402 MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
403 MODULE_DESCRIPTION("ACCES PCIe-IDIO-24 GPIO driver");
404 MODULE_LICENSE("GPL v2");