treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152
[muen/linux.git] / drivers / gpio / gpio-sch311x.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * GPIO driver for the SMSC SCH311x Super-I/O chips
4  *
5  * Copyright (C) 2013 Bruno Randolf <br1@einfach.org>
6  *
7  * SuperIO functions and chip detection:
8  * (c) Copyright 2008 Wim Van Sebroeck <wim@iguana.be>.
9  */
10
11 #include <linux/ioport.h>
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/platform_device.h>
16 #include <linux/gpio/driver.h>
17 #include <linux/bitops.h>
18 #include <linux/io.h>
19
20 #define DRV_NAME                        "gpio-sch311x"
21
22 #define SCH311X_GPIO_CONF_DIR           BIT(0)
23 #define SCH311X_GPIO_CONF_INVERT        BIT(1)
24 #define SCH311X_GPIO_CONF_OPEN_DRAIN    BIT(7)
25
26 #define SIO_CONFIG_KEY_ENTER            0x55
27 #define SIO_CONFIG_KEY_EXIT             0xaa
28
29 #define GP1                             0x4b
30
31 static int sch311x_ioports[] = { 0x2e, 0x4e, 0x162e, 0x164e };
32
33 static struct platform_device *sch311x_gpio_pdev;
34
35 struct sch311x_pdev_data {              /* platform device data */
36         unsigned short runtime_reg;     /* runtime register base address */
37 };
38
39 struct sch311x_gpio_block {             /* one GPIO block runtime data */
40         struct gpio_chip chip;
41         unsigned short data_reg;        /* from definition below */
42         unsigned short *config_regs;    /* pointer to definition below */
43         unsigned short runtime_reg;     /* runtime register */
44         spinlock_t lock;                /* lock for this GPIO block */
45 };
46
47 struct sch311x_gpio_priv {              /* driver private data */
48         struct sch311x_gpio_block blocks[6];
49 };
50
51 struct sch311x_gpio_block_def {         /* register address definitions */
52         unsigned short data_reg;
53         unsigned short config_regs[8];
54         unsigned short base;
55 };
56
57 /* Note: some GPIOs are not available, these are marked with 0x00 */
58
59 static struct sch311x_gpio_block_def sch311x_gpio_blocks[] = {
60         {
61                 .data_reg = 0x4b,       /* GP1 */
62                 .config_regs = {0x23, 0x24, 0x25, 0x26, 0x27, 0x29, 0x2a, 0x2b},
63                 .base = 10,
64         },
65         {
66                 .data_reg = 0x4c,       /* GP2 */
67                 .config_regs = {0x00, 0x2c, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x32},
68                 .base = 20,
69         },
70         {
71                 .data_reg = 0x4d,       /* GP3 */
72                 .config_regs = {0x33, 0x34, 0x35, 0x36, 0x37, 0x00, 0x39, 0x3a},
73                 .base = 30,
74         },
75         {
76                 .data_reg = 0x4e,       /* GP4 */
77                 .config_regs = {0x3b, 0x00, 0x3d, 0x00, 0x6e, 0x6f, 0x72, 0x73},
78                 .base = 40,
79         },
80         {
81                 .data_reg = 0x4f,       /* GP5 */
82                 .config_regs = {0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46},
83                 .base = 50,
84         },
85         {
86                 .data_reg = 0x50,       /* GP6 */
87                 .config_regs = {0x47, 0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59},
88                 .base = 60,
89         },
90 };
91
92 /*
93  *      Super-IO functions
94  */
95
96 static inline int sch311x_sio_enter(int sio_config_port)
97 {
98         /* Don't step on other drivers' I/O space by accident. */
99         if (!request_muxed_region(sio_config_port, 2, DRV_NAME)) {
100                 pr_err(DRV_NAME "I/O address 0x%04x already in use\n",
101                        sio_config_port);
102                 return -EBUSY;
103         }
104
105         outb(SIO_CONFIG_KEY_ENTER, sio_config_port);
106         return 0;
107 }
108
109 static inline void sch311x_sio_exit(int sio_config_port)
110 {
111         outb(SIO_CONFIG_KEY_EXIT, sio_config_port);
112         release_region(sio_config_port, 2);
113 }
114
115 static inline int sch311x_sio_inb(int sio_config_port, int reg)
116 {
117         outb(reg, sio_config_port);
118         return inb(sio_config_port + 1);
119 }
120
121 static inline void sch311x_sio_outb(int sio_config_port, int reg, int val)
122 {
123         outb(reg, sio_config_port);
124         outb(val, sio_config_port + 1);
125 }
126
127
128 /*
129  *      GPIO functions
130  */
131
132 static int sch311x_gpio_request(struct gpio_chip *chip, unsigned offset)
133 {
134         struct sch311x_gpio_block *block = gpiochip_get_data(chip);
135
136         if (block->config_regs[offset] == 0) /* GPIO is not available */
137                 return -ENODEV;
138
139         if (!request_region(block->runtime_reg + block->config_regs[offset],
140                             1, DRV_NAME)) {
141                 dev_err(chip->parent, "Failed to request region 0x%04x.\n",
142                         block->runtime_reg + block->config_regs[offset]);
143                 return -EBUSY;
144         }
145         return 0;
146 }
147
148 static void sch311x_gpio_free(struct gpio_chip *chip, unsigned offset)
149 {
150         struct sch311x_gpio_block *block = gpiochip_get_data(chip);
151
152         if (block->config_regs[offset] == 0) /* GPIO is not available */
153                 return;
154
155         release_region(block->runtime_reg + block->config_regs[offset], 1);
156 }
157
158 static int sch311x_gpio_get(struct gpio_chip *chip, unsigned offset)
159 {
160         struct sch311x_gpio_block *block = gpiochip_get_data(chip);
161         u8 data;
162
163         spin_lock(&block->lock);
164         data = inb(block->runtime_reg + block->data_reg);
165         spin_unlock(&block->lock);
166
167         return !!(data & BIT(offset));
168 }
169
170 static void __sch311x_gpio_set(struct sch311x_gpio_block *block,
171                                unsigned offset, int value)
172 {
173         u8 data = inb(block->runtime_reg + block->data_reg);
174         if (value)
175                 data |= BIT(offset);
176         else
177                 data &= ~BIT(offset);
178         outb(data, block->runtime_reg + block->data_reg);
179 }
180
181 static void sch311x_gpio_set(struct gpio_chip *chip, unsigned offset,
182                              int value)
183 {
184         struct sch311x_gpio_block *block = gpiochip_get_data(chip);
185
186         spin_lock(&block->lock);
187         __sch311x_gpio_set(block, offset, value);
188         spin_unlock(&block->lock);
189 }
190
191 static int sch311x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
192 {
193         struct sch311x_gpio_block *block = gpiochip_get_data(chip);
194         u8 data;
195
196         spin_lock(&block->lock);
197         data = inb(block->runtime_reg + block->config_regs[offset]);
198         data |= SCH311X_GPIO_CONF_DIR;
199         outb(data, block->runtime_reg + block->config_regs[offset]);
200         spin_unlock(&block->lock);
201
202         return 0;
203 }
204
205 static int sch311x_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
206                                       int value)
207 {
208         struct sch311x_gpio_block *block = gpiochip_get_data(chip);
209         u8 data;
210
211         spin_lock(&block->lock);
212
213         data = inb(block->runtime_reg + block->config_regs[offset]);
214         data &= ~SCH311X_GPIO_CONF_DIR;
215         outb(data, block->runtime_reg + block->config_regs[offset]);
216         __sch311x_gpio_set(block, offset, value);
217
218         spin_unlock(&block->lock);
219         return 0;
220 }
221
222 static int sch311x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
223 {
224         struct sch311x_gpio_block *block = gpiochip_get_data(chip);
225         u8 data;
226
227         spin_lock(&block->lock);
228         data = inb(block->runtime_reg + block->config_regs[offset]);
229         spin_unlock(&block->lock);
230
231         return !!(data & SCH311X_GPIO_CONF_DIR);
232 }
233
234 static int sch311x_gpio_set_config(struct gpio_chip *chip, unsigned offset,
235                                    unsigned long config)
236 {
237         struct sch311x_gpio_block *block = gpiochip_get_data(chip);
238         enum pin_config_param param = pinconf_to_config_param(config);
239         u8 data;
240
241         switch (param) {
242         case PIN_CONFIG_DRIVE_OPEN_DRAIN:
243                 spin_lock(&block->lock);
244                 data = inb(block->runtime_reg + block->config_regs[offset]);
245                 data |= SCH311X_GPIO_CONF_OPEN_DRAIN;
246                 outb(data, block->runtime_reg + block->config_regs[offset]);
247                 spin_unlock(&block->lock);
248                 return 0;
249         case PIN_CONFIG_DRIVE_PUSH_PULL:
250                 spin_lock(&block->lock);
251                 data = inb(block->runtime_reg + block->config_regs[offset]);
252                 data &= ~SCH311X_GPIO_CONF_OPEN_DRAIN;
253                 outb(data, block->runtime_reg + block->config_regs[offset]);
254                 spin_unlock(&block->lock);
255                 return 0;
256         default:
257                 break;
258         }
259         return -ENOTSUPP;
260 }
261
262 static int sch311x_gpio_probe(struct platform_device *pdev)
263 {
264         struct sch311x_pdev_data *pdata = dev_get_platdata(&pdev->dev);
265         struct sch311x_gpio_priv *priv;
266         struct sch311x_gpio_block *block;
267         int err, i;
268
269         /* we can register all GPIO data registers at once */
270         if (!devm_request_region(&pdev->dev, pdata->runtime_reg + GP1, 6,
271                 DRV_NAME)) {
272                 dev_err(&pdev->dev, "Failed to request region 0x%04x-0x%04x.\n",
273                         pdata->runtime_reg + GP1, pdata->runtime_reg + GP1 + 5);
274                 return -EBUSY;
275         }
276
277         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
278         if (!priv)
279                 return -ENOMEM;
280
281         platform_set_drvdata(pdev, priv);
282
283         for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) {
284                 block = &priv->blocks[i];
285
286                 spin_lock_init(&block->lock);
287
288                 block->chip.label = DRV_NAME;
289                 block->chip.owner = THIS_MODULE;
290                 block->chip.request = sch311x_gpio_request;
291                 block->chip.free = sch311x_gpio_free;
292                 block->chip.direction_input = sch311x_gpio_direction_in;
293                 block->chip.direction_output = sch311x_gpio_direction_out;
294                 block->chip.get_direction = sch311x_gpio_get_direction;
295                 block->chip.set_config = sch311x_gpio_set_config;
296                 block->chip.get = sch311x_gpio_get;
297                 block->chip.set = sch311x_gpio_set;
298                 block->chip.ngpio = 8;
299                 block->chip.parent = &pdev->dev;
300                 block->chip.base = sch311x_gpio_blocks[i].base;
301                 block->config_regs = sch311x_gpio_blocks[i].config_regs;
302                 block->data_reg = sch311x_gpio_blocks[i].data_reg;
303                 block->runtime_reg = pdata->runtime_reg;
304
305                 err = gpiochip_add_data(&block->chip, block);
306                 if (err < 0) {
307                         dev_err(&pdev->dev,
308                                 "Could not register gpiochip, %d\n", err);
309                         goto exit_err;
310                 }
311                 dev_info(&pdev->dev,
312                          "SMSC SCH311x GPIO block %d registered.\n", i);
313         }
314
315         return 0;
316
317 exit_err:
318         /* release already registered chips */
319         for (--i; i >= 0; i--)
320                 gpiochip_remove(&priv->blocks[i].chip);
321         return err;
322 }
323
324 static int sch311x_gpio_remove(struct platform_device *pdev)
325 {
326         struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev);
327         int i;
328
329         for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) {
330                 gpiochip_remove(&priv->blocks[i].chip);
331                 dev_info(&pdev->dev,
332                          "SMSC SCH311x GPIO block %d unregistered.\n", i);
333         }
334         return 0;
335 }
336
337 static struct platform_driver sch311x_gpio_driver = {
338         .driver.name    = DRV_NAME,
339         .probe          = sch311x_gpio_probe,
340         .remove         = sch311x_gpio_remove,
341 };
342
343
344 /*
345  *      Init & exit routines
346  */
347
348 static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
349 {
350         int err = 0, reg;
351         unsigned short base_addr;
352         u8 dev_id;
353
354         err = sch311x_sio_enter(sio_config_port);
355         if (err)
356                 return err;
357
358         /* Check device ID. */
359         reg = sch311x_sio_inb(sio_config_port, 0x20);
360         switch (reg) {
361         case 0x7c: /* SCH3112 */
362                 dev_id = 2;
363                 break;
364         case 0x7d: /* SCH3114 */
365                 dev_id = 4;
366                 break;
367         case 0x7f: /* SCH3116 */
368                 dev_id = 6;
369                 break;
370         default:
371                 err = -ENODEV;
372                 goto exit;
373         }
374
375         /* Select logical device A (runtime registers) */
376         sch311x_sio_outb(sio_config_port, 0x07, 0x0a);
377
378         /* Check if Logical Device Register is currently active */
379         if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0)
380                 pr_info("Seems that LDN 0x0a is not active...\n");
381
382         /* Get the base address of the runtime registers */
383         base_addr = (sch311x_sio_inb(sio_config_port, 0x60) << 8) |
384                            sch311x_sio_inb(sio_config_port, 0x61);
385         if (!base_addr) {
386                 pr_err("Base address not set\n");
387                 err = -ENODEV;
388                 goto exit;
389         }
390         *addr = base_addr;
391
392         pr_info("Found an SMSC SCH311%d chip at 0x%04x\n", dev_id, base_addr);
393
394 exit:
395         sch311x_sio_exit(sio_config_port);
396         return err;
397 }
398
399 static int __init sch311x_gpio_pdev_add(const unsigned short addr)
400 {
401         struct sch311x_pdev_data pdata;
402         int err;
403
404         pdata.runtime_reg = addr;
405
406         sch311x_gpio_pdev = platform_device_alloc(DRV_NAME, -1);
407         if (!sch311x_gpio_pdev)
408                 return -ENOMEM;
409
410         err = platform_device_add_data(sch311x_gpio_pdev,
411                                        &pdata, sizeof(pdata));
412         if (err) {
413                 pr_err(DRV_NAME "Platform data allocation failed\n");
414                 goto err;
415         }
416
417         err = platform_device_add(sch311x_gpio_pdev);
418         if (err) {
419                 pr_err(DRV_NAME "Device addition failed\n");
420                 goto err;
421         }
422         return 0;
423
424 err:
425         platform_device_put(sch311x_gpio_pdev);
426         return err;
427 }
428
429 static int __init sch311x_gpio_init(void)
430 {
431         int err, i;
432         unsigned short addr = 0;
433
434         for (i = 0; i < ARRAY_SIZE(sch311x_ioports); i++)
435                 if (sch311x_detect(sch311x_ioports[i], &addr) == 0)
436                         break;
437
438         if (!addr)
439                 return -ENODEV;
440
441         err = platform_driver_register(&sch311x_gpio_driver);
442         if (err)
443                 return err;
444
445         err = sch311x_gpio_pdev_add(addr);
446         if (err)
447                 goto unreg_platform_driver;
448
449         return 0;
450
451 unreg_platform_driver:
452         platform_driver_unregister(&sch311x_gpio_driver);
453         return err;
454 }
455
456 static void __exit sch311x_gpio_exit(void)
457 {
458         platform_device_unregister(sch311x_gpio_pdev);
459         platform_driver_unregister(&sch311x_gpio_driver);
460 }
461
462 module_init(sch311x_gpio_init);
463 module_exit(sch311x_gpio_exit);
464
465 MODULE_AUTHOR("Bruno Randolf <br1@einfach.org>");
466 MODULE_DESCRIPTION("SMSC SCH311x GPIO Driver");
467 MODULE_LICENSE("GPL");
468 MODULE_ALIAS("platform:gpio-sch311x");