Sun Aug 28 07:48:51 2011 UTC ()
Add a new ioctl, GPIOPULSE to gpio(4) to allow for pulsing a pin.
If a pin can pulse in hardware, that will be used, else it will
be pulsed in software.  There is no way yet to set the pulse frequency
for pins that pulse in hardware.  While here, make the code mpsafe and
allow more than one thread in the driver (access to ioctl is serialized).


(mbalmer)
diff -r1.18 -r1.19 src/share/man/man4/gpio.4
diff -r1.35 -r1.36 src/sys/dev/gpio/gpio.c
diff -r1.11 -r1.12 src/sys/dev/gpio/gpiovar.h
diff -r1.8 -r1.9 src/sys/sys/gpio.h
diff -r1.8 -r1.9 src/usr.sbin/gpioctl/gpioctl.8
diff -r1.10 -r1.11 src/usr.sbin/gpioctl/gpioctl.c

cvs diff -r1.18 -r1.19 src/share/man/man4/gpio.4 (expand / switch to unified diff)

--- src/share/man/man4/gpio.4 2010/03/22 18:58:31 1.18
+++ src/share/man/man4/gpio.4 2011/08/28 07:48:50 1.19
@@ -1,31 +1,31 @@ @@ -1,31 +1,31 @@
1.\" $NetBSD: gpio.4,v 1.18 2010/03/22 18:58:31 joerg Exp $ 1.\" $NetBSD: gpio.4,v 1.19 2011/08/28 07:48:50 mbalmer Exp $
2.\" $OpenBSD: gpio.4,v 1.5 2004/11/23 09:39:29 reyk Exp $ 2.\" $OpenBSD: gpio.4,v 1.5 2004/11/23 09:39:29 reyk Exp $
3.\" 3.\"
4.\" Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> 4.\" Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
5.\" 5.\"
6.\" Permission to use, copy, modify, and distribute this software for any 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 7.\" purpose with or without fee is hereby granted, provided that the above
8.\" copyright notice and this permission notice appear in all copies. 8.\" copyright notice and this permission notice appear in all copies.
9.\" 9.\"
10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 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 15.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17.\" 17.\"
18.Dd September 27, 2009 18.Dd August 21, 2011
19.Dt GPIO 4 19.Dt GPIO 4
20.Os 20.Os
21.Sh NAME 21.Sh NAME
22.Nm gpio 22.Nm gpio
23.Nd General Purpose Input/Output 23.Nd General Purpose Input/Output
24.Sh SYNOPSIS 24.Sh SYNOPSIS
25.Cd "gpio* at elansc?" 25.Cd "gpio* at elansc?"
26.Cd "gpio* at epgpio?" 26.Cd "gpio* at epgpio?"
27.Cd "gpio* at gcscpcib?" 27.Cd "gpio* at gcscpcib?"
28.Cd "gpio* at gpiosim?" 28.Cd "gpio* at gpiosim?"
29.Cd "gpio* at gscpcib?" 29.Cd "gpio* at gscpcib?"
30.Cd "gpio* at ichlpcib?" 30.Cd "gpio* at ichlpcib?"
31.Cd "gpio* at nsclpcsio?" 31.Cd "gpio* at nsclpcsio?"
@@ -113,26 +113,51 @@ field must be either @@ -113,26 +113,51 @@ field must be either
113.Dv GPIO_PIN_LOW 113.Dv GPIO_PIN_LOW
114(logical 0) or 114(logical 0) or
115.Dv GPIO_PIN_HIGH 115.Dv GPIO_PIN_HIGH
116(logical 1). 116(logical 1).
117On return, the 117On return, the
118.Fa gp_value 118.Fa gp_value
119field contains the old pin state. 119field contains the old pin state.
120.Pp 120.Pp
121.It Dv GPIOTOGGLE (struct gpio_req) 121.It Dv GPIOTOGGLE (struct gpio_req)
122Toggles the pin output value, i.e. changes it to the opposite. 122Toggles the pin output value, i.e. changes it to the opposite.
123.Fa gp_value 123.Fa gp_value
124field is ignored and on return contains the old pin state. 124field is ignored and on return contains the old pin state.
125.Pp 125.Pp
 126.It Dv GPIOPULSE (struct gpio_pulse)
 127Starts pulsing the pin:
 128.Bd -literal
 129/* GPIO pulse request */
 130struct gpio_pulse {
 131 char gp_name[GPIOMAXNAME]; /* pin name */
 132 int gp_pin; /* pin number */
 133 struct timeval gp_pulse_on; /* "on" period */
 134 struct timeval gp_pulse_off; /* "off" period */
 135};
 136.Ed
 137.Pp
 138The
 139.Fa gp_name
 140or
 141.Fa gp_pin
 142field must be set before calling.
 143If
 144.Fa gp_pulse_on
 145or
 146.Fa gp_pulse_off
 147is set to zero, a default of
 148.Xr hz 9 / 2
 149is assumed for both periods.
 150.Pp
126.It Dv GPIOSET (struct gpio_set) 151.It Dv GPIOSET (struct gpio_set)
127Changes pin configuration flags with the new ones provided in the 152Changes pin configuration flags with the new ones provided in the
128.Fa gpio_set 153.Fa gpio_set
129structure: 154structure:
130.Bd -literal 155.Bd -literal
131#define GPIOMAXNAME 64 156#define GPIOMAXNAME 64
132 157
133struct gpio_set { 158struct gpio_set {
134 char gp_name[GPIOMAXNAME]; /* pin name */ 159 char gp_name[GPIOMAXNAME]; /* pin name */
135 int gp_pin; /* pin number */ 160 int gp_pin; /* pin number */
136 int gp_caps; /* pin capabilities (ro) */ 161 int gp_caps; /* pin capabilities (ro) */
137 int gp_flags; /* pin configuration flags */ 162 int gp_flags; /* pin configuration flags */
138 char gp_name2[GPIOMAXNAME]; /* new name */ 163 char gp_name2[GPIOMAXNAME]; /* new name */

cvs diff -r1.35 -r1.36 src/sys/dev/gpio/gpio.c (expand / switch to unified diff)

--- src/sys/dev/gpio/gpio.c 2011/08/12 08:00:52 1.35
+++ src/sys/dev/gpio/gpio.c 2011/08/28 07:48:50 1.36
@@ -1,104 +1,114 @@ @@ -1,104 +1,114 @@
1/* $NetBSD: gpio.c,v 1.35 2011/08/12 08:00:52 mbalmer Exp $ */ 1/* $NetBSD: gpio.c,v 1.36 2011/08/28 07:48:50 mbalmer Exp $ */
2/* $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */ 2/* $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2008, 2009, 2010, 2011 Marc Balmer <marc@msys.ch> 5 * Copyright (c) 2008, 2009, 2010, 2011 Marc Balmer <marc@msys.ch>
6 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org> 6 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
7 * 7 *
8 * Permission to use, copy, modify, and distribute this software for any 8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above 9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies. 10 * copyright notice and this permission notice appear in all copies.
11 * 11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */ 19 */
20 20
21#include <sys/cdefs.h> 21#include <sys/cdefs.h>
22__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.35 2011/08/12 08:00:52 mbalmer Exp $"); 22__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.36 2011/08/28 07:48:50 mbalmer Exp $");
23 23
24/* 24/*
25 * General Purpose Input/Output framework. 25 * General Purpose Input/Output framework.
26 */ 26 */
27 27
28#include <sys/param.h> 28#include <sys/param.h>
 29#include <sys/callout.h>
29#include <sys/systm.h> 30#include <sys/systm.h>
30#include <sys/conf.h> 31#include <sys/conf.h>
31#include <sys/device.h> 32#include <sys/device.h>
32#include <sys/fcntl.h> 33#include <sys/fcntl.h>
33#include <sys/ioctl.h> 34#include <sys/ioctl.h>
34#include <sys/gpio.h> 35#include <sys/gpio.h>
 36#include <sys/kernel.h>
35#include <sys/vnode.h> 37#include <sys/vnode.h>
36#include <sys/kmem.h> 38#include <sys/kmem.h>
 39#include <sys/mutex.h>
 40#include <sys/condvar.h>
37#include <sys/queue.h> 41#include <sys/queue.h>
38#include <sys/kauth.h> 42#include <sys/kauth.h>
39#ifdef _MODULE 43#ifdef _MODULE
40#include <sys/module.h> 44#include <sys/module.h>
41#endif 45#endif
42#include <dev/gpio/gpiovar.h> 46#include <dev/gpio/gpiovar.h>
43 47
44#include "locators.h" 48#include "locators.h"
45 49
46#ifdef GPIO_DEBUG 50#ifdef GPIO_DEBUG
47#define DPRINTFN(n, x) do { if (gpiodebug > (n)) printf x; } while (0) 51#define DPRINTFN(n, x) do { if (gpiodebug > (n)) printf x; } while (0)
48int gpiodebug = 0; 52int gpiodebug = 0;
49#else 53#else
50#define DPRINTFN(n, x) 54#define DPRINTFN(n, x)
51#endif 55#endif
52#define DPRINTF(x) DPRINTFN(0, x) 56#define DPRINTF(x) DPRINTFN(0, x)
53 57
54struct gpio_softc { 58struct gpio_softc {
55 device_t sc_dev; 59 device_t sc_dev;
56 60
57 gpio_chipset_tag_t sc_gc; /* GPIO controller */ 61 gpio_chipset_tag_t sc_gc; /* GPIO controller */
58 gpio_pin_t *sc_pins; /* pins array */ 62 gpio_pin_t *sc_pins; /* pins array */
59 int sc_npins; /* number of pins */ 63 int sc_npins; /* number of pins */
60 64
61 int sc_opened; 65 kmutex_t sc_mtx;
 66 kcondvar_t sc_ioctl; /* ioctl in progress */
 67 int sc_ioctl_busy; /* ioctl is busy */
62 LIST_HEAD(, gpio_dev) sc_devs; /* devices */ 68 LIST_HEAD(, gpio_dev) sc_devs; /* devices */
63 LIST_HEAD(, gpio_name) sc_names; /* named pins */ 69 LIST_HEAD(, gpio_name) sc_names; /* named pins */
64}; 70};
65 71
66static int gpio_match(device_t, cfdata_t, void *); 72static int gpio_match(device_t, cfdata_t, void *);
67int gpio_submatch(device_t, cfdata_t, const int *, void *); 73int gpio_submatch(device_t, cfdata_t, const int *, void *);
68static void gpio_attach(device_t, device_t, void *); 74static void gpio_attach(device_t, device_t, void *);
69static int gpio_rescan(device_t, const char *, const int *); 75static int gpio_rescan(device_t, const char *, const int *);
70static void gpio_childdetached(device_t, device_t); 76static void gpio_childdetached(device_t, device_t);
71static bool gpio_resume(device_t, const pmf_qual_t *); 77static bool gpio_resume(device_t, const pmf_qual_t *);
72static int gpio_detach(device_t, int); 78static int gpio_detach(device_t, int);
73static int gpio_search(device_t, cfdata_t, const int *, void *); 79static int gpio_search(device_t, cfdata_t, const int *, void *);
74static int gpio_print(void *, const char *); 80static int gpio_print(void *, const char *);
75static int gpio_pinbyname(struct gpio_softc *, char *); 81static int gpio_pinbyname(struct gpio_softc *, char *);
 82static void gpio_pulse(void *);
 83static int gpio_ioctl(struct gpio_softc *, u_long, void *, int,
 84 struct lwp *);
76 85
77/* Old API */ 86/* Old API */
78static int gpio_ioctl_oapi(struct gpio_softc *, u_long, void *, int, 87static int gpio_ioctl_oapi(struct gpio_softc *, u_long, void *, int,
79 kauth_cred_t); 88 kauth_cred_t);
80 89
81CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc), 90CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc),
82 gpio_match, gpio_attach, gpio_detach, NULL, gpio_rescan, 91 gpio_match, gpio_attach, gpio_detach, NULL, gpio_rescan,
83 gpio_childdetached, DVF_DETACH_SHUTDOWN); 92 gpio_childdetached, DVF_DETACH_SHUTDOWN);
84 93
85dev_type_open(gpioopen); 94dev_type_open(gpioopen);
86dev_type_close(gpioclose); 95dev_type_close(gpioclose);
87dev_type_ioctl(gpioioctl); 96dev_type_ioctl(gpioioctl);
 97dev_type_ioctl(gpioioctl_locked);
