xref: /openbsd/sys/dev/fdt/amlpinctrl.c (revision 4cfece93)
1 /*	$OpenBSD: amlpinctrl.c,v 1.5 2019/10/06 16:17:06 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2019 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22 
23 #include <machine/bus.h>
24 #include <machine/fdt.h>
25 
26 #include <dev/ofw/openfirm.h>
27 #include <dev/ofw/ofw_gpio.h>
28 #include <dev/ofw/ofw_pinctrl.h>
29 #include <dev/ofw/fdt.h>
30 
31 #define BIAS_DISABLE	0x00
32 #define BIAS_PULL_UP	0x01
33 #define BIAS_PULL_DOWN	0x02
34 
35 #define GPIOZ_0		0
36 #define GPIOZ_1		1
37 #define GPIOZ_7		7
38 #define GPIOZ_8		8
39 #define GPIOZ_14	14
40 #define GPIOZ_15	15
41 #define GPIOH_0		16
42 #define GPIOH_1		17
43 #define GPIOH_2		18
44 #define GPIOH_3		19
45 #define GPIOH_6		22
46 #define GPIOH_7		23
47 #define BOOT_0		25
48 #define BOOT_1		26
49 #define BOOT_2		27
50 #define BOOT_3		28
51 #define BOOT_4		29
52 #define BOOT_5		30
53 #define BOOT_6		31
54 #define BOOT_7		32
55 #define BOOT_8		33
56 #define BOOT_10		35
57 #define BOOT_13		38
58 #define GPIOC_0		41
59 #define GPIOC_1		42
60 #define GPIOC_2		43
61 #define GPIOC_3		44
62 #define GPIOC_4		45
63 #define GPIOC_5		46
64 #define GPIOC_6		47
65 #define GPIOA_0		49
66 #define GPIOA_14	63
67 #define GPIOA_15	64
68 #define GPIOX_0		65
69 #define GPIOX_10	75
70 #define GPIOX_11	76
71 #define GPIOX_17	82
72 #define GPIOX_18	83
73 
74 #define PERIPHS_PIN_MUX_0		0xb0
75 #define PERIPHS_PIN_MUX_3		0xb3
76 #define PERIPHS_PIN_MUX_6		0xb6
77 #define PERIPHS_PIN_MUX_9		0xb9
78 #define PERIPHS_PIN_MUX_B		0xbb
79 #define PERIPHS_PIN_MUX_D		0xbd
80 #define PREG_PAD_GPIO0_EN_N		0x10
81 #define PREG_PAD_GPIO1_EN_N		0x13
82 #define PREG_PAD_GPIO2_EN_N		0x16
83 #define PREG_PAD_GPIO3_EN_N		0x19
84 #define PREG_PAD_GPIO4_EN_N		0x1c
85 #define PREG_PAD_GPIO5_EN_N		0x20
86 #define PAD_PULL_UP_EN_0		0x48
87 #define PAD_PULL_UP_EN_1		0x49
88 #define PAD_PULL_UP_EN_2		0x4a
89 #define PAD_PULL_UP_EN_3		0x4b
90 #define PAD_PULL_UP_EN_4		0x4c
91 #define PAD_PULL_UP_EN_5		0x4d
92 #define PAD_PULL_UP_0			0x3a
93 #define PAD_PULL_UP_1			0x3b
94 #define PAD_PULL_UP_2			0x3c
95 #define PAD_PULL_UP_3			0x3d
96 #define PAD_PULL_UP_4			0x3e
97 #define PAD_PULL_UP_5			0x3f
98 #define PAD_DS_0A			0xd0
99 #define PAD_DS_1A			0xd1
100 #define PAD_DS_2A			0xd2
101 #define PAD_DS_3A			0xd4
102 #define PAD_DS_4A			0xd5
103 #define PAD_DS_5A			0xd6
104 
105 struct aml_gpio_bank {
106 	uint8_t first_pin, num_pins;
107 	uint8_t mux_reg;
108 	uint8_t gpio_reg;
109 	uint8_t pull_reg;
110 	uint8_t pull_en_reg;
111 	uint8_t ds_reg;
112 };
113 
114 struct aml_pin_group {
115 	const char *name;
116 	uint8_t	pin;
117 	uint8_t func;
118 	const char *function;
119 };
120 
121 struct aml_gpio_bank aml_g12a_gpio_banks[] = {
122 	/* BOOT */
123 	{ BOOT_0, 16, PERIPHS_PIN_MUX_0 - PERIPHS_PIN_MUX_0,
124 	  PREG_PAD_GPIO0_EN_N - PREG_PAD_GPIO0_EN_N,
125 	  PAD_PULL_UP_0 - PAD_PULL_UP_0,
126 	  PAD_PULL_UP_EN_0 - PAD_PULL_UP_EN_0, PAD_DS_0A - PAD_DS_0A },
127 
128 	/* GPIOC */
129 	{ GPIOC_0, 8, PERIPHS_PIN_MUX_9 - PERIPHS_PIN_MUX_0,
130 	  PREG_PAD_GPIO1_EN_N - PREG_PAD_GPIO0_EN_N,
131 	  PAD_PULL_UP_1 - PAD_PULL_UP_0,
132 	  PAD_PULL_UP_EN_1 - PAD_PULL_UP_EN_0, PAD_DS_1A - PAD_DS_0A },
133 
134 	/* GPIOX */
135 	{ GPIOX_0, 20, PERIPHS_PIN_MUX_3 - PERIPHS_PIN_MUX_0,
136 	  PREG_PAD_GPIO2_EN_N - PREG_PAD_GPIO0_EN_N,
137 	  PAD_PULL_UP_2 - PAD_PULL_UP_0,
138 	  PAD_PULL_UP_EN_2 - PAD_PULL_UP_EN_0, PAD_DS_2A - PAD_DS_0A },
139 
140 	/* GPIOH */
141 	{ GPIOH_0, 9, PERIPHS_PIN_MUX_B - PERIPHS_PIN_MUX_0,
142 	  PREG_PAD_GPIO3_EN_N - PREG_PAD_GPIO0_EN_N,
143 	  PAD_PULL_UP_3 - PAD_PULL_UP_0,
144 	  PAD_PULL_UP_EN_3 - PAD_PULL_UP_EN_0, PAD_DS_3A - PAD_DS_0A },
145 
146 	/* GPIOZ */
147 	{ GPIOZ_0, 16, PERIPHS_PIN_MUX_6 - PERIPHS_PIN_MUX_0,
148 	  PREG_PAD_GPIO4_EN_N - PREG_PAD_GPIO0_EN_N,
149 	  PAD_PULL_UP_4 - PAD_PULL_UP_0,
150 	  PAD_PULL_UP_EN_4 - PAD_PULL_UP_EN_0, PAD_DS_4A - PAD_DS_0A },
151 
152 	/* GPIOA */
153 	{ GPIOA_0, 16, PERIPHS_PIN_MUX_D - PERIPHS_PIN_MUX_0,
154 	  PREG_PAD_GPIO5_EN_N - PREG_PAD_GPIO0_EN_N,
155 	  PAD_PULL_UP_5 - PAD_PULL_UP_0,
156 	  PAD_PULL_UP_EN_5 - PAD_PULL_UP_EN_0, PAD_DS_5A - PAD_DS_0A },
157 
158 	{ }
159 };
160 
161 struct aml_pin_group aml_g12a_pin_groups[] = {
162 	/* GPIOZ */
163 	{ "i2c0_sda_z0", GPIOZ_0, 4, "i2c0" },
164 	{ "i2c0_sck_z1", GPIOZ_1, 4, "i2c0" },
165 	{ "i2c0_sda_z7", GPIOZ_7, 7, "i2c0" },
166 	{ "i2c0_sck_z8", GPIOZ_8, 7, "i2c0" },
167 	{ "i2c2_sda_z", GPIOZ_14, 3, "i2c2" },
168 	{ "i2c2_sck_z", GPIOZ_15, 3, "i2c2" },
169 
170 	/* GPIOA */
171 	{ "i2c3_sda_a", GPIOA_14, 2, "i2c3" },
172 	{ "i2c3_sck_a", GPIOA_15, 2, "i2c3" },
173 
174 	/* BOOT */
175 	{ "emmc_nand_d0", BOOT_0, 1, "emmc" },
176 	{ "emmc_nand_d1", BOOT_1, 1, "emmc" },
177 	{ "emmc_nand_d2", BOOT_2, 1, "emmc" },
178 	{ "emmc_nand_d3", BOOT_3, 1, "emmc" },
179 	{ "emmc_nand_d4", BOOT_4, 1, "emmc" },
180 	{ "emmc_nand_d5", BOOT_5, 1, "emmc" },
181 	{ "emmc_nand_d6", BOOT_6, 1, "emmc" },
182 	{ "emmc_nand_d7", BOOT_7, 1, "emmc" },
183 	{ "BOOT_8", BOOT_8, 0, "gpio_periphs" },
184 	{ "emmc_clk", BOOT_8, 1, "emmc" },
185 	{ "emmc_cmd", BOOT_10, 1, "emmc" },
186 	{ "emmc_nand_ds", BOOT_13, 1, "emmc" },
187 
188 	/* GPIOC */
189 	{ "sdcard_d0_c", GPIOC_0, 1, "sdcard" },
190 	{ "sdcard_d1_c", GPIOC_1, 1, "sdcard" },
191 	{ "sdcard_d2_c", GPIOC_2, 1, "sdcard" },
192 	{ "sdcard_d3_c", GPIOC_3, 1, "sdcard" },
193 	{ "GPIOC_4", GPIOC_4, 0, "gpio_periphs" },
194 	{ "sdcard_clk_c", GPIOC_4, 1, "sdcard" },
195 	{ "sdcard_cmd_c", GPIOC_5, 1, "sdcard" },
196 	{ "i2c0_sda_c", GPIOC_5, 3, "i2c0" },
197 	{ "i2c0_sck_c", GPIOC_6, 3, "i2c0" },
198 
199 	/* GPIOX */
200 	{ "i2c1_sda_x", GPIOX_10, 5, "i2c1" },
201 	{ "i2c1_sck_x", GPIOX_11, 5, "i2c1" },
202 	{ "i2c2_sda_x", GPIOX_17, 1, "i2c2" },
203 	{ "i2c2_sck_x", GPIOX_18, 1, "i2c2" },
204 
205 	/* GPIOH */
206 	{ "i2c3_sda_h", GPIOH_0, 2, "i2c3" },
207 	{ "i2c3_sck_h", GPIOH_1, 2, "i2c3" },
208 	{ "i2c1_sda_h2", GPIOH_2, 2, "i2c1" },
209 	{ "i2c1_sck_h3", GPIOH_3, 2, "i2c1" },
210 	{ "i2c1_sda_h6", GPIOH_6, 4, "i2c1" },
211 	{ "i2c1_sck_h7", GPIOH_7, 4, "i2c1" },
212 
213 	{ }
214 };
215 
216 struct amlpinctrl_softc {
217 	struct device		sc_dev;
218 	bus_space_tag_t		sc_iot;
219 	bus_space_handle_t	sc_gpio_ioh;
220 	bus_space_handle_t	sc_pull_ioh;
221 	bus_space_handle_t	sc_pull_en_ioh;
222 	bus_space_handle_t	sc_mux_ioh;
223 	bus_space_handle_t	sc_ds_ioh;
224 
225 	struct aml_gpio_bank	*sc_gpio_banks;
226 	struct aml_pin_group	*sc_pin_groups;
227 
228 	struct gpio_controller	sc_gc;
229 };
230 
231 int	amlpinctrl_match(struct device *, void *, void *);
232 void	amlpinctrl_attach(struct device *, struct device *, void *);
233 
234 struct cfattach amlpinctrl_ca = {
235 	sizeof(struct amlpinctrl_softc), amlpinctrl_match, amlpinctrl_attach
236 };
237 
238 struct cfdriver amlpinctrl_cd = {
239 	NULL, "amlpinctrl", DV_DULL
240 };
241 
242 int	amlpinctrl_pinctrl(uint32_t, void *);
243 void	amlpinctrl_config_pin(void *, uint32_t *, int);
244 int	amlpinctrl_get_pin(void *, uint32_t *);
245 void	amlpinctrl_set_pin(void *, uint32_t *, int);
246 
247 int
248 amlpinctrl_match(struct device *parent, void *match, void *aux)
249 {
250 	struct fdt_attach_args *faa = aux;
251 	int node = faa->fa_node;
252 
253 	return OF_is_compatible(node, "amlogic,meson-g12a-periphs-pinctrl");
254 }
255 
256 void
257 amlpinctrl_attach(struct device *parent, struct device *self, void *aux)
258 {
259 	struct amlpinctrl_softc *sc = (struct amlpinctrl_softc *)self;
260 	struct fdt_attach_args *faa = aux;
261 	uint64_t addr[5], size[5];
262 	uint32_t *cell;
263 	uint32_t acells, scells;
264 	uint32_t reg[20];
265 	int node = faa->fa_node;
266 	int child;
267 	int i, len, line;
268 
269 	for (child = OF_child(node); child; child = OF_peer(child)) {
270 		if (OF_getproplen(child, "gpio-controller") == 0)
271 			break;
272 	}
273 	if (child == 0) {
274 		printf(": no register banks\n");
275 		return;
276 	}
277 
278 	acells = OF_getpropint(node, "#address-cells", faa->fa_acells);
279 	scells = OF_getpropint(node, "#size-cells", faa->fa_scells);
280 	len = OF_getproplen(child, "reg");
281 	line = (acells + scells) * sizeof(uint32_t);
282 	if (acells < 1 || acells > 2 || scells < 1 || scells > 2 ||
283 	    len > sizeof(reg) || (len / line) > nitems(addr)) {
284 		printf(": unexpected register layout\n");
285 		return;
286 	}
287 
288 	OF_getpropintarray(child, "reg", reg, len);
289 	for (i = 0, cell = reg; i < len / line; i++) {
290 		addr[i] = cell[0];
291 		if (acells > 1)
292 			addr[i] = (addr[i] << 32) | cell[1];
293 		cell += acells;
294 		size[i] = cell[0];
295 		if (scells > 1)
296 			size[i] = (size[i] << 32) | cell[1];
297 		cell += scells;
298 	}
299 
300 	sc->sc_iot = faa->fa_iot;
301 	if (bus_space_map(sc->sc_iot, addr[0], size[0], 0, &sc->sc_gpio_ioh)) {
302 		printf(": can't map gpio registers\n");
303 		return;
304 	}
305 	if (bus_space_map(sc->sc_iot, addr[1], size[1], 0, &sc->sc_pull_ioh)) {
306 		printf(": can't map pull registers\n");
307 		return;
308 	}
309 	if (bus_space_map(sc->sc_iot, addr[2], size[2], 0, &sc->sc_pull_en_ioh)) {
310 		printf(": can't map pull-enable registers\n");
311 		return;
312 	}
313 	if (bus_space_map(sc->sc_iot, addr[3], size[3], 0, &sc->sc_mux_ioh)) {
314 		printf(": can't map mux registers\n");
315 		return;
316 	}
317 	if (bus_space_map(sc->sc_iot, addr[4], size[4], 0, &sc->sc_ds_ioh)) {
318 		printf(": can't map ds registers\n");
319 		return;
320 	}
321 
322 	printf("\n");
323 
324 	sc->sc_gpio_banks = aml_g12a_gpio_banks;
325 	sc->sc_pin_groups = aml_g12a_pin_groups;
326 
327 	pinctrl_register(faa->fa_node, amlpinctrl_pinctrl, sc);
328 
329 	sc->sc_gc.gc_node = child;
330 	sc->sc_gc.gc_cookie = sc;
331 	sc->sc_gc.gc_config_pin = amlpinctrl_config_pin;
332 	sc->sc_gc.gc_get_pin = amlpinctrl_get_pin;
333 	sc->sc_gc.gc_set_pin = amlpinctrl_set_pin;
334 	gpio_controller_register(&sc->sc_gc);
335 }
336 
337 struct aml_gpio_bank *
338 amlpinctrl_lookup_bank(struct amlpinctrl_softc *sc, uint32_t pin)
339 {
340 	struct aml_gpio_bank *bank;
341 
342 	for (bank = sc->sc_gpio_banks; bank->num_pins > 0; bank++) {
343 		if (pin >= bank->first_pin &&
344 		    pin < bank->first_pin + bank->num_pins)
345 			return bank;
346 	}
347 
348 	return NULL;
349 }
350 
351 struct aml_pin_group *
352 amlpinctrl_lookup_group(struct amlpinctrl_softc *sc, const char *name)
353 {
354 	struct aml_pin_group *group;
355 
356 	for (group = sc->sc_pin_groups; group->name; group++) {
357 		if (strcmp(name, group->name) == 0)
358 			return group;
359 	}
360 
361 	return NULL;
362 }
363 
364 void
365 amlpinctrl_config_func(struct amlpinctrl_softc *sc, const char *name,
366     const char *function, int bias, int ds)
367 {
368 	struct aml_pin_group *group;
369 	struct aml_gpio_bank *bank;
370 	bus_addr_t off;
371 	uint32_t pin;
372 	uint32_t reg;
373 
374 	group = amlpinctrl_lookup_group(sc, name);
375 	if (group == NULL) {
376 		printf("%s: %s\n", __func__, name);
377 		return;
378 	}
379 	if (strcmp(function, group->function) != 0) {
380 		printf("%s: mismatched function %s\n", __func__, function);
381 		return;
382 	}
383 
384 	bank = amlpinctrl_lookup_bank(sc, group->pin);
385 	KASSERT(bank);
386 
387 	pin = group->pin - bank->first_pin;
388 
389 	/* mux */
390 	off = (bank->mux_reg + pin / 8) << 2;
391 	reg = bus_space_read_4(sc->sc_iot, sc->sc_mux_ioh, off);
392 	reg &= ~(0xf << ((pin % 8) * 4));
393 	reg |= (group->func << ((pin % 8) * 4));
394 	bus_space_write_4(sc->sc_iot, sc->sc_mux_ioh, off, reg);
395 
396 	/* pull */
397 	off = bank->pull_reg << 2;
398 	reg = bus_space_read_4(sc->sc_iot, sc->sc_pull_ioh, off);
399 	if (bias == BIAS_PULL_UP)
400 		reg |= (1 << pin);
401 	else
402 		reg &= ~(1 << pin);
403 	bus_space_write_4(sc->sc_iot, sc->sc_pull_ioh, off, reg);
404 
405 	/* pull-enable */
406 	off = bank->pull_en_reg << 2;
407 	reg = bus_space_read_4(sc->sc_iot, sc->sc_pull_en_ioh, off);
408 	if (bias != BIAS_DISABLE)
409 		reg |= (1 << pin);
410 	else
411 		reg &= ~(1 << pin);
412 	bus_space_write_4(sc->sc_iot, sc->sc_pull_en_ioh, off, reg);
413 
414 	if (ds < 0)
415 		return;
416 	else if (ds <= 500)
417 		ds = 0;
418 	else if (ds <= 2500)
419 		ds = 1;
420 	else if (ds <= 3000)
421 		ds = 2;
422 	else if (ds <= 4000)
423 		ds = 3;
424 	else {
425 		printf("%s: invalid drive-strength %d\n", __func__, ds);
426 		ds = 3;
427 	}
428 
429 	/* ds */
430 	off = (bank->ds_reg + pin / 16) << 2;
431 	reg = bus_space_read_4(sc->sc_iot, sc->sc_ds_ioh, off);
432 	reg &= ~(0x3 << ((pin % 16) * 2));
433 	reg |= (ds << ((pin % 16) * 2));
434 	bus_space_write_4(sc->sc_iot, sc->sc_ds_ioh, off, reg);
435 }
436 
437 int
438 amlpinctrl_pinctrl(uint32_t phandle, void *cookie)
439 {
440 	struct amlpinctrl_softc *sc = cookie;
441 	int node, child;
442 
443 	node = OF_getnodebyphandle(phandle);
444 	if (node == 0)
445 		return -1;
446 
447 	for (child = OF_child(node); child; child = OF_peer(child)) {
448 		char function[16];
449 		char *groups;
450 		char *group;
451 		int bias, ds;
452 		int len;
453 
454 		memset(function, 0, sizeof(function));
455 		OF_getprop(child, "function", function, sizeof(function));
456 		function[sizeof(function) - 1] = 0;
457 
458 		/* Bias */
459 		if (OF_getproplen(child, "bias-pull-up") == 0)
460 			bias = BIAS_PULL_UP;
461 		else if (OF_getproplen(child, "bias-pull-down") == 0)
462 			bias = BIAS_PULL_DOWN;
463 		else
464 			bias = BIAS_DISABLE;
465 
466 		/* Drive-strength */
467 		ds = OF_getpropint(child, "drive-strength-microamp", -1);
468 
469 		len = OF_getproplen(child, "groups");
470 		if (len <= 0) {
471 			printf("%s: 0x%08x\n", __func__, phandle);
472 			continue;
473 		}
474 
475 		groups = malloc(len, M_TEMP, M_WAITOK);
476 		OF_getprop(child, "groups", groups, len);
477 
478 		group = groups;
479 		while (group < groups + len) {
480 			amlpinctrl_config_func(sc, group, function, bias, ds);
481 			group += strlen(group) + 1;
482 		}
483 
484 		free(groups, M_TEMP, len);
485 	}
486 
487 	return 0;
488 }
489 
490 void
491 amlpinctrl_config_pin(void *cookie, uint32_t *cells, int config)
492 {
493 	struct amlpinctrl_softc *sc = cookie;
494 	struct aml_gpio_bank *bank;
495 	bus_addr_t off;
496 	uint32_t pin = cells[0];
497 	uint32_t reg;
498 
499 	bank = amlpinctrl_lookup_bank(sc, pin);
500 	if (bank == NULL) {
501 		printf("%s: 0x%08x 0x%08x\n", __func__, cells[0], cells[1]);
502 		return;
503 	}
504 
505 	pin = pin - bank->first_pin;
506 
507 	/* mux */
508 	off = (bank->mux_reg + pin / 8) << 2;
509 	reg = bus_space_read_4(sc->sc_iot, sc->sc_mux_ioh, off);
510 	reg &= ~(0xf << ((pin % 8) * 4));
511 	bus_space_write_4(sc->sc_iot, sc->sc_mux_ioh, off, reg);
512 
513 	/* gpio */
514 	off = bank->gpio_reg << 2;
515 	reg = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh, off);
516 	if (config & GPIO_CONFIG_OUTPUT)
517 		reg &= ~(1 << pin);
518 	else
519 		reg |= (1 << pin);
520 	bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh, off, reg);
521 }
522 
523 int
524 amlpinctrl_get_pin(void *cookie, uint32_t *cells)
525 {
526 	struct amlpinctrl_softc *sc = cookie;
527 	struct aml_gpio_bank *bank;
528 	bus_addr_t off;
529 	uint32_t pin = cells[0];
530 	uint32_t flags = cells[1];
531 	uint32_t reg;
532 	int val;
533 
534 	bank = amlpinctrl_lookup_bank(sc, pin);
535 	if (bank == NULL) {
536 		printf("%s: 0x%08x 0x%08x\n", __func__, cells[0], cells[1]);
537 		return 0;
538 	}
539 
540 	pin = pin - bank->first_pin;
541 
542 	/* gpio */
543 	off = (bank->gpio_reg + 2) << 2;
544 	reg = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh, off);
545 	val = (reg >> pin) & 1;
546 	if (flags & GPIO_ACTIVE_LOW)
547 		val = !val;
548 
549 	return val;
550 }
551 
552 void
553 amlpinctrl_set_pin(void *cookie, uint32_t *cells, int val)
554 {
555 	struct amlpinctrl_softc *sc = cookie;
556 	struct aml_gpio_bank *bank;
557 	bus_addr_t off;
558 	uint32_t pin = cells[0];
559 	uint32_t flags = cells[1];
560 	int reg;
561 
562 	bank = amlpinctrl_lookup_bank(sc, pin);
563 	if (bank == NULL) {
564 		printf("%s: 0x%08x 0x%08x\n", __func__, cells[0], cells[1]);
565 		return;
566 	}
567 
568 	if (flags & GPIO_ACTIVE_LOW)
569 		val = !val;
570 
571 	pin = pin - bank->first_pin;
572 
573 	/* gpio */
574 	off = (bank->gpio_reg + 1) << 2;
575 	reg = bus_space_read_4(sc->sc_iot, sc->sc_gpio_ioh, off);
576 	if (val)
577 		reg |= (1 << pin);
578 	else
579 		reg &= ~(1 << pin);
580 	bus_space_write_4(sc->sc_iot, sc->sc_gpio_ioh, off, reg);
581 }
582