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