88 98
89const struct cdevsw gpio_cdevsw = { 99const struct cdevsw gpio_cdevsw = {
90 gpioopen, gpioclose, noread, nowrite, gpioioctl, 100 gpioopen, gpioclose, noread, nowrite, gpioioctl,
91 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER, 101 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER | D_MPSAFE
92}; 102};
93 103
94extern struct cfdriver gpio_cd; 104extern struct cfdriver gpio_cd;
95 105
96static int 106static int
97gpio_match(device_t parent, cfdata_t cf, void *aux) 107gpio_match(device_t parent, cfdata_t cf, void *aux)
98{ 108{
99 return 1; 109 return 1;
100} 110}
101 111
102int 112int
103gpio_submatch(device_t parent, cfdata_t cf, const int *ip, void *aux) 113gpio_submatch(device_t parent, cfdata_t cf, const int *ip, void *aux)
104{ 114{
@@ -134,52 +144,71 @@ gpio_rescan(device_t self, const char *i @@ -134,52 +144,71 @@ gpio_rescan(device_t self, const char *i
134{ 144{
135 struct gpio_softc *sc = device_private(self); 145 struct gpio_softc *sc = device_private(self);
136 146
137 config_search_loc(gpio_search, self, ifattr, locators, sc); 147 config_search_loc(gpio_search, self, ifattr, locators, sc);
138 148
139 return 0; 149 return 0;
140} 150}
141 151
142static void 152static void
143gpio_attach(device_t parent, device_t self, void *aux) 153gpio_attach(device_t parent, device_t self, void *aux)
144{ 154{
145 struct gpio_softc *sc = device_private(self); 155 struct gpio_softc *sc = device_private(self);
146 struct gpiobus_attach_args *gba = aux; 156 struct gpiobus_attach_args *gba = aux;
147 157 int pin;
148 sc->sc_dev = self; 158 sc->sc_dev = self;
149 sc->sc_gc = gba->gba_gc; 159 sc->sc_gc = gba->gba_gc;
150 sc->sc_pins = gba->gba_pins; 160 sc->sc_pins = gba->gba_pins;
151 sc->sc_npins = gba->gba_npins; 161 sc->sc_npins = gba->gba_npins;
152 162
153 printf(": %d pins\n", sc->sc_npins); 163 printf(": %d pins\n", sc->sc_npins);
154 164
 165 for (pin = 0; pin < sc->sc_npins; pin++) {
 166 callout_init(&sc->sc_pins[pin].pin_pulse, CALLOUT_MPSAFE);
 167 callout_setfunc(&sc->sc_pins[pin].pin_pulse, gpio_pulse,
 168 &sc->sc_pins[pin]);
 169 }
155 if (!pmf_device_register(self, NULL, gpio_resume)) 170 if (!pmf_device_register(self, NULL, gpio_resume))
156 aprint_error_dev(self, "couldn't establish power handler\n"); 171 aprint_error_dev(self, "couldn't establish power handler\n");
 172 mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM);
 173 cv_init(&sc->sc_ioctl, "gpioctl");
157 174
158 /* 175 /*
159 * Attach all devices that can be connected to the GPIO pins 176 * Attach all devices that can be connected to the GPIO pins
160 * described in the kernel configuration file. 177 * described in the kernel configuration file.
161 */ 178 */
162 gpio_rescan(self, "gpio", NULL); 179 gpio_rescan(self, "gpio", NULL);
163} 180}
164 181
165static int 182static int
166gpio_detach(device_t self, int flags) 183gpio_detach(device_t self, int flags)
167{ 184{
168 int rc; 185 struct gpio_softc *sc;
 186 int pin, rc;
 187
 188 sc = device_private(self);
 189
 190 for (pin = 0; pin < sc->sc_npins; pin++) {
 191 if (sc->sc_pins[pin].pin_state & GPIO_PIN_PULSE) {
 192 callout_halt(&sc->sc_pins[pin].pin_pulse, NULL);
 193 callout_destroy(&sc->sc_pins[pin].pin_pulse);
 194 sc->sc_pins[pin].pin_state &= ~GPIO_PIN_PULSE;
 195 }
 196 }
169 197
170 if ((rc = config_detach_children(self, flags)) != 0) 198 if ((rc = config_detach_children(self, flags)) != 0)
171 return rc; 199 return rc;
172 200 mutex_destroy(&sc->sc_mtx);
 201 cv_destroy(&sc->sc_ioctl);
173#if 0 202#if 0
174 int maj, mn; 203 int maj, mn;
175 204
176 /* Locate the major number */ 205 /* Locate the major number */
177 for (maj = 0; maj < nchrdev; maj++) 206 for (maj = 0; maj < nchrdev; maj++)
178 if (cdevsw[maj].d_open == gpioopen) 207 if (cdevsw[maj].d_open == gpioopen)
179 break; 208 break;
180 209
181 /* Nuke the vnodes for any open instances (calls close) */ 210 /* Nuke the vnodes for any open instances (calls close) */
182 mn = device_unit(self); 211 mn = device_unit(self);
183 vdevgone(maj, mn, mn, VCHR); 212 vdevgone(maj, mn, mn, VCHR);
184#endif 213#endif
185 return 0; 214 return 0;
@@ -218,49 +247,49 @@ int @@ -218,49 +247,49 @@ int
218gpiobus_print(void *aux, const char *pnp) 247gpiobus_print(void *aux, const char *pnp)
219{ 248{
220#if 0 249#if 0
221 struct gpiobus_attach_args *gba = aux; 250 struct gpiobus_attach_args *gba = aux;
222#endif 251#endif
223 if (pnp != NULL) 252 if (pnp != NULL)
224 aprint_normal("gpiobus at %s", pnp); 253 aprint_normal("gpiobus at %s", pnp);
225 254
226 return UNCONF; 255 return UNCONF;
227} 256}
228 257
229/* return 1 if all pins can be mapped, 0 if not */ 258/* return 1 if all pins can be mapped, 0 if not */
230int 259int
231gpio_pin_can_map(void *gpio, int offset, u_int32_t mask) 260gpio_pin_can_map(void *gpio, int offset, uint32_t mask)
232{ 261{
233 struct gpio_softc *sc = gpio; 262 struct gpio_softc *sc = gpio;
234 int npins, pin, i; 263 int npins, pin, i;
235 264
236 npins = gpio_npins(mask); 265 npins = gpio_npins(mask);
237 if (npins > sc->sc_npins) 266 if (npins > sc->sc_npins)
238 return 0; 267 return 0;
239 268
240 for (npins = 0, i = 0; i < 32; i++) 269 for (npins = 0, i = 0; i < 32; i++)
241 if (mask & (1 << i)) { 270 if (mask & (1 << i)) {
242 pin = offset + i; 271 pin = offset + i;
243 if (pin < 0 || pin >= sc->sc_npins) 272 if (pin < 0 || pin >= sc->sc_npins)
244 return 0; 273 return 0;
245 if (sc->sc_pins[pin].pin_mapped) 274 if (sc->sc_pins[pin].pin_mapped)
246 return 0; 275 return 0;
247 } 276 }
248 277
249 return 1; 278 return 1;
250} 279}
251 280
252int 281int
253gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map) 282gpio_pin_map(void *gpio, int offset, uint32_t mask, struct gpio_pinmap *map)
254{ 283{
255 struct gpio_softc *sc = gpio; 284 struct gpio_softc *sc = gpio;
256 int npins, pin, i; 285 int npins, pin, i;
257 286
258 npins = gpio_npins(mask); 287 npins = gpio_npins(mask);
259 if (npins > sc->sc_npins) 288 if (npins > sc->sc_npins)
260 return 1; 289 return 1;
261 290
262 for (npins = 0, i = 0; i < 32; i++) 291 for (npins = 0, i = 0; i < 32; i++)
263 if (mask & (1 << i)) { 292 if (mask & (1 << i)) {
264 pin = offset + i; 293 pin = offset + i;
265 if (pin < 0 || pin >= sc->sc_npins) 294 if (pin < 0 || pin >= sc->sc_npins)
266 return 1; 295 return 1;
@@ -310,196 +339,289 @@ gpio_pin_ctl(void *gpio, struct gpio_pin @@ -310,196 +339,289 @@ gpio_pin_ctl(void *gpio, struct gpio_pin
310 339
311 return gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags); 340 return gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags);
312} 341}
313 342
314int 343int
315gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin) 344gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin)
316{ 345{
317 struct gpio_softc *sc = gpio; 346 struct gpio_softc *sc = gpio;
318 347
319 return sc->sc_pins[map->pm_map[pin]].pin_caps; 348 return sc->sc_pins[map->pm_map[pin]].pin_caps;
320} 349}
321 350
322int 351int
323gpio_npins(u_int32_t mask) 352gpio_npins(uint32_t mask)
324{ 353{
325 int npins, i; 354 int npins, i;
326 355
327 for (npins = 0, i = 0; i < 32; i++) 356 for (npins = 0, i = 0; i < 32; i++)
328 if (mask & (1 << i)) 357 if (mask & (1 << i))
329 npins++; 358 npins++;
330 359
331 return npins; 360 return npins;
332} 361}
333 362
334int 363int
 364gpio_lock(void *data)
 365{
 366 struct gpio_softc *sc;
 367 int error;
 368
 369 error = 0;
 370 sc = (struct gpio_softc *)data;
 371 mutex_enter(&sc->sc_mtx);
 372 while (sc->sc_ioctl_busy) {
 373 error = cv_wait_sig(&sc->sc_ioctl, &sc->sc_mtx);
 374 if (error)
 375 break;
 376 }
 377 if (!error)
 378 sc->sc_ioctl_busy = 1;
 379 mutex_exit(&sc->sc_mtx);
 380 return error;
 381}
 382
 383void
 384gpio_unlock(void *data)
 385{
 386 struct gpio_softc *sc;
 387
 388 sc = (struct gpio_softc *)data;
 389 mutex_enter(&sc->sc_mtx);
 390 sc->sc_ioctl_busy = 0;
 391 cv_signal(&sc->sc_ioctl);
 392 mutex_exit(&sc->sc_mtx);
 393}
 394
 395int
335gpioopen(dev_t dev, int flag, int mode, struct lwp *l) 396gpioopen(dev_t dev, int flag, int mode, struct lwp *l)
336{ 397{
337 struct gpio_softc *sc; 398 struct gpio_softc *sc;
338 int ret; 
339 399
340 sc = device_lookup_private(&gpio_cd, minor(dev)); 400 sc = device_lookup_private(&gpio_cd, minor(dev));
341 if (sc == NULL) 401 if (sc == NULL)
342 return ENXIO; 402 return ENXIO;
343 DPRINTF(("%s: opening\n", device_xname(sc->sc_dev))); 
344 if (sc->sc_opened) { 
345 DPRINTF(("%s: already opened\n", device_xname(sc->sc_dev))); 
346 return EBUSY; 
347 } 
348 
349 if ((ret = gpiobus_open(sc->sc_gc, sc->sc_dev))) { 
350 DPRINTF(("%s: gpiobus_open returned %d\n", 
351 device_xname(sc->sc_dev), 
352 ret)); 
353 return ret; 
354 } 
355 
356 sc->sc_opened = 1; 
357 403
358 return 0; 404 return gpiobus_open(sc->sc_gc, sc->sc_dev);
359} 405}
360 406
361int 407int
362gpioclose(dev_t dev, int flag, int mode, struct lwp *l) 408gpioclose(dev_t dev, int flag, int mode, struct lwp *l)
363{ 409{
364 struct gpio_softc *sc; 410 struct gpio_softc *sc;
365 411
366 sc = device_lookup_private(&gpio_cd, minor(dev)); 412 sc = device_lookup_private(&gpio_cd, minor(dev));
367 DPRINTF(("%s: closing\n", device_xname(sc->sc_dev))); 413 gpiobus_close(sc->sc_gc, sc->sc_dev);
368 (void)gpiobus_close(sc->sc_gc, sc->sc_dev); 
369 sc->sc_opened = 0; 
370 
371 return 0; 414 return 0;
372} 415}
373 416
374static int 417static int
375gpio_pinbyname(struct gpio_softc *sc, char *gp_name) 418gpio_pinbyname(struct gpio_softc *sc, char *gp_name)
376{ 419{
377 struct gpio_name *nm; 420 struct gpio_name *nm;
378 421
379 LIST_FOREACH(nm, &sc->sc_names, gp_next) 422 LIST_FOREACH(nm, &sc->sc_names, gp_next)
380 if (!strcmp(nm->gp_name, gp_name)) 423 if (!strcmp(nm->gp_name, gp_name))
381 return nm->gp_pin; 424 return nm->gp_pin;
382 return -1; 425 return -1;
383} 426}
384 427
 428static void
 429gpio_pulse(void *arg)
 430{
 431 struct gpio_pin *pin;
 432
 433 pin = (struct gpio_pin *)arg;
 434 if ((pin->pin_state & GPIO_PIN_PULSE) == 0)
 435 return;
 436
 437 if (pin->pin_state & GPIO_PIN_HIGH) {
 438 gpiobus_pin_write(pin->pin_gc, pin->pin_num, GPIO_PIN_LOW);
 439 pin->pin_state &= ~GPIO_PIN_HIGH;
 440 callout_schedule(&pin->pin_pulse, pin->pin_ticks_off);
 441 } else {
 442 gpiobus_pin_write(pin->pin_gc, pin->pin_num, GPIO_PIN_HIGH);
 443 pin->pin_state |= GPIO_PIN_HIGH;
 444 callout_schedule(&pin->pin_pulse, pin->pin_ticks_on);
 445 }
 446}
 447
385int 448int
386gpioioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 449gpioioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
387{ 450{
 451 int error;
388 struct gpio_softc *sc; 452 struct gpio_softc *sc;
 453
 454 sc = device_lookup_private(&gpio_cd, minor(dev));
 455
 456 error = gpio_lock(sc);
 457 if (error)
 458 return error;
 459
 460 error = gpio_ioctl(sc, cmd, data, flag, l);
 461 gpio_unlock(sc);
 462 return error;
 463}
 464
 465static int
 466gpio_ioctl(struct gpio_softc *sc, u_long cmd, void *data, int flag,
 467 struct lwp *l)
 468{
389 gpio_chipset_tag_t gc; 469 gpio_chipset_tag_t gc;
390 struct gpio_info *info; 470 struct gpio_info *info;
391 struct gpio_attach *attach; 471 struct gpio_attach *attach;
392 struct gpio_attach_args ga; 472 struct gpio_attach_args ga;
393 struct gpio_dev *gdev; 473 struct gpio_dev *gdev;
394 struct gpio_req *req; 474 struct gpio_req *req;
 475 struct gpio_pulse *pulse;
395 struct gpio_name *nm; 476 struct gpio_name *nm;
396 struct gpio_set *set; 477 struct gpio_set *set;
 478 struct gpio_pin *gpin;
397 device_t dv; 479 device_t dv;
398 cfdata_t cf; 480 cfdata_t cf;
399 kauth_cred_t cred; 481 kauth_cred_t cred;
400 int locs[GPIOCF_NLOCS]; 482 int locs[GPIOCF_NLOCS];
401 int pin, value, flags, npins; 483 int pin, value, flags, npins;
402 484
403 sc = device_lookup_private(&gpio_cd, minor(dev)); 
404 gc = sc->sc_gc; 485 gc = sc->sc_gc;
405 486
406 if (cmd != GPIOINFO && !device_is_active(sc->sc_dev)) { 487 if (cmd != GPIOINFO && !device_is_active(sc->sc_dev)) {
407 DPRINTF(("%s: device is not active\n", 488 DPRINTF(("%s: device is not active\n",
408 device_xname(sc->sc_dev))); 489 device_xname(sc->sc_dev)));
409 return EBUSY; 490 return EBUSY;
410 } 491 }
411 492
412 cred = kauth_cred_get(); 493 cred = kauth_cred_get();
413 494
414 switch (cmd) { 495 switch (cmd) {
415 case GPIOINFO: 496 case GPIOINFO:
416 info = (struct gpio_info *)data; 497 info = (struct gpio_info *)data;
417 if (!kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET, 498 if (!kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
418 NULL, NULL, NULL, NULL)) 499 NULL, NULL, NULL, NULL))
419 info->gpio_npins = sc->sc_npins; 500 info->gpio_npins = sc->sc_npins;
420 else { 501 else {
421 for (pin = npins = 0; pin < sc->sc_npins; pin++) 502 for (pin = npins = 0; pin < sc->sc_npins; pin++)
422 if (sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) 503 if (sc->sc_pins[pin].pin_flags & GPIO_PIN_SET)
423 ++npins; 504 ++npins;
424 info->gpio_npins = npins; 505 info->gpio_npins = npins;
425 } 506 }
426 break; 507 break;
427 case GPIOREAD: 508 case GPIOREAD:
428 req = (struct gpio_req *)data; 509 req = (struct gpio_req *)data;
429 510
430 if (req->gp_name[0] != '\0') { 511 if (req->gp_name[0] != '\0')
431 pin = gpio_pinbyname(sc, req->gp_name); 512 pin = gpio_pinbyname(sc, req->gp_name);
432 if (pin == -1) 513 else
433 return EINVAL; 
434 } else 
435 pin = req->gp_pin; 514 pin = req->gp_pin;
436 515
437 if (pin < 0 || pin >= sc->sc_npins) 516 if (pin < 0 || pin >= sc->sc_npins)
438 return EINVAL; 517 return EINVAL;
439 518
440 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && 519 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
441 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET, 520 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
442 NULL, NULL, NULL, NULL)) 521 NULL, NULL, NULL, NULL))
443 return EPERM; 522 return EPERM;
444 523
445 /* return read value */ 524 /* return read value */
446 req->gp_value = gpiobus_pin_read(gc, pin); 525 req->gp_value = gpiobus_pin_read(gc, pin);
447 break; 526 break;
448 case GPIOWRITE: 527 case GPIOWRITE:
449 if ((flag & FWRITE) == 0) 528 if ((flag & FWRITE) == 0)
450 return EBADF; 529 return EBADF;
451 530
452 req = (struct gpio_req *)data; 531 req = (struct gpio_req *)data;
453 532
454 if (req->gp_name[0] != '\0') { 533 if (req->gp_name[0] != '\0')
455 pin = gpio_pinbyname(sc, req->gp_name); 534 pin = gpio_pinbyname(sc, req->gp_name);
456 if (pin == -1) 535 else
457 return EINVAL; 
458 } else 
459 pin = req->gp_pin; 536 pin = req->gp_pin;
460 537
461 if (pin < 0 || pin >= sc->sc_npins) 538 if (pin < 0 || pin >= sc->sc_npins)
462 return EINVAL; 539 return EINVAL;
463 540
464 if (sc->sc_pins[pin].pin_mapped) 541 if (sc->sc_pins[pin].pin_mapped)
465 return EBUSY; 542 return EBUSY;
466 543
467 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && 544 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
468 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET, 545 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
469 NULL, NULL, NULL, NULL)) 546 NULL, NULL, NULL, NULL))
470 return EPERM; 547 return EPERM;
471 548
472 value = req->gp_value; 549 value = req->gp_value;
473 if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH) 550 if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
474 return EINVAL; 551 return EINVAL;
475 552
 553 if (sc->sc_pins[pin].pin_state & GPIO_PIN_PULSE) {
 554 callout_halt(&sc->sc_pins[pin].pin_pulse, NULL);
 555 sc->sc_pins[pin].pin_state &= ~GPIO_PIN_PULSE;
 556 }
