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