gpioc.c revision 213237
1213237Sgonzo#include <sys/cdefs.h>
2213237Sgonzo__FBSDID("$FreeBSD: head/sys/dev/gpio/gpioc.c 213237 2010-09-28 03:24:53Z gonzo $");
3213237Sgonzo
4213237Sgonzo#include <sys/param.h>
5213237Sgonzo#include <sys/systm.h>
6213237Sgonzo#include <sys/types.h>
7213237Sgonzo
8213237Sgonzo#include <sys/bus.h>
9213237Sgonzo#include <sys/conf.h>
10213237Sgonzo#include <sys/ioccom.h>
11213237Sgonzo#include <sys/kernel.h>
12213237Sgonzo#include <sys/malloc.h>
13213237Sgonzo#include <sys/module.h>
14213237Sgonzo#include <sys/queue.h>
15213237Sgonzo#include <machine/bus.h>
16213237Sgonzo#include <machine/resource.h>
17213237Sgonzo
18213237Sgonzo#include <sys/gpio.h>
19213237Sgonzo#include "gpio_if.h"
20213237Sgonzo
21213237Sgonzo#undef GPIOC_DEBUG
22213237Sgonzo#ifdef GPIOC_DEBUG
23213237Sgonzo#define dprintf printf
24213237Sgonzo#else
25213237Sgonzo#define dprintf(x, arg...)
26213237Sgonzo#endif
27213237Sgonzo
28213237Sgonzostatic int gpioc_probe(device_t dev);
29213237Sgonzostatic int gpioc_attach(device_t dev);
30213237Sgonzostatic int gpioc_detach(device_t dev);
31213237Sgonzo
32213237Sgonzostatic d_ioctl_t	gpioc_ioctl;
33213237Sgonzo
34213237Sgonzostatic struct cdevsw gpioc_cdevsw = {
35213237Sgonzo	.d_version	= D_VERSION,
36213237Sgonzo	.d_ioctl	= gpioc_ioctl,
37213237Sgonzo	.d_name		= "gpioc",
38213237Sgonzo#if __FreeBSD_version >= 800039
39213237Sgonzo	.d_flags	= D_PSEUDO | D_NEEDMINOR
40213237Sgonzo#endif
41213237Sgonzo};
42213237Sgonzo
43213237Sgonzostruct gpioc_softc {
44213237Sgonzo	device_t	sc_dev;		/* gpiocX dev */
45213237Sgonzo	device_t	sc_pdev;	/* gpioX dev */
46213237Sgonzo	struct cdev	*sc_ctl_dev;	/* controller device */
47213237Sgonzo	int		sc_unit;
48213237Sgonzo};
49213237Sgonzo
50213237Sgonzostatic int
51213237Sgonzogpioc_probe(device_t dev)
52213237Sgonzo{
53213237Sgonzo	device_set_desc(dev, "GPIO controller");
54213237Sgonzo	return (0);
55213237Sgonzo}
56213237Sgonzo
57213237Sgonzostatic int
58213237Sgonzogpioc_attach(device_t dev)
59213237Sgonzo{
60213237Sgonzo	struct gpioc_softc *sc = device_get_softc(dev);
61213237Sgonzo
62213237Sgonzo	sc->sc_dev = dev;
63213237Sgonzo	sc->sc_pdev = device_get_parent(dev);
64213237Sgonzo	sc->sc_unit = device_get_unit(dev);
65213237Sgonzo	sc->sc_ctl_dev = make_dev(&gpioc_cdevsw, sc->sc_unit,
66213237Sgonzo	    UID_ROOT, GID_WHEEL, 0600, "gpioc%d", sc->sc_unit);
67213237Sgonzo	if (!sc->sc_ctl_dev) {
68213237Sgonzo		printf("Failed to create gpioc%d", sc->sc_unit);
69213237Sgonzo		return (ENXIO);
70213237Sgonzo	}
71213237Sgonzo	sc->sc_ctl_dev->si_drv1 = sc;
72213237Sgonzo
73213237Sgonzo	return (0);
74213237Sgonzo}
75213237Sgonzo
76213237Sgonzostatic int
77213237Sgonzogpioc_detach(device_t dev)
78213237Sgonzo{
79213237Sgonzo	struct gpioc_softc *sc = device_get_softc(dev);
80213237Sgonzo	int err;
81213237Sgonzo
82213237Sgonzo	if (sc->sc_ctl_dev);
83213237Sgonzo		destroy_dev(sc->sc_ctl_dev);
84213237Sgonzo
85213237Sgonzo	if ((err = bus_generic_detach(dev)) != 0)
86213237Sgonzo		return (err);
87213237Sgonzo
88213237Sgonzo	return (0);
89213237Sgonzo}
90213237Sgonzo
91213237Sgonzostatic int
92213237Sgonzogpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
93213237Sgonzo    struct thread *td)
94213237Sgonzo{
95213237Sgonzo	int max_pin, res;
96213237Sgonzo	struct gpioc_softc *sc = cdev->si_drv1;
97213237Sgonzo	struct gpio_pin pin;
98213237Sgonzo	struct gpio_req req;
99213237Sgonzo
100213237Sgonzo	switch (cmd) {
101213237Sgonzo		case GPIOMAXPIN:
102213237Sgonzo			max_pin = -1;
103213237Sgonzo			res = GPIO_PIN_MAX(sc->sc_pdev, &max_pin);
104213237Sgonzo			bcopy(&max_pin, arg, sizeof(max_pin));
105213237Sgonzo			break;
106213237Sgonzo		case GPIOGETCONFIG:
107213237Sgonzo			bcopy(arg, &pin, sizeof(pin));
108213237Sgonzo			dprintf("get config pin %d\n", pin.gp_pin);
109213237Sgonzo			res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin,
110213237Sgonzo			    &pin.gp_flags);
111213237Sgonzo			/* Fail early */
112213237Sgonzo			if (res)
113213237Sgonzo				break;
114213237Sgonzo			GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps);
115213237Sgonzo			GPIO_PIN_GETNAME(sc->sc_pdev, pin.gp_pin, pin.gp_name);
116213237Sgonzo			bcopy(&pin, arg, sizeof(pin));
117213237Sgonzo			break;
118213237Sgonzo		case GPIOSETCONFIG:
119213237Sgonzo			bcopy(arg, &pin, sizeof(pin));
120213237Sgonzo			dprintf("set config pin %d\n", pin.gp_pin);
121213237Sgonzo			res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin,
122213237Sgonzo			    pin.gp_flags);
123213237Sgonzo			break;
124213237Sgonzo		case GPIOGET:
125213237Sgonzo			bcopy(arg, &req, sizeof(req));
126213237Sgonzo			res = GPIO_PIN_GET(sc->sc_pdev, req.gp_pin,
127213237Sgonzo			    &req.gp_value);
128213237Sgonzo			dprintf("read pin %d -> %d\n",
129213237Sgonzo			    req.gp_pin, req.gp_value);
130213237Sgonzo			bcopy(&req, arg, sizeof(req));
131213237Sgonzo			break;
132213237Sgonzo		case GPIOSET:
133213237Sgonzo			bcopy(arg, &req, sizeof(req));
134213237Sgonzo			res = GPIO_PIN_SET(sc->sc_pdev, req.gp_pin,
135213237Sgonzo			    req.gp_value);
136213237Sgonzo			dprintf("write pin %d -> %d\n",
137213237Sgonzo			    req.gp_pin, req.gp_value);
138213237Sgonzo			break;
139213237Sgonzo		case GPIOTOGGLE:
140213237Sgonzo			bcopy(arg, &req, sizeof(req));
141213237Sgonzo			dprintf("toggle pin %d\n",
142213237Sgonzo			    req.gp_pin);
143213237Sgonzo			res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin);
144213237Sgonzo			break;
145213237Sgonzo		default:
146213237Sgonzo			return (ENOTTY);
147213237Sgonzo			break;
148213237Sgonzo	}
149213237Sgonzo
150213237Sgonzo	return (res);
151213237Sgonzo}
152213237Sgonzo
153213237Sgonzostatic device_method_t gpioc_methods[] = {
154213237Sgonzo	/* Device interface */
155213237Sgonzo	DEVMETHOD(device_probe,		gpioc_probe),
156213237Sgonzo	DEVMETHOD(device_attach,	gpioc_attach),
157213237Sgonzo	DEVMETHOD(device_detach,	gpioc_detach),
158213237Sgonzo	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
159213237Sgonzo	DEVMETHOD(device_suspend,	bus_generic_suspend),
160213237Sgonzo	DEVMETHOD(device_resume,	bus_generic_resume),
161213237Sgonzo
162213237Sgonzo	{ 0, 0 }
163213237Sgonzo};
164213237Sgonzo
165213237Sgonzostatic driver_t gpioc_driver = {
166213237Sgonzo	"gpioc",
167213237Sgonzo	gpioc_methods,
168213237Sgonzo	sizeof(struct gpioc_softc)
169213237Sgonzo};
170213237Sgonzo
171213237Sgonzodevclass_t	gpioc_devclass;
172213237Sgonzo
173213237SgonzoDRIVER_MODULE(gpioc, gpio, gpioc_driver, gpioc_devclass, 0, 0);
174213237SgonzoMODULE_VERSION(gpioc, 1);
175