476 gpiobus_pin_write(gc, pin, value); 557 gpiobus_pin_write(gc, pin, value);
477 /* return old value */ 558 /* return old value */
478 req->gp_value = sc->sc_pins[pin].pin_state; 559 req->gp_value = sc->sc_pins[pin].pin_state;
479 /* update current value */ 560 /* update current value */
480 sc->sc_pins[pin].pin_state = value; 561 sc->sc_pins[pin].pin_state = value;
481 break; 562 break;
 563 case GPIOPULSE:
 564 if ((flag & FWRITE) == 0)
 565 return EBADF;
 566
 567 pulse = (struct gpio_pulse *)data;
 568 if (pulse->gp_name[0] != '\0')
 569 pin = gpio_pinbyname(sc, pulse->gp_name);
 570 else
 571 pin = pulse->gp_pin;
 572
 573 if (pin < 0 || pin >= sc->sc_npins)
 574 return EINVAL;
 575
 576 gpin = &sc->sc_pins[pin];
 577 if (gpin->pin_mapped)
 578 return EBUSY;
 579
 580 if (!(gpin->pin_flags & GPIO_PIN_SET) &&
 581 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 582 NULL, NULL, NULL, NULL))
 583 return EPERM;
 584
 585 if (gpin->pin_flags & GPIO_PIN_PULSATE) {
 586 gpiobus_pin_write(gc, pin, GPIO_PIN_HIGH);
 587 gpin->pin_state = GPIO_PIN_PULSE;
 588 return 0;
 589 }
 590
 591 if (gpin->pin_state & GPIO_PIN_PULSE)
 592 callout_halt(&gpin->pin_pulse, NULL);
 593
 594 gpin->pin_gc = gc;
 595
 596 gpin->pin_ticks_on = tvtohz(&pulse->gp_pulse_on);
 597 gpin->pin_ticks_off = tvtohz(&pulse->gp_pulse_off);
 598 if (gpin->pin_ticks_on == 0 || gpin->pin_ticks_off == 0) {
 599 gpin->pin_ticks_on = hz / 2;
 600 gpin->pin_ticks_off = hz / 2;
 601 }
 602 gpiobus_pin_write(gc, pin, GPIO_PIN_HIGH);
 603 gpin->pin_state = GPIO_PIN_HIGH | GPIO_PIN_PULSE;
 604 callout_schedule(&gpin->pin_pulse, gpin->pin_ticks_on);
 605 break;
