Sat Jul 25 16:17:10 2009 UTC ()
Rework the GPIO framework.  Tie it to the kauth(9) framework to control
access to the GPIO pins.  Device drivers using GPIO pins can now be
attached and detached at runtime.  GPIO pins can be named for easier
reference from userland programs.  Introduce a new gpiosim(4) driver,
which is used for development.

Reviewed by many.


(mbalmer)
diff -r1.4 -r1.5 src/sys/dev/gpio/files.gpio
diff -r1.18 -r1.19 src/sys/dev/gpio/gpio.c
diff -r1.6 -r1.7 src/sys/dev/gpio/gpioow.c
diff -r0 -r1.1 src/sys/dev/gpio/gpiosim.c
diff -r1.7 -r1.8 src/sys/dev/gpio/gpiovar.h
diff -r1.3 -r1.4 src/sys/sys/gpio.h

cvs diff -r1.4 -r1.5 src/sys/dev/gpio/files.gpio (expand / switch to unified diff)

--- src/sys/dev/gpio/files.gpio 2006/04/07 18:55:21 1.4
+++ src/sys/dev/gpio/files.gpio 2009/07/25 16:17:10 1.5
@@ -1,11 +1,17 @@ @@ -1,11 +1,17 @@
1# $NetBSD: files.gpio,v 1.4 2006/04/07 18:55:21 riz Exp $ 1# $NetBSD: files.gpio,v 1.5 2009/07/25 16:17:10 mbalmer Exp $
2 2
3define gpio {offset, mask} 3define gpio {[offset = -1], [mask = 0]}
4 4
5device gpio: gpio 5device gpio: gpio
6attach gpio at gpiobus 6attach gpio at gpiobus
7file dev/gpio/gpio.c gpio needs-flag 7file dev/gpio/gpio.c gpio needs-flag
8 8
 9# GPIO simulator
 10device gpiosim: gpiobus
 11attach gpiosim at root
 12file dev/gpio/gpiosim.c gpiosim needs-flag
 13
 14# 1-Wire bus bit-banging
9device gpioow: onewirebus, onewire_bitbang 15device gpioow: onewirebus, onewire_bitbang
10attach gpioow at gpio 16attach gpioow at gpio
11file dev/gpio/gpioow.c gpioow 17file dev/gpio/gpioow.c gpioow

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

--- src/sys/dev/gpio/gpio.c 2009/04/02 00:09:33 1.18
+++ src/sys/dev/gpio/gpio.c 2009/07/25 16:17:10 1.19
@@ -1,90 +1,119 @@ @@ -1,90 +1,119 @@
1/* $NetBSD: gpio.c,v 1.18 2009/04/02 00:09:33 dyoung Exp $ */ 1/* $NetBSD: gpio.c,v 1.19 2009/07/25 16:17:10 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 Marc Balmer <marc@msys.ch>
5 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org> 6 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
6 * 7 *
7 * Permission to use, copy, modify, and distribute this software for any 8 * Permission to use, copy, modify, and distribute this software for any
8 * 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
9 * copyright notice and this permission notice appear in all copies. 10 * copyright notice and this permission notice appear in all copies.
10 * 11 *
11 * 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
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * 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
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * 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
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */ 19 */
19 20
20#include <sys/cdefs.h> 21#include <sys/cdefs.h>
21__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.18 2009/04/02 00:09:33 dyoung Exp $"); 22__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.19 2009/07/25 16:17:10 mbalmer Exp $");
22 23
23/* 24/*
24 * General Purpose Input/Output framework. 25 * General Purpose Input/Output framework.
25 */ 26 */
26 27
27#include <sys/param.h> 28#include <sys/param.h>
28#include <sys/systm.h> 29#include <sys/systm.h>
29#include <sys/conf.h> 30#include <sys/conf.h>
30#include <sys/device.h> 31#include <sys/device.h>
 32#include <sys/fcntl.h>
31#include <sys/ioctl.h> 33#include <sys/ioctl.h>
32#include <sys/gpio.h> 34#include <sys/gpio.h>
33#include <sys/vnode.h> 35#include <sys/vnode.h>
 36#include <sys/kmem.h>
 37#include <sys/queue.h>
 38#include <sys/kauth.h>
34 39
35#include <dev/gpio/gpiovar.h> 40#include <dev/gpio/gpiovar.h>
36 41
37#include "locators.h" 42#include "locators.h"
38 43
39struct gpio_softc { 44#ifdef GPIO_DEBUG
40 device_t sc_dev; 45#define DPRINTF(n, x) do { if (gpiodebug > (n)) printf x; } while (0)
 46int gpiodebug = 0;
 47#else
 48#define DPRINTFN(n, x)
 49#endif
 50#define DPRINTF(x) DPRINTFN(0, x)
41 51
42 gpio_chipset_tag_t sc_gc; /* our GPIO controller */ 52struct gpio_softc {
43 gpio_pin_t *sc_pins; /* pins array */ 53 device_t sc_dev;
44 int sc_npins; /* total number of pins */ 
45 54
46 int sc_opened; 55 gpio_chipset_tag_t sc_gc; /* GPIO controller */
47 int sc_dying; 56 gpio_pin_t *sc_pins; /* pins array */
 57 int sc_npins; /* number of pins */
 58
 59 int sc_opened;
 60 LIST_HEAD(, gpio_dev) sc_devs; /* devices */
 61 LIST_HEAD(, gpio_name) sc_names; /* named pins */
48}; 62};
49 63
50int gpio_match(device_t, cfdata_t, void *); 64int gpio_match(device_t, cfdata_t, void *);
 65int gpio_submatch(device_t, cfdata_t, const int *, void *);
51void gpio_attach(device_t, device_t, void *); 66void gpio_attach(device_t, device_t, void *);
52bool gpio_resume(device_t PMF_FN_PROTO); 67bool gpio_resume(device_t PMF_FN_PROTO);
53int gpio_detach(device_t, int); 68int gpio_detach(device_t, int);
54int gpio_activate(device_t, enum devact); 69int gpio_activate(device_t, enum devact);
55int gpio_search(device_t, cfdata_t, const int *, void *); 70int gpio_search(device_t, cfdata_t, const int *, void *);
56int gpio_print(void *, const char *); 71int gpio_print(void *, const char *);
 72int gpio_pinbyname(struct gpio_softc *, char *);
 73
 74/* Old API */
 75int gpio_ioctl_oapi(struct gpio_softc *, u_long, void *, int, kauth_cred_t);
