drm/vc4: txp: Protect device resources
[platform/kernel/linux-starfive.git] / drivers / mfd / wm8350-gpio.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * wm8350-core.c  --  Device access for Wolfson WM8350
4  *
5  * Copyright 2007, 2008 Wolfson Microelectronics PLC.
6  *
7  * Author: Liam Girdwood
8  */
9
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/errno.h>
13
14 #include <linux/mfd/wm8350/core.h>
15 #include <linux/mfd/wm8350/gpio.h>
16 #include <linux/mfd/wm8350/pmic.h>
17
18 static int gpio_set_dir(struct wm8350 *wm8350, int gpio, int dir)
19 {
20         int ret;
21
22         wm8350_reg_unlock(wm8350);
23         if (dir == WM8350_GPIO_DIR_OUT)
24                 ret = wm8350_clear_bits(wm8350,
25                                         WM8350_GPIO_CONFIGURATION_I_O,
26                                         1 << gpio);
27         else
28                 ret = wm8350_set_bits(wm8350,
29                                       WM8350_GPIO_CONFIGURATION_I_O,
30                                       1 << gpio);
31         wm8350_reg_lock(wm8350);
32         return ret;
33 }
34
35 static int wm8350_gpio_set_debounce(struct wm8350 *wm8350, int gpio, int db)
36 {
37         if (db == WM8350_GPIO_DEBOUNCE_ON)
38                 return wm8350_set_bits(wm8350, WM8350_GPIO_DEBOUNCE,
39                                        1 << gpio);
40         else
41                 return wm8350_clear_bits(wm8350,
42                                          WM8350_GPIO_DEBOUNCE, 1 << gpio);
43 }
44
45 static int gpio_set_func(struct wm8350 *wm8350, int gpio, int func)
46 {
47         u16 reg;
48
49         wm8350_reg_unlock(wm8350);
50         switch (gpio) {
51         case 0:
52                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
53                     & ~WM8350_GP0_FN_MASK;
54                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
55                                  reg | ((func & 0xf) << 0));
56                 break;
57         case 1:
58                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
59                     & ~WM8350_GP1_FN_MASK;
60                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
61                                  reg | ((func & 0xf) << 4));
62                 break;
63         case 2:
64                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
65                     & ~WM8350_GP2_FN_MASK;
66                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
67                                  reg | ((func & 0xf) << 8));
68                 break;
69         case 3:
70                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
71                     & ~WM8350_GP3_FN_MASK;
72                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
73                                  reg | ((func & 0xf) << 12));
74                 break;
75         case 4:
76                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
77                     & ~WM8350_GP4_FN_MASK;
78                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
79                                  reg | ((func & 0xf) << 0));
80                 break;
81         case 5:
82                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
83                     & ~WM8350_GP5_FN_MASK;
84                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
85                                  reg | ((func & 0xf) << 4));
86                 break;
87         case 6:
88                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
89                     & ~WM8350_GP6_FN_MASK;
90                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
91                                  reg | ((func & 0xf) << 8));
92                 break;
93         case 7:
94                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
95                     & ~WM8350_GP7_FN_MASK;
96                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
97                                  reg | ((func & 0xf) << 12));
98                 break;
99         case 8:
100                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
101                     & ~WM8350_GP8_FN_MASK;
102                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
103                                  reg | ((func & 0xf) << 0));
104                 break;
105         case 9:
106                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
107                     & ~WM8350_GP9_FN_MASK;
108                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
109                                  reg | ((func & 0xf) << 4));
110                 break;
111         case 10:
112                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
113                     & ~WM8350_GP10_FN_MASK;
114                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
115                                  reg | ((func & 0xf) << 8));
116                 break;
117         case 11:
118                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
119                     & ~WM8350_GP11_FN_MASK;
120                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
121                                  reg | ((func & 0xf) << 12));
122                 break;
123         case 12:
124                 reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_4)
125                     & ~WM8350_GP12_FN_MASK;
126                 wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_4,
127                                  reg | ((func & 0xf) << 0));
128                 break;
129         default:
130                 wm8350_reg_lock(wm8350);
131                 return -EINVAL;
132         }
133
134         wm8350_reg_lock(wm8350);
135         return 0;
136 }
137
138 static int gpio_set_pull_up(struct wm8350 *wm8350, int gpio, int up)
139 {
140         if (up)
141                 return wm8350_set_bits(wm8350,
142                                        WM8350_GPIO_PIN_PULL_UP_CONTROL,
143                                        1 << gpio);
144         else
145                 return wm8350_clear_bits(wm8350,
146                                          WM8350_GPIO_PIN_PULL_UP_CONTROL,
147                                          1 << gpio);
148 }
149
150 static int gpio_set_pull_down(struct wm8350 *wm8350, int gpio, int down)
151 {
152         if (down)
153                 return wm8350_set_bits(wm8350,
154                                        WM8350_GPIO_PULL_DOWN_CONTROL,
155                                        1 << gpio);
156         else
157                 return wm8350_clear_bits(wm8350,
158                                          WM8350_GPIO_PULL_DOWN_CONTROL,
159                                          1 << gpio);
160 }
161
162 static int gpio_set_polarity(struct wm8350 *wm8350, int gpio, int pol)
163 {
164         if (pol == WM8350_GPIO_ACTIVE_HIGH)
165                 return wm8350_set_bits(wm8350,
166                                        WM8350_GPIO_PIN_POLARITY_TYPE,
167                                        1 << gpio);
168         else
169                 return wm8350_clear_bits(wm8350,
170                                          WM8350_GPIO_PIN_POLARITY_TYPE,
171                                          1 << gpio);
172 }
173
174 static int gpio_set_invert(struct wm8350 *wm8350, int gpio, int invert)
175 {
176         if (invert == WM8350_GPIO_INVERT_ON)
177                 return wm8350_set_bits(wm8350, WM8350_GPIO_INT_MODE, 1 << gpio);
178         else
179                 return wm8350_clear_bits(wm8350,
180                                          WM8350_GPIO_INT_MODE, 1 << gpio);
181 }
182
183 int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func,
184                        int pol, int pull, int invert, int debounce)
185 {
186         /* make sure we never pull up and down at the same time */
187         if (pull == WM8350_GPIO_PULL_NONE) {
188                 if (gpio_set_pull_up(wm8350, gpio, 0))
189                         goto err;
190                 if (gpio_set_pull_down(wm8350, gpio, 0))
191                         goto err;
192         } else if (pull == WM8350_GPIO_PULL_UP) {
193                 if (gpio_set_pull_down(wm8350, gpio, 0))
194                         goto err;
195                 if (gpio_set_pull_up(wm8350, gpio, 1))
196                         goto err;
197         } else if (pull == WM8350_GPIO_PULL_DOWN) {
198                 if (gpio_set_pull_up(wm8350, gpio, 0))
199                         goto err;
200                 if (gpio_set_pull_down(wm8350, gpio, 1))
201                         goto err;
202         }
203
204         if (gpio_set_invert(wm8350, gpio, invert))
205                 goto err;
206         if (gpio_set_polarity(wm8350, gpio, pol))
207                 goto err;
208         if (wm8350_gpio_set_debounce(wm8350, gpio, debounce))
209                 goto err;
210         if (gpio_set_dir(wm8350, gpio, dir))
211                 goto err;
212         return gpio_set_func(wm8350, gpio, func);
213
214 err:
215         return -EIO;
216 }
217 EXPORT_SYMBOL_GPL(wm8350_gpio_config);