482 case GPIOTOGGLE: 606 case GPIOTOGGLE:
483 if ((flag & FWRITE) == 0) 607 if ((flag & FWRITE) == 0)
484 return EBADF; 608 return EBADF;
485 609
486 req = (struct gpio_req *)data; 610 req = (struct gpio_req *)data;
487 611
488 if (req->gp_name[0] != '\0') { 612 if (req->gp_name[0] != '\0')
489 pin = gpio_pinbyname(sc, req->gp_name); 613 pin = gpio_pinbyname(sc, req->gp_name);
490 if (pin == -1) 614 else
491 return EINVAL; 
492 } else 
493 pin = req->gp_pin; 615 pin = req->gp_pin;
494 616
495 if (pin < 0 || pin >= sc->sc_npins) 617 if (pin < 0 || pin >= sc->sc_npins)
496 return EINVAL; 618 return EINVAL;
497 619
498 if (sc->sc_pins[pin].pin_mapped) 620 if (sc->sc_pins[pin].pin_mapped)
499 return EBUSY; 621 return EBUSY;
500 622
501 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && 623 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
502 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET, 624 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
503 NULL, NULL, NULL, NULL)) 625 NULL, NULL, NULL, NULL))
504 return EPERM; 626 return EPERM;
505 627
@@ -516,80 +638,79 @@ gpioioctl(dev_t dev, u_long cmd, void *d @@ -516,80 +638,79 @@ gpioioctl(dev_t dev, u_long cmd, void *d
516 NULL, NULL, NULL, NULL)) 638 NULL, NULL, NULL, NULL))
517 return EPERM; 639 return EPERM;
518 640
519 attach = (struct gpio_attach *)data; 641 attach = (struct gpio_attach *)data;
520 642
521 /* do not try to attach if the pins are already mapped */ 643 /* do not try to attach if the pins are already mapped */
522 if (!gpio_pin_can_map(sc, attach->ga_offset, attach->ga_mask)) 644 if (!gpio_pin_can_map(sc, attach->ga_offset, attach->ga_mask))
523 return EBUSY; 645 return EBUSY;
524 646
525 ga.ga_gpio = sc; 647 ga.ga_gpio = sc;
526 ga.ga_dvname = attach->ga_dvname; 648 ga.ga_dvname = attach->ga_dvname;
527 ga.ga_offset = attach->ga_offset; 649 ga.ga_offset = attach->ga_offset;
528 ga.ga_mask = attach->ga_mask; 650 ga.ga_mask = attach->ga_mask;
529 DPRINTF(("%s: attach %s with offset %d and mask 0x%02x\n", 651 ga.ga_nolock = 1;
530 device_xname(sc->sc_dev), ga.ga_dvname, ga.ga_offset, 652 DPRINTF(("%s: attach %s with offset %d and mask "
531 ga.ga_mask)); 653 "0x%02x\n", device_xname(sc->sc_dev), ga.ga_dvname,
 654 ga.ga_offset, ga.ga_mask));
532 655
533 locs[GPIOCF_OFFSET] = ga.ga_offset; 656 locs[GPIOCF_OFFSET] = ga.ga_offset;
534 locs[GPIOCF_MASK] = ga.ga_mask; 657 locs[GPIOCF_MASK] = ga.ga_mask;
535 658
536 cf = config_search_loc(NULL, sc->sc_dev, "gpio", locs, &ga); 659 cf = config_search_loc(NULL, sc->sc_dev, "gpio", locs, &ga);
537 if (cf != NULL) { 660 if (cf != NULL) {
538 dv = config_attach_loc(sc->sc_dev, cf, locs, &ga, 661 dv = config_attach_loc(sc->sc_dev, cf, locs, &ga,
539 gpiobus_print); 662 gpiobus_print);
540 if (dv != NULL) { 663 if (dv != NULL) {
541 gdev = kmem_alloc(sizeof(struct gpio_dev), 664 gdev = kmem_alloc(sizeof(struct gpio_dev),
542 KM_SLEEP); 665 KM_SLEEP);
543 gdev->sc_dev = dv; 666 gdev->sc_dev = dv;
544 LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next); 667 LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next);
545 } else 668 } else
546 return EINVAL; 669 return EINVAL;
547 } else 670 } else
548 return EINVAL; 671 return EINVAL;
549 break; 672 return 0;
550 case GPIODETACH: 673 case GPIODETACH:
551 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET, 674 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
552 NULL, NULL, NULL, NULL)) 675 NULL, NULL, NULL, NULL))
553 return EPERM; 676 return EPERM;
554 677
555 attach = (struct gpio_attach *)data; 678 attach = (struct gpio_attach *)data;
556 LIST_FOREACH(gdev, &sc->sc_devs, sc_next) { 679 LIST_FOREACH(gdev, &sc->sc_devs, sc_next) {
557 if (strcmp(device_xname(gdev->sc_dev), 680 if (strcmp(device_xname(gdev->sc_dev),
558 attach->ga_dvname) == 0) { 681 attach->ga_dvname) == 0) {
559 if (config_detach(gdev->sc_dev, 0) == 0) { 682 if (config_detach(gdev->sc_dev, 0) == 0) {
560 LIST_REMOVE(gdev, sc_next); 683 LIST_REMOVE(gdev, sc_next);
561 kmem_free(gdev, 684 kmem_free(gdev,
562 sizeof(struct gpio_dev)); 685 sizeof(struct gpio_dev));
563 return 0; 686 return 0;
564 } 687 }
565 break; 688 break;
566 } 689 }
567 } 690 }
568 return EINVAL; 691 return EINVAL;
569 break; 
570 case GPIOSET: 692 case GPIOSET:
571 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET, 693 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
572 NULL, NULL, NULL, NULL)) 694 NULL, NULL, NULL, NULL))
573 return EPERM; 695 return EPERM;
574 696
575 set = (struct gpio_set *)data; 697 set = (struct gpio_set *)data;
576 698
577 if (set->gp_name[0] != '\0') { 699 if (set->gp_name[0] != '\0')
578 pin = gpio_pinbyname(sc, set->gp_name); 700 pin = gpio_pinbyname(sc, set->gp_name);
579 if (pin == -1) 701 else
580 return EINVAL; 
581 } else 
582 pin = set->gp_pin; 702 pin = set->gp_pin;
 703