57 76
58CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc), 77CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc),
59 gpio_match, gpio_attach, gpio_detach, gpio_activate, NULL, NULL, 78 gpio_match, gpio_attach, gpio_detach, gpio_activate, NULL, NULL,
60 DVF_DETACH_SHUTDOWN); 79 DVF_DETACH_SHUTDOWN);
61 80
62dev_type_open(gpioopen); 81dev_type_open(gpioopen);
63dev_type_close(gpioclose); 82dev_type_close(gpioclose);
64dev_type_ioctl(gpioioctl); 83dev_type_ioctl(gpioioctl);
65 84
66const struct cdevsw gpio_cdevsw = { 85const struct cdevsw gpio_cdevsw = {
67 gpioopen, gpioclose, noread, nowrite, gpioioctl, 86 gpioopen, gpioclose, noread, nowrite, gpioioctl,
68 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER, 87 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
69}; 88};
70 89
71extern struct cfdriver gpio_cd; 90extern struct cfdriver gpio_cd;
72 91
73int 92int
74gpio_match(device_t parent, cfdata_t cf, void *aux) 93gpio_match(device_t parent, cfdata_t cf, void *aux)
75{ 94{
 95 return 1;
 96}
 97
 98int
 99gpio_submatch(device_t parent, cfdata_t cf, const int *ip, void *aux)
 100{
 101 struct gpio_attach_args *ga = aux;
76 102
77 return (1); 103 if (ga->ga_offset == -1)
 104 return 0;
 105
 106 return strcmp(ga->ga_dvname, cf->cf_name) == 0;
78} 107}
79 108
80bool 109bool
81gpio_resume(device_t self PMF_FN_ARGS) 110gpio_resume(device_t self PMF_FN_ARGS)
82{ 111{
83 struct gpio_softc *sc = device_private(self); 112 struct gpio_softc *sc = device_private(self);
84 int pin; 113 int pin;
85 114
86 for (pin = 0; pin < sc->sc_npins; pin++) { 115 for (pin = 0; pin < sc->sc_npins; pin++) {
87 gpiobus_pin_ctl(sc->sc_gc, pin, sc->sc_pins[pin].pin_flags); 116 gpiobus_pin_ctl(sc->sc_gc, pin, sc->sc_pins[pin].pin_flags);
88 gpiobus_pin_write(sc->sc_gc, pin, sc->sc_pins[pin].pin_state); 117 gpiobus_pin_write(sc->sc_gc, pin, sc->sc_pins[pin].pin_state);
89 } 118 }
90 return true; 119 return true;
@@ -118,290 +147,586 @@ gpio_detach(device_t self, int flags) @@ -118,290 +147,586 @@ gpio_detach(device_t self, int flags)
118{ 147{
119#if 0 148#if 0
120 int maj, mn; 149 int maj, mn;
121 150
122 /* Locate the major number */ 151 /* Locate the major number */
123 for (maj = 0; maj < nchrdev; maj++) 152 for (maj = 0; maj < nchrdev; maj++)
124 if (cdevsw[maj].d_open == gpioopen) 153 if (cdevsw[maj].d_open == gpioopen)
125 break; 154 break;
126 155
127 /* Nuke the vnodes for any open instances (calls close) */ 156 /* Nuke the vnodes for any open instances (calls close) */
128 mn = device_unit(self); 157 mn = device_unit(self);
129 vdevgone(maj, mn, mn, VCHR); 158 vdevgone(maj, mn, mn, VCHR);
130#endif 159#endif
131 160 return 0;
132 return (0); 
133} 161}
134 162
135int 163int
136gpio_activate(device_t self, enum devact act) 164gpio_activate(device_t self, enum devact act)
137{ 165{
138 struct gpio_softc *sc = device_private(self); 166 printf("gpio_active: ");
139 
140 switch (act) { 167 switch (act) {
141 case DVACT_ACTIVATE: 168 case DVACT_ACTIVATE:
142 return (EOPNOTSUPP); 169 DPRINTF(("ACTIVATE\n"));
 170 return EOPNOTSUPP;
143 case DVACT_DEACTIVATE: 171 case DVACT_DEACTIVATE:
144 sc->sc_dying = 1; 172 DPRINTF(("DEACTIVATE\n"));
145 break; 173 break;
146 } 174 }
147 175 return 0;
148 return (0); 
149} 176}
150 177
151int 178int
152gpio_search(device_t parent, cfdata_t cf, 179gpio_search(device_t parent, cfdata_t cf,
153 const int *ldesc, void *aux) 180 const int *ldesc, void *aux)
154{ 181{
155 struct gpio_attach_args ga; 182 struct gpio_attach_args ga;
156 183
157 ga.ga_gpio = aux; 184 ga.ga_gpio = aux;
158 ga.ga_offset = cf->cf_loc[GPIOCF_OFFSET]; 185 ga.ga_offset = cf->cf_loc[GPIOCF_OFFSET];
159 ga.ga_mask = cf->cf_loc[GPIOCF_MASK]; 186 ga.ga_mask = cf->cf_loc[GPIOCF_MASK];
160 187
161 if (config_match(parent, cf, &ga) > 0) 188 if (config_match(parent, cf, &ga) > 0)
162 config_attach(parent, cf, &ga, gpio_print); 189 config_attach(parent, cf, &ga, gpio_print);
163 190
164 return (0); 191 return 0;
165} 192}
166 193
167int 194int
168gpio_print(void *aux, const char *pnp) 195gpio_print(void *aux, const char *pnp)
169{ 196{
170 struct gpio_attach_args *ga = aux; 197 struct gpio_attach_args *ga = aux;
171 int i; 198 int i;
172 199
173 printf(" pins"); 200 printf(" pins");
174 for (i = 0; i < 32; i++) 201 for (i = 0; i < 32; i++)
175 if (ga->ga_mask & (1 << i)) 202 if (ga->ga_mask & (1 << i))
176 printf(" %d", ga->ga_offset + i); 203 printf(" %d", ga->ga_offset + i);
177 204
178 return (UNCONF); 205 return UNCONF;
179} 206}
180 207
181int 208int
182gpiobus_print(void *aux, const char *pnp) 209gpiobus_print(void *aux, const char *pnp)
183{ 210{
184#if 0 211#if 0
185 struct gpiobus_attach_args *gba = aux; 212 struct gpiobus_attach_args *gba = aux;
186#endif 213#endif
187 if (pnp != NULL) 214 if (pnp != NULL)
188 printf("%s at %s", "gpiobus", pnp); 215 printf("gpiobus at %s", pnp);
189 216
190 return (UNCONF); 217 return UNCONF;
191} 218}
192 219
193int 220int
194gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map) 221gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map)
195{ 222{
196 struct gpio_softc *sc = gpio; 223 struct gpio_softc *sc = gpio;
197 int npins, pin, i; 224 int npins, pin, i;
198 225
199 npins = gpio_npins(mask); 226 npins = gpio_npins(mask);
200 if (npins > sc->sc_npins) 227 if (npins > sc->sc_npins)
201 return (1); 228 return 1;
202 229
203 for (npins = 0, i = 0; i < 32; i++) 230 for (npins = 0, i = 0; i < 32; i++)
204 if (mask & (1 << i)) { 231 if (mask & (1 << i)) {
205 pin = offset + i; 232 pin = offset + i;
206 if (pin < 0 || pin >= sc->sc_npins) 233 if (pin < 0 || pin >= sc->sc_npins)
207 return (1); 234 return 1;
208 if (sc->sc_pins[pin].pin_mapped) 235 if (sc->sc_pins[pin].pin_mapped)
209 return (1); 236 return 1;
210 sc->sc_pins[pin].pin_mapped = 1; 237 sc->sc_pins[pin].pin_mapped = 1;
211 map->pm_map[npins++] = pin; 238 map->pm_map[npins++] = pin;
212 } 239 }
213 map->pm_size = npins; 240 map->pm_size = npins;
214 241
215 return (0); 242 return 0;
216} 243}
217 244
218void 245void
219gpio_pin_unmap(void *gpio, struct gpio_pinmap *map) 246gpio_pin_unmap(void *gpio, struct gpio_pinmap *map)
220{ 247{
221 struct gpio_softc *sc = gpio; 248 struct gpio_softc *sc = gpio;
222 int pin, i; 249 int pin, i;
223 250
224 for (i = 0; i < map->pm_size; i++) { 251 for (i = 0; i < map->pm_size; i++) {
225 pin = map->pm_map[i]; 252 pin = map->pm_map[i];
226 sc->sc_pins[pin].pin_mapped = 0; 253 sc->sc_pins[pin].pin_mapped = 0;
227 } 254 }
228} 255}
229 256
230int 257int
231gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin) 258gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin)
232{ 259{
233 struct gpio_softc *sc = gpio; 260 struct gpio_softc *sc = gpio;
234 261
235 return (gpiobus_pin_read(sc->sc_gc, map->pm_map[pin])); 262 return gpiobus_pin_read(sc->sc_gc, map->pm_map[pin]);
236} 263}
237 264
238void 265void
239gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value) 266gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value)
240{ 267{
241 struct gpio_softc *sc = gpio; 268 struct gpio_softc *sc = gpio;
242 269
243 gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value); 270 gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value);
244 sc->sc_pins[map->pm_map[pin]].pin_state = value; 271 sc->sc_pins[map->pm_map[pin]].pin_state = value;
245} 272}
246 273
247void 274void
248gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags) 275gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags)
249{ 276{
250 struct gpio_softc *sc = gpio; 277 struct gpio_softc *sc = gpio;
251 278
252 return (gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags)); 279 return gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags);
253} 280}
254 281
255int 282int
256gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin) 283gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin)
257{ 284{
258 struct gpio_softc *sc = gpio; 285 struct gpio_softc *sc = gpio;
259 286
260 return (sc->sc_pins[map->pm_map[pin]].pin_caps); 287 return sc->sc_pins[map->pm_map[pin]].pin_caps;
261} 288}
262 289
263int 290int
264gpio_npins(u_int32_t mask) 291gpio_npins(u_int32_t mask)
265{ 292{
266 int npins, i; 293 int npins, i;
267 294
268 for (npins = 0, i = 0; i < 32; i++) 295 for (npins = 0, i = 0; i < 32; i++)
269 if (mask & (1 << i)) 296 if (mask & (1 << i))
270 npins++; 297 npins++;
271 298
272 return (npins); 299 return npins;
273} 300}
274 301
275int 302int
276gpioopen(dev_t dev, int flag, int mode, 303gpioopen(dev_t dev, int flag, int mode,
277 struct lwp *l) 304 struct lwp *l)
278{ 305{
279 struct gpio_softc *sc; 306 struct gpio_softc *sc;
280 int ret; 307 int ret;
281 308
282 sc = device_lookup_private(&gpio_cd, minor(dev)); 309 sc = device_lookup_private(&gpio_cd, minor(dev));
283 if (sc == NULL) 310 if (sc == NULL)
284 return (ENXIO); 311 return ENXIO;
285 312 DPRINTF(("%s: opening\n", sc->sc_dev->dv_xname));
286 if (sc->sc_opened) 313 if (sc->sc_opened) {
287 return (EBUSY); 314 DPRINTF(("%s: already opened\n", sc->sc_dev->dv_xname));
 315 return EBUSY;
 316 }
288 317
289 if ((ret = gpiobus_open(sc->sc_gc, sc->sc_dev))) 318 if ((ret = gpiobus_open(sc->sc_gc, sc->sc_dev))) {
 319 DPRINTF(("%s: gpiobus_open returned %d\n", sc->sc_dev->dv_xname,
 320 ret));
290 return ret; 321 return ret;
 322 }
291 323
292 sc->sc_opened = 1; 324 sc->sc_opened = 1;
293 325
294 return (0); 326 return 0;
295} 327}
296 328
297int 329int
298gpioclose(dev_t dev, int flag, int mode, 330gpioclose(dev_t dev, int flag, int mode,
299 struct lwp *l) 331 struct lwp *l)
300{ 332{
301 struct gpio_softc *sc; 333 struct gpio_softc *sc;
302 334
303 sc = device_lookup_private(&gpio_cd, minor(dev)); 335 sc = device_lookup_private(&gpio_cd, minor(dev));
 336 DPRINTF(("%s: closing\n", sc->sc_dev->dv_xname));
304 gpiobus_close(sc->sc_gc, sc->sc_dev); 337 gpiobus_close(sc->sc_gc, sc->sc_dev);
305 sc->sc_opened = 0; 338 sc->sc_opened = 0;
306 339
307 return (0); 340 return 0;
 341}
 342
 343int
 344gpio_pinbyname(struct gpio_softc *sc, char *gp_name)
 345{
 346 struct gpio_name *nm;
 347
 348 LIST_FOREACH(nm, &sc->sc_names, gp_next)
 349 if (!strcmp(nm->gp_name, gp_name))
 350 return nm->gp_pin;
 351 return -1;
308} 352}
309 353
310int 354int
311gpioioctl(dev_t dev, u_long cmd, void *data, int flag, 355gpioioctl(dev_t dev, u_long cmd, void *data, int flag,
312 struct lwp *l) 356 struct lwp *l)
313{ 357{
314 struct gpio_softc *sc; 358 struct gpio_softc *sc;
315 gpio_chipset_tag_t gc; 359 gpio_chipset_tag_t gc;
316 struct gpio_info *info; 360 struct gpio_info *info;
317 struct gpio_pin_op *op; 361 struct gpio_attach *attach;
318 struct gpio_pin_ctl *ctl; 362 struct gpio_attach_args ga;
319 int pin, value, flags; 363 struct gpio_dev *gdev;
 364 struct gpio_req *req;
 365 struct gpio_name *nm;
 366 struct gpio_set *set;
 367 struct device *dv;
 368 kauth_cred_t cred;
 369 int locs[GPIOCF_NLOCS];
 370 int pin, value, flags, npins, found;
320 371
321 sc = device_lookup_private(&gpio_cd, minor(dev)); 372 sc = device_lookup_private(&gpio_cd, minor(dev));
322 gc = sc->sc_gc; 373 gc = sc->sc_gc;
323 374
324 if (cmd != GPIOINFO && !device_is_active(sc->sc_dev)) 375 if (cmd != GPIOINFO && !device_is_active(sc->sc_dev)) {
 376 DPRINTF(("%s: device is not active\n", sc->sc_dev->dv_xname));
325 return EBUSY; 377 return EBUSY;
 378 }
 379
 380 cred = kauth_cred_get();
326 381
327 switch (cmd) { 382 switch (cmd) {
328 case GPIOINFO: 383 case GPIOINFO:
329 info = (struct gpio_info *)data; 384 info = (struct gpio_info *)data;
 385 if (!kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 386 NULL, NULL, NULL, NULL))
 387 info->gpio_npins = sc->sc_npins;
 388 else {
 389 for (pin = npins = 0; pin < sc->sc_npins; pin++)
 390 if (sc->sc_pins[pin].pin_flags & GPIO_PIN_SET)
 391 ++npins;
 392 info->gpio_npins = npins;
 393 }
 394 break;
 395 case GPIOREAD:
 396 req = (struct gpio_req *)data;
 397
 398 if (req->gp_name[0] != '\0') {
 399 pin = gpio_pinbyname(sc, req->gp_name);
 400 if (pin == -1)
 401 return EINVAL;
 402 } else
 403 pin = req->gp_pin;
 404
 405 if (pin < 0 || pin >= sc->sc_npins)
 406 return EINVAL;
 407
 408 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
 409 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 410 NULL, NULL, NULL, NULL))
 411 return EPERM;
 412
 413 /* return read value */
 414 req->gp_value = gpiobus_pin_read(gc, pin);
 415 break;
 416 case GPIOWRITE:
 417 if ((flag & FWRITE) == 0)
 418 return EBADF;
 419
 420 req = (struct gpio_req *)data;
 421
 422 if (req->gp_name[0] != '\0') {
 423 pin = gpio_pinbyname(sc, req->gp_name);
 424 if (pin == -1)
 425 return EINVAL;
 426 } else
 427 pin = req->gp_pin;
 428
 429 if (pin < 0 || pin >= sc->sc_npins)
 430 return EINVAL;
 431
 432 if (sc->sc_pins[pin].pin_mapped)
 433 return EBUSY;
 434
 435 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
 436 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 437 NULL, NULL, NULL, NULL))
 438 return EPERM;
