xref: /freebsd/sys/dev/gpio/bytgpio.c (revision ccf5e68e5bb2cdabb4686d81c2d63c2f6304d0a4)
1 /*-
2  * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include "opt_acpi.h"
31 
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/gpio.h>
35 #include <sys/kernel.h>
36 #include <sys/module.h>
37 #include <sys/proc.h>
38 #include <sys/rman.h>
39 
40 #include <machine/bus.h>
41 #include <machine/resource.h>
42 
43 #include <contrib/dev/acpica/include/acpi.h>
44 #include <contrib/dev/acpica/include/accommon.h>
45 
46 #include <dev/acpica/acpivar.h>
47 #include <dev/gpio/gpiobusvar.h>
48 
49 #include "gpio_if.h"
50 
51 /**
52  *	Macros for driver mutex locking
53  */
54 #define	BYTGPIO_LOCK(_sc)		mtx_lock_spin(&(_sc)->sc_mtx)
55 #define	BYTGPIO_UNLOCK(_sc)		mtx_unlock_spin(&(_sc)->sc_mtx)
56 #define	BYTGPIO_LOCK_INIT(_sc)		\
57 	mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
58 	    "bytgpio", MTX_SPIN)
59 #define	BYTGPIO_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx)
60 #define	BYTGPIO_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
61 #define	BYTGPIO_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED)
62 
63 struct bytgpio_softc {
64 	ACPI_HANDLE		sc_handle;
65 	device_t		sc_dev;
66 	device_t		sc_busdev;
67 	struct mtx		sc_mtx;
68 	int			sc_mem_rid;
69 	struct resource		*sc_mem_res;
70 	int			sc_npins;
71 	const char*		sc_bank_prefix;
72 	const int		*sc_pinpad_map;
73 };
74 
75 static int	bytgpio_probe(device_t dev);
76 static int	bytgpio_attach(device_t dev);
77 
78 #define SCORE_UID		1
79 #define SCORE_BANK_PREFIX	"GPIO_S0_SC"
80 const int bytgpio_score_pins[] = {
81 	85, 89, 93, 96, 99, 102, 98, 101, 34, 37, 36, 38, 39, 35, 40,
82 	84, 62, 61, 64, 59, 54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
83 	52, 49, 48, 43, 46, 41, 45, 42, 58, 44, 95, 105, 70, 68, 67,
84 	66, 69, 71, 65, 72, 86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
85 	80, 82, 13, 12, 15, 14, 17, 18, 19, 16, 2, 1, 0, 4, 6, 7, 9,
86 	8, 33, 32, 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, 24, 22, 5,
87 	3, 10, 11, 106, 87, 91, 104, 97, 100
88 };
89 #define SCORE_PINS	nitems(bytgpio_score_pins)
90 
91 #define NCORE_UID		2
92 #define NCORE_BANK_PREFIX	"GPIO_S0_NC"
93 const int bytgpio_ncore_pins[] = {
94 	19, 18, 17, 20, 21, 22, 24, 25, 23, 16, 14, 15, 12, 26, 27,
95 	1, 4, 8, 11, 0, 3, 6, 10, 13, 2, 5, 9, 7
96 };
97 #define	NCORE_PINS	nitems(bytgpio_ncore_pins)
98 
99 #define SUS_UID		3
100 #define SUS_BANK_PREFIX	"GPIO_S5_"
101 const int bytgpio_sus_pins[] = {
102         29, 33, 30, 31, 32, 34, 36, 35, 38, 37, 18, 7, 11, 20, 17, 1,
103 	8, 10, 19, 12, 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, 26, 51,
104 	56, 54, 49, 55, 48, 57, 50, 58, 52, 53, 59, 40
105 };
106 #define	SUS_PINS	nitems(bytgpio_sus_pins)
107 
108 #define	BYGPIO_PIN_REGISTER(sc, pin, reg)	((sc)->sc_pinpad_map[(pin)] * 16 + (reg))
109 #define	BYTGPIO_PCONF0		0x0000
110 #define	BYTGPIO_PAD_VAL		0x0008
111 #define		BYTGPIO_PAD_VAL_LEVEL		(1 << 0)
112 #define		BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED	(1 << 1)
113 #define		BYTGPIO_PAD_VAL_I_INPUT_ENABLED	(1 << 2)
114 #define		BYTGPIO_PAD_VAL_DIR_MASK		(3 << 1)
115 
116 static inline uint32_t
117 bytgpio_read_4(struct bytgpio_softc *sc, bus_size_t off)
118 {
119 	return (bus_read_4(sc->sc_mem_res, off));
120 }
121 
122 static inline void
123 bytgpio_write_4(struct bytgpio_softc *sc, bus_size_t off,
124     uint32_t val)
125 {
126 	bus_write_4(sc->sc_mem_res, off, val);
127 }
128 
129 static device_t
130 bytgpio_get_bus(device_t dev)
131 {
132 	struct bytgpio_softc *sc;
133 
134 	sc = device_get_softc(dev);
135 
136 	return (sc->sc_busdev);
137 }
138 
139 static int
140 bytgpio_pin_max(device_t dev, int *maxpin)
141 {
142 	struct bytgpio_softc *sc;
143 
144 	sc = device_get_softc(dev);
145 
146 	*maxpin = sc->sc_npins - 1;
147 
148 	return (0);
149 }
150 
151 static int
152 bytgpio_valid_pin(struct bytgpio_softc *sc, int pin)
153 {
154 
155 	if (pin >= sc->sc_npins || sc->sc_mem_res == NULL)
156 		return (EINVAL);
157 
158 	return (0);
159 }
160 
161 static int
162 bytgpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
163 {
164 	struct bytgpio_softc *sc;
165 
166 	sc = device_get_softc(dev);
167 	if (bytgpio_valid_pin(sc, pin) != 0)
168 		return (EINVAL);
169 
170 	*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
171 
172 	return (0);
173 }
174 
175 static int
176 bytgpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
177 {
178 	struct bytgpio_softc *sc;
179 	uint32_t reg, val;
180 
181 	sc = device_get_softc(dev);
182 	if (bytgpio_valid_pin(sc, pin) != 0)
183 		return (EINVAL);
184 
185 	/* Get the current pin state */
186 	BYTGPIO_LOCK(sc);
187 	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
188 	val = bytgpio_read_4(sc, reg);
189 	*flags = 0;
190 	if ((val & BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED) == 0)
191 		*flags |= GPIO_PIN_OUTPUT;
192 	/*
193 	 * this bit can be cleared to read current output value
194 	 * sou output bit takes precedense
195 	 */
196 	else if ((val & BYTGPIO_PAD_VAL_I_INPUT_ENABLED) == 0)
197 		*flags |= GPIO_PIN_INPUT;
198 	BYTGPIO_UNLOCK(sc);
199 
200 	return (0);
201 }
202 
203 static int
204 bytgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
205 {
206 	struct bytgpio_softc *sc;
207 	uint32_t reg, val;
208 	uint32_t allowed;
209 
210 	sc = device_get_softc(dev);
211 	if (bytgpio_valid_pin(sc, pin) != 0)
212 		return (EINVAL);
213 
214 	allowed = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
215 
216 	/*
217 	 * Only directtion flag allowed
218 	 */
219 	if (flags & ~allowed)
220 		return (EINVAL);
221 
222 	/*
223 	 * Not both directions simultaneously
224 	 */
225 	if ((flags & allowed) == allowed)
226 		return (EINVAL);
227 
228 	/* Set the GPIO mode and state */
229 	BYTGPIO_LOCK(sc);
230 	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
231 	val = bytgpio_read_4(sc, reg);
232 	val = val | BYTGPIO_PAD_VAL_DIR_MASK;
233 	if (flags & GPIO_PIN_INPUT)
234 		val = val & ~BYTGPIO_PAD_VAL_I_INPUT_ENABLED;
235 	if (flags & GPIO_PIN_OUTPUT)
236 		val = val & ~BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED;
237 	bytgpio_write_4(sc, reg, val);
238 	BYTGPIO_UNLOCK(sc);
239 
240 	return (0);
241 }
242 
243 static int
244 bytgpio_pin_getname(device_t dev, uint32_t pin, char *name)
245 {
246 	struct bytgpio_softc *sc;
247 
248 	sc = device_get_softc(dev);
249 	if (bytgpio_valid_pin(sc, pin) != 0)
250 		return (EINVAL);
251 
252 	/* Set a very simple name */
253 	snprintf(name, GPIOMAXNAME, "%s%u", sc->sc_bank_prefix, pin);
254 	name[GPIOMAXNAME - 1] = '\0';
255 
256 	return (0);
257 }
258 
259 static int
260 bytgpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
261 {
262 	struct bytgpio_softc *sc;
263 	uint32_t reg, val;
264 
265 	sc = device_get_softc(dev);
266 	if (bytgpio_valid_pin(sc, pin) != 0)
267 		return (EINVAL);
268 
269 	BYTGPIO_LOCK(sc);
270 	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
271 	val = bytgpio_read_4(sc, reg);
272 	if (value == GPIO_PIN_LOW)
273 		val = val & ~BYTGPIO_PAD_VAL_LEVEL;
274 	else
275 		val = val | BYTGPIO_PAD_VAL_LEVEL;
276 	bytgpio_write_4(sc, reg, val);
277 	BYTGPIO_UNLOCK(sc);
278 
279 	return (0);
280 }
281 
282 static int
283 bytgpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
284 {
285 	struct bytgpio_softc *sc;
286 	uint32_t reg, val;
287 
288 	sc = device_get_softc(dev);
289 	if (bytgpio_valid_pin(sc, pin) != 0)
290 		return (EINVAL);
291 
292 	BYTGPIO_LOCK(sc);
293 	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
294 	/*
295 	 * Enable input to read current value
296 	 */
297 	val = bytgpio_read_4(sc, reg);
298 	val = val & ~BYTGPIO_PAD_VAL_I_INPUT_ENABLED;
299 	bytgpio_write_4(sc, reg, val);
300 	/*
301 	 * And read actual value
302 	 */
303 	val = bytgpio_read_4(sc, reg);
304 	if (val & BYTGPIO_PAD_VAL_LEVEL)
305 		*value = GPIO_PIN_HIGH;
306 	else
307 		*value = GPIO_PIN_LOW;
308 	BYTGPIO_UNLOCK(sc);
309 
310 	return (0);
311 }
312 
313 static int
314 bytgpio_pin_toggle(device_t dev, uint32_t pin)
315 {
316 	struct bytgpio_softc *sc;
317 	uint32_t reg, val;
318 
319 	sc = device_get_softc(dev);
320 	if (bytgpio_valid_pin(sc, pin) != 0)
321 		return (EINVAL);
322 
323 	/* Toggle the pin */
324 	BYTGPIO_LOCK(sc);
325 	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
326 	val = bytgpio_read_4(sc, reg);
327 	val = val ^ BYTGPIO_PAD_VAL_LEVEL;
328 	bytgpio_write_4(sc, reg, val);
329 	BYTGPIO_UNLOCK(sc);
330 
331 	return (0);
332 }
333 
334 static int
335 bytgpio_probe(device_t dev)
336 {
337 	static char *gpio_ids[] = { "INT33FC", NULL };
338 
339 	if (acpi_disabled("gpio") ||
340 	    ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids) == NULL)
341 	return (ENXIO);
342 
343 	device_set_desc(dev, "Intel Baytrail GPIO Controller");
344 	return (0);
345 }
346 
347 static int
348 bytgpio_attach(device_t dev)
349 {
350 	struct bytgpio_softc	*sc;
351 	ACPI_STATUS status;
352 	int uid;
353 
354 	sc = device_get_softc(dev);
355 	sc->sc_dev = dev;
356 	sc->sc_handle = acpi_get_handle(dev);
357 	status = acpi_GetInteger(sc->sc_handle, "_UID", &uid);
358 	if (ACPI_FAILURE(status)) {
359 		device_printf(dev, "failed to read _UID\n");
360 		return (ENXIO);
361 	}
362 
363 	switch (uid) {
364 	case SCORE_UID:
365 		sc->sc_npins = SCORE_PINS;
366 		sc->sc_bank_prefix = SCORE_BANK_PREFIX;
367 		sc->sc_pinpad_map = bytgpio_score_pins;
368 		break;
369 	case NCORE_UID:
370 		sc->sc_npins = NCORE_PINS;
371 		sc->sc_bank_prefix = NCORE_BANK_PREFIX;
372 		sc->sc_pinpad_map = bytgpio_ncore_pins;
373 		break;
374 	case SUS_UID:
375 		sc->sc_npins = SUS_PINS;
376 		sc->sc_bank_prefix = SUS_BANK_PREFIX;
377 		sc->sc_pinpad_map = bytgpio_sus_pins;
378 		break;
379 	default:
380 		device_printf(dev, "invalid _UID value: %d\n", uid);
381 	}
382 
383 	sc->sc_mem_rid = 0;
384 	sc->sc_mem_res = bus_alloc_resource_any(sc->sc_dev,
385 	    SYS_RES_MEMORY, &sc->sc_mem_rid, RF_ACTIVE);
386 	if (sc->sc_mem_res == NULL) {
387 		device_printf(dev, "can't allocate resource\n");
388 		goto error;
389 	}
390 
391 	BYTGPIO_LOCK_INIT(sc);
392 
393 	sc->sc_busdev = gpiobus_attach_bus(dev);
394 	if (sc->sc_busdev == NULL) {
395 		BYTGPIO_LOCK_DESTROY(sc);
396 		bus_release_resource(dev, SYS_RES_MEMORY,
397 		    sc->sc_mem_rid, sc->sc_mem_res);
398 		return (ENXIO);
399 	}
400 
401 	return (0);
402 
403 error:
404 	return (ENXIO);
405 }
406 
407 static device_method_t bytgpio_methods[] = {
408 	/* Device interface */
409 	DEVMETHOD(device_probe, bytgpio_probe),
410 	DEVMETHOD(device_attach, bytgpio_attach),
411 
412 	/* GPIO protocol */
413 	DEVMETHOD(gpio_get_bus, bytgpio_get_bus),
414 	DEVMETHOD(gpio_pin_max, bytgpio_pin_max),
415 	DEVMETHOD(gpio_pin_getname, bytgpio_pin_getname),
416 	DEVMETHOD(gpio_pin_getflags, bytgpio_pin_getflags),
417 	DEVMETHOD(gpio_pin_getcaps, bytgpio_pin_getcaps),
418 	DEVMETHOD(gpio_pin_setflags, bytgpio_pin_setflags),
419 	DEVMETHOD(gpio_pin_get, bytgpio_pin_get),
420 	DEVMETHOD(gpio_pin_set, bytgpio_pin_set),
421 	DEVMETHOD(gpio_pin_toggle, bytgpio_pin_toggle),
422 
423 	DEVMETHOD_END
424 };
425 
426 static driver_t bytgpio_driver = {
427 	"gpio",
428 	bytgpio_methods,
429 	sizeof(struct bytgpio_softc),
430 };
431 
432 static devclass_t bytgpio_devclass;
433 DRIVER_MODULE(bytgpio, acpi, bytgpio_driver, bytgpio_devclass, 0, 0);
434 MODULE_DEPEND(bytgpio, acpi, 1, 1, 1);
435 MODULE_DEPEND(bytgpio, gpio, 1, 1, 1);
436