exynos_gpio.c revision 1.19 1 /* $NetBSD: exynos_gpio.c,v 1.19 2015/12/27 02:43:42 marty Exp $ */
2
3 /*-
4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Reinoud Zandijk
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "opt_exynos.h"
33 #include "opt_arm_debug.h"
34 #include "gpio.h"
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(1, "$NetBSD: exynos_gpio.c,v 1.19 2015/12/27 02:43:42 marty Exp $");
38
39 #include <sys/param.h>
40 #include <sys/bus.h>
41 #include <sys/device.h>
42 #include <sys/intr.h>
43 #include <sys/systm.h>
44 #include <sys/kmem.h>
45 #include <sys/gpio.h>
46
47 #include <dev/gpio/gpiovar.h>
48
49 #include <arm/samsung/exynos_reg.h>
50 #include <arm/samsung/exynos_var.h>
51 #include <arm/samsung/exynos_intr.h>
52 #include <arm/samsung/exynos_pinctrl.h>
53
54 #include <dev/fdt/fdtvar.h>
55
56 struct exynos_gpio_pin_cfg {
57 uint32_t cfg;
58 uint32_t pud;
59 uint32_t drv;
60 uint32_t conpwd;
61 uint32_t pudpwd;
62 };
63
64 struct exynos_gpio_softc;
65
66 struct exynos_gpio_bank {
67 const char bank_name[6];
68 device_t bank_dev;
69 struct gpio_chipset_tag bank_gc;
70 struct exynos_gpio_softc *bank_sc;
71 gpio_pin_t bank_pins[8];
72
73 const bus_addr_t bank_core_offset;
74 const uint8_t bank_bits;
75
76 uint8_t bank_pin_mask;
77 uint8_t bank_pin_inuse_mask;
78 bus_space_handle_t bank_bsh;
79 struct exynos_gpio_pin_cfg bank_cfg;
80 struct exynos_gpio_bank * bank_next;
81 };
82
83 struct exynos_gpio_softc {
84 device_t sc_dev;
85 bus_space_tag_t sc_bst;
86 bus_space_handle_t sc_bsh;
87 };
88
89 struct exynos_gpio_pin {
90 struct exynos_gpio_softc *pin_sc;
91 int pin_no;
92 u_int pin_flags;
93 int pin_actlo;
94 const struct exynos_gpio_bank *pin_bank;
95 };
96
97
98 //#define GPIO_REG(v,s,o) (EXYNOS##v##_GPIO_##s##_OFFSET + (o))
99 #define GPIO_REG(v,s,o) ((o))
100 #define GPIO_GRP(v, s, o, n, b) \
101 { \
102 .bank_name = #n, \
103 .bank_core_offset = GPIO_REG(v,s,o), \
104 .bank_bits = b, \
105 }
106
107 static struct exynos_gpio_bank exynos5_banks[] = {
108 GPIO_GRP(5, MUXA, 0x0000, gpy7, 8),
109 GPIO_GRP(5, MUXA, 0x0C00, gpx0, 8),
110 GPIO_GRP(5, MUXA, 0x0C20, gpx1, 8),
111 GPIO_GRP(5, MUXA, 0x0C40, gpx2, 8),
112 GPIO_GRP(5, MUXA, 0x0C60, gpx3, 8),
113
114 GPIO_GRP(5, MUXB, 0x0000, gpc0, 8),
115 GPIO_GRP(5, MUXB, 0x0020, gpc1, 8),
116 GPIO_GRP(5, MUXB, 0x0040, gpc2, 7),
117 GPIO_GRP(5, MUXB, 0x0060, gpc3, 4),
118 GPIO_GRP(5, MUXB, 0x0080, gpc4, 2),
119 GPIO_GRP(5, MUXB, 0x00A0, gpd1, 8),
120 GPIO_GRP(5, MUXB, 0x00C0, gpy0, 6),
121 GPIO_GRP(5, MUXB, 0x00E0, gpy1, 4),
122 GPIO_GRP(5, MUXB, 0x0100, gpy2, 6),
123 GPIO_GRP(5, MUXB, 0x0120, gpy3, 8),
124 GPIO_GRP(5, MUXB, 0x0140, gpy4, 8),
125 GPIO_GRP(5, MUXB, 0x0160, gpy5, 8),
126 GPIO_GRP(5, MUXB, 0x0180, gpy6, 8),
127
128 GPIO_GRP(5, MUXC, 0x0000, gpe0, 8),
129 GPIO_GRP(5, MUXC, 0x0020, gpe1, 2),
130 GPIO_GRP(5, MUXC, 0x0040, gpf0, 6),
131 GPIO_GRP(5, MUXC, 0x0060, gpf1, 8),
132 GPIO_GRP(5, MUXC, 0x0080, gpg0, 8),
133 GPIO_GRP(5, MUXC, 0x00A0, gpg1, 8),
134 GPIO_GRP(5, MUXC, 0x00C0, gpg2, 2),
135 GPIO_GRP(5, MUXC, 0x00E0, gpj4, 4),
136
137 GPIO_GRP(5, MUXD, 0x0000, gpa0, 8),
138 GPIO_GRP(5, MUXD, 0x0020, gpa1, 6),
139 GPIO_GRP(5, MUXD, 0x0040, gpa2, 8),
140 GPIO_GRP(5, MUXD, 0x0060, gpb0, 5),
141 GPIO_GRP(5, MUXD, 0x0080, gpb1, 5),
142 GPIO_GRP(5, MUXD, 0x00A0, gpb2, 4),
143 GPIO_GRP(5, MUXD, 0x00C0, gpb3, 8),
144 GPIO_GRP(5, MUXD, 0x00E0, gpb4, 2),
145 GPIO_GRP(5, MUXD, 0x0100, gph0, 4),
146
147 GPIO_GRP(5, MUXE, 0x0000, gpz0, 7),
148
149 };
150
151 struct exynos_gpio_bank *exynos_gpio_banks = exynos5_banks;
152
153 static int exynos_gpio_pin_read(void *, int);
154 static void exynos_gpio_pin_write(void *, int, int);
155 static void exynos_gpio_pin_ctl(void *, int, int);
156 static void *exynos_gpio_fdt_acquire(device_t, const void *,
157 size_t, int);
158 static void exynos_gpio_fdt_release(device_t, void *);
159
160 static int exynos_gpio_fdt_read(device_t, void *, bool);
161 static void exynos_gpio_fdt_write(device_t, void *, int, bool);
162 static struct exynos_gpio_bank *
163 exynos_gpio_pin_lookup(const char *pinname, int *ppin);
164 static int exynos_gpio_cfprint(void *, const char *);
165
166 struct fdtbus_gpio_controller_func exynos_gpio_funcs = {
167 .acquire = exynos_gpio_fdt_acquire,
168 .release = exynos_gpio_fdt_release,
169 .read = exynos_gpio_fdt_read,
170 .write = exynos_gpio_fdt_write
171 };
172 #define GPIO_WRITE(bank, reg, val) \
173 bus_space_write_4((bank)->bank_sc->sc_bst, \
174 (bank)->bank_sc->sc_bsh, \
175 (bank)->bank_core_offset + (reg), (val))
176 #define GPIO_READ(bank, reg) \
177 bus_space_read_4((bank)->bank_sc->sc_bst, \
178 (bank)->bank_sc->sc_bsh, \
179 (bank)->bank_core_offset + (reg))
180
181 static int
182 exynos_gpio_cfprint(void *priv, const char *pnp)
183 {
184 struct gpiobus_attach_args *gba = priv;
185 struct exynos_gpio_bank *bank = gba->gba_gc->gp_cookie;
186 const char *bankname = bank->bank_name;
187
188 if (pnp)
189 aprint_normal("gpiobus at %s", pnp);
190
191 aprint_normal(" (%s)", bankname);
192
193 return UNCONF;
194 }
195
196 static void
197 exynos_gpio_update_cfg_regs(struct exynos_gpio_bank *bank,
198 const struct exynos_gpio_pin_cfg *ncfg)
199 {
200 if (bank->bank_cfg.cfg != ncfg->cfg) {
201 GPIO_WRITE(bank, EXYNOS_GPIO_CON, ncfg->cfg);
202 bank->bank_cfg.cfg = ncfg->cfg;
203 }
204 if (bank->bank_cfg.pud != ncfg->pud) {
205 GPIO_WRITE(bank, EXYNOS_GPIO_PUD, ncfg->pud);
206 bank->bank_cfg.pud = ncfg->pud;
207 }
208
209 if (bank->bank_cfg.drv != ncfg->drv) {
210 GPIO_WRITE(bank, EXYNOS_GPIO_DRV, ncfg->drv);
211 bank->bank_cfg.drv = ncfg->drv;
212 }
213 if (bank->bank_cfg.conpwd != ncfg->conpwd) {
214 GPIO_WRITE(bank, EXYNOS_GPIO_CONPWD, ncfg->conpwd);
215 bank->bank_cfg.conpwd = ncfg->conpwd;
216 }
217 if (bank->bank_cfg.pudpwd != ncfg->pudpwd) {
218 GPIO_WRITE(bank, EXYNOS_GPIO_PUDPWD, ncfg->pudpwd);
219 bank->bank_cfg.pudpwd = ncfg->pudpwd;
220 }
221 }
222
223 static int
224 exynos_gpio_pin_read(void *cookie, int pin)
225 {
226 struct exynos_gpio_bank * const bank = cookie;
227
228 KASSERT(pin < bank->bank_bits);
229 return (bus_space_read_1(bank->bank_sc->sc_bst,
230 bank->bank_sc->sc_bsh,
231 EXYNOS_GPIO_DAT) >> pin) & 1;
232 }
233
234 static void
235 exynos_gpio_pin_write(void *cookie, int pin, int value)
236 {
237 struct exynos_gpio_bank * const bank = cookie;
238 int val;
239
240 KASSERT(pin < bank->bank_bits);
241 val = bus_space_read_1(bank->bank_sc->sc_bst,
242 bank->bank_sc->sc_bsh,
243 EXYNOS_GPIO_DAT);
244 val &= ~__BIT(pin);
245 if (value)
246 val |= __BIT(pin);
247 bus_space_write_1(bank->bank_sc->sc_bst,
248 bank->bank_sc->sc_bsh,
249 EXYNOS_GPIO_DAT, val);
250 }
251
252 static void
253 exynos_gpio_pin_ctl(void *cookie, int pin, int flags)
254 {
255 struct exynos_gpio_bank * const bank = cookie;
256 struct exynos_gpio_pin_cfg ncfg = bank->bank_cfg;
257 u_int shift;
258 int pull;
259
260 /* honour pullup requests */
261 pull = EXYNOS_GPIO_PIN_FLOAT;
262 if (flags & GPIO_PIN_PULLUP)
263 pull = EXYNOS_GPIO_PIN_PULL_UP;
264 if (flags & GPIO_PIN_PULLDOWN)
265 pull = EXYNOS_GPIO_PIN_PULL_DOWN;
266 shift = (pin & 7) << 1;
267 ncfg.pud &= ~(0x3 << shift);
268 ncfg.pud |= pull << shift;
269
270 /* honour i/o */
271 if (flags & GPIO_PIN_INPUT) {
272 ncfg.cfg &= ~(0x0f << shift);
273 ncfg.cfg |= EXYNOS_GPIO_FUNC_INPUT << shift;
274 } else if (flags & GPIO_PIN_OUTPUT) {
275 ncfg.cfg &= ~(0x0f << shift);
276 ncfg.cfg |= EXYNOS_GPIO_FUNC_OUTPUT << shift;
277 }
278
279 /* update any config registers that changed */
280 exynos_gpio_update_cfg_regs(bank, &ncfg);
281 }
282
283 void
284 exynos_gpio_bank_config(struct exynos_pinctrl_softc * parent,
285 const struct fdt_attach_args *faa, int node)
286 {
287 struct exynos_gpio_bank *bank = kmem_zalloc(sizeof(*bank), KM_SLEEP);
288 struct exynos_gpio_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
289 struct gpiobus_attach_args gba;
290 struct gpio_chipset_tag *gc_tag;
291 char result[64];
292
293 OF_getprop(node, "name", result, sizeof(result));
294 bank = exynos_gpio_pin_lookup(result, 0);
295 KASSERT(bank);
296
297 sc->sc_dev = parent->sc_dev;
298 sc->sc_bst = &armv7_generic_bs_tag;
299 sc->sc_bsh = parent->sc_bsh;
300
301 gc_tag = &bank->bank_gc;
302 gc_tag->gp_cookie = bank;
303 gc_tag->gp_pin_read = exynos_gpio_pin_read;
304 gc_tag->gp_pin_write = exynos_gpio_pin_write;
305 gc_tag->gp_pin_ctl = exynos_gpio_pin_ctl;
306 memset(&gba, 0, sizeof(gba));
307 gba.gba_gc = &bank->bank_gc;
308 gba.gba_pins = bank->bank_pins;
309 gba.gba_npins = bank->bank_bits;
310 bank->bank_sc = sc;
311 bank->bank_dev = config_found_ia(parent->sc_dev, "gpiobus", &gba,
312 exynos_gpio_cfprint);
313
314 bank->bank_pin_mask = __BIT(bank->bank_bits) - 1;
315 bank->bank_pin_inuse_mask = 0;
316
317
318 /* read in our initial settings */
319 bank->bank_cfg.cfg = GPIO_READ(bank, EXYNOS_GPIO_CON);
320 bank->bank_cfg.pud = GPIO_READ(bank, EXYNOS_GPIO_PUD);
321 bank->bank_cfg.drv = GPIO_READ(bank, EXYNOS_GPIO_DRV);
322 bank->bank_cfg.conpwd = GPIO_READ(bank, EXYNOS_GPIO_CONPWD);
323 bank->bank_cfg.pudpwd = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD);
324
325 fdtbus_register_gpio_controller(bank->bank_dev, faa->faa_phandle,
326 &exynos_gpio_funcs);
327 }
328
329 /*
330 * pinmame = gpLD[-N]
331 * L = 'a' - 'z' -+
332 * D = '0' - '9' -+ ===== bank name
333 * N = '0' - '7' ===== pin number
334 */
335
336 static struct exynos_gpio_bank *
337 exynos_gpio_pin_lookup(const char *pinname, int *ppin)
338 {
339 char bankname[5];
340 int pin = 0;
341 int n;
342 struct exynos_gpio_bank *bank;
343
344 memset(bankname, 0, sizeof(bankname));
345 for (n = 0; n < 4; n++)
346 bankname[n] = pinname[n];
347 bankname[n] = 0;
348 if (ppin && pinname[4] == '-') {
349 pin = pinname[5] - '0'; /* skip the '-' */
350 if (pin < 0 || pin > 8)
351 return NULL;
352 }
353 for (n = 0; n < __arraycount(exynos5_banks); n++) {
354 bank = &exynos_gpio_banks[n];
355 if (strcmp(bank->bank_name, bankname) == 0) {
356 if (ppin)
357 *ppin = pin;
358 return bank;
359 }
360 }
361
362 return NULL;
363 }
364
365 static void *
366 exynos_gpio_fdt_acquire(device_t dev, const void *data, size_t len, int flags)
367 {
368 const u_int *cells = data;
369 const struct exynos_gpio_bank *bank = NULL;
370 struct exynos_gpio_pin *gpin;
371 int pin = be32toh(cells[0]) & 0x0f;
372 int n;
373
374 for (n = 0; n < __arraycount(exynos5_banks); n++) {
375 if (exynos_gpio_banks[n].bank_sc->sc_dev == dev) {
376 bank = &exynos_gpio_banks[n];
377 break;
378 }
379 }
380 if (bank == NULL)
381 return NULL;
382
383 printf("gpio pin %s-%d being acquired\n", bank->bank_name, pin);
384 gpin = kmem_alloc(sizeof(*gpin), KM_SLEEP);
385 gpin->pin_sc = bank->bank_sc;
386 gpin->pin_bank = bank;
387 gpin->pin_no = pin;
388 gpin->pin_flags = flags;
389 gpin->pin_actlo = 0;
390
391 exynos_gpio_pin_ctl(&gpin->pin_bank, gpin->pin_no, gpin->pin_flags);
392
393 return gpin;
394 }
395
396 static void
397 exynos_gpio_fdt_release(device_t dev, void *priv)
398 {
399 struct exynos_gpio_pin *gpin = priv;
400
401 kmem_free(gpin, sizeof(*gpin));
402 }
403
404 static int
405 exynos_gpio_fdt_read(device_t dev, void *priv, bool raw)
406 {
407 struct exynos_gpio_pin *gpin = priv;
408 int val;
409
410 val = (bus_space_read_1(gpin->pin_sc->sc_bst,
411 gpin->pin_sc->sc_bsh,
412 EXYNOS_GPIO_DAT) >> gpin->pin_no) & 1;
413
414 if (!raw && gpin->pin_actlo)
415 val = !val;
416
417 return val;
418 }
419
420 static void
421 exynos_gpio_fdt_write(device_t dev, void *priv, int val, bool raw)
422 {
423 struct exynos_gpio_pin *gpin = priv;
424
425 if (!raw && gpin->pin_actlo)
426 val = !val;
427
428 val = bus_space_read_1(gpin->pin_sc->sc_bst,
429 gpin->pin_sc->sc_bsh,
430 EXYNOS_GPIO_DAT);
431 val &= ~__BIT(gpin->pin_no);
432 if (val)
433 val |= __BIT(gpin->pin_no);
434 bus_space_write_1(gpin->pin_sc->sc_bst,
435 gpin->pin_sc->sc_bsh,
436 EXYNOS_GPIO_DAT, val);
437
438 }
439