330 439
331 info->gpio_npins = sc->sc_npins; 440 value = req->gp_value;
 441 if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
 442 return EINVAL;
 443
 444 gpiobus_pin_write(gc, pin, value);
 445 /* return old value */
 446 req->gp_value = sc->sc_pins[pin].pin_state;
 447 /* update current value */
 448 sc->sc_pins[pin].pin_state = value;
332 break; 449 break;
 450 case GPIOTOGGLE:
 451 if ((flag & FWRITE) == 0)
 452 return EBADF;
 453
 454 req = (struct gpio_req *)data;
 455
 456 if (req->gp_name[0] != '\0') {
 457 pin = gpio_pinbyname(sc, req->gp_name);
 458 if (pin == -1)
 459 return EINVAL;
 460 } else
 461 pin = req->gp_pin;
 462
 463 if (pin < 0 || pin >= sc->sc_npins)
 464 return EINVAL;
 465
 466 if (sc->sc_pins[pin].pin_mapped)
 467 return EBUSY;
 468
 469 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
 470 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 471 NULL, NULL, NULL, NULL))
 472 return EPERM;
 473
 474 value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
 475 GPIO_PIN_HIGH : GPIO_PIN_LOW);
 476 gpiobus_pin_write(gc, pin, value);
 477 /* return old value */
 478 req->gp_value = sc->sc_pins[pin].pin_state;
 479 /* update current value */
 480 sc->sc_pins[pin].pin_state = value;
 481 break;
 482 case GPIOATTACH:
 483 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 484 NULL, NULL, NULL, NULL))
 485 return EPERM;
 486
 487 attach = (struct gpio_attach *)data;
 488 ga.ga_gpio = sc;
 489 ga.ga_dvname = attach->ga_dvname;
 490 ga.ga_offset = attach->ga_offset;
 491 ga.ga_mask = attach->ga_mask;
 492 DPRINTF(("%s: attach %s with offset %d and mask 0x%02x\n",
 493 sc->sc_dev->dv_xname, ga.ga_dvname, ga.ga_offset,
 494 ga.ga_mask));
 495
 496 locs[GPIOCF_OFFSET] = ga.ga_offset;
 497 locs[GPIOCF_MASK] = ga.ga_mask;
 498
 499 dv = config_found_sm_loc(sc->sc_dev, "gpio", locs, &ga,
 500 gpiobus_print, gpio_submatch);
 501 if (dv != NULL) {
 502 gdev = kmem_alloc(sizeof(struct gpio_dev), KM_SLEEP);
 503 gdev->sc_dev = dv;
 504 LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next);
 505 } else
 506 return EINVAL;
 507 break;
 508 case GPIODETACH:
 509 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 510 NULL, NULL, NULL, NULL))
 511 return EPERM;
 512
 513 attach = (struct gpio_attach *)data;
 514 LIST_FOREACH(gdev, &sc->sc_devs, sc_next) {
 515 if (strcmp(gdev->sc_dev->dv_xname, attach->ga_dvname)
 516 == 0) {
 517 if (config_detach(gdev->sc_dev, 0) == 0) {
 518 LIST_REMOVE(gdev, sc_next);
 519 kmem_free(gdev,
 520 sizeof(struct gpio_dev));
 521 return 0;
 522 }
 523 break;
 524 }
 525 }
 526 return EINVAL;
 527 break;
 528 case GPIOSET:
 529 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 530 NULL, NULL, NULL, NULL))
 531 return EPERM;
 532
 533 set = (struct gpio_set *)data;
 534
 535 if (set->gp_name[0] != '\0') {
 536 pin = gpio_pinbyname(sc, set->gp_name);
 537 if (pin == -1)
 538 return EINVAL;
 539 } else
 540 pin = set->gp_pin;
 541 if (pin < 0 || pin >= sc->sc_npins)
 542 return EINVAL;
 543 flags = set->gp_flags;
 544
 545 /* check that the controller supports all requested flags */
 546 if ((flags & sc->sc_pins[pin].pin_caps) != flags)
 547 return ENODEV;
 548 flags = set->gp_flags | GPIO_PIN_SET;
 549
 550 set->gp_caps = sc->sc_pins[pin].pin_caps;
 551 /* return old value */
 552 set->gp_flags = sc->sc_pins[pin].pin_flags;
 553 if (flags > 0) {
 554 gpiobus_pin_ctl(gc, pin, flags);
 555 /* update current value */
 556 sc->sc_pins[pin].pin_flags = flags;
 557 }
 558
 559 /* rename pin or new pin? */
 560 if (set->gp_name2[0] != '\0') {
 561 found = 0;
 562 LIST_FOREACH(nm, &sc->sc_names, gp_next)
 563 if (nm->gp_pin == pin) {
 564 strlcpy(nm->gp_name, set->gp_name2,
 565 sizeof(nm->gp_name));
 566 found = 1;
 567 break;
 568 }
 569 if (!found) {
 570 nm = kmem_alloc(sizeof(struct gpio_name),
 571 KM_SLEEP);
 572 strlcpy(nm->gp_name, set->gp_name2,
 573 sizeof(nm->gp_name));
 574 nm->gp_pin = set->gp_pin;
 575 LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next);
 576 }
 577 }
 578 break;
 579 case GPIOUNSET:
 580 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 581 NULL, NULL, NULL, NULL))
 582 return EPERM;
 583
 584 set = (struct gpio_set *)data;
 585 if (set->gp_name[0] != '\0') {
 586 pin = gpio_pinbyname(sc, set->gp_name);
 587 if (pin == -1)
 588 return EINVAL;
 589 } else
 590 pin = set->gp_pin;
 591
 592 if (pin < 0 || pin >= sc->sc_npins)
 593 return EINVAL;
 594 if (sc->sc_pins[pin].pin_mapped)
 595 return EBUSY;
 596 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET))
 597 return EINVAL;
 598
 599 LIST_FOREACH(nm, &sc->sc_names, gp_next) {
 600 if (nm->gp_pin == pin) {
 601 LIST_REMOVE(nm, gp_next);
 602 kmem_free(nm, sizeof(struct gpio_name));
 603 break;
 604 }
 605 }
 606 sc->sc_pins[pin].pin_flags &= ~GPIO_PIN_SET;
 607 break;
 608 default:
 609 /* Try the old API */
 610 DPRINTF(("%s: trying the old API\n", sc->sc_dev->dv_xname));
 611 return gpio_ioctl_oapi(sc, cmd, data, flag, cred);
 612 }
 613 return 0;
 614}
 615
 616int
 617gpio_ioctl_oapi(struct gpio_softc *sc, u_long cmd, void *data, int flag,
 618 kauth_cred_t cred)
 619{
 620 gpio_chipset_tag_t gc;
 621 struct gpio_pin_op *op;
 622 struct gpio_pin_ctl *ctl;
 623 int pin, value, flags;
 624
 625 gc = sc->sc_gc;
 626
 627 switch (cmd) {
333 case GPIOPINREAD: 628 case GPIOPINREAD:
334 op = (struct gpio_pin_op *)data; 629 op = (struct gpio_pin_op *)data;
335 630
336 pin = op->gp_pin; 631 pin = op->gp_pin;
 632
337 if (pin < 0 || pin >= sc->sc_npins) 633 if (pin < 0 || pin >= sc->sc_npins)
338 return (EINVAL); 634 return EINVAL;
 635
 636 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
 637 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 638 NULL, NULL, NULL, NULL))
 639 return EPERM;
