1308295Sgonzo/*-
2308295Sgonzo * Copyright (c) 2016 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
3308295Sgonzo * All rights reserved.
4308295Sgonzo *
5308295Sgonzo * Redistribution and use in source and binary forms, with or without
6308295Sgonzo * modification, are permitted provided that the following conditions
7308295Sgonzo * are met:
8308295Sgonzo * 1. Redistributions of source code must retain the above copyright
9308295Sgonzo *    notice, this list of conditions and the following disclaimer.
10308295Sgonzo * 2. Redistributions in binary form must reproduce the above copyright
11308295Sgonzo *    notice, this list of conditions and the following disclaimer in the
12308295Sgonzo *    documentation and/or other materials provided with the distribution.
13308295Sgonzo *
14308295Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15308295Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16308295Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17308295Sgonzo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18308295Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19308295Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20308295Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21308295Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22308295Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23308295Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24308295Sgonzo * SUCH DAMAGE.
25308295Sgonzo */
26308295Sgonzo
27308295Sgonzo#include <sys/cdefs.h>
28308295Sgonzo__FBSDID("$FreeBSD: stable/11/sys/dev/gpio/bytgpio.c 309375 2016-12-01 22:22:19Z gonzo $");
29308295Sgonzo
30308295Sgonzo#include "opt_acpi.h"
31308295Sgonzo
32308295Sgonzo#include <sys/param.h>
33308295Sgonzo#include <sys/bus.h>
34308295Sgonzo#include <sys/gpio.h>
35308295Sgonzo#include <sys/kernel.h>
36308295Sgonzo#include <sys/module.h>
37308295Sgonzo#include <sys/proc.h>
38308295Sgonzo#include <sys/rman.h>
39308295Sgonzo
40308295Sgonzo#include <machine/bus.h>
41308295Sgonzo#include <machine/resource.h>
42308295Sgonzo
43308295Sgonzo#include <contrib/dev/acpica/include/acpi.h>
44308295Sgonzo#include <contrib/dev/acpica/include/accommon.h>
45308295Sgonzo
46308295Sgonzo#include <dev/acpica/acpivar.h>
47308295Sgonzo#include <dev/gpio/gpiobusvar.h>
48308295Sgonzo
49308295Sgonzo#include "gpio_if.h"
50308295Sgonzo
51308295Sgonzo/**
52308295Sgonzo *	Macros for driver mutex locking
53308295Sgonzo */
54308295Sgonzo#define	BYTGPIO_LOCK(_sc)		mtx_lock_spin(&(_sc)->sc_mtx)
55308295Sgonzo#define	BYTGPIO_UNLOCK(_sc)		mtx_unlock_spin(&(_sc)->sc_mtx)
56308295Sgonzo#define	BYTGPIO_LOCK_INIT(_sc)		\
57308295Sgonzo	mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
58308295Sgonzo	    "bytgpio", MTX_SPIN)
59308295Sgonzo#define	BYTGPIO_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx)
60308295Sgonzo#define	BYTGPIO_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
61308295Sgonzo#define	BYTGPIO_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED)
62308295Sgonzo
63309375Sgonzostruct pinmap_info {
64309375Sgonzo    int reg;
65309375Sgonzo    int pad_func;
66309375Sgonzo};
67309375Sgonzo
68309375Sgonzo/* Ignore function check, no info is available at the moment */
69309375Sgonzo#define	PADCONF_FUNC_ANY	-1
70309375Sgonzo
71309375Sgonzo#define	GPIO_PIN_MAP(r, f) { .reg = (r), .pad_func = (f) }
72309375Sgonzo
73308295Sgonzostruct bytgpio_softc {
74308295Sgonzo	ACPI_HANDLE		sc_handle;
75308295Sgonzo	device_t		sc_dev;
76308295Sgonzo	device_t		sc_busdev;
77308295Sgonzo	struct mtx		sc_mtx;
78308295Sgonzo	int			sc_mem_rid;
79308295Sgonzo	struct resource		*sc_mem_res;
80308295Sgonzo	int			sc_npins;
81308295Sgonzo	const char*		sc_bank_prefix;
82309375Sgonzo	const struct pinmap_info	*sc_pinpad_map;
83309375Sgonzo	/* List of current functions for pads shared by GPIO */
84309375Sgonzo	int			*sc_pad_funcs;
85308295Sgonzo};
86308295Sgonzo
87308295Sgonzostatic int	bytgpio_probe(device_t dev);
88308295Sgonzostatic int	bytgpio_attach(device_t dev);
89309375Sgonzostatic int	bytgpio_detach(device_t dev);
90308295Sgonzo
91309375Sgonzo#define	SCORE_UID		1
92309375Sgonzo#define	SCORE_BANK_PREFIX	"GPIO_S0_SC"
93309375Sgonzoconst struct pinmap_info bytgpio_score_pins[] = {
94309375Sgonzo	GPIO_PIN_MAP(85, 0),
95309375Sgonzo	GPIO_PIN_MAP(89, 0),
96309375Sgonzo	GPIO_PIN_MAP(93, 0),
97309375Sgonzo	GPIO_PIN_MAP(96, 0),
98309375Sgonzo	GPIO_PIN_MAP(99, 0),
99309375Sgonzo	GPIO_PIN_MAP(102, 0),
100309375Sgonzo	GPIO_PIN_MAP(98, 0),
101309375Sgonzo	GPIO_PIN_MAP(101, 0),
102309375Sgonzo	GPIO_PIN_MAP(34, 0),
103309375Sgonzo	GPIO_PIN_MAP(37, 0),
104309375Sgonzo	GPIO_PIN_MAP(36, 0),
105309375Sgonzo	GPIO_PIN_MAP(38, 0),
106309375Sgonzo	GPIO_PIN_MAP(39, 0),
107309375Sgonzo	GPIO_PIN_MAP(35, 0),
108309375Sgonzo	GPIO_PIN_MAP(40, 0),
109309375Sgonzo	GPIO_PIN_MAP(84, 0),
110309375Sgonzo	GPIO_PIN_MAP(62, 0),
111309375Sgonzo	GPIO_PIN_MAP(61, 0),
112309375Sgonzo	GPIO_PIN_MAP(64, 0),
113309375Sgonzo	GPIO_PIN_MAP(59, 0),
114309375Sgonzo	GPIO_PIN_MAP(54, 0),
115309375Sgonzo	GPIO_PIN_MAP(56, 0),
116309375Sgonzo	GPIO_PIN_MAP(60, 0),
117309375Sgonzo	GPIO_PIN_MAP(55, 0),
118309375Sgonzo	GPIO_PIN_MAP(63, 0),
119309375Sgonzo	GPIO_PIN_MAP(57, 0),
120309375Sgonzo	GPIO_PIN_MAP(51, 0),
121309375Sgonzo	GPIO_PIN_MAP(50, 0),
122309375Sgonzo	GPIO_PIN_MAP(53, 0),
123309375Sgonzo	GPIO_PIN_MAP(47, 0),
124309375Sgonzo	GPIO_PIN_MAP(52, 0),
125309375Sgonzo	GPIO_PIN_MAP(49, 0),
126309375Sgonzo	GPIO_PIN_MAP(48, 0),
127309375Sgonzo	GPIO_PIN_MAP(43, 0),
128309375Sgonzo	GPIO_PIN_MAP(46, 0),
129309375Sgonzo	GPIO_PIN_MAP(41, 0),
130309375Sgonzo	GPIO_PIN_MAP(45, 0),
131309375Sgonzo	GPIO_PIN_MAP(42, 0),
132309375Sgonzo	GPIO_PIN_MAP(58, 0),
133309375Sgonzo	GPIO_PIN_MAP(44, 0),
134309375Sgonzo	GPIO_PIN_MAP(95, 0),
135309375Sgonzo	GPIO_PIN_MAP(105, 0),
136309375Sgonzo	GPIO_PIN_MAP(70, 0),
137309375Sgonzo	GPIO_PIN_MAP(68, 0),
138309375Sgonzo	GPIO_PIN_MAP(67, 0),
139309375Sgonzo	GPIO_PIN_MAP(66, 0),
140309375Sgonzo	GPIO_PIN_MAP(69, 0),
141309375Sgonzo	GPIO_PIN_MAP(71, 0),
142309375Sgonzo	GPIO_PIN_MAP(65, 0),
143309375Sgonzo	GPIO_PIN_MAP(72, 0),
144309375Sgonzo	GPIO_PIN_MAP(86, 0),
145309375Sgonzo	GPIO_PIN_MAP(90, 0),
146309375Sgonzo	GPIO_PIN_MAP(88, 0),
147309375Sgonzo	GPIO_PIN_MAP(92, 0),
148309375Sgonzo	GPIO_PIN_MAP(103, 0),
149309375Sgonzo	GPIO_PIN_MAP(77, 0),
150309375Sgonzo	GPIO_PIN_MAP(79, 0),
151309375Sgonzo	GPIO_PIN_MAP(83, 0),
152309375Sgonzo	GPIO_PIN_MAP(78, 0),
153309375Sgonzo	GPIO_PIN_MAP(81, 0),
154309375Sgonzo	GPIO_PIN_MAP(80, 0),
155309375Sgonzo	GPIO_PIN_MAP(82, 0),
156309375Sgonzo	GPIO_PIN_MAP(13, 0),
157309375Sgonzo	GPIO_PIN_MAP(12, 0),
158309375Sgonzo	GPIO_PIN_MAP(15, 0),
159309375Sgonzo	GPIO_PIN_MAP(14, 0),
160309375Sgonzo	GPIO_PIN_MAP(17, 0),
161309375Sgonzo	GPIO_PIN_MAP(18, 0),
162309375Sgonzo	GPIO_PIN_MAP(19, 0),
163309375Sgonzo	GPIO_PIN_MAP(16, 0),
164309375Sgonzo	GPIO_PIN_MAP(2, 0),
165309375Sgonzo	GPIO_PIN_MAP(1, 0),
166309375Sgonzo	GPIO_PIN_MAP(0, 0),
167309375Sgonzo	GPIO_PIN_MAP(4, 0),
168309375Sgonzo	GPIO_PIN_MAP(6, 0),
169309375Sgonzo	GPIO_PIN_MAP(7, 0),
170309375Sgonzo	GPIO_PIN_MAP(9, 0),
171309375Sgonzo	GPIO_PIN_MAP(8, 0),
172309375Sgonzo	GPIO_PIN_MAP(33, 0),
173309375Sgonzo	GPIO_PIN_MAP(32, 0),
174309375Sgonzo	GPIO_PIN_MAP(31, 0),
175309375Sgonzo	GPIO_PIN_MAP(30, 0),
176309375Sgonzo	GPIO_PIN_MAP(29, 0),
177309375Sgonzo	GPIO_PIN_MAP(27, 0),
178309375Sgonzo	GPIO_PIN_MAP(25, 0),
179309375Sgonzo	GPIO_PIN_MAP(28, 0),
180309375Sgonzo	GPIO_PIN_MAP(26, 0),
181309375Sgonzo	GPIO_PIN_MAP(23, 0),
182309375Sgonzo	GPIO_PIN_MAP(21, 0),
183309375Sgonzo	GPIO_PIN_MAP(20, 0),
184309375Sgonzo	GPIO_PIN_MAP(24, 0),
185309375Sgonzo	GPIO_PIN_MAP(22, 0),
186309375Sgonzo	GPIO_PIN_MAP(5, 1),
187309375Sgonzo	GPIO_PIN_MAP(3, 1),
188309375Sgonzo	GPIO_PIN_MAP(10, 0),
189309375Sgonzo	GPIO_PIN_MAP(11, 0),
190309375Sgonzo	GPIO_PIN_MAP(106, 0),
191309375Sgonzo	GPIO_PIN_MAP(87, 0),
192309375Sgonzo	GPIO_PIN_MAP(91, 0),
193309375Sgonzo	GPIO_PIN_MAP(104, 0),
194309375Sgonzo	GPIO_PIN_MAP(97, 0),
195309375Sgonzo	GPIO_PIN_MAP(100, 0)
196308295Sgonzo};
197308295Sgonzo
198309375Sgonzo#define	SCORE_PINS	nitems(bytgpio_score_pins)
199309375Sgonzo
200309375Sgonzo#define	NCORE_UID		2
201309375Sgonzo#define	NCORE_BANK_PREFIX	"GPIO_S0_NC"
202309375Sgonzoconst struct pinmap_info bytgpio_ncore_pins[] = {
203309375Sgonzo	GPIO_PIN_MAP(19, PADCONF_FUNC_ANY),
204309375Sgonzo	GPIO_PIN_MAP(18, PADCONF_FUNC_ANY),
205309375Sgonzo	GPIO_PIN_MAP(17, PADCONF_FUNC_ANY),
206309375Sgonzo	GPIO_PIN_MAP(20, PADCONF_FUNC_ANY),
207309375Sgonzo	GPIO_PIN_MAP(21, PADCONF_FUNC_ANY),
208309375Sgonzo	GPIO_PIN_MAP(22, PADCONF_FUNC_ANY),
209309375Sgonzo	GPIO_PIN_MAP(24, PADCONF_FUNC_ANY),
210309375Sgonzo	GPIO_PIN_MAP(25, PADCONF_FUNC_ANY),
211309375Sgonzo	GPIO_PIN_MAP(23, PADCONF_FUNC_ANY),
212309375Sgonzo	GPIO_PIN_MAP(16, PADCONF_FUNC_ANY),
213309375Sgonzo	GPIO_PIN_MAP(14, PADCONF_FUNC_ANY),
214309375Sgonzo	GPIO_PIN_MAP(15, PADCONF_FUNC_ANY),
215309375Sgonzo	GPIO_PIN_MAP(12, PADCONF_FUNC_ANY),
216309375Sgonzo	GPIO_PIN_MAP(26, PADCONF_FUNC_ANY),
217309375Sgonzo	GPIO_PIN_MAP(27, PADCONF_FUNC_ANY),
218309375Sgonzo	GPIO_PIN_MAP(1, PADCONF_FUNC_ANY),
219309375Sgonzo	GPIO_PIN_MAP(4, PADCONF_FUNC_ANY),
220309375Sgonzo	GPIO_PIN_MAP(8, PADCONF_FUNC_ANY),
221309375Sgonzo	GPIO_PIN_MAP(11, PADCONF_FUNC_ANY),
222309375Sgonzo	GPIO_PIN_MAP(0, PADCONF_FUNC_ANY),
223309375Sgonzo	GPIO_PIN_MAP(3, PADCONF_FUNC_ANY),
224309375Sgonzo	GPIO_PIN_MAP(6, PADCONF_FUNC_ANY),
225309375Sgonzo	GPIO_PIN_MAP(10, PADCONF_FUNC_ANY),
226309375Sgonzo	GPIO_PIN_MAP(13, PADCONF_FUNC_ANY),
227309375Sgonzo	GPIO_PIN_MAP(2, PADCONF_FUNC_ANY),
228309375Sgonzo	GPIO_PIN_MAP(5, PADCONF_FUNC_ANY),
229309375Sgonzo	GPIO_PIN_MAP(9, PADCONF_FUNC_ANY),
230309375Sgonzo	GPIO_PIN_MAP(7, PADCONF_FUNC_ANY)
231308295Sgonzo};
232308295Sgonzo#define	NCORE_PINS	nitems(bytgpio_ncore_pins)
233308295Sgonzo
234309375Sgonzo#define	SUS_UID		3
235309375Sgonzo#define	SUS_BANK_PREFIX	"GPIO_S5_"
236309375Sgonzoconst struct pinmap_info bytgpio_sus_pins[] = {
237309375Sgonzo	GPIO_PIN_MAP(29, 0),
238309375Sgonzo	GPIO_PIN_MAP(33, 0),
239309375Sgonzo	GPIO_PIN_MAP(30, 0),
240309375Sgonzo	GPIO_PIN_MAP(31, 0),
241309375Sgonzo	GPIO_PIN_MAP(32, 0),
242309375Sgonzo	GPIO_PIN_MAP(34, 0),
243309375Sgonzo	GPIO_PIN_MAP(36, 0),
244309375Sgonzo	GPIO_PIN_MAP(35, 0),
245309375Sgonzo	GPIO_PIN_MAP(38, 0),
246309375Sgonzo	GPIO_PIN_MAP(37, 0),
247309375Sgonzo	GPIO_PIN_MAP(18, 0),
248309375Sgonzo	GPIO_PIN_MAP(7, 1),
249309375Sgonzo	GPIO_PIN_MAP(11, 1),
250309375Sgonzo	GPIO_PIN_MAP(20, 1),
251309375Sgonzo	GPIO_PIN_MAP(17, 1),
252309375Sgonzo	GPIO_PIN_MAP(1, 1),
253309375Sgonzo	GPIO_PIN_MAP(8, 1),
254309375Sgonzo	GPIO_PIN_MAP(10, 1),
255309375Sgonzo	GPIO_PIN_MAP(19, 1),
256309375Sgonzo	GPIO_PIN_MAP(12, 1),
257309375Sgonzo	GPIO_PIN_MAP(0, 1),
258309375Sgonzo	GPIO_PIN_MAP(2, 1),
259309375Sgonzo	GPIO_PIN_MAP(23, 0),
260309375Sgonzo	GPIO_PIN_MAP(39, 0),
261309375Sgonzo	GPIO_PIN_MAP(28, 0),
262309375Sgonzo	GPIO_PIN_MAP(27, 0),
263309375Sgonzo	GPIO_PIN_MAP(22, 0),
264309375Sgonzo	GPIO_PIN_MAP(21, 0),
265309375Sgonzo	GPIO_PIN_MAP(24, 0),
266309375Sgonzo	GPIO_PIN_MAP(25, 0),
267309375Sgonzo	GPIO_PIN_MAP(26, 0),
268309375Sgonzo	GPIO_PIN_MAP(51, 0),
269309375Sgonzo	GPIO_PIN_MAP(56, 0),
270309375Sgonzo	GPIO_PIN_MAP(54, 0),
271309375Sgonzo	GPIO_PIN_MAP(49, 0),
272309375Sgonzo	GPIO_PIN_MAP(55, 0),
273309375Sgonzo	GPIO_PIN_MAP(48, 0),
274309375Sgonzo	GPIO_PIN_MAP(57, 0),
275309375Sgonzo	GPIO_PIN_MAP(50, 0),
276309375Sgonzo	GPIO_PIN_MAP(58, 0),
277309375Sgonzo	GPIO_PIN_MAP(52, 0),
278309375Sgonzo	GPIO_PIN_MAP(53, 0),
279309375Sgonzo	GPIO_PIN_MAP(59, 0),
280309375Sgonzo	GPIO_PIN_MAP(40, 0)
281308295Sgonzo};
282309375Sgonzo
283308295Sgonzo#define	SUS_PINS	nitems(bytgpio_sus_pins)
284308295Sgonzo
285309375Sgonzo#define	BYGPIO_PIN_REGISTER(sc, pin, r)	((sc)->sc_pinpad_map[(pin)].reg * 16 + (r))
286308295Sgonzo#define	BYTGPIO_PCONF0		0x0000
287309375Sgonzo#define		BYTGPIO_PCONF0_FUNC_MASK	7
288308295Sgonzo#define	BYTGPIO_PAD_VAL		0x0008
289308295Sgonzo#define		BYTGPIO_PAD_VAL_LEVEL		(1 << 0)
290308295Sgonzo#define		BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED	(1 << 1)
291308295Sgonzo#define		BYTGPIO_PAD_VAL_I_INPUT_ENABLED	(1 << 2)
292308295Sgonzo#define		BYTGPIO_PAD_VAL_DIR_MASK		(3 << 1)
293308295Sgonzo
294308295Sgonzostatic inline uint32_t
295308295Sgonzobytgpio_read_4(struct bytgpio_softc *sc, bus_size_t off)
296308295Sgonzo{
297308295Sgonzo	return (bus_read_4(sc->sc_mem_res, off));
298308295Sgonzo}
299308295Sgonzo
300308295Sgonzostatic inline void
301308295Sgonzobytgpio_write_4(struct bytgpio_softc *sc, bus_size_t off,
302308295Sgonzo    uint32_t val)
303308295Sgonzo{
304308295Sgonzo	bus_write_4(sc->sc_mem_res, off, val);
305308295Sgonzo}
306308295Sgonzo
307308295Sgonzostatic device_t
308308295Sgonzobytgpio_get_bus(device_t dev)
309308295Sgonzo{
310308295Sgonzo	struct bytgpio_softc *sc;
311308295Sgonzo
312308295Sgonzo	sc = device_get_softc(dev);
313308295Sgonzo
314308295Sgonzo	return (sc->sc_busdev);
315308295Sgonzo}
316308295Sgonzo
317308295Sgonzostatic int
318308295Sgonzobytgpio_pin_max(device_t dev, int *maxpin)
319308295Sgonzo{
320308295Sgonzo	struct bytgpio_softc *sc;
321308295Sgonzo
322308295Sgonzo	sc = device_get_softc(dev);
323308295Sgonzo
324308295Sgonzo	*maxpin = sc->sc_npins - 1;
325308295Sgonzo
326308295Sgonzo	return (0);
327308295Sgonzo}
328308295Sgonzo
329308295Sgonzostatic int
330308295Sgonzobytgpio_valid_pin(struct bytgpio_softc *sc, int pin)
331308295Sgonzo{
332308295Sgonzo
333308295Sgonzo	if (pin >= sc->sc_npins || sc->sc_mem_res == NULL)
334308295Sgonzo		return (EINVAL);
335308295Sgonzo
336308295Sgonzo	return (0);
337308295Sgonzo}
338308295Sgonzo
339309375Sgonzo/*
340309375Sgonzo * Returns true if pad configured to be used as GPIO
341309375Sgonzo */
342309375Sgonzostatic bool
343309375Sgonzobytgpio_pad_is_gpio(struct bytgpio_softc *sc, int pin)
344309375Sgonzo{
345309375Sgonzo	if ((sc->sc_pinpad_map[pin].pad_func == PADCONF_FUNC_ANY) ||
346309375Sgonzo	    (sc->sc_pad_funcs[pin] == sc->sc_pinpad_map[pin].pad_func))
347309375Sgonzo		return (true);
348309375Sgonzo	else
349309375Sgonzo		return (false);
350309375Sgonzo}
351309375Sgonzo
352308295Sgonzostatic int
353308295Sgonzobytgpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
354308295Sgonzo{
355308295Sgonzo	struct bytgpio_softc *sc;
356308295Sgonzo
357308295Sgonzo	sc = device_get_softc(dev);
358308295Sgonzo	if (bytgpio_valid_pin(sc, pin) != 0)
359308295Sgonzo		return (EINVAL);
360308295Sgonzo
361309375Sgonzo	*caps = 0;
362309375Sgonzo	if (bytgpio_pad_is_gpio(sc, pin))
363309375Sgonzo		*caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
364308295Sgonzo
365308295Sgonzo	return (0);
366308295Sgonzo}
367308295Sgonzo
368308295Sgonzostatic int
369308295Sgonzobytgpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
370308295Sgonzo{
371308295Sgonzo	struct bytgpio_softc *sc;
372308295Sgonzo	uint32_t reg, val;
373308295Sgonzo
374308295Sgonzo	sc = device_get_softc(dev);
375308295Sgonzo	if (bytgpio_valid_pin(sc, pin) != 0)
376308295Sgonzo		return (EINVAL);
377308295Sgonzo
378309375Sgonzo	*flags = 0;
379309375Sgonzo	if (!bytgpio_pad_is_gpio(sc, pin))
380309375Sgonzo		return (0);
381309375Sgonzo
382308295Sgonzo	/* Get the current pin state */
383308295Sgonzo	BYTGPIO_LOCK(sc);
384308295Sgonzo	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
385308295Sgonzo	val = bytgpio_read_4(sc, reg);
386308295Sgonzo	if ((val & BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED) == 0)
387308295Sgonzo		*flags |= GPIO_PIN_OUTPUT;
388308295Sgonzo	/*
389308295Sgonzo	 * this bit can be cleared to read current output value
390308295Sgonzo	 * sou output bit takes precedense
391308295Sgonzo	 */
392308295Sgonzo	else if ((val & BYTGPIO_PAD_VAL_I_INPUT_ENABLED) == 0)
393308295Sgonzo		*flags |= GPIO_PIN_INPUT;
394308295Sgonzo	BYTGPIO_UNLOCK(sc);
395308295Sgonzo
396308295Sgonzo	return (0);
397308295Sgonzo}
398308295Sgonzo
399308295Sgonzostatic int
400308295Sgonzobytgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
401308295Sgonzo{
402308295Sgonzo	struct bytgpio_softc *sc;
403308295Sgonzo	uint32_t reg, val;
404308295Sgonzo	uint32_t allowed;
405308295Sgonzo
406308295Sgonzo	sc = device_get_softc(dev);
407308295Sgonzo	if (bytgpio_valid_pin(sc, pin) != 0)
408308295Sgonzo		return (EINVAL);
409308295Sgonzo
410309375Sgonzo	if (bytgpio_pad_is_gpio(sc, pin))
411309375Sgonzo		allowed = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
412309375Sgonzo	else
413309375Sgonzo		allowed = 0;
414308295Sgonzo
415308295Sgonzo	/*
416308295Sgonzo	 * Only directtion flag allowed
417308295Sgonzo	 */
418308295Sgonzo	if (flags & ~allowed)
419308295Sgonzo		return (EINVAL);
420308295Sgonzo
421308295Sgonzo	/*
422308295Sgonzo	 * Not both directions simultaneously
423308295Sgonzo	 */
424308295Sgonzo	if ((flags & allowed) == allowed)
425308295Sgonzo		return (EINVAL);
426308295Sgonzo
427308295Sgonzo	/* Set the GPIO mode and state */
428308295Sgonzo	BYTGPIO_LOCK(sc);
429308295Sgonzo	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
430308295Sgonzo	val = bytgpio_read_4(sc, reg);
431308295Sgonzo	val = val | BYTGPIO_PAD_VAL_DIR_MASK;
432308295Sgonzo	if (flags & GPIO_PIN_INPUT)
433308295Sgonzo		val = val & ~BYTGPIO_PAD_VAL_I_INPUT_ENABLED;
434308295Sgonzo	if (flags & GPIO_PIN_OUTPUT)
435308295Sgonzo		val = val & ~BYTGPIO_PAD_VAL_I_OUTPUT_ENABLED;
436308295Sgonzo	bytgpio_write_4(sc, reg, val);
437308295Sgonzo	BYTGPIO_UNLOCK(sc);
438308295Sgonzo
439308295Sgonzo	return (0);
440308295Sgonzo}
441308295Sgonzo
442308295Sgonzostatic int
443308295Sgonzobytgpio_pin_getname(device_t dev, uint32_t pin, char *name)
444308295Sgonzo{
445308295Sgonzo	struct bytgpio_softc *sc;
446308295Sgonzo
447308295Sgonzo	sc = device_get_softc(dev);
448308295Sgonzo	if (bytgpio_valid_pin(sc, pin) != 0)
449308295Sgonzo		return (EINVAL);
450308295Sgonzo
451308295Sgonzo	/* Set a very simple name */
452308295Sgonzo	snprintf(name, GPIOMAXNAME, "%s%u", sc->sc_bank_prefix, pin);
453308295Sgonzo	name[GPIOMAXNAME - 1] = '\0';
454308295Sgonzo
455308295Sgonzo	return (0);
456308295Sgonzo}
457308295Sgonzo
458308295Sgonzostatic int
459308295Sgonzobytgpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
460308295Sgonzo{
461308295Sgonzo	struct bytgpio_softc *sc;
462308295Sgonzo	uint32_t reg, val;
463308295Sgonzo
464308295Sgonzo	sc = device_get_softc(dev);
465308295Sgonzo	if (bytgpio_valid_pin(sc, pin) != 0)
466308295Sgonzo		return (EINVAL);
467308295Sgonzo
468309375Sgonzo	if (!bytgpio_pad_is_gpio(sc, pin))
469309375Sgonzo		return (EINVAL);
470309375Sgonzo
471308295Sgonzo	BYTGPIO_LOCK(sc);
472308295Sgonzo	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
473308295Sgonzo	val = bytgpio_read_4(sc, reg);
474308295Sgonzo	if (value == GPIO_PIN_LOW)
475308295Sgonzo		val = val & ~BYTGPIO_PAD_VAL_LEVEL;
476308295Sgonzo	else
477308295Sgonzo		val = val | BYTGPIO_PAD_VAL_LEVEL;
478308295Sgonzo	bytgpio_write_4(sc, reg, val);
479308295Sgonzo	BYTGPIO_UNLOCK(sc);
480308295Sgonzo
481308295Sgonzo	return (0);
482308295Sgonzo}
483308295Sgonzo
484308295Sgonzostatic int
485308295Sgonzobytgpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
486308295Sgonzo{
487308295Sgonzo	struct bytgpio_softc *sc;
488308295Sgonzo	uint32_t reg, val;
489308295Sgonzo
490308295Sgonzo	sc = device_get_softc(dev);
491308295Sgonzo	if (bytgpio_valid_pin(sc, pin) != 0)
492308295Sgonzo		return (EINVAL);
493309375Sgonzo	/*
494309375Sgonzo	 * Report non-GPIO pads as pin LOW
495309375Sgonzo	 */
496309375Sgonzo	if (!bytgpio_pad_is_gpio(sc, pin)) {
497309375Sgonzo		*value = GPIO_PIN_LOW;
498309375Sgonzo		return (0);
499309375Sgonzo	}
500308295Sgonzo
501308295Sgonzo	BYTGPIO_LOCK(sc);
502308295Sgonzo	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
503308295Sgonzo	/*
504308295Sgonzo	 * And read actual value
505308295Sgonzo	 */
506308295Sgonzo	val = bytgpio_read_4(sc, reg);
507308295Sgonzo	if (val & BYTGPIO_PAD_VAL_LEVEL)
508308295Sgonzo		*value = GPIO_PIN_HIGH;
509308295Sgonzo	else
510308295Sgonzo		*value = GPIO_PIN_LOW;
511308295Sgonzo	BYTGPIO_UNLOCK(sc);
512308295Sgonzo
513308295Sgonzo	return (0);
514308295Sgonzo}
515308295Sgonzo
516308295Sgonzostatic int
517308295Sgonzobytgpio_pin_toggle(device_t dev, uint32_t pin)
518308295Sgonzo{
519308295Sgonzo	struct bytgpio_softc *sc;
520308295Sgonzo	uint32_t reg, val;
521308295Sgonzo
522308295Sgonzo	sc = device_get_softc(dev);
523308295Sgonzo	if (bytgpio_valid_pin(sc, pin) != 0)
524308295Sgonzo		return (EINVAL);
525308295Sgonzo
526309375Sgonzo	if (!bytgpio_pad_is_gpio(sc, pin))
527309375Sgonzo		return (EINVAL);
528309375Sgonzo
529308295Sgonzo	/* Toggle the pin */
530308295Sgonzo	BYTGPIO_LOCK(sc);
531308295Sgonzo	reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PAD_VAL);
532308295Sgonzo	val = bytgpio_read_4(sc, reg);
533308295Sgonzo	val = val ^ BYTGPIO_PAD_VAL_LEVEL;
534308295Sgonzo	bytgpio_write_4(sc, reg, val);
535308295Sgonzo	BYTGPIO_UNLOCK(sc);
536308295Sgonzo
537308295Sgonzo	return (0);
538308295Sgonzo}
539308295Sgonzo
540308295Sgonzostatic int
541308295Sgonzobytgpio_probe(device_t dev)
542308295Sgonzo{
543308295Sgonzo	static char *gpio_ids[] = { "INT33FC", NULL };
544308295Sgonzo
545308295Sgonzo	if (acpi_disabled("gpio") ||
546308295Sgonzo	    ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids) == NULL)
547308295Sgonzo	return (ENXIO);
548308295Sgonzo
549308295Sgonzo	device_set_desc(dev, "Intel Baytrail GPIO Controller");
550308295Sgonzo	return (0);
551308295Sgonzo}
552308295Sgonzo
553308295Sgonzostatic int
554308295Sgonzobytgpio_attach(device_t dev)
555308295Sgonzo{
556308295Sgonzo	struct bytgpio_softc	*sc;
557308295Sgonzo	ACPI_STATUS status;
558308295Sgonzo	int uid;
559309375Sgonzo	int pin;
560309375Sgonzo	uint32_t reg, val;
561308295Sgonzo
562308295Sgonzo	sc = device_get_softc(dev);
563308295Sgonzo	sc->sc_dev = dev;
564308295Sgonzo	sc->sc_handle = acpi_get_handle(dev);
565308295Sgonzo	status = acpi_GetInteger(sc->sc_handle, "_UID", &uid);
566308295Sgonzo	if (ACPI_FAILURE(status)) {
567308295Sgonzo		device_printf(dev, "failed to read _UID\n");
568308295Sgonzo		return (ENXIO);
569308295Sgonzo	}
570308295Sgonzo
571309375Sgonzo	BYTGPIO_LOCK_INIT(sc);
572309375Sgonzo
573308295Sgonzo	switch (uid) {
574308295Sgonzo	case SCORE_UID:
575308295Sgonzo		sc->sc_npins = SCORE_PINS;
576308295Sgonzo		sc->sc_bank_prefix = SCORE_BANK_PREFIX;
577308295Sgonzo		sc->sc_pinpad_map = bytgpio_score_pins;
578308295Sgonzo		break;
579308295Sgonzo	case NCORE_UID:
580308295Sgonzo		sc->sc_npins = NCORE_PINS;
581308295Sgonzo		sc->sc_bank_prefix = NCORE_BANK_PREFIX;
582308295Sgonzo		sc->sc_pinpad_map = bytgpio_ncore_pins;
583308295Sgonzo		break;
584308295Sgonzo	case SUS_UID:
585308295Sgonzo		sc->sc_npins = SUS_PINS;
586308295Sgonzo		sc->sc_bank_prefix = SUS_BANK_PREFIX;
587308295Sgonzo		sc->sc_pinpad_map = bytgpio_sus_pins;
588308295Sgonzo		break;
589308295Sgonzo	default:
590308295Sgonzo		device_printf(dev, "invalid _UID value: %d\n", uid);
591309375Sgonzo		goto error;
592308295Sgonzo	}
593308295Sgonzo
594309375Sgonzo	sc->sc_pad_funcs = malloc(sizeof(int)*sc->sc_npins, M_DEVBUF,
595309375Sgonzo	    M_WAITOK | M_ZERO);
596309375Sgonzo
597308295Sgonzo	sc->sc_mem_rid = 0;
598308295Sgonzo	sc->sc_mem_res = bus_alloc_resource_any(sc->sc_dev,
599308295Sgonzo	    SYS_RES_MEMORY, &sc->sc_mem_rid, RF_ACTIVE);
600308295Sgonzo	if (sc->sc_mem_res == NULL) {
601308295Sgonzo		device_printf(dev, "can't allocate resource\n");
602308295Sgonzo		goto error;
603308295Sgonzo	}
604308295Sgonzo
605309375Sgonzo	for (pin = 0; pin < sc->sc_npins; pin++) {
606309375Sgonzo	    reg = BYGPIO_PIN_REGISTER(sc, pin, BYTGPIO_PCONF0);
607309375Sgonzo	    val = bytgpio_read_4(sc, reg);
608309375Sgonzo	    sc->sc_pad_funcs[pin] = val & BYTGPIO_PCONF0_FUNC_MASK;
609309375Sgonzo	}
610308295Sgonzo
611308295Sgonzo	sc->sc_busdev = gpiobus_attach_bus(dev);
612308295Sgonzo	if (sc->sc_busdev == NULL) {
613308295Sgonzo		BYTGPIO_LOCK_DESTROY(sc);
614308295Sgonzo		bus_release_resource(dev, SYS_RES_MEMORY,
615308295Sgonzo		    sc->sc_mem_rid, sc->sc_mem_res);
616308295Sgonzo		return (ENXIO);
617308295Sgonzo	}
618308295Sgonzo
619308295Sgonzo	return (0);
620308295Sgonzo
621308295Sgonzoerror:
622309375Sgonzo	BYTGPIO_LOCK_DESTROY(sc);
623309375Sgonzo
624308295Sgonzo	return (ENXIO);
625308295Sgonzo}
626308295Sgonzo
627309375Sgonzo
628309375Sgonzostatic int
629309375Sgonzobytgpio_detach(device_t dev)
630309375Sgonzo{
631309375Sgonzo	struct bytgpio_softc	*sc;
632309375Sgonzo
633309375Sgonzo	sc = device_get_softc(dev);
634309375Sgonzo
635309375Sgonzo	if (sc->sc_busdev)
636309375Sgonzo		gpiobus_detach_bus(dev);
637309375Sgonzo
638309375Sgonzo	BYTGPIO_LOCK_DESTROY(sc);
639309375Sgonzo
640309375Sgonzo	if (sc->sc_pad_funcs)
641309375Sgonzo		free(sc->sc_pad_funcs, M_DEVBUF);
642309375Sgonzo
643309375Sgonzo	if (sc->sc_mem_res != NULL)
644309375Sgonzo		bus_release_resource(dev, SYS_RES_MEMORY,
645309375Sgonzo		    sc->sc_mem_rid, sc->sc_mem_res);
646309375Sgonzo
647309375Sgonzo	return (0);
648309375Sgonzo}
649309375Sgonzo
650308295Sgonzostatic device_method_t bytgpio_methods[] = {
651308295Sgonzo	/* Device interface */
652308295Sgonzo	DEVMETHOD(device_probe, bytgpio_probe),
653308295Sgonzo	DEVMETHOD(device_attach, bytgpio_attach),
654309375Sgonzo	DEVMETHOD(device_detach, bytgpio_detach),
655308295Sgonzo
656308295Sgonzo	/* GPIO protocol */
657308295Sgonzo	DEVMETHOD(gpio_get_bus, bytgpio_get_bus),
658308295Sgonzo	DEVMETHOD(gpio_pin_max, bytgpio_pin_max),
659308295Sgonzo	DEVMETHOD(gpio_pin_getname, bytgpio_pin_getname),
660308295Sgonzo	DEVMETHOD(gpio_pin_getflags, bytgpio_pin_getflags),
661308295Sgonzo	DEVMETHOD(gpio_pin_getcaps, bytgpio_pin_getcaps),
662308295Sgonzo	DEVMETHOD(gpio_pin_setflags, bytgpio_pin_setflags),
663308295Sgonzo	DEVMETHOD(gpio_pin_get, bytgpio_pin_get),
664308295Sgonzo	DEVMETHOD(gpio_pin_set, bytgpio_pin_set),
665308295Sgonzo	DEVMETHOD(gpio_pin_toggle, bytgpio_pin_toggle),
666308295Sgonzo
667308295Sgonzo	DEVMETHOD_END
668308295Sgonzo};
669308295Sgonzo
670308295Sgonzostatic driver_t bytgpio_driver = {
671308295Sgonzo	"gpio",
672308295Sgonzo	bytgpio_methods,
673308295Sgonzo	sizeof(struct bytgpio_softc),
674308295Sgonzo};
675308295Sgonzo
676308295Sgonzostatic devclass_t bytgpio_devclass;
677308295SgonzoDRIVER_MODULE(bytgpio, acpi, bytgpio_driver, bytgpio_devclass, 0, 0);
678308295SgonzoMODULE_DEPEND(bytgpio, acpi, 1, 1, 1);
679309375SgonzoMODULE_DEPEND(bytgpio, gpiobus, 1, 1, 1);
680