1 /* $NetBSD: apple_pinctrl.c,v 1.1 2022/04/27 07:59:18 skrll Exp $ */
2 /* $OpenBSD: aplpinctrl.c,v 1.4 2022/04/06 18:59:26 naddy Exp $ */
3
4 /*-
5 * Copyright (c) 2022 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Nick Hudson
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
35 *
36 * Permission to use, copy, modify, and distribute this software for any
37 * purpose with or without fee is hereby granted, provided that the above
38 * copyright notice and this permission notice appear in all copies.
39 *
40 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
41 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
42 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
43 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
44 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
45 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
46 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
47 */
48
49 #include <sys/cdefs.h>
50 __KERNEL_RCSID(0, "$NetBSD: apple_pinctrl.c,v 1.1 2022/04/27 07:59:18 skrll Exp $");
51
52 #include <sys/param.h>
53 #include <sys/bus.h>
54 #include <sys/device.h>
55 #include <sys/kmem.h>
56
57 #include <dev/fdt/fdtvar.h>
58
59 #include <arm/pic/picvar.h>
60
61 #define APPLE_PIN(pinmux) __SHIFTOUT((pinmux), __BITS(15, 0))
62 #define APPLE_FUNC(pinmux) __SHIFTOUT((pinmux), __BITS(31, 16))
63
64 #define GPIO_PIN(pin) ((pin) * 4)
65 #define GPIO_PIN_GROUP_MASK __BITS(18, 16)
66 #define GPIO_PIN_INPUT_ENABLE __BIT(9)
67 #define GPIO_PIN_FUNC_MASK __BITS(6, 5)
68 #define GPIO_PIN_MODE_MASK __BITS(3, 1)
69 #define GPIO_PIN_MODE_INPUT __SHIFTIN(0, GPIO_PIN_MODE_MASK);
70 #define GPIO_PIN_MODE_OUTPUT __SHIFTIN(1, GPIO_PIN_MODE_MASK);
71 #define GPIO_PIN_MODE_IRQ_HI __SHIFTIN(2, GPIO_PIN_MODE_MASK);
72 #define GPIO_PIN_MODE_IRQ_LO __SHIFTIN(3, GPIO_PIN_MODE_MASK);
73 #define GPIO_PIN_MODE_IRQ_UP __SHIFTIN(4, GPIO_PIN_MODE_MASK);
74 #define GPIO_PIN_MODE_IRQ_DN __SHIFTIN(5, GPIO_PIN_MODE_MASK);
75 #define GPIO_PIN_MODE_IRQ_ANY __SHIFTIN(6, GPIO_PIN_MODE_MASK);
76 #define GPIO_PIN_MODE_IRQ_OFF __SHIFTIN(7, GPIO_PIN_MODE_MASK);
77 #define GPIO_PIN_DATA __BIT(0)
78 #define GPIO_IRQ(grp, pin) (0x800 + (grp) * 64 + ((pin) >> 5) * 4)
79
80 #define PINCTRL_READ(sc, reg) \
81 (bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)))
82 #define PINCTRL_WRITE(sc, reg, val) \
83 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
84 #define PINCTRL_SET(sc, reg, bits) \
85 PINCTRL_WRITE((sc), (reg), PINCTRL_READ((sc), (reg)) | (bits))
86 #define PINCTRL_CLR(sc, reg, bits) \
87 PINCTRL_WRITE((sc), (reg), PINCTRL_READ((sc), (reg)) & ~(bits))
88
89
90 struct apple_pinctrl_softc {
91 device_t sc_dev;
92 int sc_phandle;
93 bus_space_tag_t sc_bst;
94 bus_space_handle_t sc_bsh;
95 u_int sc_npins;
96 };
97
98 struct apple_gpio_pin {
99 int pin_no;
100 u_int pin_flags;
101 bool pin_actlo;
102 };
103
104 static const struct device_compatible_entry compat_data[] = {
105 { .compat = "apple,pinctrl" },
106 DEVICE_COMPAT_EOL
107 };
108
109 static void
apple_gpio_pin_ctl(void * cookie,int pin,int flags)110 apple_gpio_pin_ctl(void *cookie, int pin, int flags)
111 {
112 struct apple_pinctrl_softc * const sc = cookie;
113
114 KASSERT(pin < sc->sc_npins);
115
116 uint32_t reg = PINCTRL_READ(sc, GPIO_PIN(pin));
117 reg &= ~GPIO_PIN_FUNC_MASK;
118 reg &= ~GPIO_PIN_MODE_MASK;
119
120 if (flags & (GPIO_PIN_OUTPUT | GPIO_PIN_INPUT)) {
121 if (flags & GPIO_PIN_INPUT) {
122 /* for safety INPUT will override output */
123 reg |= GPIO_PIN_MODE_INPUT;
124 } else {
125 reg |= GPIO_PIN_MODE_OUTPUT;
126 }
127 }
128 PINCTRL_WRITE(sc, GPIO_PIN(pin), reg);
129 }
130
131 static void *
apple_pinctrl_gpio_acquire(device_t dev,const void * data,size_t len,int flags)132 apple_pinctrl_gpio_acquire(device_t dev, const void *data, size_t len, int flags)
133 {
134 struct apple_pinctrl_softc * const sc = device_private(dev);
135 struct apple_gpio_pin *pin;
136 const u_int *gpio = data;
137
138 if (len != 12)
139 return NULL;
140
141 const u_int pinno = be32toh(gpio[1]);
142 const bool actlo = be32toh(gpio[2]) & 1;
143
144 if (pinno >= sc->sc_npins)
145 return NULL;
146
147 pin = kmem_alloc(sizeof(*pin), KM_SLEEP);
148 pin->pin_no = pinno;
149 pin->pin_flags = flags;
150 pin->pin_actlo = actlo;
151
152 apple_gpio_pin_ctl(sc, pin->pin_no, pin->pin_flags);
153
154 return pin;
155 }
156
157 static void
apple_pinctrl_gpio_release(device_t dev,void * priv)158 apple_pinctrl_gpio_release(device_t dev, void *priv)
159 {
160 struct apple_pinctrl_softc * const sc = device_private(dev);
161 struct apple_gpio_pin *pin = priv;
162
163 apple_gpio_pin_ctl(sc, pin->pin_no, GPIO_PIN_INPUT);
164 kmem_free(pin, sizeof(*pin));
165 }
166
167 static int
apple_pinctrl_gpio_read(device_t dev,void * priv,bool raw)168 apple_pinctrl_gpio_read(device_t dev, void *priv, bool raw)
169 {
170 struct apple_pinctrl_softc * const sc = device_private(dev);
171 struct apple_gpio_pin *pin = priv;
172
173 KASSERT(pin->pin_no < sc->sc_npins);
174
175 uint32_t reg = PINCTRL_READ(sc, GPIO_PIN(pin->pin_no));
176 int val = __SHIFTOUT(reg, GPIO_PIN_DATA);
177 if (!raw && pin->pin_actlo)
178 val = !val;
179
180 return val;
181 }
182
183 static void
apple_pinctrl_gpio_write(device_t dev,void * priv,int val,bool raw)184 apple_pinctrl_gpio_write(device_t dev, void *priv, int val, bool raw)
185 {
186 struct apple_pinctrl_softc * const sc = device_private(dev);
187 struct apple_gpio_pin *pin = priv;
188
189 KASSERT(pin->pin_no < sc->sc_npins);
190
191 if (!raw && pin->pin_actlo)
192 val = !val;
193
194 if (val)
195 PINCTRL_SET(sc, GPIO_PIN(pin->pin_no), GPIO_PIN_DATA);
196 else
197 PINCTRL_CLR(sc, GPIO_PIN(pin->pin_no), GPIO_PIN_DATA);
198 }
199
200 static int
apple_pinctrl_set_config(device_t dev,const void * data,size_t len)201 apple_pinctrl_set_config(device_t dev, const void *data, size_t len)
202 {
203 struct apple_pinctrl_softc * const sc = device_private(dev);
204
205 if (len != 4)
206 return -1;
207
208 int pins_len;
209 const int phandle = fdtbus_get_phandle_from_native(be32dec(data));
210 const u_int *pins = fdtbus_get_prop(phandle, "pinmux", &pins_len);
211
212 if (pins == NULL)
213 return -1;
214
215 const u_int npins = pins_len / sizeof(uint32_t);
216
217 for (u_int i = 0; i < npins; i++) {
218 uint32_t pinmux = be32dec(&pins[i]);
219 u_int pinno = APPLE_PIN(pinmux);
220 u_int func = APPLE_FUNC(pinmux);
221
222 uint32_t reg = PINCTRL_READ(sc, GPIO_PIN(pinno));
223 reg &= ~GPIO_PIN_FUNC_MASK;
224 reg |= __SHIFTIN(func, GPIO_PIN_FUNC_MASK);
225
226 PINCTRL_WRITE(sc, GPIO_PIN(pinno), reg);
227 }
228
229 return 0;
230 }
231
232 static struct fdtbus_gpio_controller_func apple_pinctrl_gpio_funcs = {
233 .acquire = apple_pinctrl_gpio_acquire,
234 .release = apple_pinctrl_gpio_release,
235 .read = apple_pinctrl_gpio_read,
236 .write = apple_pinctrl_gpio_write
237 };
238
239 static struct fdtbus_pinctrl_controller_func apple_pinctrl_funcs = {
240 .set_config = apple_pinctrl_set_config,
241 };
242
243 static int
apple_pinctrl_match(device_t parent,cfdata_t cf,void * aux)244 apple_pinctrl_match(device_t parent, cfdata_t cf, void *aux)
245 {
246 struct fdt_attach_args * const faa = aux;
247
248 return of_compatible_match(faa->faa_phandle, compat_data);
249 }
250
251 static void
apple_pinctrl_attach(device_t parent,device_t self,void * aux)252 apple_pinctrl_attach(device_t parent, device_t self, void *aux)
253 {
254 struct apple_pinctrl_softc * const sc = device_private(self);
255 struct fdt_attach_args * const faa = aux;
256 const int phandle = faa->faa_phandle;
257 bus_addr_t addr;
258 bus_size_t size;
259
260 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
261 aprint_error(": couldn't get registers\n");
262 return;
263 }
264
265 sc->sc_dev = self;
266 sc->sc_bst = faa->faa_bst;
267
268 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
269 aprint_error(": couldn't map registers\n");
270 return;
271 }
272
273 if (of_getprop_uint32(phandle, "apple,npins", &sc->sc_npins)) {
274 aprint_error(": couldn't get number of pins\n");
275 return;
276 }
277
278 if (!of_hasprop(phandle, "gpio-controller")) {
279 aprint_error(": no gpio controller");
280 return;
281 }
282
283 aprint_naive("\n");
284 aprint_normal(": Apple Pinctrl\n");
285
286 fdtbus_register_gpio_controller(self, phandle, &apple_pinctrl_gpio_funcs);
287
288 for (int child = OF_child(phandle); child; child = OF_peer(child)) {
289 if (!of_hasprop(child, "pinmux"))
290 continue;
291 fdtbus_register_pinctrl_config(self, child,
292 &apple_pinctrl_funcs);
293
294 }
295 }
296
297 CFATTACH_DECL_NEW(apple_pinctrl, sizeof(struct apple_pinctrl_softc),
298 apple_pinctrl_match, apple_pinctrl_attach, NULL, NULL);
299
300