339 640
340 /* return read value */ 641 /* return read value */
341 op->gp_value = gpiobus_pin_read(gc, pin); 642 op->gp_value = gpiobus_pin_read(gc, pin);
342 break; 643 break;
343 case GPIOPINWRITE: 644 case GPIOPINWRITE:
 645 if ((flag & FWRITE) == 0)
 646 return EBADF;
 647
344 op = (struct gpio_pin_op *)data; 648 op = (struct gpio_pin_op *)data;
345 649
346 pin = op->gp_pin; 650 pin = op->gp_pin;
 651
347 if (pin < 0 || pin >= sc->sc_npins) 652 if (pin < 0 || pin >= sc->sc_npins)
348 return (EINVAL); 653 return EINVAL;
 654
349 if (sc->sc_pins[pin].pin_mapped) 655 if (sc->sc_pins[pin].pin_mapped)
350 return (EBUSY); 656 return EBUSY;
 657
 658 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
 659 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 660 NULL, NULL, NULL, NULL))
 661 return EPERM;
351 662
352 value = op->gp_value; 663 value = op->gp_value;
353 if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH) 664 if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
354 return (EINVAL); 665 return EINVAL;
355 666
356 gpiobus_pin_write(gc, pin, value); 667 gpiobus_pin_write(gc, pin, value);
357 /* return old value */ 668 /* return old value */
358 op->gp_value = sc->sc_pins[pin].pin_state; 669 op->gp_value = sc->sc_pins[pin].pin_state;
359 /* update current value */ 670 /* update current value */
360 sc->sc_pins[pin].pin_state = value; 671 sc->sc_pins[pin].pin_state = value;
361 break; 672 break;
362 case GPIOPINTOGGLE: 673 case GPIOPINTOGGLE:
 674 if ((flag & FWRITE) == 0)
 675 return EBADF;
 676
