mfd: rk808: add rk805 support
[firefly-linux-kernel-4.4.55.git] / drivers / gpio / gpio-rk8xx.c
1 /*
2  * drivers/gpio/gpio-rk8xx.c
3  * Driver for Rockchip RK8xx PMIC GPIO
4  *
5  * Copyright (C) 2017, Rockchip Technology Co., Ltd.
6  * Author: Chen Jianhong <chenjh@rock-chips.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  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13  * kind, whether express or implied; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17
18 #include <linux/err.h>
19 #include <linux/gpio.h>
20 #include <linux/init.h>
21 #include <linux/i2c.h>
22 #include <linux/mfd/rk808.h>
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/of.h>
26 #include <linux/platform_device.h>
27
28 #define RK805_GPIO_REG          RK805_OUT_REG
29 #define RK805_OUT0_VALMASK      BIT(0)
30 #define RK805_OUT1_VALMASK      BIT(1)
31
32 struct rk8xx_gpio_reg {
33         u8 reg;
34         u8 dir_msk;
35         u8 val_msk;
36         u8 fun_msk;
37 };
38
39 struct rk8xx_gpio_info {
40         struct rk808 *rk8xx;
41         struct gpio_chip gpio_chip;
42         struct rk8xx_gpio_reg *gpio_reg;
43         int gpio_nr;
44 };
45
46 static int rk8xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
47 {
48         int err;
49         struct rk8xx_gpio_info *gi = dev_get_drvdata(chip->dev);
50
51         /* iomux */
52         if (gi->gpio_reg[offset].fun_msk) {
53                 err = regmap_update_bits(gi->rk8xx->regmap,
54                                          gi->gpio_reg[offset].reg,
55                                          gi->gpio_reg[offset].fun_msk,
56                                          gi->gpio_reg[offset].fun_msk);
57                 if (err) {
58                         dev_err(chip->dev, "set gpio%d func fail: %d\n",
59                                 offset, err);
60                         return err;
61                 }
62         }
63
64         /* direction */
65         if (gi->gpio_reg[offset].dir_msk) {
66                 err = regmap_update_bits(gi->rk8xx->regmap,
67                                          gi->gpio_reg[offset].reg,
68                                          gi->gpio_reg[offset].dir_msk,
69                                          0);
70                 if (err) {
71                         dev_err(chip->dev, "set gpio%d input fail: %d\n",
72                                 offset, err);
73                         return err;
74                 }
75         }
76
77         return 0;
78 }
79
80 static int rk8xx_gpio_direction_output(struct gpio_chip *chip,
81                                        unsigned offset, int value)
82 {
83         int err;
84         struct rk8xx_gpio_info *gi = dev_get_drvdata(chip->dev);
85
86         /* iomux */
87         if (gi->gpio_reg[offset].fun_msk) {
88                 err = regmap_update_bits(gi->rk8xx->regmap,
89                                          gi->gpio_reg[offset].reg,
90                                          gi->gpio_reg[offset].fun_msk,
91                                          gi->gpio_reg[offset].fun_msk);
92                 if (err) {
93                         dev_err(chip->dev, "set gpio%d func fail: %d\n",
94                                 offset, err);
95                         return err;
96                 }
97         }
98
99         /* direction */
100         if (gi->gpio_reg[offset].dir_msk) {
101                 err = regmap_update_bits(gi->rk8xx->regmap,
102                                          gi->gpio_reg[offset].reg,
103                                          gi->gpio_reg[offset].dir_msk,
104                                          gi->gpio_reg[offset].dir_msk);
105                 if (err) {
106                         dev_err(chip->dev,
107                                 "set gpio%d output fail: %d\n", offset, err);
108                         return err;
109                 }
110         }
111
112         if (value)
113                 err = regmap_update_bits(gi->rk8xx->regmap,
114                                          gi->gpio_reg[offset].reg,
115                                          gi->gpio_reg[offset].val_msk,
116                                          gi->gpio_reg[offset].val_msk);
117         else
118                 err = regmap_update_bits(gi->rk8xx->regmap,
119                                          gi->gpio_reg[offset].reg,
120                                          gi->gpio_reg[offset].val_msk,
121                                          0);
122         if (err) {
123                 dev_err(chip->dev, "set gpio%d value fail: %d\n", offset, err);
124                 return err;
125         }
126
127         return 0;
128 }
129
130 static int rk8xx_gpio_get_value(struct gpio_chip *chip, unsigned offset)
131 {
132         int err;
133         unsigned int val;
134         struct rk8xx_gpio_info *gi = dev_get_drvdata(chip->dev);
135
136         err = regmap_read(gi->rk8xx->regmap, gi->gpio_reg[offset].reg, &val);
137         if (err) {
138                 dev_err(chip->dev, "get gpio%d value fail: %d\n", offset, err);
139                 return err;
140         }
141
142         return (val & gi->gpio_reg[offset].val_msk) ? 1 : 0;
143 }
144
145 static void rk8xx_gpio_set_value(struct gpio_chip *chip,
146                                  unsigned offset, int value)
147 {
148         int err;
149         struct rk8xx_gpio_info *gi = dev_get_drvdata(chip->dev);
150
151         if (value)
152                 err = regmap_update_bits(gi->rk8xx->regmap,
153                                          gi->gpio_reg[offset].reg,
154                                          gi->gpio_reg[offset].val_msk,
155                                          gi->gpio_reg[offset].val_msk);
156         else
157                 err = regmap_update_bits(gi->rk8xx->regmap,
158                                          gi->gpio_reg[offset].reg,
159                                          gi->gpio_reg[offset].val_msk,
160                                          0);
161         if (err)
162                 dev_err(chip->dev, "set gpio%d value fail: %d\n", offset, err);
163 }
164
165 /* rk805: two gpio: output only */
166 static struct rk8xx_gpio_reg rk805_gpio_reg[] = {
167         {
168                 .reg = RK805_GPIO_REG,
169                 .val_msk = RK805_OUT0_VALMASK,
170         },
171         {
172                 .reg = RK805_GPIO_REG,
173                 .val_msk = RK805_OUT1_VALMASK,
174         },
175 };
176
177 static int rk8xx_gpio_probe(struct platform_device *pdev)
178 {
179         struct rk808 *rk8xx = dev_get_drvdata(pdev->dev.parent);
180         struct rk8xx_gpio_info *gi;
181         struct device_node *np;
182         int ret;
183
184         np = of_find_node_by_name(pdev->dev.parent->of_node, "gpio");
185         if (np) {
186                 if (!of_device_is_available(np)) {
187                         dev_info(&pdev->dev, "device is disabled\n");
188                         return -EINVAL;
189                 }
190         }
191
192         gi = devm_kzalloc(&pdev->dev, sizeof(*gi), GFP_KERNEL);
193         if (!gi)
194                 return -ENOMEM;
195
196         switch (rk8xx->variant) {
197         case RK805_ID:
198                 gi->gpio_reg = rk805_gpio_reg;
199                 gi->gpio_nr = ARRAY_SIZE(rk805_gpio_reg);
200                 break;
201         default:
202                 dev_err(&pdev->dev, "unsupported RK8XX ID %lu\n",
203                         rk8xx->variant);
204                 return -EINVAL;
205         }
206
207         gi->rk8xx = rk8xx;
208         gi->gpio_chip.base = -1;
209         gi->gpio_chip.can_sleep = true;
210         gi->gpio_chip.dev = &pdev->dev;
211         gi->gpio_chip.ngpio = gi->gpio_nr;
212         gi->gpio_chip.label = pdev->name;
213         gi->gpio_chip.get = rk8xx_gpio_get_value;
214         gi->gpio_chip.set = rk8xx_gpio_set_value;
215         gi->gpio_chip.direction_input = rk8xx_gpio_direction_input;
216         gi->gpio_chip.direction_output = rk8xx_gpio_direction_output;
217         gi->gpio_chip.owner = THIS_MODULE;
218 #ifdef CONFIG_OF_GPIO
219         gi->gpio_chip.of_node = rk8xx->i2c->dev.of_node;
220 #endif
221         platform_set_drvdata(pdev, gi);
222
223         ret = gpiochip_add(&gi->gpio_chip);
224         if (ret)
225                 dev_err(&pdev->dev, "register rk8xx gpiochip fail: %d\n", ret);
226
227         return ret;
228 }
229
230 static int rk8xx_gpio_remove(struct platform_device *pdev)
231 {
232         struct rk8xx_gpio_info *gi = platform_get_drvdata(pdev);
233
234         gpiochip_remove(&gi->gpio_chip);
235
236         return 0;
237 }
238
239 static struct platform_driver rk8xx_gpio_driver = {
240         .probe = rk8xx_gpio_probe,
241         .remove = rk8xx_gpio_remove,
242         .driver = {
243                 .name = "rk8xx-gpio",
244                 .owner = THIS_MODULE,
245         },
246 };
247
248 static int rk8xx_gpio_init(void)
249 {
250         return platform_driver_register(&rk8xx_gpio_driver);
251 }
252 subsys_initcall(rk8xx_gpio_init);
253
254 static void rk8xx_gpio_exit(void)
255 {
256         platform_driver_unregister(&rk8xx_gpio_driver);
257 }
258 module_exit(rk8xx_gpio_exit);
259
260 MODULE_LICENSE("GPL v2");
261 MODULE_DESCRIPTION("RK8xx GPIO driver");
262 MODULE_AUTHOR("Chen Jianhong <chenjh@rock-chips.com>");