1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 *
30 */
31
32#ifndef	__GPIOBUS_H__
33#define	__GPIOBUS_H__
34
35#include "opt_platform.h"
36
37#include <sys/lock.h>
38#include <sys/mutex.h>
39#include <sys/rman.h>
40
41#ifdef FDT
42#include <dev/ofw/ofw_bus_subr.h>
43#endif
44
45#ifdef	INTRNG
46#include <sys/intr.h>
47#endif
48
49#include "gpio_if.h"
50
51#ifdef FDT
52#define	GPIOBUS_IVAR(d) (struct gpiobus_ivar *)				\
53	&((struct ofw_gpiobus_devinfo *)device_get_ivars(d))->opd_dinfo
54#else
55#define	GPIOBUS_IVAR(d) (struct gpiobus_ivar *) device_get_ivars(d)
56#endif
57#define	GPIOBUS_SOFTC(d) (struct gpiobus_softc *) device_get_softc(d)
58#define	GPIOBUS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
59#define	GPIOBUS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
60#define	GPIOBUS_LOCK_INIT(_sc) mtx_init(&_sc->sc_mtx,			\
61	    device_get_nameunit(_sc->sc_dev), "gpiobus", MTX_DEF)
62#define	GPIOBUS_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx)
63#define	GPIOBUS_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED)
64#define	GPIOBUS_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED)
65
66#define	GPIOBUS_WAIT		1
67#define	GPIOBUS_DONTWAIT	2
68
69/* Use default interrupt mode -  for gpio_alloc_intr_resource */
70#define GPIO_INTR_CONFORM	GPIO_INTR_NONE
71
72struct gpiobus_pin_data
73{
74	int		mapped;		/* pin is mapped/reserved. */
75	char		*name;		/* pin name. */
76};
77
78#ifdef INTRNG
79struct intr_map_data_gpio {
80	struct intr_map_data	hdr;
81	u_int			gpio_pin_num;
82	u_int			gpio_pin_flags;
83	u_int		 	gpio_intr_mode;
84};
85#endif
86
87struct gpiobus_softc
88{
89	struct mtx	sc_mtx;		/* bus mutex */
90	struct rman	sc_intr_rman;	/* isr resources */
91	device_t	sc_busdev;	/* bus device */
92	device_t	sc_owner;	/* bus owner */
93	device_t	sc_dev;		/* driver device */
94	int		sc_npins;	/* total pins on bus */
95	struct gpiobus_pin_data	*sc_pins; /* pin data */
96};
97
98struct gpiobus_pin
99{
100	device_t	dev;	/* gpio device */
101	uint32_t	flags;	/* pin flags */
102	uint32_t	pin;	/* pin number */
103};
104typedef struct gpiobus_pin *gpio_pin_t;
105
106struct gpiobus_ivar
107{
108	struct resource_list	rl;	/* isr resource list */
109	uint32_t	npins;	/* pins total */
110	uint32_t	*pins;	/* pins map */
111};
112
113enum gpiobus_ivars {
114	GPIOBUS_IVAR_NPINS	= 10500,
115	GPIOBUS_IVAR_PINS,
116};
117
118#define GPIOBUS_ACCESSOR(var, ivar, type)                                 \
119        __BUS_ACCESSOR(gpiobus, var, GPIOBUS, ivar, type)
120
121GPIOBUS_ACCESSOR(npins,		NPINS,		uint32_t)
122GPIOBUS_ACCESSOR(pins,		PINS,		const uint32_t *)
123
124#undef GPIOBUS_ACCESSOR
125
126#ifdef FDT
127struct ofw_gpiobus_devinfo {
128	struct gpiobus_ivar	opd_dinfo;
129	struct ofw_bus_devinfo	opd_obdinfo;
130};
131
132static __inline int
133gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
134    pcell_t *gpios, uint32_t *pin, uint32_t *flags)
135{
136	return (GPIO_MAP_GPIOS(bus, dev, gparent, gcells, gpios, pin, flags));
137}
138
139device_t ofw_gpiobus_add_fdt_child(device_t, const char *, phandle_t);
140int ofw_gpiobus_parse_gpios(device_t, char *, struct gpiobus_pin **);
141void ofw_gpiobus_register_provider(device_t);
142void ofw_gpiobus_unregister_provider(device_t);
143
144/* Acquire a pin by parsing FDT data. */
145int gpio_pin_get_by_ofw_name(device_t consumer, phandle_t node,
146    char *name, gpio_pin_t *gpio);
147int gpio_pin_get_by_ofw_idx(device_t consumer, phandle_t node,
148    int idx, gpio_pin_t *gpio);
149int gpio_pin_get_by_ofw_property(device_t consumer, phandle_t node,
150    char *name, gpio_pin_t *gpio);
151int gpio_pin_get_by_ofw_propidx(device_t consumer, phandle_t node,
152    char *name, int idx, gpio_pin_t *gpio);
153#endif /* FDT */
154
155/* Acquire a pin by bus and pin number. */
156int gpio_pin_get_by_bus_pinnum(device_t _bus, uint32_t _pinnum, gpio_pin_t *_gp);
157
158/* Acquire a pin by child and index (used by direct children of gpiobus). */
159int gpio_pin_get_by_child_index(device_t _child, uint32_t _idx, gpio_pin_t *_gp);
160
161/* Release a pin acquired via any gpio_pin_get_xxx() function. */
162void gpio_pin_release(gpio_pin_t gpio);
163
164/* Work with gpio pins acquired using the functions above. */
165int gpio_pin_getcaps(gpio_pin_t pin, uint32_t *caps);
166int gpio_pin_is_active(gpio_pin_t pin, bool *active);
167int gpio_pin_set_active(gpio_pin_t pin, bool active);
168int gpio_pin_setflags(gpio_pin_t pin, uint32_t flags);
169struct resource *gpio_alloc_intr_resource(device_t consumer_dev, int *rid,
170    u_int alloc_flags, gpio_pin_t pin, uint32_t intr_mode);
171
172/*
173 * Functions shared between gpiobus and other bus classes that derive from it;
174 * these should not be called directly by other drivers.
175 */
176int gpio_check_flags(uint32_t, uint32_t);
177device_t gpiobus_attach_bus(device_t);
178int gpiobus_detach_bus(device_t);
179int gpiobus_init_softc(device_t);
180int gpiobus_alloc_ivars(struct gpiobus_ivar *);
181void gpiobus_free_ivars(struct gpiobus_ivar *);
182int gpiobus_acquire_pin(device_t, uint32_t);
183int gpiobus_release_pin(device_t, uint32_t);
184
185extern driver_t gpiobus_driver;
186
187#endif	/* __GPIOBUS_H__ */
188