583 if (pin < 0 || pin >= sc->sc_npins) 704 if (pin < 0 || pin >= sc->sc_npins)
584 return EINVAL; 705 return EINVAL;
585 flags = set->gp_flags; 706 flags = set->gp_flags;
586 707
587 /* check that the controller supports all requested flags */ 708 /* check that the controller supports all requested flags */
588 if ((flags & sc->sc_pins[pin].pin_caps) != flags) 709 if ((flags & sc->sc_pins[pin].pin_caps) != flags)
589 return ENODEV; 710 return ENODEV;
590 flags = set->gp_flags | GPIO_PIN_SET; 711 flags = set->gp_flags | GPIO_PIN_SET;
591 712
592 set->gp_caps = sc->sc_pins[pin].pin_caps; 713 set->gp_caps = sc->sc_pins[pin].pin_caps;
593 /* return old value */ 714 /* return old value */
594 set->gp_flags = sc->sc_pins[pin].pin_flags; 715 set->gp_flags = sc->sc_pins[pin].pin_flags;
595 if (flags > 0) { 716 if (flags > 0) {
@@ -619,31 +740,29 @@ gpioioctl(dev_t dev, u_long cmd, void *d @@ -619,31 +740,29 @@ gpioioctl(dev_t dev, u_long cmd, void *d
619 strlcpy(nm->gp_name, set->gp_name2, 740 strlcpy(nm->gp_name, set->gp_name2,
620 sizeof(nm->gp_name)); 741 sizeof(nm->gp_name));
621 nm->gp_pin = set->gp_pin; 742 nm->gp_pin = set->gp_pin;
622 LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next); 743 LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next);
623 } 744 }
624 } 745 }
625 break; 746 break;
626 case GPIOUNSET: 747 case GPIOUNSET:
627 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET, 748 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
628 NULL, NULL, NULL, NULL)) 749 NULL, NULL, NULL, NULL))
629 return EPERM; 750 return EPERM;
630 751
631 set = (struct gpio_set *)data; 752 set = (struct gpio_set *)data;
632 if (set->gp_name[0] != '\0') { 753 if (set->gp_name[0] != '\0')
633 pin = gpio_pinbyname(sc, set->gp_name); 754 pin = gpio_pinbyname(sc, set->gp_name);
634 if (pin == -1) 755 else
635 return EINVAL; 
636 } else 
637 pin = set->gp_pin; 756 pin = set->gp_pin;
638 757
639 if (pin < 0 || pin >= sc->sc_npins) 758 if (pin < 0 || pin >= sc->sc_npins)
640 return EINVAL; 759 return EINVAL;
641 if (sc->sc_pins[pin].pin_mapped) 760 if (sc->sc_pins[pin].pin_mapped)
642 return EBUSY; 761 return EBUSY;
643 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET)) 762 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET))
644 return EINVAL; 763 return EINVAL;
645 764
646 LIST_FOREACH(nm, &sc->sc_names, gp_next) { 765 LIST_FOREACH(nm, &sc->sc_names, gp_next) {
647 if (nm->gp_pin == pin) { 766 if (nm->gp_pin == pin) {
648 LIST_REMOVE(nm, gp_next); 767 LIST_REMOVE(nm, gp_next);
649 kmem_free(nm, sizeof(struct gpio_name)); 768 kmem_free(nm, sizeof(struct gpio_name));

cvs diff -r1.11 -r1.12 src/sys/dev/gpio/gpiovar.h (expand / switch to unified diff)

--- src/sys/dev/gpio/gpiovar.h 2011/08/12 08:00:52 1.11
+++ src/sys/dev/gpio/gpiovar.h 2011/08/28 07:48:50 1.12
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: gpiovar.h,v 1.11 2011/08/12 08:00:52 mbalmer Exp $ */ 1/* $NetBSD: gpiovar.h,v 1.12 2011/08/28 07:48:50 mbalmer Exp $ */
2/* $OpenBSD: gpiovar.h,v 1.3 2006/01/14 12:33:49 grange Exp $ */ 2/* $OpenBSD: gpiovar.h,v 1.3 2006/01/14 12:33:49 grange Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org> 5 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
@@ -25,76 +25,84 @@ @@ -25,76 +25,84 @@
25/* GPIO controller description */ 25/* GPIO controller description */
26typedef struct gpio_chipset_tag { 26typedef struct gpio_chipset_tag {
27 void *gp_cookie; 27 void *gp_cookie;
28 28
29 int (*gp_gc_open)(void *, device_t); 29 int (*gp_gc_open)(void *, device_t);
30 void (*gp_gc_close)(void *, device_t); 30 void (*gp_gc_close)(void *, device_t);
31 int (*gp_pin_read)(void *, int); 31 int (*gp_pin_read)(void *, int);
32 void (*gp_pin_write)(void *, int, int); 32 void (*gp_pin_write)(void *, int, int);
33 void (*gp_pin_ctl)(void *, int, int); 33 void (*gp_pin_ctl)(void *, int, int);
34} *gpio_chipset_tag_t; 34} *gpio_chipset_tag_t;
35 35
36/* GPIO pin description */ 36/* GPIO pin description */
37typedef struct gpio_pin { 37typedef struct gpio_pin {
38 int pin_num; /* number */ 38 int pin_num; /* number */
39 int pin_caps; /* capabilities */ 39 int pin_caps; /* capabilities */
40 int pin_flags; /* current configuration */ 40 int pin_flags; /* current configuration */
41 int pin_state; /* current state */ 41 int pin_state; /* current state */
42 int pin_mapped; /* is mapped */ 42 int pin_mapped; /* is mapped */
 43 callout_t pin_pulse; /* for pulsing */
 44 int pin_ticks_on; /* "on" period */
 45 int pin_ticks_off; /* "off" period */
 46 gpio_chipset_tag_t pin_gc; /* reference the controller */
43} gpio_pin_t; 47} gpio_pin_t;
44 48
45/* Attach GPIO framework to the controller */ 49/* Attach GPIO framework to the controller */
46struct gpiobus_attach_args { 50struct gpiobus_attach_args {
47 gpio_chipset_tag_t gba_gc; /* underlying controller */ 51 gpio_chipset_tag_t gba_gc; /* underlying controller */
48 gpio_pin_t *gba_pins; /* pins array */ 52 gpio_pin_t *gba_pins; /* pins array */
49 int gba_npins; /* total number of pins */ 53 int gba_npins; /* total number of pins */
50}; 54};
51 55
52int gpiobus_print(void *, const char *); 56int gpiobus_print(void *, const char *);
53 57
54/* GPIO framework private methods */ 58/* GPIO framework private methods */
55#define gpiobus_open(gc, dev) \ 59#define gpiobus_open(gc, dev) \
56 ((gc)->gp_gc_open ? ((gc)->gp_gc_open((gc)->gp_cookie, dev)) : 0) 60 ((gc)->gp_gc_open ? ((gc)->gp_gc_open((gc)->gp_cookie, dev)) : 0)
57#define gpiobus_close(gc, dev) \ 61#define gpiobus_close(gc, dev) \
58 ((gc)->gp_gc_close ? ((gc)->gp_gc_close((gc)->gp_cookie, dev)), 1 : 0) 62 ((gc)->gp_gc_close ? ((gc)->gp_gc_close((gc)->gp_cookie, dev)), 1 : 0)
59#define gpiobus_pin_read(gc, pin) \ 63#define gpiobus_pin_read(gc, pin) \
60 ((gc)->gp_pin_read((gc)->gp_cookie, (pin))) 64 ((gc)->gp_pin_read((gc)->gp_cookie, (pin)))
61#define gpiobus_pin_write(gc, pin, value) \ 65#define gpiobus_pin_write(gc, pin, value) \
62 ((gc)->gp_pin_write((gc)->gp_cookie, (pin), (value))) 66 ((gc)->gp_pin_write((gc)->gp_cookie, (pin), (value)))
63#define gpiobus_pin_ctl(gc, pin, flags) \ 67#define gpiobus_pin_ctl(gc, pin, flags) \
64 ((gc)->gp_pin_ctl((gc)->gp_cookie, (pin), (flags))) 68 ((gc)->gp_pin_ctl((gc)->gp_cookie, (pin), (flags)))
65 69
66/* Attach devices connected to the GPIO pins */ 70/* Attach devices connected to the GPIO pins */
67struct gpio_attach_args { 71struct gpio_attach_args {
68 void *ga_gpio; 72 void *ga_gpio;
69 int ga_offset; 73 int ga_offset;
70 u_int32_t ga_mask; 74 uint32_t ga_mask;
71 char *ga_dvname; 75 char *ga_dvname;
 76 int ga_nolock;
72}; 77};
73 78
74/* GPIO pin map */ 79/* GPIO pin map */
75struct gpio_pinmap { 80struct gpio_pinmap {
76 int *pm_map; /* pin map */ 81 int *pm_map; /* pin map */
77 int pm_size; /* map size */ 82 int pm_size; /* map size */
78}; 83};
79 84
80struct gpio_dev { 85struct gpio_dev {
81 device_t sc_dev; /* the gpio device */ 86 device_t sc_dev; /* the gpio device */
82 LIST_ENTRY(gpio_dev) sc_next; 87 LIST_ENTRY(gpio_dev) sc_next;
83}; 88};
84 89
85struct gpio_name { 90struct gpio_name {
86 char gp_name[GPIOMAXNAME]; 91 char gp_name[GPIOMAXNAME];
87 int gp_pin; 92 int gp_pin;
88 LIST_ENTRY(gpio_name) gp_next; 93 LIST_ENTRY(gpio_name) gp_next;
89}; 94};
90 95
91int gpio_pin_can_map(void *, int, u_int32_t); 96int gpio_pin_can_map(void *, int, uint32_t);
92int gpio_pin_map(void *, int, u_int32_t, struct gpio_pinmap *); 97int gpio_pin_map(void *, int, uint32_t, struct gpio_pinmap *);
93void gpio_pin_unmap(void *, struct gpio_pinmap *); 98void gpio_pin_unmap(void *, struct gpio_pinmap *);
94int gpio_pin_read(void *, struct gpio_pinmap *, int); 99int gpio_pin_read(void *, struct gpio_pinmap *, int);
95void gpio_pin_write(void *, struct gpio_pinmap *, int, int); 100void gpio_pin_write(void *, struct gpio_pinmap *, int, int);
96void gpio_pin_ctl(void *, struct gpio_pinmap *, int, int); 101void gpio_pin_ctl(void *, struct gpio_pinmap *, int, int);
97int gpio_pin_caps(void *, struct gpio_pinmap *, int); 102int gpio_pin_caps(void *, struct gpio_pinmap *, int);
98int gpio_npins(u_int32_t); 103int gpio_npins(uint32_t);
 104
 105int gpio_lock(void *);
 106void gpio_unlock(void *);
99 107
100#endif /* !_DEV_GPIO_GPIOVAR_H_ */ 108#endif /* !_DEV_GPIO_GPIOVAR_H_ */

cvs diff -r1.8 -r1.9 src/sys/sys/gpio.h (expand / switch to unified diff)

--- src/sys/sys/gpio.h 2011/06/23 00:46:37 1.8
+++ src/sys/sys/gpio.h 2011/08/28 07:48:50 1.9
@@ -1,38 +1,41 @@ @@ -1,38 +1,41 @@
1/* $NetBSD: gpio.h,v 1.8 2011/06/23 00:46:37 matt Exp $ */ 1/* $NetBSD: gpio.h,v 1.9 2011/08/28 07:48:50 mbalmer Exp $ */
2/* $OpenBSD: gpio.h,v 1.7 2008/11/26 14:51:20 mbalmer Exp $ */ 2/* $OpenBSD: gpio.h,v 1.7 2008/11/26 14:51:20 mbalmer Exp $ */
3/* 3/*
4 * Copyright (c) 2009 Marc Balmer <marc@msys.ch> 4 * Copyright (c) 2009 Marc Balmer <marc@msys.ch>
5 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> 5 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */ 18 */
19 19
20#ifndef _SYS_GPIO_H_ 20#ifndef _SYS_GPIO_H_
21#define _SYS_GPIO_H_ 21#define _SYS_GPIO_H_
22 22
 23#include <sys/time.h>
 24
23/* GPIO pin states */ 25/* GPIO pin states */
24#define GPIO_PIN_LOW 0x00 /* low level (logical 0) */ 26#define GPIO_PIN_LOW 0x00 /* low level (logical 0) */
25#define GPIO_PIN_HIGH 0x01 /* high level (logical 1) */ 27#define GPIO_PIN_HIGH 0x01 /* high level (logical 1) */
 28#define GPIO_PIN_PULSE 0x02 /* pulsing, or-ed with state */
26 29
27/* Max name length of a pin */ 30/* Max name length of a pin */
28#define GPIOMAXNAME 64 31#define GPIOMAXNAME 64
29 32
30/* GPIO pin configuration flags */ 33/* GPIO pin configuration flags */
31#define GPIO_PIN_INPUT 0x0001 /* input direction */ 34#define GPIO_PIN_INPUT 0x0001 /* input direction */
32#define GPIO_PIN_OUTPUT 0x0002 /* output direction */ 35#define GPIO_PIN_OUTPUT 0x0002 /* output direction */
33#define GPIO_PIN_INOUT 0x0004 /* bi-directional */ 36#define GPIO_PIN_INOUT 0x0004 /* bi-directional */
34#define GPIO_PIN_OPENDRAIN 0x0008 /* open-drain output */ 37#define GPIO_PIN_OPENDRAIN 0x0008 /* open-drain output */
35#define GPIO_PIN_PUSHPULL 0x0010 /* push-pull output */ 38#define GPIO_PIN_PUSHPULL 0x0010 /* push-pull output */
36#define GPIO_PIN_TRISTATE 0x0020 /* output disabled */ 39#define GPIO_PIN_TRISTATE 0x0020 /* output disabled */
37#define GPIO_PIN_PULLUP 0x0040 /* internal pull-up enabled */ 40#define GPIO_PIN_PULLUP 0x0040 /* internal pull-up enabled */
38#define GPIO_PIN_PULLDOWN 0x0080 /* internal pull-down enabled */ 41#define GPIO_PIN_PULLDOWN 0x0080 /* internal pull-down enabled */
@@ -41,65 +44,74 @@ @@ -41,65 +44,74 @@
41#define GPIO_PIN_USER 0x0400 /* user != 0 can access */ 44#define GPIO_PIN_USER 0x0400 /* user != 0 can access */
42#define GPIO_PIN_PULSATE 0x0800 /* pulsate in hardware */ 45#define GPIO_PIN_PULSATE 0x0800 /* pulsate in hardware */
43#define GPIO_PIN_INTR 0x1000 /* can be as an interrupt */ 46#define GPIO_PIN_INTR 0x1000 /* can be as an interrupt */
44#define GPIO_PIN_INTR_HIGH 0x2000 /* interrupt leading edge high */ 47#define GPIO_PIN_INTR_HIGH 0x2000 /* interrupt leading edge high */
45#define GPIO_PIN_SET 0x8000 /* set for securelevel access */ 48#define GPIO_PIN_SET 0x8000 /* set for securelevel access */
46 49
47/* GPIO controller description */ 50/* GPIO controller description */
48struct gpio_info { 51struct gpio_info {
49 int gpio_npins; /* total number of pins available */ 52 int gpio_npins; /* total number of pins available */
50}; 53};
51 54
52/* GPIO pin request (read/write/toggle) */ 55/* GPIO pin request (read/write/toggle) */
53struct gpio_req { 56struct gpio_req {
54 char gp_name[GPIOMAXNAME]; /* pin name */ 57 char gp_name[GPIOMAXNAME]; /* pin name */
55 int gp_pin; /* pin number */ 58 int gp_pin; /* pin number */
56 int gp_value; /* value */ 59 int gp_value; /* value */
 60};
 61
 62/* GPIO pulse request */
 63struct gpio_pulse {
 64 char gp_name[GPIOMAXNAME]; /* pin name */
 65 int gp_pin; /* pin number */
 66 struct timeval gp_pulse_on; /* "on" period */
 67 struct timeval gp_pulse_off; /* "off" period */
57}; 68};
58 69
59/* GPIO pin configuration */ 70/* GPIO pin configuration */
60struct gpio_set { 71struct gpio_set {
61 char gp_name[GPIOMAXNAME]; 72 char gp_name[GPIOMAXNAME];
62 int gp_pin; 73 int gp_pin;
63 int gp_caps; 74 int gp_caps;
64 int gp_flags; 75 int gp_flags;
65 char gp_name2[GPIOMAXNAME]; /* new name */ 76 char gp_name2[GPIOMAXNAME]; /* new name */
66}; 77};
67 78
68/* Attach/detach device drivers that use GPIO pins */ 79/* Attach/detach device drivers that use GPIO pins */
69struct gpio_attach { 80struct gpio_attach {
70 char ga_dvname[16]; /* device name */ 81 char ga_dvname[16]; /* device name */
71 int ga_offset; /* pin number */ 82 int ga_offset; /* pin number */
72 u_int32_t ga_mask; /* binary mask */ 83 uint32_t ga_mask; /* binary mask */
73}; 84};
74 85
75/* GPIO pin control (old API) */ 86/* GPIO pin control (old API) */
76struct gpio_pin_ctl { 87struct gpio_pin_ctl {
77 int gp_pin; /* pin number */ 88 int gp_pin; /* pin number */
78 int gp_caps; /* pin capabilities (read-only) */ 89 int gp_caps; /* pin capabilities (read-only) */
79 int gp_flags; /* pin configuration flags */ 90 int gp_flags; /* pin configuration flags */
80}; 91};
81 92
82/* GPIO pin operation (read/write/toggle) (old API) */ 93/* GPIO pin operation (read/write/toggle) (old API) */
83struct gpio_pin_op { 94struct gpio_pin_op {
84 int gp_pin; /* pin number */ 95 int gp_pin; /* pin number */
85 int gp_value; /* value */ 96 int gp_value; /* value */
86}; 97};
87 98
88#define GPIOINFO _IOR('G', 0, struct gpio_info) 99#define GPIOINFO _IOR('G', 0, struct gpio_info)
89 100
90/* the old API, kept for backwards compatibility */ 101/* the old API, kept for backwards compatibility */
91#define GPIOPINREAD _IOWR('G', 1, struct gpio_pin_op) 102#define GPIOPINREAD _IOWR('G', 1, struct gpio_pin_op)
92#define GPIOPINWRITE _IOWR('G', 2, struct gpio_pin_op) 103#define GPIOPINWRITE _IOWR('G', 2, struct gpio_pin_op)
93#define GPIOPINTOGGLE _IOWR('G', 3, struct gpio_pin_op) 104#define GPIOPINTOGGLE _IOWR('G', 3, struct gpio_pin_op)
94#define GPIOPINCTL _IOWR('G', 4, struct gpio_pin_ctl) 105#define GPIOPINCTL _IOWR('G', 4, struct gpio_pin_ctl)
95 106
96/* the new API */ 107/* the new API */
97#define GPIOSET _IOWR('G', 5, struct gpio_set) 108#define GPIOSET _IOWR('G', 5, struct gpio_set)
98#define GPIOUNSET _IOWR('G', 6, struct gpio_set) 109#define GPIOUNSET _IOWR('G', 6, struct gpio_set)
99#define GPIOREAD _IOWR('G', 7, struct gpio_req) 110#define GPIOREAD _IOWR('G', 7, struct gpio_req)
100#define GPIOWRITE _IOWR('G', 8, struct gpio_req) 111#define GPIOWRITE _IOWR('G', 8, struct gpio_req)
101#define GPIOTOGGLE _IOWR('G', 9, struct gpio_req) 112#define GPIOTOGGLE _IOWR('G', 9, struct gpio_req)
102#define GPIOATTACH _IOWR('G', 10, struct gpio_attach) 113#define GPIOATTACH _IOWR('G', 10, struct gpio_attach)
103#define GPIODETACH _IOWR('G', 11, struct gpio_attach) 114#define GPIODETACH _IOWR('G', 11, struct gpio_attach)
 115#define GPIOPULSE _IOWR('G', 12, struct gpio_pulse)
104 116
105#endif /* !_SYS_GPIO_H_ */ 117#endif /* !_SYS_GPIO_H_ */

cvs diff -r1.8 -r1.9 src/usr.sbin/gpioctl/gpioctl.8 (expand / switch to unified diff)

--- src/usr.sbin/gpioctl/gpioctl.8 2011/08/12 08:02:33 1.8
+++ src/usr.sbin/gpioctl/gpioctl.8 2011/08/28 07:48:50 1.9
@@ -1,31 +1,31 @@ @@ -1,31 +1,31 @@
1.\" $NetBSD: gpioctl.8,v 1.8 2011/08/12 08:02:33 mbalmer Exp $ 1.\" $NetBSD: gpioctl.8,v 1.9 2011/08/28 07:48:50 mbalmer Exp $
2.\" 2.\"
3.\" Copyright (c) 2009, 2010 Marc Balmer <marc@msys.ch> 3.\" Copyright (c) 2009, 2010, 2011 Marc Balmer <marc@msys.ch>
4.\" Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> 4.\" Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
5.\" 5.\"
6.\" Permission to use, copy, modify, and distribute this software for any 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 7.\" purpose with or without fee is hereby granted, provided that the above
8.\" copyright notice and this permission notice appear in all copies. 8.\" copyright notice and this permission notice appear in all copies.
9.\" 9.\"
10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 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 15.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17.\" 17.\"
18.Dd September 25, 2009 18.Dd August 21, 2011
19.Dt GPIOCTL 8 19.Dt GPIOCTL 8
20.Os 20.Os
21.Sh NAME 21.Sh NAME
22.Nm gpioctl 22.Nm gpioctl
23.Nd control GPIO devices 23.Nd control GPIO devices
24.Sh SYNOPSIS 24.Sh SYNOPSIS
25.Nm gpioctl 25.Nm gpioctl
26.Op Fl q 26.Op Fl q
27.Ar device 27.Ar device
28attach 28attach
29.Ar device 29.Ar device
30.Ar offset 30.Ar offset
31.Ar mask 31.Ar mask
@@ -38,26 +38,32 @@ detach @@ -38,26 +38,32 @@ detach
38.Op Fl q 38.Op Fl q
39.Ar device 39.Ar device
40.Ar pin 40.Ar pin
41.Op Ar 0 | 1 | 2 41.Op Ar 0 | 1 | 2
42.Nm gpioctl 42.Nm gpioctl
43.Op Fl q 43.Op Fl q
44.Ar device 44.Ar device
45.Ar pin 45.Ar pin
46.Op Ar on | off | toggle 46.Op Ar on | off | toggle
47.Nm gpioctl 47.Nm gpioctl
48.Op Fl q 48.Op Fl q
49.Ar device 49.Ar device
50.Ar pin 50.Ar pin
 51pulse
 52.Op Ar frequency Op Ar duty cycle
 53.Nm gpioctl
 54.Op Fl q
 55.Ar device
 56.Ar pin
51set 57set
52.Op Ar flags 58.Op Ar flags
53.Op Ar name 59.Op Ar name
54.Nm gpioctl 60.Nm gpioctl
55.Op Fl q 61.Op Fl q
56.Ar device 62.Ar device
57.Ar pin 63.Ar pin
58unset 64unset
59.Sh DESCRIPTION 65.Sh DESCRIPTION
60The 66The
61.Nm 67.Nm
62program allows manipulation of GPIO 68program allows manipulation of GPIO
63(General Purpose Input/Output) device pins. 69(General Purpose Input/Output) device pins.
@@ -82,36 +88,49 @@ or @@ -82,36 +88,49 @@ or
82GPIO pins can be either 88GPIO pins can be either
83.Dq read 89.Dq read
84or 90or
85.Dq written 91.Dq written
86with the values of logical 0 or 1. 92with the values of logical 0 or 1.
87If only a 93If only a
88.Ar pin 94.Ar pin
89number is specified on the command line, the pin state will be read 95number is specified on the command line, the pin state will be read
90from the GPIO controller and displayed. 96from the GPIO controller and displayed.
91To write to a pin, a value must be specified after the 97To write to a pin, a value must be specified after the
92.Ar pin 98.Ar pin
93number. 99number.
94Values can be either 0 or 1. 100Values can be either 0 or 1.
95A value of 2 has a special meaning: it 101A value of 2
96.Dq toggles 102.Dq toggles
97the pin, i.e. changes its state to the opposite. 103the pin, i.e. changes its state to the opposite.
98Instead of the numerical values, the word 104Instead of the numerical values, the word
99.Ar on , 105.Ar on ,
100.Ar off , 106.Ar off ,
101or 107or
102.Ar toggle 108.Ar toggle
103can be used. 109can be used.
104.Pp 110.Pp
 111To
 112.Dq pulse
 113a pin, use the pulse command line option with an optional frequency value
 114in hertz and an optional duty cycle in percent.
 115If no frequency is specified, 1 Hz is assumed.
 116If no duty cycle is specified, 50% are assumed.
 117If the underlying hardware is not capable of pulsing in hardware,
 118pulsing is done in software using the
 119.Xr callout 9
 120facility.
 121The frequency and duty cycle arguments are ignored for pins that are able to
 122pulse in hardware.
 123.Pp
105Only pins that have been configured at securelevel 0, typically during system 124Only pins that have been configured at securelevel 0, typically during system
106startup, are accessible once the securelevel has been raised. 125startup, are accessible once the securelevel has been raised.
107Pins can be given symbolic names for easier use. 126Pins can be given symbolic names for easier use.
108Besides using individual pins, device drivers that use GPIO pins can be 127Besides using individual pins, device drivers that use GPIO pins can be
109attached to a 128attached to a
110.Xr gpio 4 129.Xr gpio 4
111device using the 130device using the
112.Nm 131.Nm
113command. 132command.
114.Pp 133.Pp
115The following configuration 134The following configuration
116.Ar flags 135.Ar flags
117are supported by the GPIO framework: 136are supported by the GPIO framework:
@@ -197,15 +216,15 @@ Toggle the error_led: @@ -197,15 +216,15 @@ Toggle the error_led:
197.Xr gpio 4 216.Xr gpio 4
198.Sh HISTORY 217.Sh HISTORY
199The 218The
200.Nm 219.Nm
201command first appeared in 220command first appeared in
202.Ox 3.6 221.Ox 3.6
203and 222and
204.Nx 4.0 . 223.Nx 4.0 .
205.Sh AUTHORS 224.Sh AUTHORS
206The 225The
207.Nm 226.Nm
208program was written by 227program was written by
209.An Alexander Yurchenko Aq grange@openbsd.org . 228.An Alexander Yurchenko Aq grange@openbsd.org .
210Device attachment was added by 229Device attachment and pulsing was added by
211.An Marc Balmer Aq marc@msys.ch . 230.An Marc Balmer Aq marc@msys.ch .

cvs diff -r1.10 -r1.11 src/usr.sbin/gpioctl/gpioctl.c (expand / switch to unified diff)

--- src/usr.sbin/gpioctl/gpioctl.c 2011/08/12 08:06:23 1.10
+++ src/usr.sbin/gpioctl/gpioctl.c 2011/08/28 07:48:50 1.11
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: gpioctl.c,v 1.10 2011/08/12 08:06:23 mbalmer Exp $ */ 1/* $NetBSD: gpioctl.c,v 1.11 2011/08/28 07:48:50 mbalmer Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2008, 2010 Marc Balmer <mbalmer@NetBSD.org> 4 * Copyright (c) 2008, 2010 Marc Balmer <mbalmer@NetBSD.org>
5 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> 5 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
@@ -22,40 +22,41 @@ @@ -22,40 +22,41 @@
22 */ 22 */
23 23
24#include <sys/types.h> 24#include <sys/types.h>
25#include <sys/gpio.h> 25#include <sys/gpio.h>
26#include <sys/ioctl.h> 26#include <sys/ioctl.h>
27 27
28#include <err.h> 28#include <err.h>
29#include <errno.h> 29#include <errno.h>
30#include <fcntl.h> 30#include <fcntl.h>
31#include <limits.h> 31#include <limits.h>
32#include <paths.h> 32#include <paths.h>
33#include <stdio.h> 33#include <stdio.h>
34#include <stdlib.h> 34#include <stdlib.h>
 35#include <time.h>
35#include <string.h> 36#include <string.h>
36#include <unistd.h> 37#include <unistd.h>
37 38
38 
39char *dev; 39char *dev;
40int devfd = -1; 40int devfd = -1;
41int quiet = 0; 41int quiet = 0;
42 42
43static void getinfo(void); 43static void getinfo(void);
44static void gpioread(int, char *); 44static void gpioread(int, char *);
45static void gpiowrite(int, char *, int); 45static void gpiowrite(int, char *, int);
 46static void gpiopulse(int, char *, double, double);
46static void gpioset(int pin, char *name, int flags, char *alias); 47static void gpioset(int pin, char *name, int flags, char *alias);
47static void gpiounset(int pin, char *name); 48static void gpiounset(int pin, char *name);
48static void devattach(char *, int, u_int32_t); 49static void devattach(char *, int, uint32_t);
49static void devdetach(char *); 50static void devdetach(char *);
50static void usage(void); 51static void usage(void);
51 52
52extern long long strtonum(const char *numstr, long long minval, 53extern long long strtonum(const char *numstr, long long minval,
53 long long maxval, const char **errstrp); 54 long long maxval, const char **errstrp);
54 55
55const struct bitstr { 56const struct bitstr {
56 unsigned int mask; 57 unsigned int mask;
57 const char *string; 58 const char *string;
58} pinflags[] = { 59} pinflags[] = {
59 { GPIO_PIN_INPUT, "in" }, 60 { GPIO_PIN_INPUT, "in" },
60 { GPIO_PIN_OUTPUT, "out" }, 61 { GPIO_PIN_OUTPUT, "out" },
61 { GPIO_PIN_INOUT, "inout" }, 62 { GPIO_PIN_INOUT, "inout" },
@@ -64,51 +65,54 @@ const struct bitstr { @@ -64,51 +65,54 @@ const struct bitstr {
64 { GPIO_PIN_TRISTATE, "tri" }, 65 { GPIO_PIN_TRISTATE, "tri" },
65 { GPIO_PIN_PULLUP, "pu" }, 66 { GPIO_PIN_PULLUP, "pu" },
66 { GPIO_PIN_PULLDOWN, "pd" }, 67 { GPIO_PIN_PULLDOWN, "pd" },
67 { GPIO_PIN_INVIN, "iin" }, 68 { GPIO_PIN_INVIN, "iin" },
68 { GPIO_PIN_INVOUT, "iout" }, 69 { GPIO_PIN_INVOUT, "iout" },
69 { GPIO_PIN_PULSATE, "pulsate" }, 70 { GPIO_PIN_PULSATE, "pulsate" },
70 { 0, NULL }, 71 { 0, NULL },
71}; 72};
72 73
73int 74int
74main(int argc, char *argv[]) 75main(int argc, char *argv[])
75{ 76{
76 const struct bitstr *bs; 77 const struct bitstr *bs;
 78 double freq, dc;
77 int pin, ch, n, fl = 0, value = 0; 79 int pin, ch, n, fl = 0, value = 0;
78 const char *errstr; 80 const char *errstr;
79 char *ep; 81 char *ep;
80 int ga_offset = -1; 82 int ga_offset = -1;
81 u_int32_t ga_mask = 0; 83 uint32_t ga_mask = 0;
82 long lval; 84 long lval;
83 char *nam = NULL; 85 char *nam = NULL;
84 char devn[32]; 86 char devn[32];
85 87
86 while ((ch = getopt(argc, argv, "q")) != -1) 88 while ((ch = getopt(argc, argv, "q")) != -1)
87 switch (ch) { 89 switch (ch) {
88 case 'q': 90 case 'q':
89 quiet = 1; 91 quiet = 1;
90 break; 92 break;
91 default: 93 default:
92 usage(); 94 usage();
93 /* NOTREACHED */ 95 /* NOTREACHED */
94 } 96 }
95 argc -= optind; 97 argc -= optind;
96 argv += optind; 98 argv += optind;
97 99
98 if (argc < 1) 100 if (argc < 1)
99 usage(); 101 usage();
100 dev = argv[0]; 102 dev = argv[0];
101 103
 104 freq = dc = 0.0;
 105
102 if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) { 106 if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) {
103 (void)snprintf(devn, sizeof(devn), "%s%s", _PATH_DEV, dev); 107 (void)snprintf(devn, sizeof(devn), "%s%s", _PATH_DEV, dev);
104 dev = devn; 108 dev = devn;
105 } 109 }
106 110
107 if ((devfd = open(dev, O_RDWR)) == -1) 111 if ((devfd = open(dev, O_RDWR)) == -1)
108 err(EXIT_FAILURE, "%s", dev); 112 err(EXIT_FAILURE, "%s", dev);
109 113
110 if (argc == 1) { 114 if (argc == 1) {
111 getinfo(); 115 getinfo();
112 return EXIT_SUCCESS; 116 return EXIT_SUCCESS;
113 } 117 }
114 118
@@ -130,56 +134,66 @@ main(int argc, char *argv[]) @@ -130,56 +134,66 @@ main(int argc, char *argv[])
130 errx(EXIT_FAILURE, "invalid mask (not a number)"); 134 errx(EXIT_FAILURE, "invalid mask (not a number)");
131 if ((errno == ERANGE && (lval == LONG_MAX 135 if ((errno == ERANGE && (lval == LONG_MAX
132 || lval == LONG_MIN)) || (unsigned long)lval > UINT_MAX) 136 || lval == LONG_MIN)) || (unsigned long)lval > UINT_MAX)
133 errx(EXIT_FAILURE, "mask out of range"); 137 errx(EXIT_FAILURE, "mask out of range");
134 ga_mask = lval; 138 ga_mask = lval;
135 devattach(driver, ga_offset, ga_mask); 139 devattach(driver, ga_offset, ga_mask);
136 return EXIT_SUCCESS; 140 return EXIT_SUCCESS;
137 } else if (!strcmp(argv[1], "detach")) { 141 } else if (!strcmp(argv[1], "detach")) {
138 if (argc != 3) 142 if (argc != 3)
139 usage(); 143 usage();
140 devdetach(argv[2]); 144 devdetach(argv[2]);
141 } else { 145 } else {
142 char *nm = NULL; 146 char *nm = NULL;
143  147
144 /* expecting a pin number or name */ 148 /* expecting a pin number or name */
145 pin = strtonum(argv[1], 0, INT_MAX, &errstr); 149 pin = strtonum(argv[1], 0, INT_MAX, &errstr);
146 if (errstr) 150 if (errstr)
147 nm = argv[1]; /* try named pin */ 151 nm = argv[1]; /* try named pin */
148 if (argc > 2) {  152 if (argc > 2) {
149 if (!strcmp(argv[2], "set")) { 153 if (!strcmp(argv[2], "set")) {
150 for (n = 3; n < argc; n++) { 154 for (n = 3; n < argc; n++) {
151 for (bs = pinflags; bs->string != NULL; 155 for (bs = pinflags; bs->string != NULL;
152 bs++) { 156 bs++) {
153 if (!strcmp(argv[n], 157 if (!strcmp(argv[n],
154 bs->string)) { 158 bs->string)) {
155 fl |= bs->mask; 159 fl |= bs->mask;
156 break; 160 break;
157 } 161 }
158 } 162 }
159 if (bs->string == NULL) 163 if (bs->string == NULL)
160 nam = argv[n]; 164 nam = argv[n];
161 } 165 }
162 gpioset(pin, nm, fl, nam); 166 gpioset(pin, nm, fl, nam);
163 } else if (!strcmp(argv[2], "unset")) { 167 } else if (!strcmp(argv[2], "unset")) {
164 gpiounset(pin, nm); 168 gpiounset(pin, nm);
 169 } else if (!strcmp(argv[2], "pulse")) {
 170 if (argc == 4) {
 171 freq = atof(argv[3]);
 172 dc = 50.0;
 173 } else if (argc == 5) {
 174 freq = atof(argv[3]);
 175 dc = atof(argv[4]);
 176 } else
 177 freq = dc = 0.0;
 178 gpiopulse(pin, nm, freq, dc);
165 } else { 179 } else {
166 value = strtonum(argv[2], INT_MIN, INT_MAX, 180 value = strtonum(argv[2], INT_MIN, INT_MAX,
167 &errstr); 181 &errstr);
168 if (errstr) { 182 if (errstr) {
169 if (!strcmp(argv[2], "on")) 183 if (!strcmp(argv[2], "on"))
170 value = 1; 184 value = GPIO_PIN_HIGH;
171 else if (!strcmp(argv[2], "off")) 185 else if (!strcmp(argv[2], "off"))
172 value = 0; 186 value = GPIO_PIN_LOW;
173 else if (!strcmp(argv[2], "toggle")) 187 else if (!strcmp(argv[2], "toggle"))
174 value = 2; 188 value = 2;
175 else 189 else
176 errx(EXIT_FAILURE, 190 errx(EXIT_FAILURE,
177 "%s: invalid value", 191 "%s: invalid value",
178 argv[2]); 192 argv[2]);
179 } 193 }
180 gpiowrite(pin, nm, value); 194 gpiowrite(pin, nm, value);
181 } 195 }
182 } else 196 } else
183 gpioread(pin, nm); 197 gpioread(pin, nm);
184 } 198 }
185 199
@@ -226,47 +240,104 @@ gpioread(int pin, char *gp_name) @@ -226,47 +240,104 @@ gpioread(int pin, char *gp_name)
226static void 240static void
227gpiowrite(int pin, char *gp_name, int value) 241gpiowrite(int pin, char *gp_name, int value)
228{ 242{
229 struct gpio_req req; 243 struct gpio_req req;
230 244
231 if (value < 0 || value > 2) 245 if (value < 0 || value > 2)
232 errx(EXIT_FAILURE, "%d: invalid value", value); 246 errx(EXIT_FAILURE, "%d: invalid value", value);
233 247
234 memset(&req, 0, sizeof(req)); 248 memset(&req, 0, sizeof(req));
235 if (gp_name != NULL) 249 if (gp_name != NULL)
236 strlcpy(req.gp_name, gp_name, sizeof(req.gp_name)); 250 strlcpy(req.gp_name, gp_name, sizeof(req.gp_name));
237 else 251 else
238 req.gp_pin = pin; 252 req.gp_pin = pin;
239 req.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH); 253
240 if (value < 2) { 254 if (value == GPIO_PIN_HIGH || value == GPIO_PIN_LOW) {
 255 req.gp_value = value;
241 if (ioctl(devfd, GPIOWRITE, &req) == -1) 256 if (ioctl(devfd, GPIOWRITE, &req) == -1)
242 err(EXIT_FAILURE, "GPIOWRITE"); 257 err(EXIT_FAILURE, "GPIOWRITE");
243 } else { 258 } else {
244 if (ioctl(devfd, GPIOTOGGLE, &req) == -1) 259 if (ioctl(devfd, GPIOTOGGLE, &req) == -1)
245 err(EXIT_FAILURE, "GPIOTOGGLE"); 260 err(EXIT_FAILURE, "GPIOTOGGLE");
246 } 261 }
247 262
248 if (quiet) 263 if (quiet)
249 return; 264 return;
250 265
251 if (gp_name) 266 if (gp_name)
252 printf("pin %s: state %d -> %d\n", gp_name, req.gp_value, 267 printf("pin %s: state %d -> %d\n", gp_name, req.gp_value,
253 (value < 2 ? value : 1 - req.gp_value)); 268 (value < 2 ? value : 1 - req.gp_value));
254 else 269 else
255 printf("pin %d: state %d -> %d\n", pin, req.gp_value, 270 printf("pin %d: state %d -> %d\n", pin, req.gp_value,
256 (value < 2 ? value : 1 - req.gp_value)); 271 (value < 2 ? value : 1 - req.gp_value));
257} 272}
258 273
259static void 274static void
 275gpiopulse(int pin, char *gp_name, double freq, double dc)
 276{
 277 struct gpio_pulse pulse;
 278 suseconds_t period, on, off;
 279
 280 if (freq < 0.0 || (dc < 0.0 || dc >= 100.0))
 281 errx(EXIT_FAILURE, "%.f Hz, %.f%% duty cycle: invalid value",
 282 freq, dc);
 283
 284 memset(&pulse, 0, sizeof(pulse));
 285 if (gp_name != NULL)
 286 strlcpy(pulse.gp_name, gp_name, sizeof(pulse.gp_name));
 287 else
 288 pulse.gp_pin = pin;
 289
 290 if (freq > 0.0 && dc > 0.0) {
 291 period = 1000000 / freq;
 292 on = period * dc / 100;
 293 off = period - on;
 294
 295 if (on >= 1000000) {
 296 pulse.gp_pulse_on.tv_sec = on / 1000000;
 297 on -= pulse.gp_pulse_on.tv_sec * 1000000;
 298 pulse.gp_pulse_on.tv_usec = on;
 299 } else {
 300 pulse.gp_pulse_on.tv_sec = 0;
 301 pulse.gp_pulse_on.tv_usec = on;
 302 }
 303 if (off >= 1000000) {
 304 pulse.gp_pulse_off.tv_sec = off / 1000000;
 305 off -= pulse.gp_pulse_off.tv_sec * 1000000;
 306 pulse.gp_pulse_off.tv_usec = off;
 307 } else {
 308 pulse.gp_pulse_off.tv_sec = 0;
 309 pulse.gp_pulse_off.tv_usec = off;
 310 }
 311 } else { /* gpio(4) defaults */
 312 freq = 1.0;
 313 dc = 50.0;
 314 }
 315
 316 if (ioctl(devfd, GPIOPULSE, &pulse) == -1)
 317 err(EXIT_FAILURE, "GPIOPULSE");
 318
 319 if (quiet)
 320 return;
 321
 322 if (gp_name)
 323 printf("pin %s: pulse at %.f Hz with a %.f%% duty cylce\n",
 324 gp_name, freq, dc);
 325 else
 326 printf("pin %d: pulse at %.f Hz with a %.f%% duty cylce\n",
 327 pin, freq, dc);
 328}
 329
 330static void
260gpioset(int pin, char *name, int fl, char *alias) 331gpioset(int pin, char *name, int fl, char *alias)
261{ 332{
262 struct gpio_set set; 333 struct gpio_set set;
263 const struct bitstr *bs; 334 const struct bitstr *bs;
264 335
265 memset(&set, 0, sizeof(set)); 336 memset(&set, 0, sizeof(set));
266 if (name != NULL) 337 if (name != NULL)
267 strlcpy(set.gp_name, name, sizeof(set.gp_name)); 338 strlcpy(set.gp_name, name, sizeof(set.gp_name));
268 else 339 else
269 set.gp_pin = pin; 340 set.gp_pin = pin;
270 set.gp_flags = fl; 341 set.gp_flags = fl;
271 342
272 if (alias != NULL) 343 if (alias != NULL)
@@ -304,27 +375,27 @@ gpiounset(int pin, char *name) @@ -304,27 +375,27 @@ gpiounset(int pin, char *name)
304 struct gpio_set set; 375 struct gpio_set set;
305 376
306 memset(&set, 0, sizeof(set)); 377 memset(&set, 0, sizeof(set));
307 if (name != NULL) 378 if (name != NULL)
308 strlcpy(set.gp_name, name, sizeof(set.gp_name)); 379 strlcpy(set.gp_name, name, sizeof(set.gp_name));
309 else 380 else
310 set.gp_pin = pin; 381 set.gp_pin = pin;
311 382
312 if (ioctl(devfd, GPIOUNSET, &set) == -1) 383 if (ioctl(devfd, GPIOUNSET, &set) == -1)
313 err(EXIT_FAILURE, "GPIOUNSET"); 384 err(EXIT_FAILURE, "GPIOUNSET");
314} 385}
315 386
316static void 387static void
317devattach(char *dvname, int offset, u_int32_t mask) 388devattach(char *dvname, int offset, uint32_t mask)
318{ 389{
319 struct gpio_attach attach; 390 struct gpio_attach attach;
320 391
321 memset(&attach, 0, sizeof(attach)); 392 memset(&attach, 0, sizeof(attach));
322 strlcpy(attach.ga_dvname, dvname, sizeof(attach.ga_dvname)); 393 strlcpy(attach.ga_dvname, dvname, sizeof(attach.ga_dvname));
323 attach.ga_offset = offset; 394 attach.ga_offset = offset;
324 attach.ga_mask = mask; 395 attach.ga_mask = mask;
325 if (ioctl(devfd, GPIOATTACH, &attach) == -1) 396 if (ioctl(devfd, GPIOATTACH, &attach) == -1)
326 err(EXIT_FAILURE, "GPIOATTACH"); 397 err(EXIT_FAILURE, "GPIOATTACH");
327} 398}
328 399
329static void 400static void
330devdetach(char *dvname) 401devdetach(char *dvname)
@@ -335,22 +406,24 @@ devdetach(char *dvname) @@ -335,22 +406,24 @@ devdetach(char *dvname)
335 strlcpy(attach.ga_dvname, dvname, sizeof(attach.ga_dvname)); 406 strlcpy(attach.ga_dvname, dvname, sizeof(attach.ga_dvname));
336 if (ioctl(devfd, GPIODETACH, &attach) == -1) 407 if (ioctl(devfd, GPIODETACH, &attach) == -1)
337 err(EXIT_FAILURE, "GPIODETACH"); 408 err(EXIT_FAILURE, "GPIODETACH");
338} 409}
339 410
340static void 411static void
341usage(void) 412usage(void)
342{ 413{
343 const char *progname; 414 const char *progname;
344 415
345 progname = getprogname(); 416 progname = getprogname();
346 fprintf(stderr, "usage: %s [-q] device [pin] [0 | 1 | 2 | " 417 fprintf(stderr, "usage: %s [-q] device [pin] [0 | 1 | 2 | "
347 "on | off | toggle]\n", progname); 418 "on | off | toggle]\n", progname);
 419 fprintf(stderr, "usage: %s [-q] device pin pulse [frequency "
 420 "[duty cycle]]\n", progname);
348 fprintf(stderr, " %s [-q] device pin set [flags] [name]\n", 421 fprintf(stderr, " %s [-q] device pin set [flags] [name]\n",
349 progname); 422 progname);
350 fprintf(stderr, " %s [-q] device pin unset\n", progname); 423 fprintf(stderr, " %s [-q] device pin unset\n", progname);
351 fprintf(stderr, " %s [-q] device attach device offset mask\n", 424 fprintf(stderr, " %s [-q] device attach device offset mask\n",
352 progname); 425 progname);
353 fprintf(stderr, " %s [-q] device detach device\n", progname); 426 fprintf(stderr, " %s [-q] device detach device\n", progname);
354 427
355 exit(EXIT_FAILURE); 428 exit(EXIT_FAILURE);
356} 429}