xref: /freebsd/sys/dev/p2sb/lewisburg_gpiocm.c (revision cf416f56eb73006b32f9279da6a848299ede3f1d)
13706af42SArnaud Ysmal /*-
23706af42SArnaud Ysmal  * Copyright (c) 2018 Stormshield
33706af42SArnaud Ysmal  * All rights reserved.
43706af42SArnaud Ysmal  *
53706af42SArnaud Ysmal  * Redistribution and use in source and binary forms, with or without
63706af42SArnaud Ysmal  * modification, are permitted provided that the following conditions
73706af42SArnaud Ysmal  * are met:
83706af42SArnaud Ysmal  * 1. Redistributions of source code must retain the above copyright
93706af42SArnaud Ysmal  *    notice, this list of conditions and the following disclaimer.
103706af42SArnaud Ysmal  * 2. Redistributions in binary form must reproduce the above copyright
113706af42SArnaud Ysmal  *    notice, this list of conditions and the following disclaimer in the
123706af42SArnaud Ysmal  *    documentation and/or other materials provided with the distribution.
133706af42SArnaud Ysmal  *
143706af42SArnaud Ysmal  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
153706af42SArnaud Ysmal  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
163706af42SArnaud Ysmal  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
173706af42SArnaud Ysmal  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
183706af42SArnaud Ysmal  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
193706af42SArnaud Ysmal  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
203706af42SArnaud Ysmal  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
213706af42SArnaud Ysmal  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
223706af42SArnaud Ysmal  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
233706af42SArnaud Ysmal  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
243706af42SArnaud Ysmal  * SUCH DAMAGE.
253706af42SArnaud Ysmal  */
263706af42SArnaud Ysmal 
273706af42SArnaud Ysmal #include <sys/param.h>
283706af42SArnaud Ysmal #include <sys/module.h>
293706af42SArnaud Ysmal #include <sys/systm.h>
303706af42SArnaud Ysmal #include <sys/errno.h>
313706af42SArnaud Ysmal #include <sys/kernel.h>
323706af42SArnaud Ysmal #include <sys/malloc.h>
333706af42SArnaud Ysmal #include <sys/bus.h>
343706af42SArnaud Ysmal #include <sys/gpio.h>
353706af42SArnaud Ysmal 
363706af42SArnaud Ysmal #include <machine/bus.h>
373706af42SArnaud Ysmal #include <sys/rman.h>
383706af42SArnaud Ysmal #include <machine/resource.h>
393706af42SArnaud Ysmal 
403706af42SArnaud Ysmal #include "gpio_if.h"
413706af42SArnaud Ysmal 
423706af42SArnaud Ysmal #include "lewisburg_gpiocm.h"
433706af42SArnaud Ysmal #include "p2sb.h"
443706af42SArnaud Ysmal 
453706af42SArnaud Ysmal #define PADBAR	0x00c
463706af42SArnaud Ysmal 
473706af42SArnaud Ysmal #define PADCFG0_GPIORXDIS	(1<<9)
483706af42SArnaud Ysmal #define PADCFG0_GPIOTXDIS	(1<<8)
493706af42SArnaud Ysmal #define PADCFG0_GPIORXSTATE	(1<<1)
503706af42SArnaud Ysmal #define PADCFG0_GPIOTXSTATE	(1<<0)
513706af42SArnaud Ysmal 
523706af42SArnaud Ysmal #define MAX_PAD_PER_GROUP	24
533706af42SArnaud Ysmal 
543706af42SArnaud Ysmal #define LBGGPIOCM_READ(sc, reg) p2sb_port_read_4(sc->p2sb, sc->port, reg)
553706af42SArnaud Ysmal #define LBGGPIOCM_WRITE(sc, reg, val) \
563706af42SArnaud Ysmal 	p2sb_port_write_4(sc->p2sb, sc->port, reg, val)
573706af42SArnaud Ysmal #define LBGGPIOCM_LOCK(sc) p2sb_lock(sc->p2sb)
583706af42SArnaud Ysmal #define LBGGPIOCM_UNLOCK(sc) p2sb_unlock(sc->p2sb)
593706af42SArnaud Ysmal 
603706af42SArnaud Ysmal struct lbggroup {
613706af42SArnaud Ysmal 	int groupid;
623706af42SArnaud Ysmal 	int npins;
633706af42SArnaud Ysmal 	int pins_off;
643706af42SArnaud Ysmal 	device_t dev;
653706af42SArnaud Ysmal 	char grpname;
663706af42SArnaud Ysmal };
673706af42SArnaud Ysmal 
683706af42SArnaud Ysmal struct lbgcommunity {
693706af42SArnaud Ysmal 	uint8_t npins;
703706af42SArnaud Ysmal 	const char *name;
713706af42SArnaud Ysmal 	uint32_t pad_off;
723706af42SArnaud Ysmal 	struct lbggroup groups[3];
733706af42SArnaud Ysmal 	int ngroups;
743706af42SArnaud Ysmal 	const char *grpnames;
753706af42SArnaud Ysmal };
763706af42SArnaud Ysmal #define LBG_COMMUNITY(n, np, g) \
773706af42SArnaud Ysmal { \
783706af42SArnaud Ysmal 	.name = n, \
793706af42SArnaud Ysmal 	.npins = np, \
803706af42SArnaud Ysmal 	.grpnames = g, \
813706af42SArnaud Ysmal }
823706af42SArnaud Ysmal 
833706af42SArnaud Ysmal static struct lbgcommunity lbg_communities[] = {
843706af42SArnaud Ysmal 	LBG_COMMUNITY("LewisBurg GPIO Community 0", 72, "ABF"),
853706af42SArnaud Ysmal 	LBG_COMMUNITY("LewisBurg GPIO Community 1", 61, "CDE"),
863706af42SArnaud Ysmal 	LBG_COMMUNITY("LewisBurg GPIO Community 2", 0, ""),
873706af42SArnaud Ysmal 	LBG_COMMUNITY("LewisBurg GPIO Community 3", 12, "I"),
883706af42SArnaud Ysmal 	LBG_COMMUNITY("LewisBurg GPIO Community 4", 36, "JK"),
893706af42SArnaud Ysmal 	LBG_COMMUNITY("LewisBurg GPIO Community 5", 66, "GHL"),
903706af42SArnaud Ysmal };
913706af42SArnaud Ysmal 
923706af42SArnaud Ysmal struct lbggpiocm_softc
933706af42SArnaud Ysmal {
943706af42SArnaud Ysmal 	int port;
953706af42SArnaud Ysmal 	device_t p2sb;
963706af42SArnaud Ysmal 	struct lbgcommunity *community;
973706af42SArnaud Ysmal };
983706af42SArnaud Ysmal 
993706af42SArnaud Ysmal static struct lbggroup *lbggpiocm_get_group(struct lbggpiocm_softc *sc,
1003706af42SArnaud Ysmal     device_t child);
1013706af42SArnaud Ysmal 
1023706af42SArnaud Ysmal static __inline struct lbggroup *
lbggpiocm_get_group(struct lbggpiocm_softc * sc,device_t child)1033706af42SArnaud Ysmal lbggpiocm_get_group(struct lbggpiocm_softc *sc, device_t child)
1043706af42SArnaud Ysmal {
1053706af42SArnaud Ysmal 	int i;
1063706af42SArnaud Ysmal 
1073706af42SArnaud Ysmal 	for (i = 0; i < sc->community->ngroups; ++i)
1083706af42SArnaud Ysmal 		if (sc->community->groups[i].dev == child)
1093706af42SArnaud Ysmal 			return (&sc->community->groups[i]);
1103706af42SArnaud Ysmal 	return (NULL);
1113706af42SArnaud Ysmal }
1123706af42SArnaud Ysmal 
1133706af42SArnaud Ysmal 
1143706af42SArnaud Ysmal static __inline uint32_t
lbggpiocm_getpad(struct lbggpiocm_softc * sc,uint32_t pin)1153706af42SArnaud Ysmal lbggpiocm_getpad(struct lbggpiocm_softc *sc, uint32_t pin)
1163706af42SArnaud Ysmal {
1173706af42SArnaud Ysmal 
1183706af42SArnaud Ysmal 	if (pin >= sc->community->npins)
1193706af42SArnaud Ysmal 		return (0);
1203706af42SArnaud Ysmal 
1213706af42SArnaud Ysmal 	return (sc->community->pad_off + 2 * 4 * pin);
1223706af42SArnaud Ysmal }
1233706af42SArnaud Ysmal 
1243706af42SArnaud Ysmal int
lbggpiocm_get_group_npins(device_t dev,device_t child)1253706af42SArnaud Ysmal lbggpiocm_get_group_npins(device_t dev, device_t child)
1263706af42SArnaud Ysmal {
1273706af42SArnaud Ysmal 	struct lbggpiocm_softc *sc = device_get_softc(dev);
1283706af42SArnaud Ysmal 	struct lbggroup *group;
1293706af42SArnaud Ysmal 
1303706af42SArnaud Ysmal 	group = lbggpiocm_get_group(sc, child);
1313706af42SArnaud Ysmal 	if (group != NULL)
1323706af42SArnaud Ysmal 		return (group->npins);
1333706af42SArnaud Ysmal 	return (-1);
1343706af42SArnaud Ysmal }
1353706af42SArnaud Ysmal 
1363706af42SArnaud Ysmal char
lbggpiocm_get_group_name(device_t dev,device_t child)1373706af42SArnaud Ysmal lbggpiocm_get_group_name(device_t dev, device_t child)
1383706af42SArnaud Ysmal {
1393706af42SArnaud Ysmal 	struct lbggpiocm_softc *sc = device_get_softc(dev);
1403706af42SArnaud Ysmal 	struct lbggroup *group;
1413706af42SArnaud Ysmal 
1423706af42SArnaud Ysmal 	group = lbggpiocm_get_group(sc, child);
1433706af42SArnaud Ysmal 	if (group != NULL)
1443706af42SArnaud Ysmal 		return (group->grpname);
1453706af42SArnaud Ysmal 	return ('\0');
1463706af42SArnaud Ysmal }
1473706af42SArnaud Ysmal 
1483706af42SArnaud Ysmal static int
lbggpiocm_pin2cpin(struct lbggpiocm_softc * sc,device_t child,uint32_t pin)1493706af42SArnaud Ysmal lbggpiocm_pin2cpin(struct lbggpiocm_softc *sc, device_t child, uint32_t pin)
1503706af42SArnaud Ysmal {
1513706af42SArnaud Ysmal 	struct lbggroup *group;
1523706af42SArnaud Ysmal 
1533706af42SArnaud Ysmal 	group = lbggpiocm_get_group(sc, child);
1543706af42SArnaud Ysmal 	if (group != NULL)
1553706af42SArnaud Ysmal 		return (pin + group->pins_off);
1563706af42SArnaud Ysmal 	return (-1);
1573706af42SArnaud Ysmal }
1583706af42SArnaud Ysmal 
1593706af42SArnaud Ysmal int
lbggpiocm_pin_setflags(device_t dev,device_t child,uint32_t pin,uint32_t flags)1603706af42SArnaud Ysmal lbggpiocm_pin_setflags(device_t dev, device_t child, uint32_t pin, uint32_t flags)
1613706af42SArnaud Ysmal {
1623706af42SArnaud Ysmal 	struct lbggpiocm_softc *sc = device_get_softc(dev);
1633706af42SArnaud Ysmal 	uint32_t padreg, padval;
1643706af42SArnaud Ysmal 	int rpin;
1653706af42SArnaud Ysmal 
1663706af42SArnaud Ysmal 	if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
1673706af42SArnaud Ysmal 	    (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
1683706af42SArnaud Ysmal 		return (EINVAL);
1693706af42SArnaud Ysmal 
1703706af42SArnaud Ysmal 	if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 0)
1713706af42SArnaud Ysmal 		return (EINVAL);
1723706af42SArnaud Ysmal 
1733706af42SArnaud Ysmal 	rpin = lbggpiocm_pin2cpin(sc, child, pin);
1743706af42SArnaud Ysmal 	if (rpin < 0)
1753706af42SArnaud Ysmal 		return (EINVAL);
1763706af42SArnaud Ysmal 
1773706af42SArnaud Ysmal 	padreg = lbggpiocm_getpad(sc, rpin);
1783706af42SArnaud Ysmal 
1793706af42SArnaud Ysmal 	LBGGPIOCM_LOCK(sc);
1803706af42SArnaud Ysmal 	padval = LBGGPIOCM_READ(sc, padreg);
1813706af42SArnaud Ysmal 
1823706af42SArnaud Ysmal 	if (flags & GPIO_PIN_INPUT) {
1833706af42SArnaud Ysmal 		padval &= ~PADCFG0_GPIORXDIS;
1843706af42SArnaud Ysmal 		padval |= PADCFG0_GPIOTXDIS;
1853706af42SArnaud Ysmal 	} else if (flags & GPIO_PIN_OUTPUT) {
1863706af42SArnaud Ysmal 		padval &= ~PADCFG0_GPIOTXDIS;
1873706af42SArnaud Ysmal 		padval |= PADCFG0_GPIORXDIS;
1883706af42SArnaud Ysmal 	}
1893706af42SArnaud Ysmal 
1903706af42SArnaud Ysmal 	LBGGPIOCM_WRITE(sc, padreg, padval);
1913706af42SArnaud Ysmal 	LBGGPIOCM_UNLOCK(sc);
1923706af42SArnaud Ysmal 
1933706af42SArnaud Ysmal 	return (0);
1943706af42SArnaud Ysmal }
1953706af42SArnaud Ysmal 
1963706af42SArnaud Ysmal int
lbggpiocm_pin_get(device_t dev,device_t child,uint32_t pin,uint32_t * value)1973706af42SArnaud Ysmal lbggpiocm_pin_get(device_t dev, device_t child, uint32_t pin, uint32_t *value)
1983706af42SArnaud Ysmal {
1993706af42SArnaud Ysmal 	struct lbggpiocm_softc *sc = device_get_softc(dev);
2003706af42SArnaud Ysmal 	uint32_t padreg, val;
2013706af42SArnaud Ysmal 	int rpin;
2023706af42SArnaud Ysmal 
2033706af42SArnaud Ysmal 	if (value == NULL)
2043706af42SArnaud Ysmal 		return (EINVAL);
2053706af42SArnaud Ysmal 
2063706af42SArnaud Ysmal 	rpin = lbggpiocm_pin2cpin(sc, child, pin);
2073706af42SArnaud Ysmal 	if (rpin < 0)
2083706af42SArnaud Ysmal 		return (EINVAL);
2093706af42SArnaud Ysmal 
2103706af42SArnaud Ysmal 	padreg = lbggpiocm_getpad(sc, rpin);
2113706af42SArnaud Ysmal 
2123706af42SArnaud Ysmal 	LBGGPIOCM_LOCK(sc);
2133706af42SArnaud Ysmal 	val = LBGGPIOCM_READ(sc, padreg);
2143706af42SArnaud Ysmal 	LBGGPIOCM_UNLOCK(sc);
2153706af42SArnaud Ysmal 
2163706af42SArnaud Ysmal 	if (!(val & PADCFG0_GPIOTXDIS))
2173706af42SArnaud Ysmal 		*value = !!(val & PADCFG0_GPIOTXSTATE);
2183706af42SArnaud Ysmal 	else
2193706af42SArnaud Ysmal 		*value = !!(val & PADCFG0_GPIORXSTATE);
2203706af42SArnaud Ysmal 
2213706af42SArnaud Ysmal 	return (0);
2223706af42SArnaud Ysmal }
2233706af42SArnaud Ysmal 
2243706af42SArnaud Ysmal int
lbggpiocm_pin_set(device_t dev,device_t child,uint32_t pin,uint32_t value)2253706af42SArnaud Ysmal lbggpiocm_pin_set(device_t dev, device_t child, uint32_t pin, uint32_t value)
2263706af42SArnaud Ysmal {
2273706af42SArnaud Ysmal 	struct lbggpiocm_softc *sc = device_get_softc(dev);
2283706af42SArnaud Ysmal 	uint32_t padreg, padcfg;
2293706af42SArnaud Ysmal 	int rpin;
2303706af42SArnaud Ysmal 
2313706af42SArnaud Ysmal 	rpin = lbggpiocm_pin2cpin(sc, child, pin);
2323706af42SArnaud Ysmal 	if (rpin < 0)
2333706af42SArnaud Ysmal 		return (EINVAL);
2343706af42SArnaud Ysmal 
2353706af42SArnaud Ysmal 	padreg = lbggpiocm_getpad(sc, rpin);
2363706af42SArnaud Ysmal 
2373706af42SArnaud Ysmal 	LBGGPIOCM_LOCK(sc);
2383706af42SArnaud Ysmal 
2393706af42SArnaud Ysmal 	padcfg = LBGGPIOCM_READ(sc, padreg);
2403706af42SArnaud Ysmal 	if (value)
2413706af42SArnaud Ysmal 		padcfg |= PADCFG0_GPIOTXSTATE;
2423706af42SArnaud Ysmal 	else
2433706af42SArnaud Ysmal 		padcfg &= ~PADCFG0_GPIOTXSTATE;
2443706af42SArnaud Ysmal 	LBGGPIOCM_WRITE(sc, padreg, padcfg);
2453706af42SArnaud Ysmal 
2463706af42SArnaud Ysmal 	LBGGPIOCM_UNLOCK(sc);
2473706af42SArnaud Ysmal 
2483706af42SArnaud Ysmal 	return (0);
2493706af42SArnaud Ysmal }
2503706af42SArnaud Ysmal 
2513706af42SArnaud Ysmal int
lbggpiocm_pin_toggle(device_t dev,device_t child,uint32_t pin)2523706af42SArnaud Ysmal lbggpiocm_pin_toggle(device_t dev, device_t child, uint32_t pin)
2533706af42SArnaud Ysmal {
2543706af42SArnaud Ysmal 	struct lbggpiocm_softc *sc = device_get_softc(dev);
2553706af42SArnaud Ysmal 	uint32_t padreg, padcfg;
2563706af42SArnaud Ysmal 	int rpin;
2573706af42SArnaud Ysmal 
2583706af42SArnaud Ysmal 	rpin = lbggpiocm_pin2cpin(sc, child, pin);
2593706af42SArnaud Ysmal 	if (rpin < 0)
2603706af42SArnaud Ysmal 		return (EINVAL);
2613706af42SArnaud Ysmal 
2623706af42SArnaud Ysmal 	padreg = lbggpiocm_getpad(sc, rpin);
2633706af42SArnaud Ysmal 
2643706af42SArnaud Ysmal 	LBGGPIOCM_LOCK(sc);
2653706af42SArnaud Ysmal 	padcfg = LBGGPIOCM_READ(sc, padreg);
2663706af42SArnaud Ysmal 	padcfg ^= PADCFG0_GPIOTXSTATE;
2673706af42SArnaud Ysmal 	LBGGPIOCM_WRITE(sc, padreg, padcfg);
2683706af42SArnaud Ysmal 
2693706af42SArnaud Ysmal 	LBGGPIOCM_UNLOCK(sc);
2703706af42SArnaud Ysmal 
2713706af42SArnaud Ysmal 	return (0);
2723706af42SArnaud Ysmal }
2733706af42SArnaud Ysmal 
2743706af42SArnaud Ysmal static int
lbggpiocm_probe(device_t dev)2753706af42SArnaud Ysmal lbggpiocm_probe(device_t dev)
2763706af42SArnaud Ysmal {
2773706af42SArnaud Ysmal 	struct lbggpiocm_softc *sc = device_get_softc(dev);
2783706af42SArnaud Ysmal 	int unit;
2793706af42SArnaud Ysmal 
2803706af42SArnaud Ysmal 	sc->p2sb = device_get_parent(dev);
2813706af42SArnaud Ysmal 	unit = device_get_unit(dev);
2823706af42SArnaud Ysmal 	KASSERT(unit < nitems(lbg_communities), ("Wrong number of devices or communities"));
2833706af42SArnaud Ysmal 	sc->port = p2sb_get_port(sc->p2sb, unit);
2843706af42SArnaud Ysmal 	sc->community = &lbg_communities[unit];
2853706af42SArnaud Ysmal 	if (sc->port < 0)
2863706af42SArnaud Ysmal 		return (ENXIO);
2873706af42SArnaud Ysmal 
2883706af42SArnaud Ysmal 	device_set_desc(dev, sc->community->name);
2893706af42SArnaud Ysmal 	return (BUS_PROBE_DEFAULT);
2903706af42SArnaud Ysmal }
2913706af42SArnaud Ysmal 
2923706af42SArnaud Ysmal static int
lbggpiocm_attach(device_t dev)2933706af42SArnaud Ysmal lbggpiocm_attach(device_t dev)
2943706af42SArnaud Ysmal {
2953706af42SArnaud Ysmal 	uint32_t npins;
2963706af42SArnaud Ysmal 	struct lbggpiocm_softc *sc;
2973706af42SArnaud Ysmal 	struct lbggroup *group;
2983706af42SArnaud Ysmal 	int i;
2993706af42SArnaud Ysmal 
3003706af42SArnaud Ysmal 	sc = device_get_softc(dev);
3013706af42SArnaud Ysmal 	if (sc->community->npins == 0)
3023706af42SArnaud Ysmal 		return (ENXIO);
3033706af42SArnaud Ysmal 
3043706af42SArnaud Ysmal 	LBGGPIOCM_LOCK(sc);
3053706af42SArnaud Ysmal 	sc->community->pad_off = LBGGPIOCM_READ(sc, PADBAR);
3063706af42SArnaud Ysmal 	LBGGPIOCM_UNLOCK(sc);
3073706af42SArnaud Ysmal 
3083706af42SArnaud Ysmal 	npins = sc->community->npins;
3093706af42SArnaud Ysmal 	for (i = 0; i < nitems(sc->community->groups) && npins > 0; ++i) {
3103706af42SArnaud Ysmal 		group = &sc->community->groups[i];
3113706af42SArnaud Ysmal 
3123706af42SArnaud Ysmal 		group->groupid = i;
3133706af42SArnaud Ysmal 		group->grpname = sc->community->grpnames[i];
3143706af42SArnaud Ysmal 		group->pins_off = i * MAX_PAD_PER_GROUP;
3153706af42SArnaud Ysmal 		group->npins = npins < MAX_PAD_PER_GROUP ? npins :
3163706af42SArnaud Ysmal 			MAX_PAD_PER_GROUP;
3173706af42SArnaud Ysmal 		npins -= group->npins;
3183706af42SArnaud Ysmal 		group->dev = device_add_child(dev, "gpio", -1);
3193706af42SArnaud Ysmal 	}
3203706af42SArnaud Ysmal 	sc->community->ngroups = i;
32118250ec6SJohn Baldwin 	bus_attach_children(dev);
32218250ec6SJohn Baldwin 	return (0);
3233706af42SArnaud Ysmal }
3243706af42SArnaud Ysmal 
3253706af42SArnaud Ysmal static device_method_t lbggpiocm_methods[] = {
3263706af42SArnaud Ysmal 	/* Device interface */
3273706af42SArnaud Ysmal 	DEVMETHOD(device_probe,		lbggpiocm_probe),
3283706af42SArnaud Ysmal 	DEVMETHOD(device_attach,	lbggpiocm_attach),
329*cf416f56SJohn Baldwin 	DEVMETHOD(device_detach,	bus_generic_detach),
3303706af42SArnaud Ysmal 
3313706af42SArnaud Ysmal 	DEVMETHOD_END
3323706af42SArnaud Ysmal };
3333706af42SArnaud Ysmal 
3343706af42SArnaud Ysmal static driver_t lbggpiocm_driver = {
3353706af42SArnaud Ysmal 	"lbggpiocm",
3363706af42SArnaud Ysmal 	lbggpiocm_methods,
3373706af42SArnaud Ysmal 	sizeof(struct lbggpiocm_softc)
3383706af42SArnaud Ysmal };
339ba58fd66SJohn Baldwin 
340ba58fd66SJohn Baldwin DRIVER_MODULE(lbggpiocm, p2sb, lbggpiocm_driver, NULL, NULL);
341