97bebcd597c15dd75e288b5b7b743f3c999637dd
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / rt5025-gpio.c
1 /*
2  *  drivers/gpio/rt5025-gpio.c
3  *  Driver foo Richtek RT5025 PMIC GPIO
4  *
5  *  Copyright (C) 2013 Richtek Electronics
6  *  cy_huang <cy_huang@richtek.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/err.h>
17 #include <linux/gpio.h>
18 #include <linux/i2c.h>
19 #include <linux/slab.h>
20 #include <linux/platform_device.h>
21
22 #include <linux/mfd/rt5025.h>
23 #include <linux/mfd/rt5025-gpio.h>
24
25 struct rt5025_gpio_info {
26         struct i2c_client *i2c;
27         unsigned gpio_base;
28         unsigned irq_base;
29         struct gpio_chip gpio_chip;
30 };
31
32 static inline int find_rt5025_gpioreg(unsigned off, int *gpio_reg)
33 {
34         int ret = 0;
35         switch (off)
36         {
37                 case 0:
38                 case 1:
39                 case 2:
40                         *gpio_reg = RT5025_REG_GPIO0 + off;
41                         break;
42                 default:
43                         ret = -EINVAL;
44         }
45         return ret;
46 }
47
48 static int rt5025_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
49 {
50         struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
51         int gpio_reg = 0;
52         int ret = 0;
53         
54         ret = find_rt5025_gpioreg(offset , &gpio_reg);
55         if (ret < 0)
56         {
57                 dev_err(chip->dev, "not a valid gpio index\n");
58                 return ret;
59         }
60
61         ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_DIRMASK);
62         if (ret<0)
63         {
64                 dev_err(chip->dev, "set gpio input fail\n");
65                 return ret;
66         }
67
68         return 0;
69 }
70
71 static int rt5025_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
72 {
73         struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
74         int gpio_reg = 0;
75         int ret = 0;
76         
77         ret = find_rt5025_gpioreg(offset, &gpio_reg);
78         if (ret < 0)
79         {
80                 dev_err(chip->dev, "not a valid gpio index\n");
81                 return ret;
82         }
83         
84         ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_DIRSHIFT);
85         if (ret<0)
86         {
87                 dev_err(chip->dev, "clr gpio direction fail\n");
88                 return ret;
89         }
90
91         ret = rt5025_set_bits(gi->i2c, gpio_reg, RT5025_GPIO_OUTPUT<<RT5025_GPIO_DIRSHIFT);
92         if (ret<0)
93         {
94                 dev_err(chip->dev, "set gpio output dir fail\n");
95                 return ret;
96         }
97
98         if (value)
99                 ret = rt5025_set_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
100         else
101                 ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
102
103         if (ret<0)
104         {
105                 dev_err(chip->dev, "set gpio output value fail\n");
106                 return ret;
107         }
108
109         return 0;
110 }
111
112 static int rt5025_gpio_get_value(struct gpio_chip *chip, unsigned offset)
113 {
114         struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
115         int gpio_reg = 0;
116         int ret = 0;
117         
118         ret = find_rt5025_gpioreg(offset, &gpio_reg);
119         if (ret < 0)
120         {
121                 dev_err(chip->dev, "not a valid gpio index\n");
122                 return ret;
123         }
124         
125         ret = rt5025_reg_read(gi->i2c, gpio_reg);
126         if (ret<0)
127         {
128                 dev_err(chip->dev, "read gpio register fail\n");
129                 return ret;
130         }
131
132         return (ret&RT5025_GPIO_IVALUEMASK)?1:0;
133 }
134
135 static void rt5025_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
136 {
137         struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
138         int gpio_reg = 0;
139         int ret = 0;
140         
141         ret = find_rt5025_gpioreg(offset, &gpio_reg);
142         if (ret < 0)
143         {
144                 dev_err(chip->dev, "not a valid gpio index\n");
145                 return;
146         }
147
148         if (value)
149                 ret = rt5025_set_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
150         else
151                 ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
152
153         if (ret<0)
154         {
155                 dev_err(chip->dev, "read gpio register fail\n");
156         }
157 }
158
159 static int __devinit rt5025_gpio_probe(struct platform_device *pdev)
160 {
161         struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
162         struct rt5025_platform_data *pdata = chip->dev->platform_data;
163         struct rt5025_gpio_info *gi;
164         int ret = 0;
165
166         gi = kzalloc(sizeof(*gi), GFP_KERNEL);
167         if (!gi)
168                 return -ENOMEM;
169
170         gi->i2c = chip->i2c;
171         gi->gpio_base = pdata->gpio_data->gpio_base;
172         gi->irq_base = pdata->gpio_data->irq_base;
173
174         gi->gpio_chip.direction_input  = rt5025_gpio_direction_input;
175         gi->gpio_chip.direction_output = rt5025_gpio_direction_output;
176         gi->gpio_chip.get = rt5025_gpio_get_value;
177         gi->gpio_chip.set = rt5025_gpio_set_value;
178         gi->gpio_chip.can_sleep = 0;
179
180         gi->gpio_chip.base = gi->gpio_base;
181         gi->gpio_chip.ngpio = RT5025_GPIO_NR;
182         gi->gpio_chip.label = pdev->name;
183         gi->gpio_chip.dev = &pdev->dev;
184         gi->gpio_chip.owner = THIS_MODULE;
185
186         ret = gpiochip_add(&gi->gpio_chip);
187         if (ret)
188                 goto out_dev;
189                 
190         platform_set_drvdata(pdev, gi);
191         return ret;
192 out_dev:
193         kfree(gi);
194         return ret;
195 }
196
197 static int __devexit rt5025_gpio_remove(struct platform_device *pdev)
198 {
199         int ret;
200         struct rt5025_gpio_info *gi = platform_get_drvdata(pdev);
201
202         ret = gpiochip_remove(&gi->gpio_chip);
203         kfree(gi);
204
205         platform_set_drvdata(pdev, NULL);
206         return 0;
207 }
208
209 static struct platform_driver rt5025_gpio_driver = 
210 {
211         .driver = {
212                 .name = RT5025_DEVICE_NAME "-gpio",
213                 .owner = THIS_MODULE,
214         },
215         .probe = rt5025_gpio_probe,
216         .remove = __devexit_p(rt5025_gpio_remove),
217 };
218
219 static int __init rt5025_gpio_init(void)
220 {
221         return platform_driver_register(&rt5025_gpio_driver);
222 }
223 subsys_initcall_sync(rt5025_gpio_init);
224
225 static void __exit rt5025_gpio_exit(void)
226 {
227         platform_driver_unregister(&rt5025_gpio_driver);
228 }
229 module_exit(rt5025_gpio_exit);
230
231 MODULE_LICENSE("GPL v2");
232 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
233 MODULE_DESCRIPTION("GPIO driver for RT5025");
234 MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-gpio");
235 MODULE_VERSION(RT5025_DRV_VER);