xref: /openbsd-src/sys/dev/gpio/gpio.c (revision cf2525843d483a385de106a1361b2b9c18d96583)
1 /*	$OpenBSD: gpio.c,v 1.7 2006/03/26 18:48:17 grange Exp $	*/
2 
3 /*
4  * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * General Purpose Input/Output framework.
21  */
22 
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/conf.h>
26 #include <sys/device.h>
27 #include <sys/fcntl.h>
28 #include <sys/ioctl.h>
29 #include <sys/gpio.h>
30 #include <sys/vnode.h>
31 
32 #include <dev/gpio/gpiovar.h>
33 
34 struct gpio_softc {
35 	struct device sc_dev;
36 
37 	gpio_chipset_tag_t sc_gc;	/* our GPIO controller */
38 	gpio_pin_t *sc_pins;		/* pins array */
39 	int sc_npins;			/* total number of pins */
40 
41 	int sc_opened;
42 };
43 
44 int	gpio_match(struct device *, void *, void *);
45 void	gpio_attach(struct device *, struct device *, void *);
46 int	gpio_detach(struct device *, int);
47 int	gpio_search(struct device *, void *, void *);
48 int	gpio_print(void *, const char *);
49 
50 struct cfattach gpio_ca = {
51 	sizeof (struct gpio_softc),
52 	gpio_match,
53 	gpio_attach,
54 	gpio_detach
55 };
56 
57 struct cfdriver gpio_cd = {
58 	NULL, "gpio", DV_DULL
59 };
60 
61 int
62 gpio_match(struct device *parent, void *match, void *aux)
63 {
64 	struct cfdata *cf = match;
65 	struct gpiobus_attach_args *gba = aux;
66 
67 	if (strcmp(gba->gba_name, cf->cf_driver->cd_name) != 0)
68 		return (0);
69 
70 	return (1);
71 }
72 
73 void
74 gpio_attach(struct device *parent, struct device *self, void *aux)
75 {
76 	struct gpio_softc *sc = (struct gpio_softc *)self;
77 	struct gpiobus_attach_args *gba = aux;
78 
79 	sc->sc_gc = gba->gba_gc;
80 	sc->sc_pins = gba->gba_pins;
81 	sc->sc_npins = gba->gba_npins;
82 
83 	printf(": %d pins\n", sc->sc_npins);
84 
85 	/*
86 	 * Attach all devices that can be connected to the GPIO pins
87 	 * described in the kernel configuration file.
88 	 */
89 	config_search(gpio_search, self, sc);
90 }
91 
92 int
93 gpio_detach(struct device *self, int flags)
94 {
95 	int maj, mn;
96 
97 	/* Locate the major number */
98 	for (maj = 0; maj < nchrdev; maj++)
99 		if (cdevsw[maj].d_open == gpioopen)
100 			break;
101 
102 	/* Nuke the vnodes for any open instances (calls close) */
103 	mn = self->dv_unit;
104 	vdevgone(maj, mn, mn, VCHR);
105 
106 	return (0);
107 }
108 
109 int
110 gpio_search(struct device *parent, void *arg, void *aux)
111 {
112 	struct cfdata *cf = arg;
113 	struct gpio_attach_args ga;
114 
115 	ga.ga_gpio = aux;
116 	ga.ga_offset = cf->cf_loc[0];
117 	ga.ga_mask = cf->cf_loc[1];
118 
119 	if (cf->cf_attach->ca_match(parent, cf, &ga) > 0)
120 		config_attach(parent, cf, &ga, gpio_print);
121 
122 	return (0);
123 }
124 
125 int
126 gpio_print(void *aux, const char *pnp)
127 {
128 	struct gpio_attach_args *ga = aux;
129 	int i;
130 
131 	printf(" pins");
132 	for (i = 0; i < 32; i++)
133 		if (ga->ga_mask & (1 << i))
134 			printf(" %d", ga->ga_offset + i);
135 
136 	return (UNCONF);
137 }
138 
139 int
140 gpiobus_print(void *aux, const char *pnp)
141 {
142 	struct gpiobus_attach_args *gba = aux;
143 
144 	if (pnp != NULL)
145 		printf("%s at %s", gba->gba_name, pnp);
146 
147 	return (UNCONF);
148 }
149 
150 int
151 gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map)
152 {
153 	struct gpio_softc *sc = gpio;
154 	int npins, pin, i;
155 
156 	npins = gpio_npins(mask);
157 	if (npins > sc->sc_npins)
158 		return (1);
159 
160 	for (npins = 0, i = 0; i < 32; i++)
161 		if (mask & (1 << i)) {
162 			pin = offset + i;
163 			if (pin < 0 || pin >= sc->sc_npins)
164 				return (1);
165 			if (sc->sc_pins[pin].pin_mapped)
166 				return (1);
167 			sc->sc_pins[pin].pin_mapped = 1;
168 			map->pm_map[npins++] = pin;
169 		}
170 	map->pm_size = npins;
171 
172 	return (0);
173 }
174 
175 void
176 gpio_pin_unmap(void *gpio, struct gpio_pinmap *map)
177 {
178 	struct gpio_softc *sc = gpio;
179 	int pin, i;
180 
181 	for (i = 0; i < map->pm_size; i++) {
182 		pin = map->pm_map[i];
183 		sc->sc_pins[pin].pin_mapped = 0;
184 	}
185 }
186 
187 int
188 gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin)
189 {
190 	struct gpio_softc *sc = gpio;
191 
192 	return (gpiobus_pin_read(sc->sc_gc, map->pm_map[pin]));
193 }
194 
195 void
196 gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value)
197 {
198 	struct gpio_softc *sc = gpio;
199 
200 	return (gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value));
201 }
202 
203 void
204 gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags)
205 {
206 	struct gpio_softc *sc = gpio;
207 
208 	return (gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags));
209 }
210 
211 int
212 gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin)
213 {
214 	struct gpio_softc *sc = gpio;
215 
216 	return (sc->sc_pins[map->pm_map[pin]].pin_caps);
217 }
218 
219 int
220 gpio_npins(u_int32_t mask)
221 {
222 	int npins, i;
223 
224 	for (npins = 0, i = 0; i < 32; i++)
225 		if (mask & (1 << i))
226 			npins++;
227 
228 	return (npins);
229 }
230 
231 int
232 gpioopen(dev_t dev, int flag, int mode, struct proc *p)
233 {
234 	struct gpio_softc *sc;
235 
236 	sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
237 	if (sc == NULL)
238 		return (ENXIO);
239 
240 	if (sc->sc_opened)
241 		return (EBUSY);
242 	sc->sc_opened = 1;
243 
244 	return (0);
245 }
246 
247 int
248 gpioclose(dev_t dev, int flag, int mode, struct proc *p)
249 {
250 	struct gpio_softc *sc;
251 
252 	sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
253 	sc->sc_opened = 0;
254 
255 	return (0);
256 }
257 
258 int
259 gpioioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
260 {
261 	struct gpio_softc *sc;
262 	gpio_chipset_tag_t gc;
263 	struct gpio_info *info;
264 	struct gpio_pin_op *op;
265 	struct gpio_pin_ctl *ctl;
266 	int pin, value, flags;
267 
268 	sc = (struct gpio_softc *)device_lookup(&gpio_cd, minor(dev));
269 	gc = sc->sc_gc;
270 
271 	switch (cmd) {
272 	case GPIOINFO:
273 		info = (struct gpio_info *)data;
274 
275 		info->gpio_npins = sc->sc_npins;
276 		break;
277 	case GPIOPINREAD:
278 		op = (struct gpio_pin_op *)data;
279 
280 		pin = op->gp_pin;
281 		if (pin < 0 || pin >= sc->sc_npins)
282 			return (EINVAL);
283 
284 		/* return read value */
285 		op->gp_value = gpiobus_pin_read(gc, pin);
286 		break;
287 	case GPIOPINWRITE:
288 		if ((flag & FWRITE) == 0)
289 			return (EBADF);
290 
291 		op = (struct gpio_pin_op *)data;
292 
293 		pin = op->gp_pin;
294 		if (pin < 0 || pin >= sc->sc_npins)
295 			return (EINVAL);
296 		if (sc->sc_pins[pin].pin_mapped)
297 			return (EBUSY);
298 
299 		value = op->gp_value;
300 		if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
301 			return (EINVAL);
302 
303 		gpiobus_pin_write(gc, pin, value);
304 		/* return old value */
305 		op->gp_value = sc->sc_pins[pin].pin_state;
306 		/* update current value */
307 		sc->sc_pins[pin].pin_state = value;
308 		break;
309 	case GPIOPINTOGGLE:
310 		if ((flag & FWRITE) == 0)
311 			return (EBADF);
312 
313 		op = (struct gpio_pin_op *)data;
314 
315 		pin = op->gp_pin;
316 		if (pin < 0 || pin >= sc->sc_npins)
317 			return (EINVAL);
318 		if (sc->sc_pins[pin].pin_mapped)
319 			return (EBUSY);
320 
321 		value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
322 		    GPIO_PIN_HIGH : GPIO_PIN_LOW);
323 		gpiobus_pin_write(gc, pin, value);
324 		/* return old value */
325 		op->gp_value = sc->sc_pins[pin].pin_state;
326 		/* update current value */
327 		sc->sc_pins[pin].pin_state = value;
328 		break;
329 	case GPIOPINCTL:
330 		if ((flag & FWRITE) == 0)
331 			return (EBADF);
332 
333 		ctl = (struct gpio_pin_ctl *)data;
334 
335 		pin = ctl->gp_pin;
336 		if (pin < 0 || pin >= sc->sc_npins)
337 			return (EINVAL);
338 		if (sc->sc_pins[pin].pin_mapped)
339 			return (EBUSY);
340 
341 		flags = ctl->gp_flags;
342 		/* check that the controller supports all requested flags */
343 		if ((flags & sc->sc_pins[pin].pin_caps) != flags)
344 			return (ENODEV);
345 
346 		ctl->gp_caps = sc->sc_pins[pin].pin_caps;
347 		/* return old value */
348 		ctl->gp_flags = sc->sc_pins[pin].pin_flags;
349 		if (flags > 0) {
350 			gpiobus_pin_ctl(gc, pin, flags);
351 			/* update current value */
352 			sc->sc_pins[pin].pin_flags = flags;
353 		}
354 		break;
355 	default:
356 		return (ENOTTY);
357 	}
358 
359 	return (0);
360 }
361