16b34b16eSOleksandr Tymoshenko /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
46b34b16eSOleksandr Tymoshenko * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org>
56b34b16eSOleksandr Tymoshenko * All rights reserved.
66b34b16eSOleksandr Tymoshenko *
76b34b16eSOleksandr Tymoshenko * Redistribution and use in source and binary forms, with or without
86b34b16eSOleksandr Tymoshenko * modification, are permitted provided that the following conditions
96b34b16eSOleksandr Tymoshenko * are met:
106b34b16eSOleksandr Tymoshenko * 1. Redistributions of source code must retain the above copyright
116b34b16eSOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer.
126b34b16eSOleksandr Tymoshenko * 2. Redistributions in binary form must reproduce the above copyright
136b34b16eSOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer in the
146b34b16eSOleksandr Tymoshenko * documentation and/or other materials provided with the distribution.
156b34b16eSOleksandr Tymoshenko *
165f958b85SOleksandr Tymoshenko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
175f958b85SOleksandr Tymoshenko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
185f958b85SOleksandr Tymoshenko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
195f958b85SOleksandr Tymoshenko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
205f958b85SOleksandr Tymoshenko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
215f958b85SOleksandr Tymoshenko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
225f958b85SOleksandr Tymoshenko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
235f958b85SOleksandr Tymoshenko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
245f958b85SOleksandr Tymoshenko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
255f958b85SOleksandr Tymoshenko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
265f958b85SOleksandr Tymoshenko * SUCH DAMAGE.
276b34b16eSOleksandr Tymoshenko *
286b34b16eSOleksandr Tymoshenko */
296b34b16eSOleksandr Tymoshenko
306b34b16eSOleksandr Tymoshenko #ifndef __GPIOBUS_H__
316b34b16eSOleksandr Tymoshenko #define __GPIOBUS_H__
326b34b16eSOleksandr Tymoshenko
336d866ed3SLuiz Otavio O Souza #include "opt_platform.h"
346d866ed3SLuiz Otavio O Souza
356b34b16eSOleksandr Tymoshenko #include <sys/lock.h>
366b34b16eSOleksandr Tymoshenko #include <sys/mutex.h>
37138bf909SLuiz Otavio O Souza #include <sys/rman.h>
386b34b16eSOleksandr Tymoshenko
396d866ed3SLuiz Otavio O Souza #ifdef FDT
406d866ed3SLuiz Otavio O Souza #include <dev/ofw/ofw_bus_subr.h>
416d866ed3SLuiz Otavio O Souza #endif
426d866ed3SLuiz Otavio O Souza
4301decb50SAdrian Chadd #ifdef INTRNG
4401decb50SAdrian Chadd #include <sys/intr.h>
4501decb50SAdrian Chadd #endif
4601decb50SAdrian Chadd
478d250595SLuiz Otavio O Souza #include "gpio_if.h"
488d250595SLuiz Otavio O Souza
49b09d4398SLuiz Otavio O Souza #ifdef FDT
50b09d4398SLuiz Otavio O Souza #define GPIOBUS_IVAR(d) (struct gpiobus_ivar *) \
51b09d4398SLuiz Otavio O Souza &((struct ofw_gpiobus_devinfo *)device_get_ivars(d))->opd_dinfo
52b09d4398SLuiz Otavio O Souza #else
536b34b16eSOleksandr Tymoshenko #define GPIOBUS_IVAR(d) (struct gpiobus_ivar *) device_get_ivars(d)
54b09d4398SLuiz Otavio O Souza #endif
556b34b16eSOleksandr Tymoshenko #define GPIOBUS_SOFTC(d) (struct gpiobus_softc *) device_get_softc(d)
566d866ed3SLuiz Otavio O Souza #define GPIOBUS_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
576d866ed3SLuiz Otavio O Souza #define GPIOBUS_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
586d866ed3SLuiz Otavio O Souza #define GPIOBUS_LOCK_INIT(_sc) mtx_init(&_sc->sc_mtx, \
596d866ed3SLuiz Otavio O Souza device_get_nameunit(_sc->sc_dev), "gpiobus", MTX_DEF)
606d866ed3SLuiz Otavio O Souza #define GPIOBUS_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx)
616d866ed3SLuiz Otavio O Souza #define GPIOBUS_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED)
626d866ed3SLuiz Otavio O Souza #define GPIOBUS_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED)
636b34b16eSOleksandr Tymoshenko
649d35acacSLuiz Otavio O Souza #define GPIOBUS_WAIT 1
659d35acacSLuiz Otavio O Souza #define GPIOBUS_DONTWAIT 2
669d35acacSLuiz Otavio O Souza
6739f6c1bdSMichal Meloun /* Use default interrupt mode - for gpio_alloc_intr_resource */
6839f6c1bdSMichal Meloun #define GPIO_INTR_CONFORM GPIO_INTR_NONE
6939f6c1bdSMichal Meloun
70d752f0f6SLuiz Otavio O Souza struct gpiobus_pin_data
71d752f0f6SLuiz Otavio O Souza {
72d752f0f6SLuiz Otavio O Souza int mapped; /* pin is mapped/reserved. */
73d752f0f6SLuiz Otavio O Souza char *name; /* pin name. */
74d752f0f6SLuiz Otavio O Souza };
75d752f0f6SLuiz Otavio O Souza
76895c8b1cSMichal Meloun #ifdef INTRNG
77949883bdSMichal Meloun struct intr_map_data_gpio {
78949883bdSMichal Meloun struct intr_map_data hdr;
79949883bdSMichal Meloun u_int gpio_pin_num;
80949883bdSMichal Meloun u_int gpio_pin_flags;
81949883bdSMichal Meloun u_int gpio_intr_mode;
82949883bdSMichal Meloun };
83895c8b1cSMichal Meloun #endif
84949883bdSMichal Meloun
856b34b16eSOleksandr Tymoshenko struct gpiobus_softc
866b34b16eSOleksandr Tymoshenko {
876b34b16eSOleksandr Tymoshenko struct mtx sc_mtx; /* bus mutex */
88138bf909SLuiz Otavio O Souza struct rman sc_intr_rman; /* isr resources */
896b34b16eSOleksandr Tymoshenko device_t sc_busdev; /* bus device */
906b34b16eSOleksandr Tymoshenko device_t sc_owner; /* bus owner */
916b34b16eSOleksandr Tymoshenko device_t sc_dev; /* driver device */
926b34b16eSOleksandr Tymoshenko int sc_npins; /* total pins on bus */
93d752f0f6SLuiz Otavio O Souza struct gpiobus_pin_data *sc_pins; /* pin data */
946b34b16eSOleksandr Tymoshenko };
956b34b16eSOleksandr Tymoshenko
96e8da3e8aSLuiz Otavio O Souza struct gpiobus_pin
97e8da3e8aSLuiz Otavio O Souza {
98e8da3e8aSLuiz Otavio O Souza device_t dev; /* gpio device */
99e8da3e8aSLuiz Otavio O Souza uint32_t flags; /* pin flags */
100e8da3e8aSLuiz Otavio O Souza uint32_t pin; /* pin number */
101e8da3e8aSLuiz Otavio O Souza };
1028a4ba038SMichal Meloun typedef struct gpiobus_pin *gpio_pin_t;
103e8da3e8aSLuiz Otavio O Souza
1046b34b16eSOleksandr Tymoshenko struct gpiobus_ivar
1056b34b16eSOleksandr Tymoshenko {
106138bf909SLuiz Otavio O Souza struct resource_list rl; /* isr resource list */
1076b34b16eSOleksandr Tymoshenko uint32_t npins; /* pins total */
1086b34b16eSOleksandr Tymoshenko uint32_t *pins; /* pins map */
1096b34b16eSOleksandr Tymoshenko };
1106b34b16eSOleksandr Tymoshenko
111061b38cdSAndriy Gapon enum gpiobus_ivars {
112061b38cdSAndriy Gapon GPIOBUS_IVAR_NPINS = 10500,
113061b38cdSAndriy Gapon GPIOBUS_IVAR_PINS,
114061b38cdSAndriy Gapon };
115061b38cdSAndriy Gapon
116061b38cdSAndriy Gapon #define GPIOBUS_ACCESSOR(var, ivar, type) \
117061b38cdSAndriy Gapon __BUS_ACCESSOR(gpiobus, var, GPIOBUS, ivar, type)
118061b38cdSAndriy Gapon
119061b38cdSAndriy Gapon GPIOBUS_ACCESSOR(npins, NPINS, uint32_t)
120061b38cdSAndriy Gapon GPIOBUS_ACCESSOR(pins, PINS, const uint32_t *)
121061b38cdSAndriy Gapon
122061b38cdSAndriy Gapon #undef GPIOBUS_ACCESSOR
123061b38cdSAndriy Gapon
1246d866ed3SLuiz Otavio O Souza #ifdef FDT
125628a40b5SLuiz Otavio O Souza struct ofw_gpiobus_devinfo {
126628a40b5SLuiz Otavio O Souza struct gpiobus_ivar opd_dinfo;
127628a40b5SLuiz Otavio O Souza struct ofw_bus_devinfo opd_obdinfo;
128628a40b5SLuiz Otavio O Souza };
129628a40b5SLuiz Otavio O Souza
1308d250595SLuiz Otavio O Souza static __inline int
gpio_map_gpios(device_t bus,phandle_t dev,phandle_t gparent,int gcells,pcell_t * gpios,uint32_t * pin,uint32_t * flags)1318d250595SLuiz Otavio O Souza gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
1328d250595SLuiz Otavio O Souza pcell_t *gpios, uint32_t *pin, uint32_t *flags)
1338d250595SLuiz Otavio O Souza {
1348d250595SLuiz Otavio O Souza return (GPIO_MAP_GPIOS(bus, dev, gparent, gcells, gpios, pin, flags));
1358d250595SLuiz Otavio O Souza }
1368d250595SLuiz Otavio O Souza
137e8da3e8aSLuiz Otavio O Souza device_t ofw_gpiobus_add_fdt_child(device_t, const char *, phandle_t);
138e8da3e8aSLuiz Otavio O Souza int ofw_gpiobus_parse_gpios(device_t, char *, struct gpiobus_pin **);
139dbdb1205SLuiz Otavio O Souza void ofw_gpiobus_register_provider(device_t);
140dbdb1205SLuiz Otavio O Souza void ofw_gpiobus_unregister_provider(device_t);
1418a4ba038SMichal Meloun
14237045806SIan Lepore /* Acquire a pin by parsing FDT data. */
14351702162SOleksandr Tymoshenko int gpio_pin_get_by_ofw_name(device_t consumer, phandle_t node,
14451702162SOleksandr Tymoshenko char *name, gpio_pin_t *gpio);
14551702162SOleksandr Tymoshenko int gpio_pin_get_by_ofw_idx(device_t consumer, phandle_t node,
14651702162SOleksandr Tymoshenko int idx, gpio_pin_t *gpio);
14751702162SOleksandr Tymoshenko int gpio_pin_get_by_ofw_property(device_t consumer, phandle_t node,
14851702162SOleksandr Tymoshenko char *name, gpio_pin_t *gpio);
149dc027dc6SIan Lepore int gpio_pin_get_by_ofw_propidx(device_t consumer, phandle_t node,
150dc027dc6SIan Lepore char *name, int idx, gpio_pin_t *gpio);
15137045806SIan Lepore #endif /* FDT */
15237045806SIan Lepore
15337045806SIan Lepore /* Acquire a pin by bus and pin number. */
15437045806SIan Lepore int gpio_pin_get_by_bus_pinnum(device_t _bus, uint32_t _pinnum, gpio_pin_t *_gp);
15537045806SIan Lepore
15637045806SIan Lepore /* Acquire a pin by child and index (used by direct children of gpiobus). */
15737045806SIan Lepore int gpio_pin_get_by_child_index(device_t _child, uint32_t _idx, gpio_pin_t *_gp);
15837045806SIan Lepore
15937045806SIan Lepore /* Release a pin acquired via any gpio_pin_get_xxx() function. */
1608a4ba038SMichal Meloun void gpio_pin_release(gpio_pin_t gpio);
16137045806SIan Lepore
16237045806SIan Lepore /* Work with gpio pins acquired using the functions above. */
1635030d499SIan Lepore int gpio_pin_getcaps(gpio_pin_t pin, uint32_t *caps);
1648a4ba038SMichal Meloun int gpio_pin_is_active(gpio_pin_t pin, bool *active);
1658a4ba038SMichal Meloun int gpio_pin_set_active(gpio_pin_t pin, bool active);
1668a4ba038SMichal Meloun int gpio_pin_setflags(gpio_pin_t pin, uint32_t flags);
16739f6c1bdSMichal Meloun struct resource *gpio_alloc_intr_resource(device_t consumer_dev, int *rid,
16839f6c1bdSMichal Meloun u_int alloc_flags, gpio_pin_t pin, uint32_t intr_mode);
16937045806SIan Lepore
17037045806SIan Lepore /*
17137045806SIan Lepore * Functions shared between gpiobus and other bus classes that derive from it;
17237045806SIan Lepore * these should not be called directly by other drivers.
17337045806SIan Lepore */
174667357dcSLuiz Otavio O Souza int gpio_check_flags(uint32_t, uint32_t);
1757836352bSLuiz Otavio O Souza device_t gpiobus_attach_bus(device_t);
1767836352bSLuiz Otavio O Souza int gpiobus_detach_bus(device_t);
17792adaa58SAhmad Khalifa int gpiobus_attach(device_t);
17892adaa58SAhmad Khalifa int gpiobus_detach(device_t);
17988516632SLuiz Otavio O Souza int gpiobus_init_softc(device_t);
18050196301SLuiz Otavio O Souza int gpiobus_alloc_ivars(struct gpiobus_ivar *);
18150196301SLuiz Otavio O Souza void gpiobus_free_ivars(struct gpiobus_ivar *);
182*bc0d10d0SColin Percival int gpiobus_read_ivar(device_t, device_t, int, uintptr_t *);
183c45b8422SIan Lepore int gpiobus_acquire_pin(device_t, uint32_t);
1843381a389SOleksandr Tymoshenko int gpiobus_release_pin(device_t, uint32_t);
1856d866ed3SLuiz Otavio O Souza
1866d866ed3SLuiz Otavio O Souza extern driver_t gpiobus_driver;
1876d866ed3SLuiz Otavio O Souza
1886b34b16eSOleksandr Tymoshenko #endif /* __GPIOBUS_H__ */
189