xref: /openbsd-src/sys/dev/ofw/ofw_gpio.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: ofw_gpio.c,v 1.2 2016/07/27 21:13:49 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2016 Mark Kettenis
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/types.h>
19 #include <sys/systm.h>
20 
21 #include <dev/ofw/openfirm.h>
22 #include <dev/ofw/ofw_gpio.h>
23 
24 LIST_HEAD(, gpio_controller) gpio_controllers =
25 	LIST_HEAD_INITIALIZER(gpio_controllers);
26 
27 void
28 gpio_controller_register(struct gpio_controller *gc)
29 {
30 	gc->gc_cells = OF_getpropint(gc->gc_node, "#gpio-cells", 2);
31 	gc->gc_phandle = OF_getpropint(gc->gc_node, "phandle", 0);
32 	if (gc->gc_phandle == 0)
33 		return;
34 
35 	LIST_INSERT_HEAD(&gpio_controllers, gc, gc_list);
36 }
37 
38 void
39 gpio_controller_config_pin(uint32_t *cells, int config)
40 {
41 	struct gpio_controller *gc;
42 	uint32_t phandle = cells[0];
43 
44 	LIST_FOREACH(gc, &gpio_controllers, gc_list) {
45 		if (gc->gc_phandle == phandle)
46 			break;
47 	}
48 
49 	if (gc && gc->gc_config_pin)
50 		gc->gc_config_pin(gc->gc_cookie, &cells[1], config);
51 }
52 
53 int
54 gpio_controller_get_pin(uint32_t *cells)
55 {
56 	struct gpio_controller *gc;
57 	uint32_t phandle = cells[0];
58 	int val = 0;
59 
60 	LIST_FOREACH(gc, &gpio_controllers, gc_list) {
61 		if (gc->gc_phandle == phandle)
62 			break;
63 	}
64 
65 	if (gc && gc->gc_get_pin)
66 		val = gc->gc_get_pin(gc->gc_cookie, &cells[1]);
67 
68 	return val;
69 }
70 
71 void
72 gpio_controller_set_pin(uint32_t *cells, int val)
73 {
74 	struct gpio_controller *gc;
75 	uint32_t phandle = cells[0];
76 
77 	LIST_FOREACH(gc, &gpio_controllers, gc_list) {
78 		if (gc->gc_phandle == phandle)
79 			break;
80 	}
81 
82 	if (gc && gc->gc_set_pin)
83 		gc->gc_set_pin(gc->gc_cookie, &cells[1], val);
84 }
85 
86 uint32_t *
87 gpio_controller_next_pin(uint32_t *cells)
88 {
89 	struct gpio_controller *gc;
90 	uint32_t phandle = cells[0];
91 
92 	LIST_FOREACH(gc, &gpio_controllers, gc_list)
93 		if (gc->gc_phandle == phandle)
94 			return cells + gc->gc_cells + 1;
95 
96 	return NULL;
97 }
98