source: trunk/target/linux/ar71xx/files/drivers/gpio/nxp_74hc153.c @ 21698

Last change on this file since 21698 was 21698, checked in by juhosg, 7 years ago

ar71xx: fix 2.6.34 build errors

File size: 5.7 KB
Line 
1/*
2 *  NXP 74HC153 - Dual 4-input multiplexer GPIO driver
3 *
4 *  Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
5 *
6 *  This program is free software; you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License version 2 as
8 *  published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/init.h>
13#include <linux/gpio.h>
14#include <linux/slab.h>
15#include <linux/platform_device.h>
16#include <linux/nxp_74hc153.h>
17
18#define NXP_74HC153_NUM_GPIOS   8
19#define NXP_74HC153_S0_MASK     0x1
20#define NXP_74HC153_S1_MASK     0x2
21#define NXP_74HC153_BANK_MASK   0x4
22
23struct nxp_74hc153_chip {
24        struct device           *parent;
25        struct gpio_chip        gpio_chip;
26        struct mutex            lock;
27};
28
29static struct nxp_74hc153_chip *gpio_to_nxp(struct gpio_chip *gc)
30{
31        return container_of(gc, struct nxp_74hc153_chip, gpio_chip);
32}
33
34static int nxp_74hc153_direction_input(struct gpio_chip *gc, unsigned offset)
35{
36        return 0;
37}
38
39static int nxp_74hc153_direction_output(struct gpio_chip *gc,
40                                        unsigned offset, int val)
41{
42        return -EINVAL;
43}
44
45static int nxp_74hc153_get_value(struct gpio_chip *gc, unsigned offset)
46{
47        struct nxp_74hc153_chip *nxp;
48        struct nxp_74hc153_platform_data *pdata;
49        unsigned s0;
50        unsigned s1;
51        unsigned pin;
52        int ret;
53
54        nxp = gpio_to_nxp(gc);
55        pdata = nxp->parent->platform_data;
56
57        s0 = !!(offset & NXP_74HC153_S0_MASK);
58        s1 = !!(offset & NXP_74HC153_S1_MASK);
59        pin = (offset & NXP_74HC153_BANK_MASK) ? pdata->gpio_pin_2y
60                                               : pdata->gpio_pin_1y;
61
62        mutex_lock(&nxp->lock);
63        gpio_set_value(pdata->gpio_pin_s0, s0);
64        gpio_set_value(pdata->gpio_pin_s1, s1);
65        ret = gpio_get_value(pin);
66        mutex_unlock(&nxp->lock);
67
68        return ret;
69}
70
71static void nxp_74hc153_set_value(struct gpio_chip *gc,
72                                  unsigned offset, int val)
73{
74        /* not supported */
75}
76
77static int __devinit nxp_74hc153_probe(struct platform_device *pdev)
78{
79        struct nxp_74hc153_platform_data *pdata;
80        struct nxp_74hc153_chip *nxp;
81        struct gpio_chip *gc;
82        int err;
83
84        pdata = pdev->dev.platform_data;
85        if (pdata == NULL) {
86                dev_dbg(&pdev->dev, "no platform data specified\n");
87                return -EINVAL;
88        }
89
90        nxp = kzalloc(sizeof(struct nxp_74hc153_chip), GFP_KERNEL);
91        if (nxp == NULL) {
92                dev_err(&pdev->dev, "no memory for private data\n");
93                return -ENOMEM;
94        }
95
96        err = gpio_request(pdata->gpio_pin_s0, dev_name(&pdev->dev));
97        if (err) {
98                dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n",
99                        pdata->gpio_pin_s0, err);
100                goto err_free_nxp;
101        }
102
103        err = gpio_request(pdata->gpio_pin_s1, dev_name(&pdev->dev));
104        if (err) {
105                dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n",
106                        pdata->gpio_pin_s1, err);
107                goto err_free_s0;
108        }
109
110        err = gpio_request(pdata->gpio_pin_1y, dev_name(&pdev->dev));
111        if (err) {
112                dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n",
113                        pdata->gpio_pin_1y, err);
114                goto err_free_s1;
115        }
116
117        err = gpio_request(pdata->gpio_pin_2y, dev_name(&pdev->dev));
118        if (err) {
119                dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n",
120                        pdata->gpio_pin_2y, err);
121                goto err_free_1y;
122        }
123
124        err = gpio_direction_output(pdata->gpio_pin_s0, 0);
125        if (err) {
126                dev_err(&pdev->dev,
127                        "unable to set direction of gpio %u, err=%d\n",
128                        pdata->gpio_pin_s0, err);
129                goto err_free_2y;
130        }
131
132        err = gpio_direction_output(pdata->gpio_pin_s1, 0);
133        if (err) {
134                dev_err(&pdev->dev,
135                        "unable to set direction of gpio %u, err=%d\n",
136                        pdata->gpio_pin_s1, err);
137                goto err_free_2y;
138        }
139
140        err = gpio_direction_input(pdata->gpio_pin_1y);
141        if (err) {
142                dev_err(&pdev->dev,
143                        "unable to set direction of gpio %u, err=%d\n",
144                        pdata->gpio_pin_1y, err);
145                goto err_free_2y;
146        }
147
148        err = gpio_direction_input(pdata->gpio_pin_2y);
149        if (err) {
150                dev_err(&pdev->dev,
151                        "unable to set direction of gpio %u, err=%d\n",
152                        pdata->gpio_pin_2y, err);
153                goto err_free_2y;
154        }
155
156        nxp->parent = &pdev->dev;
157        mutex_init(&nxp->lock);
158
159        gc = &nxp->gpio_chip;
160
161        gc->direction_input  = nxp_74hc153_direction_input;
162        gc->direction_output = nxp_74hc153_direction_output;
163        gc->get = nxp_74hc153_get_value;
164        gc->set = nxp_74hc153_set_value;
165        gc->can_sleep = 1;
166
167        gc->base = pdata->gpio_base;
168        gc->ngpio = NXP_74HC153_NUM_GPIOS;
169        gc->label = dev_name(nxp->parent);
170        gc->dev = nxp->parent;
171        gc->owner = THIS_MODULE;
172
173        err = gpiochip_add(&nxp->gpio_chip);
174        if (err) {
175                dev_err(&pdev->dev, "unable to add gpio chip, err=%d\n", err);
176                goto err_free_2y;
177        }
178
179        platform_set_drvdata(pdev, nxp);
180        return 0;
181
182 err_free_2y:
183        gpio_free(pdata->gpio_pin_2y);
184 err_free_1y:
185        gpio_free(pdata->gpio_pin_1y);
186 err_free_s1:
187        gpio_free(pdata->gpio_pin_s1);
188 err_free_s0:
189        gpio_free(pdata->gpio_pin_s0);
190 err_free_nxp:
191        kfree(nxp);
192        return err;
193}
194
195static int nxp_74hc153_remove(struct platform_device *pdev)
196{
197        struct nxp_74hc153_chip *nxp = platform_get_drvdata(pdev);
198        struct nxp_74hc153_platform_data *pdata = pdev->dev.platform_data;
199
200        if (nxp) {
201                int err;
202
203                err = gpiochip_remove(&nxp->gpio_chip);
204                if (err) {
205                        dev_err(&pdev->dev,
206                                "unable to remove gpio chip, err=%d\n",
207                                err);
208                        return err;
209                }
210
211                gpio_free(pdata->gpio_pin_2y);
212                gpio_free(pdata->gpio_pin_1y);
213                gpio_free(pdata->gpio_pin_s1);
214                gpio_free(pdata->gpio_pin_s0);
215
216                kfree(nxp);
217                platform_set_drvdata(pdev, NULL);
218        }
219
220        return 0;
221}
222
223static struct platform_driver nxp_74hc153_driver = {
224        .probe          = nxp_74hc153_probe,
225        .remove         = __devexit_p(nxp_74hc153_remove),
226        .driver = {
227                .name   = NXP_74HC153_DRIVER_NAME,
228                .owner  = THIS_MODULE,
229        },
230};
231
232static int __init nxp_74hc153_init(void)
233{
234        return platform_driver_register(&nxp_74hc153_driver);
235}
236subsys_initcall(nxp_74hc153_init);
237
238static void __exit nxp_74hc153_exit(void)
239{
240        platform_driver_unregister(&nxp_74hc153_driver);
241}
242module_exit(nxp_74hc153_exit);
243
244MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
245MODULE_DESCRIPTION("GPIO expander driver for NXP 74HC153");
246MODULE_LICENSE("GPL v2");
247MODULE_ALIAS("platform:" NXP_74HC153_DRIVER_NAME);
Note: See TracBrowser for help on using the repository browser.