xref: /netbsd-src/sys/arch/arm/samsung/exynos_gpio.c (revision 7c192b2a5e1093666e67801684f930ef49b3b363)
1 /*	$NetBSD: exynos_gpio.c,v 1.23 2015/12/31 03:50:34 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.23 2015/12/31 03:50:34 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_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 void
179 exynos_gpio_update_cfg_regs(struct exynos_gpio_bank *bank,
180 	const struct exynos_gpio_pin_cfg *ncfg)
181 {
182 	if (bank->bank_cfg.cfg != ncfg->cfg) {
183 		GPIO_WRITE(bank, EXYNOS_GPIO_CON, ncfg->cfg);
184 		bank->bank_cfg.cfg = ncfg->cfg;
185 	}
186 	if (bank->bank_cfg.pud != ncfg->pud) {
187 		GPIO_WRITE(bank, EXYNOS_GPIO_PUD, ncfg->pud);
188 		bank->bank_cfg.pud = ncfg->pud;
189 	}
190 
191 	if (bank->bank_cfg.drv != ncfg->drv) {
192 		GPIO_WRITE(bank, EXYNOS_GPIO_DRV, ncfg->drv);
193 		bank->bank_cfg.drv = ncfg->drv;
194 	}
195 	if (bank->bank_cfg.conpwd != ncfg->conpwd) {
196 		GPIO_WRITE(bank, EXYNOS_GPIO_CONPWD, ncfg->conpwd);
197 		bank->bank_cfg.conpwd = ncfg->conpwd;
198 	}
199 	if (bank->bank_cfg.pudpwd != ncfg->pudpwd) {
200 		GPIO_WRITE(bank, EXYNOS_GPIO_PUDPWD, ncfg->pudpwd);
201 		bank->bank_cfg.pudpwd = ncfg->pudpwd;
202 	}
203 }
204 
205 static int
206 exynos_gpio_pin_read(void *cookie, int pin)
207 {
208 	struct exynos_gpio_bank * const bank = cookie;
209 
210 	KASSERT(pin < bank->bank_bits);
211 	return (bus_space_read_1(bank->bank_sc->sc_bst,
212 				 bank->bank_sc->sc_bsh,
213 		EXYNOS_GPIO_DAT) >> pin) & 1;
214 }
215 
216 static void
217 exynos_gpio_pin_write(void *cookie, int pin, int value)
218 {
219 	struct exynos_gpio_bank * const bank = cookie;
220 	int val;
221 
222 	KASSERT(pin < bank->bank_bits);
223 	val = bus_space_read_1(bank->bank_sc->sc_bst,
224 			       bank->bank_sc->sc_bsh,
225 			       EXYNOS_GPIO_DAT);
226 	val &= ~__BIT(pin);
227 	if (value)
228 		val |= __BIT(pin);
229 	bus_space_write_1(bank->bank_sc->sc_bst,
230 			  bank->bank_sc->sc_bsh,
231 		EXYNOS_GPIO_DAT, val);
232 }
233 
234 static void
235 exynos_gpio_pin_ctl(void *cookie, int pin, int flags)
236 {
237 	struct exynos_gpio_bank * const bank = cookie;
238 	struct exynos_gpio_pin_cfg ncfg = bank->bank_cfg;
239 	u_int shift;
240 	int pull;
241 
242 	/* honour pullup requests */
243 	pull = EXYNOS_GPIO_PIN_FLOAT;
244 	if (flags & GPIO_PIN_PULLUP)
245 		pull = EXYNOS_GPIO_PIN_PULL_UP;
246 	if (flags & GPIO_PIN_PULLDOWN)
247 		pull = EXYNOS_GPIO_PIN_PULL_DOWN;
248 	shift = (pin & 7) << 1;
249 	ncfg.pud &= ~(0x3 << shift);
250 	ncfg.pud |= pull << shift;
251 
252 	/* honour i/o */
253 	if (flags & GPIO_PIN_INPUT) {
254 		ncfg.cfg &= ~(0x0f << shift);
255 		ncfg.cfg |= EXYNOS_GPIO_FUNC_INPUT << shift;
256 	} else if (flags & GPIO_PIN_OUTPUT) {
257 		ncfg.cfg &= ~(0x0f << shift);
258 		ncfg.cfg |= EXYNOS_GPIO_FUNC_OUTPUT << shift;
259 	}
260 
261 	/* update any config registers that changed */
262 	exynos_gpio_update_cfg_regs(bank, &ncfg);
263 }
264 
265 void exynos_gpio_pin_ctl_read(const struct exynos_gpio_bank *bank,
266 			      struct exynos_gpio_pin_cfg *cfg)
267 {
268 	cfg->cfg = GPIO_READ(bank, EXYNOS_GPIO_CON);
269 	cfg->pud = GPIO_READ(bank, EXYNOS_GPIO_PUD);
270 	cfg->drv = GPIO_READ(bank, EXYNOS_GPIO_DRV);
271 	cfg->conpwd = GPIO_READ(bank, EXYNOS_GPIO_CONPWD);
272 	cfg->pudpwd = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD);
273 }
274 
275 void exynos_gpio_pin_ctl_write(const struct exynos_gpio_bank *bank,
276 			       const struct exynos_gpio_pin_cfg *cfg)
277 {
278 		GPIO_WRITE(bank, EXYNOS_GPIO_CON, cfg->cfg);
279 		GPIO_WRITE(bank, EXYNOS_GPIO_PUD, cfg->pud);
280 		GPIO_WRITE(bank, EXYNOS_GPIO_DRV, cfg->drv);
281 		GPIO_WRITE(bank, EXYNOS_GPIO_CONPWD, cfg->conpwd);
282 		GPIO_WRITE(bank, EXYNOS_GPIO_PUDPWD, cfg->pudpwd);
283 }
284 
285 struct exynos_gpio_softc *
286 exynos_gpio_bank_config(struct exynos_pinctrl_softc * parent,
287 			const struct fdt_attach_args *faa, int node)
288 {
289 	struct exynos_gpio_bank *bank = kmem_zalloc(sizeof(*bank), KM_SLEEP);
290 	struct exynos_gpio_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
291 	struct gpiobus_attach_args gba;
292 	struct gpio_chipset_tag *gc_tag;
293 	char result[64];
294 
295 	OF_getprop(node, "name", result, sizeof(result));
296 	bank = exynos_gpio_bank_lookup(result);
297 	if (bank == NULL) {
298 		aprint_error_dev(parent->sc_dev, "no bank found for %s\n",
299 		    result);
300 		return NULL;
301 	}
302 
303 	sc->sc_dev = parent->sc_dev;
304 	sc->sc_bst = &armv7_generic_bs_tag;
305 	sc->sc_bsh = parent->sc_bsh;
306 	sc->sc_bank = bank;
307 
308 	gc_tag = &bank->bank_gc;
309 	gc_tag->gp_cookie = bank;
310 	gc_tag->gp_pin_read  = exynos_gpio_pin_read;
311 	gc_tag->gp_pin_write = exynos_gpio_pin_write;
312 	gc_tag->gp_pin_ctl   = exynos_gpio_pin_ctl;
313 	memset(&gba, 0, sizeof(gba));
314 	gba.gba_gc = &bank->bank_gc;
315 	gba.gba_pins = bank->bank_pins;
316 	gba.gba_npins = bank->bank_bits;
317 	bank->bank_sc = sc;
318 	bank->bank_dev = config_found_ia(parent->sc_dev, "gpiobus", &gba,
319 					 exynos_gpio_cfprint);
320 
321 	bank->bank_pin_mask = __BIT(bank->bank_bits) - 1;
322 	bank->bank_pin_inuse_mask = 0;
323 
324 
325 	/* read in our initial settings */
326 	bank->bank_cfg.cfg = GPIO_READ(bank, EXYNOS_GPIO_CON);
327 	bank->bank_cfg.pud = GPIO_READ(bank, EXYNOS_GPIO_PUD);
328 	bank->bank_cfg.drv = GPIO_READ(bank, EXYNOS_GPIO_DRV);
329 	bank->bank_cfg.conpwd = GPIO_READ(bank, EXYNOS_GPIO_CONPWD);
330 	bank->bank_cfg.pudpwd = GPIO_READ(bank, EXYNOS_GPIO_PUDPWD);
331 
332 	fdtbus_register_gpio_controller(bank->bank_dev, node,
333 					&exynos_gpio_funcs);
334 	return sc;
335 }
336 
337 /*
338  * This function is a bit funky.  Given a string that may look like
339  * 'gpAN' or 'gpAN-P' it is meant to find a match to the part before
340  * the '-', or the four character string if the dash is not present.
341  */
342 struct exynos_gpio_bank *
343 exynos_gpio_bank_lookup(const char *name)
344 {
345 	struct exynos_gpio_bank *bank;
346 
347 	for (u_int n = 0; n < __arraycount(exynos5_banks); n++) {
348 		bank = &exynos_gpio_banks[n];
349 		if (!strncmp(bank->bank_name, name,
350 			     strlen(bank->bank_name))) {
351 			return bank;
352 		}
353 	}
354 
355 	return NULL;
356 }
357 
358 #if notyet
359 static int
360 exynos_gpio_pin_lookup(const char *name)
361 {
362 	char *p;
363 
364 	p = strchr(name, '-');
365 	if (p == NULL || p[1] < '0' || p[1] > '9')
366 		return -1;
367 
368 	return p[1] - '0';
369 }
370 #endif
371 
372 static void *
373 exynos_gpio_fdt_acquire(device_t dev, const void *data, size_t len, int flags)
374 {
375 	const u_int *cells = data;
376 	struct exynos_gpio_bank *bank = NULL;
377 	struct exynos_gpio_pin *gpin;
378 	int n;
379 
380 	if (len != 12)
381 		return NULL;
382 
383 	const int pin = be32toh(cells[1]) & 0x0f;
384 	const int actlo = be32toh(cells[2]) & 0x01;
385 
386 	for (n = 0; n < __arraycount(exynos5_banks); n++) {
387 		if (exynos_gpio_banks[n].bank_dev == dev) {
388 			bank = &exynos_gpio_banks[n];
389 			break;
390 		}
391 	}
392 	if (bank == NULL)
393 		return NULL;
394 
395 	gpin = kmem_alloc(sizeof(*gpin), KM_SLEEP);
396 	gpin->pin_sc = bank->bank_sc;
397 	gpin->pin_bank = bank;
398 	gpin->pin_no = pin;
399 	gpin->pin_flags = flags;
400 	gpin->pin_actlo = actlo;
401 
402 	exynos_gpio_pin_ctl(bank, gpin->pin_no, gpin->pin_flags);
403 
404 	return gpin;
405 }
406 
407 static void
408 exynos_gpio_fdt_release(device_t dev, void *priv)
409 {
410 	struct exynos_gpio_pin *gpin = priv;
411 
412 	kmem_free(gpin, sizeof(*gpin));
413 }
414 
415 static int
416 exynos_gpio_fdt_read(device_t dev, void *priv, bool raw)
417 {
418 	struct exynos_gpio_pin *gpin = priv;
419 	int val;
420 
421 	val = (bus_space_read_1(gpin->pin_sc->sc_bst,
422 				 gpin->pin_sc->sc_bsh,
423 				 EXYNOS_GPIO_DAT) >> gpin->pin_no) & 1;
424 
425 	if (!raw && gpin->pin_actlo)
426 		val = !val;
427 
428 	return val;
429 }
430 
431 static void
432 exynos_gpio_fdt_write(device_t dev, void *priv, int val, bool raw)
433 {
434 	struct exynos_gpio_pin *gpin = priv;
435 
436 	if (!raw && gpin->pin_actlo)
437 		val = !val;
438 
439 	val = bus_space_read_1(gpin->pin_sc->sc_bst,
440 			       gpin->pin_sc->sc_bsh,
441 			       EXYNOS_GPIO_DAT);
442 	val &= ~__BIT(gpin->pin_no);
443 	if (val)
444 		val |= __BIT(gpin->pin_no);
445 	bus_space_write_1(gpin->pin_sc->sc_bst,
446 			  gpin->pin_sc->sc_bsh,
447 			  EXYNOS_GPIO_DAT, val);
448 
449 }
450