xref: /openbsd-src/sys/dev/fdt/mvpinctrl.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /* $OpenBSD: mvpinctrl.c,v 1.1 2017/08/25 20:00:35 patrick Exp $ */
2 /*
3  * Copyright (c) 2013,2016 Patrick Wildt <patrick@blueri.se>
4  * Copyright (c) 2016 Mark Kettenis <kettenis@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/device.h>
22 #include <sys/malloc.h>
23 
24 #include <machine/intr.h>
25 #include <machine/bus.h>
26 #include <machine/fdt.h>
27 
28 #include <dev/ofw/openfirm.h>
29 #include <dev/ofw/ofw_pinctrl.h>
30 #include <dev/ofw/fdt.h>
31 
32 #define HREAD4(sc, reg)							\
33 	(bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
34 #define HWRITE4(sc, reg, val)						\
35 	bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
36 #define HSET4(sc, reg, bits)						\
37 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
38 #define HCLR4(sc, reg, bits)						\
39 	HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
40 
41 struct mvpinctrl_pin {
42 	char *pin;
43 	char *function;
44 	int value;
45 	int pid;
46 };
47 
48 struct mvpinctrl_softc {
49 	struct device		 sc_dev;
50 	bus_space_tag_t		 sc_iot;
51 	bus_space_handle_t	 sc_ioh;
52 	struct mvpinctrl_pin	*sc_pins;
53 	int			 sc_npins;
54 };
55 
56 int	mvpinctrl_match(struct device *, void *, void *);
57 void	mvpinctrl_attach(struct device *, struct device *, void *);
58 int	mvpinctrl_pinctrl(uint32_t, void *);
59 
60 struct cfattach mvpinctrl_ca = {
61 	sizeof (struct mvpinctrl_softc), mvpinctrl_match, mvpinctrl_attach
62 };
63 
64 struct cfdriver mvpinctrl_cd = {
65 	NULL, "mvpinctrl", DV_DULL
66 };
67 
68 #define STR_HELPER(x) #x
69 #define STR(x) STR_HELPER(x)
70 #define MPP(id, func, val) { STR(mpp ## id), func, val, id }
71 
72 struct mvpinctrl_pin mv88f6828_pins[] = {
73 	MPP(4,		"ge",		1),
74 	MPP(5,		"ge",		1),
75 	MPP(6,		"ge0",		1),
76 	MPP(7,		"ge0",		1),
77 	MPP(8,		"ge0",		1),
78 	MPP(9,		"ge0",		1),
79 	MPP(10,		"ge0",		1),
80 	MPP(11,		"ge0",		1),
81 	MPP(12,		"ge0",		1),
82 	MPP(13,		"ge0",		1),
83 	MPP(14,		"ge0",		1),
84 	MPP(15,		"ge0",		1),
85 	MPP(16,		"ge0",		1),
86 	MPP(17,		"ge0",		1),
87 	MPP(20,		"gpio",		0),
88 	MPP(21,		"sd0",		4),
89 	MPP(23,		"gpio",		0),
90 	MPP(28,		"sd0",		4),
91 	MPP(37,		"sd0",		4),
92 	MPP(38,		"sd0",		4),
93 	MPP(39,		"sd0",		4),
94 	MPP(40,		"sd0",		4),
95 	MPP(41,		"gpio",		0),
96 	MPP(45,		"ref",		1),
97 	MPP(46,		"ref",		1),
98 };
99 
100 int
101 mvpinctrl_match(struct device *parent, void *match, void *aux)
102 {
103 	struct fdt_attach_args *faa = aux;
104 
105 	return OF_is_compatible(faa->fa_node, "marvell,mv88f6828-pinctrl");
106 }
107 
108 void
109 mvpinctrl_attach(struct device *parent, struct device *self, void *aux)
110 {
111 	struct fdt_attach_args *faa = aux;
112 	struct mvpinctrl_softc *sc = (struct mvpinctrl_softc *) self;
113 
114 	sc->sc_iot = faa->fa_iot;
115 	if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
116 	    faa->fa_reg[0].size, 0, &sc->sc_ioh))
117 		panic("mvpinctrl_attach: bus_space_map failed!");
118 
119 	sc->sc_pins = mv88f6828_pins;
120 	sc->sc_npins = sizeof(mv88f6828_pins) / sizeof(struct mvpinctrl_pin);
121 	pinctrl_register(faa->fa_node, mvpinctrl_pinctrl, sc);
122 
123 	printf("\n");
124 }
125 
126 int
127 mvpinctrl_pinctrl(uint32_t phandle, void *cookie)
128 {
129 	struct mvpinctrl_softc *sc = cookie;
130 	char *pins, *pin, *func;
131 	int i, flen, plen, node;
132 
133 	node = OF_getnodebyphandle(phandle);
134 	if (node == 0)
135 		return -1;
136 
137 	flen = OF_getproplen(node, "marvell,function");
138 	if (flen <= 0)
139 		return -1;
140 
141 	func = malloc(flen, M_TEMP, M_WAITOK);
142 	OF_getprop(node, "marvell,function", func, flen);
143 
144 	plen = OF_getproplen(node, "marvell,pins");
145 	if (plen <= 0)
146 		return -1;
147 
148 	pin = pins = malloc(plen, M_TEMP, M_WAITOK);
149 	OF_getprop(node, "marvell,pins", pins, plen);
150 
151 	while (plen > 0) {
152 		int found = 0;
153 
154 		for (i = 0; i < sc->sc_npins; i++) {
155 			uint32_t off, shift;
156 
157 			if (strcmp(sc->sc_pins[i].pin, pin))
158 				continue;
159 			if (strcmp(sc->sc_pins[i].function, func))
160 				continue;
161 
162 			found++;
163 
164 			off = (sc->sc_pins[i].pid / 8) * sizeof(uint32_t);
165 			shift = (sc->sc_pins[i].pid % 8) * 4;
166 
167 			HWRITE4(sc, off, (HREAD4(sc, off) & ~(0xf << shift)) |
168 			    (sc->sc_pins[i].value << shift));
169 		}
170 
171 		if (found == 0)
172 			printf("%s: unsupported pin %s function %s\n",
173 			    sc->sc_dev.dv_xname, pin, func);
174 
175 		plen -= strlen(pin) + 1;
176 		pin += strlen(pin) + 1;
177 	}
178 
179 	free(func, M_TEMP, flen);
180 	free(pins, M_TEMP, plen);
181 	return 0;
182 }
183