xref: /linux/drivers/mfd/wm8350-gpio.c (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
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 wm8350_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 (wm8350_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);
223