exynos_gpio.c revision 1.25 1 /* $NetBSD: exynos_gpio.c,v 1.25 2018/07/04 22:16:42 jmcneill 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.25 2018/07/04 22:16:42 jmcneill 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_bank {
57 const char bank_name[6];
58 device_t bank_dev;
59 struct gpio_chipset_tag bank_gc;
60 struct exynos_gpio_softc *bank_sc;
61 gpio_pin_t bank_pins[8];
62
63 const bus_addr_t bank_core_offset;
64 const uint8_t bank_bits;
65
66 uint8_t bank_pin_mask;
67 uint8_t bank_pin_inuse_mask;
68 bus_space_handle_t bank_bsh;
69 struct exynos_gpio_pin_cfg bank_cfg;
70 struct exynos_gpio_bank * bank_next;
71 };
72
73 struct exynos_gpio_pin {
74 struct exynos_gpio_softc *pin_sc;
75 int pin_no;
76 u_int pin_flags;
77 int pin_actlo;
78 const struct exynos_gpio_bank *pin_bank;
79 };
80
81
82 //#define GPIO_REG(v,s,o) (EXYNOS##v##_GPIO_##s##_OFFSET + (o))
83 #define GPIO_REG(v,s,o) ((o))
84 #define GPIO_GRP(v, s, o, n, b) \
85 { \
86 .bank_name = #n, \
87 .bank_core_offset = GPIO_REG(v,s,o), \
88 .bank_bits = b, \
89 }
90
91 static struct exynos_gpio_bank exynos5_banks[] = {
92 GPIO_GRP(5, MUXA, 0x0000, gpy7, 8),
93 GPIO_GRP(5, MUXA, 0x0C00, gpx0, 8),
94 GPIO_GRP(5, MUXA, 0x0C20, gpx1, 8),
95 GPIO_GRP(5, MUXA, 0x0C40, gpx2, 8),
96 GPIO_GRP(5, MUXA, 0x0C60, gpx3, 8),
97
98 GPIO_GRP(5, MUXB, 0x0000, gpc0, 8),
99 GPIO_GRP(5, MUXB, 0x0020, gpc1, 8),
100 GPIO_GRP(5, MUXB, 0x0040, gpc2, 7),
101 GPIO_GRP(5, MUXB, 0x0060, gpc3, 4),
102 GPIO_GRP(5, MUXB, 0x0080, gpc4, 2),
103 GPIO_GRP(5, MUXB, 0x00A0, gpd1, 8),
104 GPIO_GRP(5, MUXB, 0x00C0, gpy0, 6),
105 GPIO_GRP(5, MUXB, 0x00E0, gpy1, 4),
106 GPIO_GRP(5, MUXB, 0x0100, gpy2, 6),
107 GPIO_GRP(5, MUXB, 0x0120, gpy3, 8),
108 GPIO_GRP(5, MUXB, 0x0140, gpy4, 8),
109 GPIO_GRP(5, MUXB, 0x0160, gpy5, 8),
110 GPIO_GRP(5, MUXB, 0x0180, gpy6, 8),
111
112 GPIO_GRP(5, MUXC, 0x0000, gpe0, 8),
113 GPIO_GRP(5, MUXC, 0x0020, gpe1, 2),
114 GPIO_GRP(5, MUXC, 0x0040, gpf0, 6),
115 GPIO_GRP(5, MUXC, 0x0060, gpf1, 8),
116 GPIO_GRP(5, MUXC, 0x0080, gpg0, 8),
117 GPIO_GRP(5, MUXC, 0x00A0, gpg1, 8),
118 GPIO_GRP(5, MUXC, 0x00C0, gpg2, 2),
119 GPIO_GRP(5, MUXC, 0x00E0, gpj4, 4),
120
121 GPIO_GRP(5, MUXD, 0x0000, gpa0, 8),
122 GPIO_GRP(5, MUXD, 0x0020, gpa1, 6),
123 GPIO_GRP(5, MUXD, 0x0040, gpa2, 8),
124 GPIO_GRP(5, MUXD, 0x0060, gpb0, 5),
125 GPIO_GRP(5, MUXD, 0x0080, gpb1, 5),
126 GPIO_GRP(5, MUXD, 0x00A0, gpb2, 4),
127 GPIO_GRP(5, MUXD, 0x00C0, gpb3, 8),
128 GPIO_GRP(5, MUXD, 0x00E0, gpb4, 2),
129 GPIO_GRP(5, MUXD, 0x0100, gph0, 4),
130
131 GPIO_GRP(5, MUXE, 0x0000, gpz, 7),
132
133 };
134
135 struct exynos_gpio_bank *exynos_gpio_banks = exynos5_banks;
136
137 static int exynos_gpio_pin_read(void *, int);
138 static void exynos_gpio_pin_write(void *, int, int);
139 static void exynos_gpio_pin_ctl(void *, int, int);
140 static void *exynos_gpio_fdt_acquire(device_t, const void *,
141 size_t, int);
142 static void exynos_gpio_fdt_release(device_t, void *);
143
144 static int exynos_gpio_fdt_read(device_t, void *, bool);
145 static void exynos_gpio_fdt_write(device_t, void *, int, bool);
146 static int exynos_gpio_cfprint(void *, const char *);
147
148 struct fdtbus_gpio_controller_func exynos_gpio_funcs = {
149 .acquire = exynos_gpio_fdt_acquire,
150 .release = exynos_gpio_fdt_release,
151 .read = exynos_gpio_fdt_read,
152 .write = exynos_gpio_fdt_write
153 };
154 #define GPIO_WRITE(bank, reg, val) \
155 bus_space_write_4((bank)->bank_sc->sc_bst, \
156 (bank)->bank_sc->sc_bsh, \
157 (bank)->bank_core_offset + (reg), (val))
158 #define GPIO_READ(bank, reg) \
159 bus_space_read_4((bank)->bank_sc->sc_bst, \
160 (bank)->bank_sc->sc_bsh, \
161 (bank)->bank_core_offset + (reg))
162
163 static int
164 exynos_gpio_cfprint(void *priv, const char *pnp)
165 {
166 struct gpiobus_attach_args *gba = priv;
167 struct exynos_gpio_bank *bank = gba->gba_gc->gp_cookie;
168 const char *bankname = bank->bank_name;
169
170 if (pnp)
171 aprint_normal("gpiobus at %s", pnp);
172
173 aprint_normal(" (%s)", bankname);
174
175 return UNCONF;
176 }
177
178 static int
179 exynos_gpio_pin_read(void *cookie, int pin)
180 {
181 struct exynos_gpio_bank * const bank = cookie;
182
183 KASSERT(pin < bank->bank_bits);
184 return (bus_space_read_1(bank->bank_sc->sc_bst,
185 bank->bank_sc->sc_bsh,
186 EXYNOS_GPIO_DAT) >> pin) & 1;
187 }
188
189 static void
190 exynos_gpio_pin_write(void *cookie, int pin, int value)
191 {
192 struct exynos_gpio_bank * const bank = cookie;
193 int val;
194
195 KASSERT(pin < bank->bank_bits);
196 val = bus_space_read_1(bank->bank_sc->sc_bst,
197 bank->bank_sc->sc_bsh,
198 EXYNOS_GPIO_DAT);
199 val &= ~__BIT(pin);
200 if (value)
201 val |= __BIT(pin);
202 bus_space_write_1(bank->bank_sc->sc_bst,
203 bank->bank_sc->sc_bsh,
204 EXYNOS_GPIO_DAT, val);
205 }
206
207 static void
208 exynos_gpio_pin_ctl(void *cookie, int pin, int flags)
209 {
210 struct exynos_gpio_bank * const bank = cookie;
211 struct exynos_gpio_pin_cfg ncfg = { 0 };
212
213 /* honour pullup requests */
214 if (flags & GPIO_PIN_PULLUP) {
215 ncfg.pud = EXYNOS_GPIO_PIN_PULL_UP;
216 ncfg.pud_valid = true;
217 }
218 if (flags & GPIO_PIN_PULLDOWN) {
219 ncfg.pud = EXYNOS_GPIO_PIN_PULL_DOWN;
220 ncfg.pud_valid = true;
221 }
222
223 /* honour i/o */
224 if (flags & GPIO_PIN_INPUT) {
225 ncfg.cfg = EXYNOS_GPIO_FUNC_INPUT;
226 ncfg.cfg_valid = true;
227 } else if (flags & GPIO_PIN_OUTPUT) {
228 ncfg.cfg = EXYNOS_GPIO_FUNC_OUTPUT;
229 ncfg.cfg_valid = true;
230 }
231
232 /* update any config registers that changed */
233 exynos_gpio_pin_ctl_write(bank, &ncfg, pin);
234 }
235
236 void exynos_gpio_pin_ctl_write(const struct exynos_gpio_bank *bank,
237 const struct exynos_gpio_pin_cfg *cfg,
238 int pin)
239 {
240 uint32_t val;
241
242 if (cfg->cfg_valid) {
243 val = GPIO_READ(bank, EXYNOS_GPIO_CON);
244 val &= ~(0xf << (pin * 4));
245 val |= (cfg->cfg << (pin * 4));
246 GPIO_WRITE(bank, EXYNOS_GPIO_CON, val);
247 }
248
249 if (cfg->pud_valid) {
250 val = GPIO_READ(bank, EXYNOS_GPIO_PUD);
251 val &= ~(0x3 << (pin * 2));
252 val |= (cfg->pud << (pin * 2));
253 GPIO_WRITE(bank, EXYNOS_GPIO_PUD, val);
254 }
255
256 if (cfg->drv_valid) {
257 val = GPIO_READ(bank, EXYNOS_GPIO_DRV);
258 val &= ~(0x3 << (pin * 2));
259 val |= (cfg->drv << (pin * 2));
260 GPIO_WRITE(bank, EXYNOS_GPIO_DRV, val);
261 }
262
263 if (cfg->conpwd_valid) {
264 val = GPIO_READ(bank, EXYNOS_GPIO_CONPWD);
265 val &= ~(0x3 << (pin * 2));
266 val |= (cfg->conpwd << (pin * 2));
267 GPIO_WRITE(bank, EXYNOS_GPIO_CONPWD, val);
268 }
269
270 if (cfg->pudpwd_valid) {
271 val = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD);
272 val &= ~(0x3 << (pin * 2));
273 val |= (cfg->pudpwd << (pin * 2));
274 GPIO_WRITE(bank, EXYNOS_GPIO_PUDPWD, val);
275 }
276 }
277
278 struct exynos_gpio_softc *
279 exynos_gpio_bank_config(struct exynos_pinctrl_softc * parent,
280 const struct fdt_attach_args *faa, int node)
281 {
282 struct exynos_gpio_bank *bank = kmem_zalloc(sizeof(*bank), KM_SLEEP);
283 struct exynos_gpio_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
284 struct gpiobus_attach_args gba;
285 struct gpio_chipset_tag *gc_tag;
286 char result[64];
287
288 OF_getprop(node, "name", result, sizeof(result));
289 bank = exynos_gpio_bank_lookup(result);
290 if (bank == NULL) {
291 aprint_error_dev(parent->sc_dev, "no bank found for %s\n",
292 result);
293 return NULL;
294 }
295
296 sc->sc_dev = parent->sc_dev;
297 sc->sc_bst = &armv7_generic_bs_tag;
298 sc->sc_bsh = parent->sc_bsh;
299 sc->sc_bank = bank;
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, node,
326 &exynos_gpio_funcs);
327 return sc;
328 }
329
330 /*
331 * This function is a bit funky. Given a string that may look like
332 * 'gpAN' or 'gpAN-P' it is meant to find a match to the part before
333 * the '-', or the four character string if the dash is not present.
334 */
335 struct exynos_gpio_bank *
336 exynos_gpio_bank_lookup(const char *name)
337 {
338 struct exynos_gpio_bank *bank;
339
340 for (u_int n = 0; n < __arraycount(exynos5_banks); n++) {
341 bank = &exynos_gpio_banks[n];
342 if (!strncmp(bank->bank_name, name,
343 strlen(bank->bank_name))) {
344 return bank;
345 }
346 }
347
348 return NULL;
349 }
350
351 #if notyet
352 static int
353 exynos_gpio_pin_lookup(const char *name)
354 {
355 char *p;
356
357 p = strchr(name, '-');
358 if (p == NULL || p[1] < '0' || p[1] > '9')
359 return -1;
360
361 return p[1] - '0';
362 }
363 #endif
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 struct exynos_gpio_bank *bank = NULL;
370 struct exynos_gpio_pin *gpin;
371 int n;
372
373 if (len != 12)
374 return NULL;
375
376 const int pin = be32toh(cells[1]) & 0x0f;
377 const int actlo = be32toh(cells[2]) & 0x01;
378
379 for (n = 0; n < __arraycount(exynos5_banks); n++) {
380 if (exynos_gpio_banks[n].bank_dev == dev) {
381 bank = &exynos_gpio_banks[n];
382 break;
383 }
384 }
385 if (bank == NULL)
386 return NULL;
387
388 gpin = kmem_alloc(sizeof(*gpin), KM_SLEEP);
389 gpin->pin_sc = bank->bank_sc;
390 gpin->pin_bank = bank;
391 gpin->pin_no = pin;
392 gpin->pin_flags = flags;
393 gpin->pin_actlo = actlo;
394
395 exynos_gpio_pin_ctl(bank, gpin->pin_no, gpin->pin_flags);
396
397 return gpin;
398 }
399
400 static void
401 exynos_gpio_fdt_release(device_t dev, void *priv)
402 {
403 struct exynos_gpio_pin *gpin = priv;
404
405 kmem_free(gpin, sizeof(*gpin));
406 }
407
408 static int
409 exynos_gpio_fdt_read(device_t dev, void *priv, bool raw)
410 {
411 struct exynos_gpio_pin *gpin = priv;
412 int val;
413
414 val = (bus_space_read_1(gpin->pin_sc->sc_bst,
415 gpin->pin_sc->sc_bsh,
416 EXYNOS_GPIO_DAT) >> gpin->pin_no) & 1;
417
418 if (!raw && gpin->pin_actlo)
419 val = !val;
420
421 return val;
422 }
423
424 static void
425 exynos_gpio_fdt_write(device_t dev, void *priv, int val, bool raw)
426 {
427 struct exynos_gpio_pin *gpin = priv;
428
429 if (!raw && gpin->pin_actlo)
430 val = !val;
431
432 val = bus_space_read_1(gpin->pin_sc->sc_bst,
433 gpin->pin_sc->sc_bsh,
434 EXYNOS_GPIO_DAT);
435 val &= ~__BIT(gpin->pin_no);
436 if (val)
437 val |= __BIT(gpin->pin_no);
438 bus_space_write_1(gpin->pin_sc->sc_bst,
439 gpin->pin_sc->sc_bsh,
440 EXYNOS_GPIO_DAT, val);
441
442 }
443