363 op = (struct gpio_pin_op *)data; 677 op = (struct gpio_pin_op *)data;
364 678
365 pin = op->gp_pin; 679 pin = op->gp_pin;
 680
366 if (pin < 0 || pin >= sc->sc_npins) 681 if (pin < 0 || pin >= sc->sc_npins)
367 return (EINVAL); 682 return EINVAL;
 683
368 if (sc->sc_pins[pin].pin_mapped) 684 if (sc->sc_pins[pin].pin_mapped)
369 return (EBUSY); 685 return EBUSY;
 686
 687 if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
 688 kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 689 NULL, NULL, NULL, NULL))
 690 return EPERM;
370 691
371 value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ? 692 value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
372 GPIO_PIN_HIGH : GPIO_PIN_LOW); 693 GPIO_PIN_HIGH : GPIO_PIN_LOW);
373 gpiobus_pin_write(gc, pin, value); 694 gpiobus_pin_write(gc, pin, value);
374 /* return old value */ 695 /* return old value */
375 op->gp_value = sc->sc_pins[pin].pin_state; 696 op->gp_value = sc->sc_pins[pin].pin_state;
376 /* update current value */ 697 /* update current value */
377 sc->sc_pins[pin].pin_state = value; 698 sc->sc_pins[pin].pin_state = value;
378 break; 699 break;
379 case GPIOPINCTL: 700 case GPIOPINCTL:
380 ctl = (struct gpio_pin_ctl *)data; 701 ctl = (struct gpio_pin_ctl *) data;
 702
 703 if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
 704 NULL, NULL, NULL, NULL))
 705 return EPERM;
381 706
382 pin = ctl->gp_pin; 707 pin = ctl->gp_pin;
 708
383 if (pin < 0 || pin >= sc->sc_npins) 709 if (pin < 0 || pin >= sc->sc_npins)
384 return (EINVAL); 710 return EINVAL;
385 if (sc->sc_pins[pin].pin_mapped) 711 if (sc->sc_pins[pin].pin_mapped)
386 return (EBUSY); 712 return EBUSY;
387 
388 flags = ctl->gp_flags; 713 flags = ctl->gp_flags;
 714
389 /* check that the controller supports all requested flags */ 715 /* check that the controller supports all requested flags */
390 if ((flags & sc->sc_pins[pin].pin_caps) != flags) 716 if ((flags & sc->sc_pins[pin].pin_caps) != flags)
391 return (ENODEV); 717 return ENODEV;
392 718
393 ctl->gp_caps = sc->sc_pins[pin].pin_caps; 719 ctl->gp_caps = sc->sc_pins[pin].pin_caps;
394 /* return old value */ 720 /* return old value */
395 ctl->gp_flags = sc->sc_pins[pin].pin_flags; 721 ctl->gp_flags = sc->sc_pins[pin].pin_flags;
396 if (flags > 0) { 722 if (flags > 0) {
397 gpiobus_pin_ctl(gc, pin, flags); 723 gpiobus_pin_ctl(gc, pin, flags);
398 /* update current value */ 724 /* update current value */
399 sc->sc_pins[pin].pin_flags = flags; 725 sc->sc_pins[pin].pin_flags = flags;
400 } 726 }
401 break; 727 break;
402 default: 728 default:
403 return (ENOTTY); 729 return ENOTTY;
404 } 730 }
405 731 return 0;
406 return (0); 
407} 732}

cvs diff -r1.6 -r1.7 src/sys/dev/gpio/gpioow.c (expand / switch to unified diff)

--- src/sys/dev/gpio/gpioow.c 2009/03/18 16:00:17 1.6
+++ src/sys/dev/gpio/gpioow.c 2009/07/25 16:17:10 1.7
@@ -1,34 +1,34 @@ @@ -1,34 +1,34 @@
1/* $NetBSD: gpioow.c,v 1.6 2009/03/18 16:00:17 cegger Exp $ */ 1/* $NetBSD: gpioow.c,v 1.7 2009/07/25 16:17:10 mbalmer Exp $ */
2/* $OpenBSD: gpioow.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */ 2/* $OpenBSD: gpioow.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org> 5 * Copyright (c) 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
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#include <sys/cdefs.h> 20#include <sys/cdefs.h>
21__KERNEL_RCSID(0, "$NetBSD: gpioow.c,v 1.6 2009/03/18 16:00:17 cegger Exp $"); 21__KERNEL_RCSID(0, "$NetBSD: gpioow.c,v 1.7 2009/07/25 16:17:10 mbalmer Exp $");
22 22
23/* 23/*
24 * 1-Wire bus bit-banging through GPIO pin. 24 * 1-Wire bus bit-banging through GPIO pin.
25 */ 25 */
26 26
27#include <sys/param.h> 27#include <sys/param.h>
28#include <sys/systm.h> 28#include <sys/systm.h>
29#include <sys/device.h> 29#include <sys/device.h>
30#include <sys/gpio.h> 30#include <sys/gpio.h>
31 31
32#include <dev/gpio/gpiovar.h> 32#include <dev/gpio/gpiovar.h>
33 33
34#include <dev/onewire/onewirevar.h> 34#include <dev/onewire/onewirevar.h>
@@ -67,40 +67,45 @@ CFATTACH_DECL_NEW(gpioow, sizeof(struct  @@ -67,40 +67,45 @@ CFATTACH_DECL_NEW(gpioow, sizeof(struct
67extern struct cfdriver gpioow_cd; 67extern struct cfdriver gpioow_cd;
68 68
69static const struct onewire_bbops gpioow_bbops = { 69static const struct onewire_bbops gpioow_bbops = {
70 gpioow_bb_rx, 70 gpioow_bb_rx,
71 gpioow_bb_tx, 71 gpioow_bb_tx,
72 gpioow_bb_get, 72 gpioow_bb_get,
73 gpioow_bb_set 73 gpioow_bb_set
74}; 74};
75 75
76int 76int
77gpioow_match(device_t parent, cfdata_t cf, 77gpioow_match(device_t parent, cfdata_t cf,
78 void *aux) 78 void *aux)
79{ 79{
80 return 1; 80 struct gpio_attach_args *ga = aux;
 81
 82 if (ga->ga_offset == -1)
 83 return 0;
 84
 85 return strcmp(ga->ga_dvname, cf->cf_name) == 0;
81} 86}
82 87
83void 88void
84gpioow_attach(device_t parent, device_t self, void *aux) 89gpioow_attach(device_t parent, device_t self, void *aux)
85{ 90{
86 struct gpioow_softc *sc = device_private(self); 91 struct gpioow_softc *sc = device_private(self);
87 struct gpio_attach_args *ga = aux; 92 struct gpio_attach_args *ga = aux;
88 struct onewirebus_attach_args oba; 93 struct onewirebus_attach_args oba;
89 int caps; 94 int caps;
90 95
91 /* Check that we have enough pins */ 96 /* Check that we have enough pins */
92 if (gpio_npins(ga->ga_mask) != GPIOOW_NPINS) { 97 if (gpio_npins(ga->ga_mask) != GPIOOW_NPINS) {
93 printf(": invalid pin mask\n"); 98 printf(": invalid pin mask 0x%02x\n", ga->ga_mask);
94 return; 99 return;
95 } 100 }
96 101
97 /* Map pins */ 102 /* Map pins */
98 sc->sc_gpio = ga->ga_gpio; 103 sc->sc_gpio = ga->ga_gpio;
99 sc->sc_map.pm_map = sc->__map; 104 sc->sc_map.pm_map = sc->__map;
100 if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask, 105 if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
101 &sc->sc_map)) { 106 &sc->sc_map)) {
102 printf(": can't map pins\n"); 107 printf(": can't map pins\n");
103 return; 108 return;
104 } 109 }
105 110
106 /* Configure data pin */ 111 /* Configure data pin */
@@ -141,30 +146,32 @@ gpioow_attach(device_t parent, device_t  @@ -141,30 +146,32 @@ gpioow_attach(device_t parent, device_t
141 146
142 return; 147 return;
143 148
144fail: 149fail:
145 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); 150 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
146} 151}
147 152
148int 153int
149gpioow_detach(device_t self, int flags) 154gpioow_detach(device_t self, int flags)
150{ 155{
151 struct gpioow_softc *sc = device_private(self); 156 struct gpioow_softc *sc = device_private(self);
152 int rv = 0; 157 int rv = 0;
153 158
 159 gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
 160
154 if (sc->sc_ow_dev != NULL) 161 if (sc->sc_ow_dev != NULL)
155 rv = config_detach(sc->sc_ow_dev, flags); 162 rv = config_detach(sc->sc_ow_dev, flags);
156 163
157 return (rv); 164 return rv;
158} 165}
159 166
160int 167int
161gpioow_activate(device_t self, enum devact act) 168gpioow_activate(device_t self, enum devact act)
162{ 169{
163 struct gpioow_softc *sc = device_private(self); 170 struct gpioow_softc *sc = device_private(self);
164 int rv = 0; 171 int rv = 0;
165 172
166 switch (act) { 173 switch (act) {
167 case DVACT_ACTIVATE: 174 case DVACT_ACTIVATE:
168 return (EOPNOTSUPP); 175 return (EOPNOTSUPP);
169 case DVACT_DEACTIVATE: 176 case DVACT_DEACTIVATE:
170 sc->sc_dying = 1; 177 sc->sc_dying = 1;

File Added: src/sys/dev/gpio/gpiosim.c
/* $NetBSD: gpiosim.c,v 1.1 2009/07/25 16:17:10 mbalmer Exp $ */
/*      $OpenBSD: gpiosim.c,v 1.1 2008/11/23 18:46:49 mbalmer Exp $	*/

/*
 * Copyright (c) 2007, 2008, 2009 Marc Balmer <marc@msys.ch>
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/* 32 bit wide GPIO simulator  */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/gpio.h>
#include <sys/malloc.h>
#include <sys/sysctl.h>
#include <sys/ioccom.h>

#include <dev/gpio/gpiovar.h>
#include <dev/biovar.h>

#define	GPIOSIM_NPINS	32

struct gpiosim_softc {
	struct device		sc_dev;
	u_int32_t		sc_state;
	struct gpio_chipset_tag	sc_gpio_gc;
	gpio_pin_t		sc_gpio_pins[GPIOSIM_NPINS];
};

struct gpiosim_op {
	void *cookie;
	u_int32_t mask;
	u_int32_t state;
};
#define GPIOSIMREAD	_IOWR('G', 0, struct gpiosim_op)
#define GPIOSIMWRITE	_IOW('G', 1, struct gpiosim_op)

int	gpiosim_match(device_t, cfdata_t, void *);
void	gpiosim_attach(device_t, device_t, void *);
int	gpiosim_detach(device_t, int);
int	gpiosim_ioctl(device_t, u_long cmd, void *);
int	gpiosim_activate(device_t, enum devact);

int	gpiosim_pin_read(void *, int);
void	gpiosim_pin_write(void *, int, int);
void	gpiosim_pin_ctl(void *, int, int);

CFATTACH_DECL_NEW(gpiosim, sizeof(struct gpiosim_softc), gpiosim_match,
    gpiosim_attach, gpiosim_detach, gpiosim_activate);

extern struct cfdriver gpiosim_cd;

int
gpiosim_match(device_t parent, cfdata_t match, void *aux)
{
	return 1;
}

void
gpiosim_attach(device_t parent, device_t self, void *aux)
{
	struct gpiosim_softc *sc = device_private(self);
	struct gpiobus_attach_args gba;
	int i;

	/* initialize pin array */
	for (i = 0; i < GPIOSIM_NPINS; i++) {
		sc->sc_gpio_pins[i].pin_num = i;
		sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
		    GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN |
		    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN |
		    GPIO_PIN_INVIN | GPIO_PIN_INVOUT;

		/* read initial state */
		sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_INPUT;
		sc->sc_state = 0;

		/* create controller tag */
		sc->sc_gpio_gc.gp_cookie = sc;
		sc->sc_gpio_gc.gp_pin_read = gpiosim_pin_read;
		sc->sc_gpio_gc.gp_pin_write = gpiosim_pin_write;
		sc->sc_gpio_gc.gp_pin_ctl = gpiosim_pin_ctl;

		/* gba.gba_name = "gpio"; */
		gba.gba_gc = &sc->sc_gpio_gc;
		gba.gba_pins = sc->sc_gpio_pins;
		gba.gba_npins = GPIOSIM_NPINS;
	}
	printf("\n");
	config_found_ia(self, "gpiobus", &gba, gpiobus_print);
	bio_register(&sc->sc_dev, gpiosim_ioctl);
}

int
gpiosim_detach(device_t self, int flags)
{
	return 1;
}

int
gpiosim_activate(device_t self, enum devact act)
{
	switch (act) {
	case DVACT_ACTIVATE:
		return EOPNOTSUPP;
	case DVACT_DEACTIVATE:
		break;
	}

	return 0;
}

int
gpiosim_ioctl(device_t self, u_long cmd, void * data)
{
	struct gpiosim_softc *sc = (void *)self;
	struct gpiosim_op *op = (void *)data;

	switch (cmd) {
		case GPIOSIMREAD:
			op->state = sc->sc_state;
			break;
		case GPIOSIMWRITE:
			sc->sc_state = (sc->sc_state & ~op->mask) |
			    (op->state & op->mask);
			break;
	}
	return 0;
}

int
gpiosim_pin_read(void *arg, int pin)
{
	struct gpiosim_softc *sc = (struct gpiosim_softc *)arg;

	if (sc->sc_state & (1 << pin))
		return GPIO_PIN_HIGH;
	else
		return GPIO_PIN_LOW;
}

void
gpiosim_pin_write(void *arg, int pin, int value)
{
	struct gpiosim_softc *sc = (struct gpiosim_softc *)arg;

	if (value == 0)
		sc->sc_state &= ~(1 << pin);
	else
		sc->sc_state |= (1 << pin);
}

void
gpiosim_pin_ctl(void *arg, int pin, int flags)
{
	struct gpiosim_softc *sc = (struct gpiosim_softc *)arg;

	sc->sc_gpio_pins[pin].pin_flags = flags;
}

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

--- src/sys/dev/gpio/gpiovar.h 2008/06/24 10:05:01 1.7
+++ src/sys/dev/gpio/gpiovar.h 2009/07/25 16:17:10 1.8
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: gpiovar.h,v 1.7 2008/06/24 10:05:01 gmcgarry Exp $ */ 1/* $NetBSD: gpiovar.h,v 1.8 2009/07/25 16:17:10 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
@@ -58,31 +58,43 @@ int gpiobus_print(void *, const char *); @@ -58,31 +58,43 @@ int gpiobus_print(void *, const char *);
58 ((gc)->gp_gc_close ? ((gc)->gp_gc_close((gc)->gp_cookie, dev)), 1 : 0) 58 ((gc)->gp_gc_close ? ((gc)->gp_gc_close((gc)->gp_cookie, dev)), 1 : 0)
59#define gpiobus_pin_read(gc, pin) \ 59#define gpiobus_pin_read(gc, pin) \
60 ((gc)->gp_pin_read((gc)->gp_cookie, (pin))) 60 ((gc)->gp_pin_read((gc)->gp_cookie, (pin)))
61#define gpiobus_pin_write(gc, pin, value) \ 61#define gpiobus_pin_write(gc, pin, value) \
62 ((gc)->gp_pin_write((gc)->gp_cookie, (pin), (value))) 62 ((gc)->gp_pin_write((gc)->gp_cookie, (pin), (value)))
63#define gpiobus_pin_ctl(gc, pin, flags) \ 63#define gpiobus_pin_ctl(gc, pin, flags) \
64 ((gc)->gp_pin_ctl((gc)->gp_cookie, (pin), (flags))) 64 ((gc)->gp_pin_ctl((gc)->gp_cookie, (pin), (flags)))
65 65
66/* Attach devices connected to the GPIO pins */ 66/* Attach devices connected to the GPIO pins */
67struct gpio_attach_args { 67struct gpio_attach_args {
68 void * ga_gpio; 68 void * ga_gpio;
69 int ga_offset; 69 int ga_offset;
70 u_int32_t ga_mask; 70 u_int32_t ga_mask;
 71 char *ga_dvname;
71}; 72};
72 73
73/* GPIO pin map */ 74/* GPIO pin map */
74struct gpio_pinmap { 75struct gpio_pinmap {
75 int * pm_map; /* pin map */ 76 int * pm_map; /* pin map */
76 int pm_size; /* map size */ 77 int pm_size; /* map size */
77}; 78};
78 79
 80struct gpio_dev {
 81 struct device *sc_dev; /* the gpio device */
 82 LIST_ENTRY(gpio_dev) sc_next;
 83};
 84
 85struct gpio_name {
 86 char gp_name[GPIOMAXNAME];
 87 int gp_pin;
 88 LIST_ENTRY(gpio_name) gp_next;
 89};
 90
79int gpio_pin_map(void *, int, u_int32_t, struct gpio_pinmap *); 91int gpio_pin_map(void *, int, u_int32_t, struct gpio_pinmap *);
80void gpio_pin_unmap(void *, struct gpio_pinmap *); 92void gpio_pin_unmap(void *, struct gpio_pinmap *);
81int gpio_pin_read(void *, struct gpio_pinmap *, int); 93int gpio_pin_read(void *, struct gpio_pinmap *, int);
82void gpio_pin_write(void *, struct gpio_pinmap *, int, int); 94void gpio_pin_write(void *, struct gpio_pinmap *, int, int);
83void gpio_pin_ctl(void *, struct gpio_pinmap *, int, int); 95void gpio_pin_ctl(void *, struct gpio_pinmap *, int, int);
84int gpio_pin_caps(void *, struct gpio_pinmap *, int); 96int gpio_pin_caps(void *, struct gpio_pinmap *, int);
85 97
86int gpio_npins(u_int32_t); 98int gpio_npins(u_int32_t);
87 99
88#endif /* !_DEV_GPIO_GPIOVAR_H_ */ 100#endif /* !_DEV_GPIO_GPIOVAR_H_ */

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

--- src/sys/sys/gpio.h 2008/01/09 15:11:30 1.3
+++ src/sys/sys/gpio.h 2009/07/25 16:17:10 1.4
@@ -1,62 +1,101 @@ @@ -1,62 +1,101 @@
1/* $NetBSD: gpio.h,v 1.3 2008/01/09 15:11:30 xtraeme Exp $ */ 1/* $NetBSD */
2/* $OpenBSD: gpio.h,v 1.1 2004/06/03 18:08:00 grange Exp $ */ 2/* $OpenBSD: gpio.h,v 1.7 2008/11/26 14:51:20 mbalmer 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 18
19#ifndef _SYS_GPIO_H_ 19#ifndef _SYS_GPIO_H_
20#define _SYS_GPIO_H_ 20#define _SYS_GPIO_H_
21 21
22/* GPIO pin states */ 22/* GPIO pin states */
23#define GPIO_PIN_LOW 0x00 /* low level (logical 0) */ 23#define GPIO_PIN_LOW 0x00 /* low level (logical 0) */
24#define GPIO_PIN_HIGH 0x01 /* high level (logical 1) */ 24#define GPIO_PIN_HIGH 0x01 /* high level (logical 1) */
25 25
 26/* Max name length of a pin */
 27#define GPIOMAXNAME 64
 28
26/* GPIO pin configuration flags */ 29/* GPIO pin configuration flags */
27#define GPIO_PIN_INPUT 0x0001 /* input direction */ 30#define GPIO_PIN_INPUT 0x0001 /* input direction */
28#define GPIO_PIN_OUTPUT 0x0002 /* output direction */ 31#define GPIO_PIN_OUTPUT 0x0002 /* output direction */
29#define GPIO_PIN_INOUT 0x0004 /* bi-directional */ 32#define GPIO_PIN_INOUT 0x0004 /* bi-directional */
30#define GPIO_PIN_OPENDRAIN 0x0008 /* open-drain output */ 33#define GPIO_PIN_OPENDRAIN 0x0008 /* open-drain output */
31#define GPIO_PIN_PUSHPULL 0x0010 /* push-pull output */ 34#define GPIO_PIN_PUSHPULL 0x0010 /* push-pull output */
32#define GPIO_PIN_TRISTATE 0x0020 /* output disabled */ 35#define GPIO_PIN_TRISTATE 0x0020 /* output disabled */
33#define GPIO_PIN_PULLUP 0x0040 /* internal pull-up enabled */ 36#define GPIO_PIN_PULLUP 0x0040 /* internal pull-up enabled */
34#define GPIO_PIN_PULLDOWN 0x0080 /* internal pull-down enabled */ 37#define GPIO_PIN_PULLDOWN 0x0080 /* internal pull-down enabled */
35#define GPIO_PIN_INVIN 0x0100 /* invert input */ 38#define GPIO_PIN_INVIN 0x0100 /* invert input */
36#define GPIO_PIN_INVOUT 0x0200 /* invert output */ 39#define GPIO_PIN_INVOUT 0x0200 /* invert output */
 40#define GPIO_PIN_USER 0x0400 /* user != 0 can access */
 41#define GPIO_PIN_SET 0x8000 /* set for securelevel access */
37 42
38/* GPIO controller description */ 43/* GPIO controller description */
39struct gpio_info { 44struct gpio_info {
40 int gpio_npins; /* total number of pins available */ 45 int gpio_npins; /* total number of pins available */
41}; 46};
42 47
43/* GPIO pin operation (read/write/toggle) */ 48/* GPIO pin request (read/write/toggle) */
44struct gpio_pin_op { 49struct gpio_req {
45 int gp_pin; /* pin number */ 50 char gp_name[GPIOMAXNAME]; /* pin name */
46 int gp_value; /* value */ 51 int gp_pin; /* pin number */
 52 int gp_value; /* value */
 53};
 54
 55/* GPIO pin configuration */
 56struct gpio_set {
 57 char gp_name[GPIOMAXNAME];
 58 int gp_pin;
 59 int gp_caps;
 60 int gp_flags;
 61 char gp_name2[GPIOMAXNAME]; /* new name */
 62};
 63
 64/* Attach/detach device drivers that use GPIO pins */
 65struct gpio_attach {
 66 char ga_dvname[16]; /* device name */
 67 int ga_offset; /* pin number */
 68 u_int32_t ga_mask; /* binary mask */
47}; 69};
48 70
49/* GPIO pin control */ 71/* GPIO pin control (old API) */
50struct gpio_pin_ctl { 72struct gpio_pin_ctl {
51 int gp_pin; /* pin number */ 73 int gp_pin; /* pin number */
52 int gp_caps; /* pin capabilities (read-only) */ 74 int gp_caps; /* pin capabilities (read-only) */
53 int gp_flags; /* pin configuration flags */ 75 int gp_flags; /* pin configuration flags */
54}; 76};
55 77
 78/* GPIO pin operation (read/write/toggle) (old API) */
 79struct gpio_pin_op {
 80 int gp_pin; /* pin number */
 81 int gp_value; /* value */
 82};
 83
56#define GPIOINFO _IOR('G', 0, struct gpio_info) 84#define GPIOINFO _IOR('G', 0, struct gpio_info)
 85
 86/* the old API, kept for backwards compatibility */
57#define GPIOPINREAD _IOWR('G', 1, struct gpio_pin_op) 87#define GPIOPINREAD _IOWR('G', 1, struct gpio_pin_op)
58#define GPIOPINWRITE _IOWR('G', 2, struct gpio_pin_op) 88#define GPIOPINWRITE _IOWR('G', 2, struct gpio_pin_op)
59#define GPIOPINTOGGLE _IOWR('G', 3, struct gpio_pin_op) 89#define GPIOPINTOGGLE _IOWR('G', 3, struct gpio_pin_op)
60#define GPIOPINCTL _IOWR('G', 4, struct gpio_pin_ctl) 90#define GPIOPINCTL _IOWR('G', 4, struct gpio_pin_ctl)
61 91
 92/* the new API */
 93#define GPIOSET _IOWR('G', 5, struct gpio_set)
 94#define GPIOUNSET _IOWR('G', 6, struct gpio_set)
 95#define GPIOREAD _IOWR('G', 7, struct gpio_req)
 96#define GPIOWRITE _IOWR('G', 8, struct gpio_req)
 97#define GPIOTOGGLE _IOWR('G', 9, struct gpio_req)
 98#define GPIOATTACH _IOWR('G', 10, struct gpio_attach)
 99#define GPIODETACH _IOWR('G', 11, struct gpio_attach)
 100
62#endif /* !_SYS_GPIO_H_ */ 101#endif /* !_SYS_GPIO_H_ */