1 1.75 martin /* $NetBSD: gpio.c,v 1.75 2024/12/17 12:39:39 martin Exp $ */ 2 1.5 riz /* $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */ 3 1.5 riz 4 1.1 jmcneill /* 5 1.35 mbalmer * Copyright (c) 2008, 2009, 2010, 2011 Marc Balmer <marc (at) msys.ch> 6 1.5 riz * Copyright (c) 2004, 2006 Alexander Yurchenko <grange (at) openbsd.org> 7 1.1 jmcneill * 8 1.1 jmcneill * Permission to use, copy, modify, and distribute this software for any 9 1.1 jmcneill * purpose with or without fee is hereby granted, provided that the above 10 1.1 jmcneill * copyright notice and this permission notice appear in all copies. 11 1.1 jmcneill * 12 1.1 jmcneill * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 1.1 jmcneill * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 1.1 jmcneill * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 1.1 jmcneill * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 1.1 jmcneill * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 1.1 jmcneill * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 1.1 jmcneill * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 1.1 jmcneill */ 20 1.1 jmcneill 21 1.69 thorpej #ifdef _KERNEL_OPT 22 1.69 thorpej #include "opt_fdt.h" 23 1.69 thorpej #endif 24 1.69 thorpej 25 1.2 cube #include <sys/cdefs.h> 26 1.75 martin __KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.75 2024/12/17 12:39:39 martin Exp $"); 27 1.2 cube 28 1.1 jmcneill /* 29 1.1 jmcneill * General Purpose Input/Output framework. 30 1.1 jmcneill */ 31 1.1 jmcneill 32 1.1 jmcneill #include <sys/param.h> 33 1.36 mbalmer #include <sys/callout.h> 34 1.1 jmcneill #include <sys/systm.h> 35 1.1 jmcneill #include <sys/conf.h> 36 1.1 jmcneill #include <sys/device.h> 37 1.19 mbalmer #include <sys/fcntl.h> 38 1.1 jmcneill #include <sys/ioctl.h> 39 1.1 jmcneill #include <sys/gpio.h> 40 1.36 mbalmer #include <sys/kernel.h> 41 1.1 jmcneill #include <sys/vnode.h> 42 1.19 mbalmer #include <sys/kmem.h> 43 1.36 mbalmer #include <sys/mutex.h> 44 1.36 mbalmer #include <sys/condvar.h> 45 1.19 mbalmer #include <sys/queue.h> 46 1.19 mbalmer #include <sys/kauth.h> 47 1.35 mbalmer #include <sys/module.h> 48 1.69 thorpej 49 1.1 jmcneill #include <dev/gpio/gpiovar.h> 50 1.1 jmcneill 51 1.69 thorpej #ifdef FDT 52 1.69 thorpej #include <dev/fdt/fdtvar.h> 53 1.69 thorpej #endif 54 1.69 thorpej 55 1.60 riastrad #include "ioconf.h" 56 1.3 drochner #include "locators.h" 57 1.3 drochner 58 1.19 mbalmer #ifdef GPIO_DEBUG 59 1.21 cegger #define DPRINTFN(n, x) do { if (gpiodebug > (n)) printf x; } while (0) 60 1.19 mbalmer int gpiodebug = 0; 61 1.19 mbalmer #else 62 1.19 mbalmer #define DPRINTFN(n, x) 63 1.19 mbalmer #endif 64 1.19 mbalmer #define DPRINTF(x) DPRINTFN(0, x) 65 1.19 mbalmer 66 1.1 jmcneill struct gpio_softc { 67 1.19 mbalmer device_t sc_dev; 68 1.1 jmcneill 69 1.19 mbalmer gpio_chipset_tag_t sc_gc; /* GPIO controller */ 70 1.19 mbalmer gpio_pin_t *sc_pins; /* pins array */ 71 1.19 mbalmer int sc_npins; /* number of pins */ 72 1.19 mbalmer 73 1.36 mbalmer kmutex_t sc_mtx; 74 1.36 mbalmer kcondvar_t sc_ioctl; /* ioctl in progress */ 75 1.36 mbalmer int sc_ioctl_busy; /* ioctl is busy */ 76 1.39 mbalmer kcondvar_t sc_attach; /* attach/detach in progress */ 77 1.39 mbalmer int sc_attach_busy;/* busy in attach/detach */ 78 1.45 mbalmer #ifdef COMPAT_50 79 1.19 mbalmer LIST_HEAD(, gpio_dev) sc_devs; /* devices */ 80 1.45 mbalmer #endif 81 1.19 mbalmer LIST_HEAD(, gpio_name) sc_names; /* named pins */ 82 1.1 jmcneill }; 83 1.1 jmcneill 84 1.35 mbalmer static int gpio_match(device_t, cfdata_t, void *); 85 1.35 mbalmer int gpio_submatch(device_t, cfdata_t, const int *, void *); 86 1.35 mbalmer static void gpio_attach(device_t, device_t, void *); 87 1.35 mbalmer static int gpio_rescan(device_t, const char *, const int *); 88 1.35 mbalmer static void gpio_childdetached(device_t, device_t); 89 1.35 mbalmer static bool gpio_resume(device_t, const pmf_qual_t *); 90 1.35 mbalmer static int gpio_detach(device_t, int); 91 1.35 mbalmer static int gpio_search(device_t, cfdata_t, const int *, void *); 92 1.35 mbalmer static int gpio_print(void *, const char *); 93 1.35 mbalmer static int gpio_pinbyname(struct gpio_softc *, char *); 94 1.36 mbalmer static int gpio_ioctl(struct gpio_softc *, u_long, void *, int, 95 1.36 mbalmer struct lwp *); 96 1.19 mbalmer 97 1.42 mbalmer #ifdef COMPAT_50 98 1.19 mbalmer /* Old API */ 99 1.35 mbalmer static int gpio_ioctl_oapi(struct gpio_softc *, u_long, void *, int, 100 1.68 christos struct lwp *); 101 1.42 mbalmer #endif 102 1.1 jmcneill 103 1.18 dyoung CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc), 104 1.29 dyoung gpio_match, gpio_attach, gpio_detach, NULL, gpio_rescan, 105 1.29 dyoung gpio_childdetached, DVF_DETACH_SHUTDOWN); 106 1.1 jmcneill 107 1.1 jmcneill dev_type_open(gpioopen); 108 1.1 jmcneill dev_type_close(gpioclose); 109 1.1 jmcneill dev_type_ioctl(gpioioctl); 110 1.36 mbalmer dev_type_ioctl(gpioioctl_locked); 111 1.1 jmcneill 112 1.1 jmcneill const struct cdevsw gpio_cdevsw = { 113 1.53 dholland .d_open = gpioopen, 114 1.53 dholland .d_close = gpioclose, 115 1.53 dholland .d_read = noread, 116 1.53 dholland .d_write = nowrite, 117 1.53 dholland .d_ioctl = gpioioctl, 118 1.53 dholland .d_stop = nostop, 119 1.53 dholland .d_tty = notty, 120 1.53 dholland .d_poll = nopoll, 121 1.53 dholland .d_mmap = nommap, 122 1.53 dholland .d_kqfilter = nokqfilter, 123 1.57 dholland .d_discard = nodiscard, 124 1.53 dholland .d_flag = D_OTHER | D_MPSAFE 125 1.1 jmcneill }; 126 1.1 jmcneill 127 1.35 mbalmer static int 128 1.17 cegger gpio_match(device_t parent, cfdata_t cf, void *aux) 129 1.1 jmcneill { 130 1.19 mbalmer return 1; 131 1.19 mbalmer } 132 1.19 mbalmer 133 1.19 mbalmer int 134 1.19 mbalmer gpio_submatch(device_t parent, cfdata_t cf, const int *ip, void *aux) 135 1.19 mbalmer { 136 1.19 mbalmer struct gpio_attach_args *ga = aux; 137 1.1 jmcneill 138 1.19 mbalmer if (ga->ga_offset == -1) 139 1.19 mbalmer return 0; 140 1.19 mbalmer 141 1.19 mbalmer return strcmp(ga->ga_dvname, cf->cf_name) == 0; 142 1.1 jmcneill } 143 1.1 jmcneill 144 1.35 mbalmer static bool 145 1.32 dyoung gpio_resume(device_t self, const pmf_qual_t *qual) 146 1.13 dyoung { 147 1.13 dyoung struct gpio_softc *sc = device_private(self); 148 1.13 dyoung int pin; 149 1.13 dyoung 150 1.13 dyoung for (pin = 0; pin < sc->sc_npins; pin++) { 151 1.13 dyoung gpiobus_pin_ctl(sc->sc_gc, pin, sc->sc_pins[pin].pin_flags); 152 1.13 dyoung gpiobus_pin_write(sc->sc_gc, pin, sc->sc_pins[pin].pin_state); 153 1.13 dyoung } 154 1.13 dyoung return true; 155 1.13 dyoung } 156 1.13 dyoung 157 1.35 mbalmer static void 158 1.29 dyoung gpio_childdetached(device_t self, device_t child) 159 1.29 dyoung { 160 1.45 mbalmer #ifdef COMPAT_50 161 1.39 mbalmer struct gpio_dev *gdev; 162 1.39 mbalmer struct gpio_softc *sc; 163 1.39 mbalmer int error; 164 1.39 mbalmer 165 1.39 mbalmer /* 166 1.39 mbalmer * gpio_childetached is serialized because it can be entered in 167 1.39 mbalmer * different ways concurrently, e.g. via the GPIODETACH ioctl and 168 1.39 mbalmer * drvctl(8) or modunload(8). 169 1.39 mbalmer */ 170 1.39 mbalmer sc = device_private(self); 171 1.39 mbalmer error = 0; 172 1.39 mbalmer mutex_enter(&sc->sc_mtx); 173 1.39 mbalmer while (sc->sc_attach_busy) { 174 1.39 mbalmer error = cv_wait_sig(&sc->sc_attach, &sc->sc_mtx); 175 1.39 mbalmer if (error) 176 1.39 mbalmer break; 177 1.39 mbalmer } 178 1.39 mbalmer if (!error) 179 1.39 mbalmer sc->sc_attach_busy = 1; 180 1.39 mbalmer mutex_exit(&sc->sc_mtx); 181 1.39 mbalmer if (error) 182 1.39 mbalmer return; 183 1.39 mbalmer 184 1.71 brad KERNEL_LOCK(1, NULL); 185 1.39 mbalmer LIST_FOREACH(gdev, &sc->sc_devs, sc_next) 186 1.39 mbalmer if (gdev->sc_dev == child) { 187 1.39 mbalmer LIST_REMOVE(gdev, sc_next); 188 1.39 mbalmer kmem_free(gdev, sizeof(struct gpio_dev)); 189 1.39 mbalmer break; 190 1.39 mbalmer } 191 1.71 brad KERNEL_UNLOCK_ONE(NULL); 192 1.39 mbalmer 193 1.39 mbalmer mutex_enter(&sc->sc_mtx); 194 1.39 mbalmer sc->sc_attach_busy = 0; 195 1.39 mbalmer cv_signal(&sc->sc_attach); 196 1.39 mbalmer mutex_exit(&sc->sc_mtx); 197 1.45 mbalmer #endif 198 1.29 dyoung } 199 1.29 dyoung 200 1.35 mbalmer static int 201 1.29 dyoung gpio_rescan(device_t self, const char *ifattr, const int *locators) 202 1.29 dyoung { 203 1.29 dyoung 204 1.71 brad KERNEL_LOCK(1, NULL); 205 1.65 thorpej config_search(self, NULL, 206 1.66 thorpej CFARGS(.search = gpio_search)); 207 1.71 brad KERNEL_UNLOCK_ONE(NULL); 208 1.29 dyoung 209 1.29 dyoung return 0; 210 1.29 dyoung } 211 1.29 dyoung 212 1.69 thorpej static const char * 213 1.69 thorpej gpio_pin_defname(struct gpio_softc *sc, int pin) 214 1.69 thorpej { 215 1.69 thorpej KASSERT(pin >= 0); 216 1.69 thorpej 217 1.69 thorpej #ifdef FDT 218 1.69 thorpej devhandle_t devhandle = device_handle(sc->sc_dev); 219 1.69 thorpej 220 1.69 thorpej if (devhandle_type(devhandle) == DEVHANDLE_TYPE_OF) { 221 1.69 thorpej return fdtbus_get_string_index(devhandle_to_of(devhandle), 222 1.69 thorpej "gpio-line-names", pin); 223 1.69 thorpej } 224 1.69 thorpej #endif /* FDT */ 225 1.69 thorpej 226 1.69 thorpej return NULL; 227 1.69 thorpej } 228 1.69 thorpej 229 1.35 mbalmer static void 230 1.14 dyoung gpio_attach(device_t parent, device_t self, void *aux) 231 1.1 jmcneill { 232 1.7 thorpej struct gpio_softc *sc = device_private(self); 233 1.1 jmcneill struct gpiobus_attach_args *gba = aux; 234 1.59 jmcneill struct gpio_name *nm; 235 1.59 jmcneill int pin; 236 1.47 mbalmer 237 1.17 cegger sc->sc_dev = self; 238 1.1 jmcneill sc->sc_gc = gba->gba_gc; 239 1.1 jmcneill sc->sc_pins = gba->gba_pins; 240 1.1 jmcneill sc->sc_npins = gba->gba_npins; 241 1.1 jmcneill 242 1.51 dyoung aprint_normal(": %d pins\n", sc->sc_npins); 243 1.55 msaitoh aprint_naive("\n"); 244 1.1 jmcneill 245 1.59 jmcneill /* Configure default pin names */ 246 1.59 jmcneill for (pin = 0; pin < sc->sc_npins; pin++) { 247 1.69 thorpej const char *defname; 248 1.69 thorpej 249 1.69 thorpej defname = gpio_pin_defname(sc, pin); 250 1.69 thorpej if (defname == NULL && 251 1.69 thorpej sc->sc_pins[pin].pin_defname[0] != '\0') { 252 1.69 thorpej defname = sc->sc_pins[pin].pin_defname; 253 1.69 thorpej } 254 1.69 thorpej if (defname == NULL) { 255 1.59 jmcneill continue; 256 1.69 thorpej } 257 1.59 jmcneill nm = kmem_alloc(sizeof(*nm), KM_SLEEP); 258 1.69 thorpej strlcpy(nm->gp_name, defname, sizeof(nm->gp_name)); 259 1.59 jmcneill nm->gp_pin = pin; 260 1.59 jmcneill LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next); 261 1.59 jmcneill } 262 1.59 jmcneill 263 1.13 dyoung if (!pmf_device_register(self, NULL, gpio_resume)) 264 1.13 dyoung aprint_error_dev(self, "couldn't establish power handler\n"); 265 1.36 mbalmer mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM); 266 1.36 mbalmer cv_init(&sc->sc_ioctl, "gpioctl"); 267 1.39 mbalmer cv_init(&sc->sc_attach, "gpioatch"); 268 1.1 jmcneill /* 269 1.1 jmcneill * Attach all devices that can be connected to the GPIO pins 270 1.1 jmcneill * described in the kernel configuration file. 271 1.1 jmcneill */ 272 1.29 dyoung gpio_rescan(self, "gpio", NULL); 273 1.1 jmcneill } 274 1.1 jmcneill 275 1.35 mbalmer static int 276 1.14 dyoung gpio_detach(device_t self, int flags) 277 1.1 jmcneill { 278 1.36 mbalmer struct gpio_softc *sc; 279 1.47 mbalmer int rc; 280 1.36 mbalmer 281 1.36 mbalmer sc = device_private(self); 282 1.36 mbalmer 283 1.29 dyoung if ((rc = config_detach_children(self, flags)) != 0) 284 1.29 dyoung return rc; 285 1.36 mbalmer mutex_destroy(&sc->sc_mtx); 286 1.36 mbalmer cv_destroy(&sc->sc_ioctl); 287 1.1 jmcneill #if 0 288 1.1 jmcneill int maj, mn; 289 1.1 jmcneill 290 1.1 jmcneill /* Locate the major number */ 291 1.1 jmcneill for (maj = 0; maj < nchrdev; maj++) 292 1.1 jmcneill if (cdevsw[maj].d_open == gpioopen) 293 1.1 jmcneill break; 294 1.1 jmcneill 295 1.1 jmcneill /* Nuke the vnodes for any open instances (calls close) */ 296 1.6 thorpej mn = device_unit(self); 297 1.1 jmcneill vdevgone(maj, mn, mn, VCHR); 298 1.1 jmcneill #endif 299 1.19 mbalmer return 0; 300 1.1 jmcneill } 301 1.1 jmcneill 302 1.35 mbalmer static int 303 1.31 mbalmer gpio_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 304 1.1 jmcneill { 305 1.1 jmcneill struct gpio_attach_args ga; 306 1.49 mbalmer size_t namlen; 307 1.1 jmcneill 308 1.65 thorpej ga.ga_gpio = device_private(parent); 309 1.5 riz ga.ga_offset = cf->cf_loc[GPIOCF_OFFSET]; 310 1.3 drochner ga.ga_mask = cf->cf_loc[GPIOCF_MASK]; 311 1.42 mbalmer ga.ga_flags = cf->cf_loc[GPIOCF_FLAG]; 312 1.49 mbalmer namlen = strlen(cf->cf_name) + 1; 313 1.63 chs ga.ga_dvname = kmem_alloc(namlen, KM_SLEEP); 314 1.49 mbalmer strcpy(ga.ga_dvname, cf->cf_name); 315 1.1 jmcneill 316 1.65 thorpej if (config_probe(parent, cf, &ga)) 317 1.66 thorpej config_attach(parent, cf, &ga, gpio_print, CFARGS_NONE); 318 1.49 mbalmer kmem_free(ga.ga_dvname, namlen); 319 1.19 mbalmer return 0; 320 1.1 jmcneill } 321 1.1 jmcneill 322 1.1 jmcneill int 323 1.11 christos gpio_print(void *aux, const char *pnp) 324 1.1 jmcneill { 325 1.1 jmcneill struct gpio_attach_args *ga = aux; 326 1.1 jmcneill int i; 327 1.1 jmcneill 328 1.54 christos aprint_normal(" pins"); 329 1.1 jmcneill for (i = 0; i < 32; i++) 330 1.1 jmcneill if (ga->ga_mask & (1 << i)) 331 1.54 christos aprint_normal(" %d", ga->ga_offset + i); 332 1.1 jmcneill 333 1.19 mbalmer return UNCONF; 334 1.1 jmcneill } 335 1.1 jmcneill 336 1.58 bouyer void * 337 1.58 bouyer gpio_find_device(const char *name) 338 1.58 bouyer { 339 1.58 bouyer device_t gpio_dev; 340 1.58 bouyer gpio_dev = device_find_by_xname(name); 341 1.58 bouyer if (gpio_dev == NULL) 342 1.58 bouyer return NULL; 343 1.58 bouyer return device_private(gpio_dev); 344 1.58 bouyer } 345 1.58 bouyer 346 1.58 bouyer const char * 347 1.58 bouyer gpio_get_name(void *gpio) 348 1.58 bouyer { 349 1.58 bouyer struct gpio_softc *sc = gpio; 350 1.58 bouyer return device_xname(sc->sc_dev); 351 1.58 bouyer } 352 1.58 bouyer 353 1.27 mbalmer /* return 1 if all pins can be mapped, 0 if not */ 354 1.27 mbalmer int 355 1.36 mbalmer gpio_pin_can_map(void *gpio, int offset, uint32_t mask) 356 1.27 mbalmer { 357 1.27 mbalmer struct gpio_softc *sc = gpio; 358 1.27 mbalmer int npins, pin, i; 359 1.27 mbalmer 360 1.27 mbalmer npins = gpio_npins(mask); 361 1.27 mbalmer if (npins > sc->sc_npins) 362 1.27 mbalmer return 0; 363 1.27 mbalmer 364 1.27 mbalmer for (npins = 0, i = 0; i < 32; i++) 365 1.27 mbalmer if (mask & (1 << i)) { 366 1.27 mbalmer pin = offset + i; 367 1.27 mbalmer if (pin < 0 || pin >= sc->sc_npins) 368 1.27 mbalmer return 0; 369 1.27 mbalmer if (sc->sc_pins[pin].pin_mapped) 370 1.27 mbalmer return 0; 371 1.27 mbalmer } 372 1.27 mbalmer 373 1.27 mbalmer return 1; 374 1.27 mbalmer } 375 1.27 mbalmer 376 1.8 uwe int 377 1.36 mbalmer gpio_pin_map(void *gpio, int offset, uint32_t mask, struct gpio_pinmap *map) 378 1.5 riz { 379 1.5 riz struct gpio_softc *sc = gpio; 380 1.5 riz int npins, pin, i; 381 1.5 riz 382 1.5 riz npins = gpio_npins(mask); 383 1.5 riz if (npins > sc->sc_npins) 384 1.19 mbalmer return 1; 385 1.5 riz 386 1.5 riz for (npins = 0, i = 0; i < 32; i++) 387 1.5 riz if (mask & (1 << i)) { 388 1.5 riz pin = offset + i; 389 1.5 riz if (pin < 0 || pin >= sc->sc_npins) 390 1.19 mbalmer return 1; 391 1.5 riz if (sc->sc_pins[pin].pin_mapped) 392 1.19 mbalmer return 1; 393 1.5 riz sc->sc_pins[pin].pin_mapped = 1; 394 1.5 riz map->pm_map[npins++] = pin; 395 1.5 riz } 396 1.5 riz map->pm_size = npins; 397 1.5 riz 398 1.19 mbalmer return 0; 399 1.5 riz } 400 1.5 riz 401 1.5 riz void 402 1.5 riz gpio_pin_unmap(void *gpio, struct gpio_pinmap *map) 403 1.5 riz { 404 1.5 riz struct gpio_softc *sc = gpio; 405 1.5 riz int pin, i; 406 1.5 riz 407 1.5 riz for (i = 0; i < map->pm_size; i++) { 408 1.5 riz pin = map->pm_map[i]; 409 1.5 riz sc->sc_pins[pin].pin_mapped = 0; 410 1.5 riz } 411 1.5 riz } 412 1.5 riz 413 1.5 riz int 414 1.5 riz gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin) 415 1.5 riz { 416 1.5 riz struct gpio_softc *sc = gpio; 417 1.5 riz 418 1.19 mbalmer return gpiobus_pin_read(sc->sc_gc, map->pm_map[pin]); 419 1.5 riz } 420 1.5 riz 421 1.5 riz void 422 1.5 riz gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value) 423 1.5 riz { 424 1.5 riz struct gpio_softc *sc = gpio; 425 1.5 riz 426 1.13 dyoung gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value); 427 1.13 dyoung sc->sc_pins[map->pm_map[pin]].pin_state = value; 428 1.5 riz } 429 1.5 riz 430 1.61 thorpej int 431 1.61 thorpej gpio_pin_get_conf(void *gpio, struct gpio_pinmap *map, int pin) 432 1.61 thorpej { 433 1.61 thorpej struct gpio_softc *sc = gpio; 434 1.61 thorpej int rv; 435 1.61 thorpej 436 1.61 thorpej mutex_enter(&sc->sc_mtx); 437 1.61 thorpej rv = sc->sc_pins[map->pm_map[pin]].pin_flags; 438 1.61 thorpej mutex_exit(&sc->sc_mtx); 439 1.61 thorpej 440 1.61 thorpej return (rv); 441 1.61 thorpej } 442 1.61 thorpej 443 1.61 thorpej bool 444 1.61 thorpej gpio_pin_set_conf(void *gpio, struct gpio_pinmap *map, int pin, int flags) 445 1.61 thorpej { 446 1.61 thorpej struct gpio_softc *sc = gpio; 447 1.61 thorpej int checkflags = flags & GPIO_PIN_HWCAPS; 448 1.61 thorpej 449 1.61 thorpej if ((sc->sc_pins[map->pm_map[pin]].pin_caps & checkflags) != checkflags) 450 1.61 thorpej return (false); 451 1.61 thorpej 452 1.61 thorpej gpio_pin_ctl(gpio, map, pin, flags); 453 1.61 thorpej 454 1.61 thorpej return (true); 455 1.61 thorpej } 456 1.61 thorpej 457 1.5 riz void 458 1.5 riz gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags) 459 1.5 riz { 460 1.5 riz struct gpio_softc *sc = gpio; 461 1.5 riz 462 1.61 thorpej /* loosey-goosey version of gpio_pin_set_conf(). */ 463 1.61 thorpej 464 1.58 bouyer mutex_enter(&sc->sc_mtx); 465 1.58 bouyer gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags); 466 1.61 thorpej sc->sc_pins[map->pm_map[pin]].pin_flags = flags; 467 1.58 bouyer mutex_exit(&sc->sc_mtx); 468 1.58 bouyer } 469 1.58 bouyer 470 1.58 bouyer int 471 1.61 thorpej gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin) 472 1.58 bouyer { 473 1.58 bouyer struct gpio_softc *sc = gpio; 474 1.61 thorpej 475 1.61 thorpej return sc->sc_pins[map->pm_map[pin]].pin_caps; 476 1.61 thorpej } 477 1.61 thorpej 478 1.61 thorpej int 479 1.61 thorpej gpio_pin_intrcaps(void *gpio, struct gpio_pinmap *map, int pin) 480 1.61 thorpej { 481 1.61 thorpej struct gpio_softc *sc = gpio; 482 1.61 thorpej 483 1.61 thorpej return sc->sc_pins[map->pm_map[pin]].pin_intrcaps; 484 1.61 thorpej } 485 1.61 thorpej 486 1.61 thorpej static int 487 1.61 thorpej gpio_irqmode_sanitize(int irqmode) 488 1.61 thorpej { 489 1.61 thorpej int has_edge, has_level; 490 1.61 thorpej 491 1.61 thorpej has_edge = irqmode & GPIO_INTR_EDGE_MASK; 492 1.61 thorpej has_level = irqmode & GPIO_INTR_LEVEL_MASK; 493 1.61 thorpej 494 1.61 thorpej /* Must specify an interrupt mode. */ 495 1.61 thorpej if ((irqmode & GPIO_INTR_MODE_MASK) == 0) 496 1.61 thorpej return (0); 497 1.61 thorpej 498 1.61 thorpej /* Can't specify edge and level together */ 499 1.61 thorpej if (has_level && has_edge) 500 1.61 thorpej return (0); 501 1.61 thorpej 502 1.61 thorpej /* "Be liberal in what you accept..." */ 503 1.61 thorpej if (has_edge) { 504 1.61 thorpej if (irqmode & GPIO_INTR_DOUBLE_EDGE) { 505 1.61 thorpej /* if DOUBLE is set, just pass through DOUBLE */ 506 1.61 thorpej irqmode = (irqmode & ~GPIO_INTR_EDGE_MASK) | 507 1.61 thorpej GPIO_INTR_DOUBLE_EDGE; 508 1.61 thorpej } else if ((irqmode ^ 509 1.61 thorpej (GPIO_INTR_POS_EDGE | GPIO_INTR_NEG_EDGE)) == 0) { 510 1.61 thorpej /* both POS and NEG set; treat as DOUBLE */ 511 1.61 thorpej irqmode = (irqmode & ~GPIO_INTR_EDGE_MASK) | 512 1.61 thorpej GPIO_INTR_DOUBLE_EDGE; 513 1.61 thorpej } 514 1.61 thorpej } else { 515 1.61 thorpej /* Can't specify both levels together. */ 516 1.61 thorpej if (has_level == GPIO_INTR_LEVEL_MASK) 517 1.61 thorpej return (0); 518 1.61 thorpej } 519 1.61 thorpej 520 1.61 thorpej return (irqmode); 521 1.61 thorpej } 522 1.61 thorpej 523 1.61 thorpej bool 524 1.61 thorpej gpio_pin_irqmode_issupported(void *gpio, struct gpio_pinmap *map, 525 1.61 thorpej int pin, int irqmode) 526 1.61 thorpej { 527 1.61 thorpej struct gpio_softc *sc = gpio; 528 1.61 thorpej int match; 529 1.61 thorpej 530 1.61 thorpej irqmode = gpio_irqmode_sanitize(irqmode) & GPIO_INTR_MODE_MASK; 531 1.61 thorpej 532 1.61 thorpej /* Make sure the pin can do what is being asked. */ 533 1.61 thorpej match = sc->sc_pins[map->pm_map[pin]].pin_intrcaps & irqmode; 534 1.61 thorpej 535 1.61 thorpej return (irqmode && irqmode == match); 536 1.61 thorpej } 537 1.61 thorpej 538 1.61 thorpej void * 539 1.61 thorpej gpio_intr_establish(void *gpio, struct gpio_pinmap *map, int pin, int ipl, 540 1.61 thorpej int irqmode, int (*func)(void *), void *arg) 541 1.61 thorpej { 542 1.61 thorpej struct gpio_softc *sc = gpio; 543 1.61 thorpej 544 1.61 thorpej if (sc->sc_gc->gp_intr_establish == NULL) 545 1.61 thorpej return (NULL); 546 1.61 thorpej 547 1.61 thorpej irqmode = gpio_irqmode_sanitize(irqmode); 548 1.61 thorpej if (irqmode == 0) 549 1.61 thorpej return (NULL); 550 1.61 thorpej 551 1.61 thorpej if (! gpio_pin_irqmode_issupported(gpio, map, pin, irqmode)) 552 1.61 thorpej return (NULL); 553 1.61 thorpej 554 1.61 thorpej /* XXX Right now, everything has to be at IPL_VM. */ 555 1.58 bouyer if (ipl != IPL_VM) 556 1.61 thorpej return (NULL); 557 1.61 thorpej 558 1.61 thorpej return ((*sc->sc_gc->gp_intr_establish)(sc->sc_gc->gp_cookie, 559 1.61 thorpej sc->sc_pins[map->pm_map[pin]].pin_num, ipl, irqmode, func, arg)); 560 1.58 bouyer } 561 1.58 bouyer 562 1.58 bouyer void 563 1.61 thorpej gpio_intr_disestablish(void *gpio, void *ih) 564 1.58 bouyer { 565 1.58 bouyer struct gpio_softc *sc = gpio; 566 1.61 thorpej 567 1.61 thorpej if (sc->sc_gc->gp_intr_disestablish != NULL && ih != NULL) 568 1.61 thorpej (*sc->sc_gc->gp_intr_disestablish)(sc->sc_gc->gp_cookie, ih); 569 1.5 riz } 570 1.5 riz 571 1.61 thorpej bool 572 1.61 thorpej gpio_intr_str(void *gpio, struct gpio_pinmap *map, int pin, int irqmode, 573 1.61 thorpej char *intrstr, size_t intrstrlen) 574 1.5 riz { 575 1.5 riz struct gpio_softc *sc = gpio; 576 1.61 thorpej const char *mode; 577 1.61 thorpej char hwstr[64]; 578 1.5 riz 579 1.61 thorpej if (sc->sc_gc->gp_intr_str == NULL) 580 1.61 thorpej return (false); 581 1.61 thorpej 582 1.61 thorpej irqmode = gpio_irqmode_sanitize(irqmode); 583 1.61 thorpej if (irqmode == 0) 584 1.61 thorpej return (false); 585 1.61 thorpej 586 1.61 thorpej if (irqmode & GPIO_INTR_DOUBLE_EDGE) 587 1.61 thorpej mode = "double edge"; 588 1.61 thorpej else if (irqmode & GPIO_INTR_POS_EDGE) 589 1.61 thorpej mode = "positive edge"; 590 1.61 thorpej else if (irqmode & GPIO_INTR_NEG_EDGE) 591 1.61 thorpej mode = "negative edge"; 592 1.61 thorpej else if (irqmode & GPIO_INTR_HIGH_LEVEL) 593 1.61 thorpej mode = "high level"; 594 1.61 thorpej else if (irqmode & GPIO_INTR_LOW_LEVEL) 595 1.61 thorpej mode = "low level"; 596 1.61 thorpej else 597 1.61 thorpej return (false); 598 1.61 thorpej 599 1.61 thorpej if (! (*sc->sc_gc->gp_intr_str)(sc->sc_gc->gp_cookie, 600 1.61 thorpej sc->sc_pins[map->pm_map[pin]].pin_num, 601 1.61 thorpej irqmode, hwstr, sizeof(hwstr))) 602 1.61 thorpej return (false); 603 1.61 thorpej 604 1.61 thorpej (void) snprintf(intrstr, intrstrlen, "%s (%s)", hwstr, mode); 605 1.61 thorpej 606 1.61 thorpej return (true); 607 1.5 riz } 608 1.5 riz 609 1.74 jmcneill void 610 1.74 jmcneill gpio_intr_mask(void *gpio, void *ih) 611 1.74 jmcneill { 612 1.74 jmcneill struct gpio_softc *sc = gpio; 613 1.74 jmcneill 614 1.74 jmcneill if (sc->sc_gc->gp_intr_mask == NULL) 615 1.74 jmcneill return; 616 1.74 jmcneill 617 1.74 jmcneill sc->sc_gc->gp_intr_mask(sc->sc_gc->gp_cookie, ih); 618 1.74 jmcneill } 619 1.74 jmcneill 620 1.74 jmcneill void 621 1.74 jmcneill gpio_intr_unmask(void *gpio, void *ih) 622 1.74 jmcneill { 623 1.74 jmcneill struct gpio_softc *sc = gpio; 624 1.74 jmcneill 625 1.74 jmcneill if (sc->sc_gc->gp_intr_unmask == NULL) 626 1.74 jmcneill return; 627 1.74 jmcneill 628 1.74 jmcneill sc->sc_gc->gp_intr_unmask(sc->sc_gc->gp_cookie, ih); 629 1.74 jmcneill } 630 1.74 jmcneill 631 1.5 riz int 632 1.73 brad gpio_pin_to_pin_num(void *gpio, struct gpio_pinmap *map, int pin) 633 1.73 brad { 634 1.73 brad struct gpio_softc *sc = gpio; 635 1.73 brad 636 1.73 brad return sc->sc_pins[map->pm_map[pin]].pin_num; 637 1.73 brad } 638 1.73 brad 639 1.73 brad int 640 1.36 mbalmer gpio_npins(uint32_t mask) 641 1.5 riz { 642 1.5 riz int npins, i; 643 1.5 riz 644 1.5 riz for (npins = 0, i = 0; i < 32; i++) 645 1.5 riz if (mask & (1 << i)) 646 1.5 riz npins++; 647 1.5 riz 648 1.19 mbalmer return npins; 649 1.5 riz } 650 1.5 riz 651 1.1 jmcneill int 652 1.36 mbalmer gpio_lock(void *data) 653 1.36 mbalmer { 654 1.36 mbalmer struct gpio_softc *sc; 655 1.36 mbalmer int error; 656 1.36 mbalmer 657 1.36 mbalmer error = 0; 658 1.43 mbalmer sc = data; 659 1.36 mbalmer mutex_enter(&sc->sc_mtx); 660 1.36 mbalmer while (sc->sc_ioctl_busy) { 661 1.36 mbalmer error = cv_wait_sig(&sc->sc_ioctl, &sc->sc_mtx); 662 1.36 mbalmer if (error) 663 1.36 mbalmer break; 664 1.36 mbalmer } 665 1.36 mbalmer if (!error) 666 1.36 mbalmer sc->sc_ioctl_busy = 1; 667 1.36 mbalmer mutex_exit(&sc->sc_mtx); 668 1.36 mbalmer return error; 669 1.36 mbalmer } 670 1.36 mbalmer 671 1.36 mbalmer void 672 1.36 mbalmer gpio_unlock(void *data) 673 1.36 mbalmer { 674 1.36 mbalmer struct gpio_softc *sc; 675 1.36 mbalmer 676 1.43 mbalmer sc = data; 677 1.36 mbalmer mutex_enter(&sc->sc_mtx); 678 1.36 mbalmer sc->sc_ioctl_busy = 0; 679 1.36 mbalmer cv_signal(&sc->sc_ioctl); 680 1.36 mbalmer mutex_exit(&sc->sc_mtx); 681 1.36 mbalmer } 682 1.36 mbalmer 683 1.36 mbalmer int 684 1.26 mbalmer gpioopen(dev_t dev, int flag, int mode, struct lwp *l) 685 1.1 jmcneill { 686 1.1 jmcneill struct gpio_softc *sc; 687 1.1 jmcneill 688 1.17 cegger sc = device_lookup_private(&gpio_cd, minor(dev)); 689 1.1 jmcneill if (sc == NULL) 690 1.19 mbalmer return ENXIO; 691 1.1 jmcneill 692 1.36 mbalmer return gpiobus_open(sc->sc_gc, sc->sc_dev); 693 1.1 jmcneill } 694 1.1 jmcneill 695 1.1 jmcneill int 696 1.26 mbalmer gpioclose(dev_t dev, int flag, int mode, struct lwp *l) 697 1.1 jmcneill { 698 1.1 jmcneill struct gpio_softc *sc; 699 1.1 jmcneill 700 1.17 cegger sc = device_lookup_private(&gpio_cd, minor(dev)); 701 1.50 mbalmer return gpiobus_close(sc->sc_gc, sc->sc_dev); 702 1.19 mbalmer } 703 1.19 mbalmer 704 1.35 mbalmer static int 705 1.19 mbalmer gpio_pinbyname(struct gpio_softc *sc, char *gp_name) 706 1.19 mbalmer { 707 1.19 mbalmer struct gpio_name *nm; 708 1.19 mbalmer 709 1.19 mbalmer LIST_FOREACH(nm, &sc->sc_names, gp_next) 710 1.19 mbalmer if (!strcmp(nm->gp_name, gp_name)) 711 1.19 mbalmer return nm->gp_pin; 712 1.19 mbalmer return -1; 713 1.1 jmcneill } 714 1.1 jmcneill 715 1.1 jmcneill int 716 1.26 mbalmer gpioioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 717 1.1 jmcneill { 718 1.36 mbalmer int error; 719 1.1 jmcneill struct gpio_softc *sc; 720 1.36 mbalmer 721 1.36 mbalmer sc = device_lookup_private(&gpio_cd, minor(dev)); 722 1.36 mbalmer 723 1.36 mbalmer error = gpio_lock(sc); 724 1.36 mbalmer if (error) 725 1.36 mbalmer return error; 726 1.36 mbalmer 727 1.36 mbalmer error = gpio_ioctl(sc, cmd, data, flag, l); 728 1.36 mbalmer gpio_unlock(sc); 729 1.36 mbalmer return error; 730 1.36 mbalmer } 731 1.36 mbalmer 732 1.36 mbalmer static int 733 1.36 mbalmer gpio_ioctl(struct gpio_softc *sc, u_long cmd, void *data, int flag, 734 1.36 mbalmer struct lwp *l) 735 1.36 mbalmer { 736 1.1 jmcneill gpio_chipset_tag_t gc; 737 1.1 jmcneill struct gpio_info *info; 738 1.19 mbalmer struct gpio_attach *attach; 739 1.19 mbalmer struct gpio_attach_args ga; 740 1.45 mbalmer struct gpio_req *req; 741 1.19 mbalmer struct gpio_name *nm; 742 1.19 mbalmer struct gpio_set *set; 743 1.46 mbalmer #ifdef COMPAT_50 744 1.46 mbalmer struct gpio_dev *gdev; 745 1.46 mbalmer #endif 746 1.20 mbalmer device_t dv; 747 1.24 mbalmer cfdata_t cf; 748 1.19 mbalmer int locs[GPIOCF_NLOCS]; 749 1.72 jakllsch int error, pin, value, flags; 750 1.1 jmcneill 751 1.1 jmcneill gc = sc->sc_gc; 752 1.42 mbalmer ga.ga_flags = 0; 753 1.1 jmcneill 754 1.19 mbalmer if (cmd != GPIOINFO && !device_is_active(sc->sc_dev)) { 755 1.26 mbalmer DPRINTF(("%s: device is not active\n", 756 1.26 mbalmer device_xname(sc->sc_dev))); 757 1.13 dyoung return EBUSY; 758 1.19 mbalmer } 759 1.35 mbalmer 760 1.1 jmcneill switch (cmd) { 761 1.1 jmcneill case GPIOINFO: 762 1.43 mbalmer info = data; 763 1.72 jakllsch info->gpio_npins = sc->sc_npins; 764 1.19 mbalmer break; 765 1.19 mbalmer case GPIOREAD: 766 1.43 mbalmer req = data; 767 1.19 mbalmer 768 1.36 mbalmer if (req->gp_name[0] != '\0') 769 1.64 tnn req->gp_pin = gpio_pinbyname(sc, req->gp_name); 770 1.64 tnn pin = req->gp_pin; 771 1.19 mbalmer 772 1.19 mbalmer if (pin < 0 || pin >= sc->sc_npins) 773 1.19 mbalmer return EINVAL; 774 1.19 mbalmer 775 1.19 mbalmer if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && 776 1.68 christos kauth_authorize_device(l->l_cred, 777 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 778 1.19 mbalmer return EPERM; 779 1.19 mbalmer 780 1.19 mbalmer /* return read value */ 781 1.19 mbalmer req->gp_value = gpiobus_pin_read(gc, pin); 782 1.64 tnn LIST_FOREACH(nm, &sc->sc_names, gp_next) 783 1.64 tnn if (nm->gp_pin == pin) { 784 1.64 tnn strlcpy(req->gp_name, nm->gp_name, GPIOMAXNAME); 785 1.64 tnn break; 786 1.64 tnn } 787 1.19 mbalmer break; 788 1.19 mbalmer case GPIOWRITE: 789 1.19 mbalmer if ((flag & FWRITE) == 0) 790 1.19 mbalmer return EBADF; 791 1.19 mbalmer 792 1.43 mbalmer req = data; 793 1.19 mbalmer 794 1.36 mbalmer if (req->gp_name[0] != '\0') 795 1.19 mbalmer pin = gpio_pinbyname(sc, req->gp_name); 796 1.36 mbalmer else 797 1.19 mbalmer pin = req->gp_pin; 798 1.19 mbalmer 799 1.19 mbalmer if (pin < 0 || pin >= sc->sc_npins) 800 1.19 mbalmer return EINVAL; 801 1.19 mbalmer 802 1.19 mbalmer if (sc->sc_pins[pin].pin_mapped) 803 1.19 mbalmer return EBUSY; 804 1.19 mbalmer 805 1.19 mbalmer if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && 806 1.68 christos kauth_authorize_device(l->l_cred, 807 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 808 1.19 mbalmer return EPERM; 809 1.1 jmcneill 810 1.19 mbalmer value = req->gp_value; 811 1.19 mbalmer if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH) 812 1.19 mbalmer return EINVAL; 813 1.19 mbalmer 814 1.52 mbalmer /* return old value */ 815 1.52 mbalmer req->gp_value = gpiobus_pin_read(gc, pin); 816 1.19 mbalmer gpiobus_pin_write(gc, pin, value); 817 1.19 mbalmer /* update current value */ 818 1.19 mbalmer sc->sc_pins[pin].pin_state = value; 819 1.1 jmcneill break; 820 1.19 mbalmer case GPIOTOGGLE: 821 1.19 mbalmer if ((flag & FWRITE) == 0) 822 1.19 mbalmer return EBADF; 823 1.19 mbalmer 824 1.43 mbalmer req = data; 825 1.19 mbalmer 826 1.36 mbalmer if (req->gp_name[0] != '\0') 827 1.19 mbalmer pin = gpio_pinbyname(sc, req->gp_name); 828 1.36 mbalmer else 829 1.19 mbalmer pin = req->gp_pin; 830 1.19 mbalmer 831 1.19 mbalmer if (pin < 0 || pin >= sc->sc_npins) 832 1.19 mbalmer return EINVAL; 833 1.19 mbalmer 834 1.19 mbalmer if (sc->sc_pins[pin].pin_mapped) 835 1.19 mbalmer return EBUSY; 836 1.19 mbalmer 837 1.19 mbalmer if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && 838 1.68 christos kauth_authorize_device(l->l_cred, 839 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 840 1.19 mbalmer return EPERM; 841 1.19 mbalmer 842 1.19 mbalmer value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ? 843 1.19 mbalmer GPIO_PIN_HIGH : GPIO_PIN_LOW); 844 1.19 mbalmer gpiobus_pin_write(gc, pin, value); 845 1.19 mbalmer /* return old value */ 846 1.19 mbalmer req->gp_value = sc->sc_pins[pin].pin_state; 847 1.19 mbalmer /* update current value */ 848 1.19 mbalmer sc->sc_pins[pin].pin_state = value; 849 1.19 mbalmer break; 850 1.19 mbalmer case GPIOATTACH: 851 1.43 mbalmer attach = data; 852 1.42 mbalmer ga.ga_flags = attach->ga_flags; 853 1.42 mbalmer #ifdef COMPAT_50 854 1.42 mbalmer /* FALLTHROUGH */ 855 1.42 mbalmer case GPIOATTACH50: 856 1.42 mbalmer /* 857 1.42 mbalmer * The double assignment to 'attach' in case of GPIOATTACH 858 1.42 mbalmer * and COMPAT_50 is on purpose. It ensures backward 859 1.67 andvar * compatibility in case we are called through the old 860 1.42 mbalmer * GPIOATTACH50 ioctl(2), which had not the ga_flags field 861 1.42 mbalmer * in struct gpio_attach. 862 1.42 mbalmer */ 863 1.43 mbalmer attach = data; 864 1.42 mbalmer #endif 865 1.68 christos if (kauth_authorize_device(l->l_cred, 866 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 867 1.19 mbalmer return EPERM; 868 1.27 mbalmer 869 1.27 mbalmer /* do not try to attach if the pins are already mapped */ 870 1.27 mbalmer if (!gpio_pin_can_map(sc, attach->ga_offset, attach->ga_mask)) 871 1.27 mbalmer return EBUSY; 872 1.27 mbalmer 873 1.39 mbalmer error = 0; 874 1.39 mbalmer mutex_enter(&sc->sc_mtx); 875 1.39 mbalmer while (sc->sc_attach_busy) { 876 1.39 mbalmer error = cv_wait_sig(&sc->sc_attach, &sc->sc_mtx); 877 1.39 mbalmer if (error) 878 1.39 mbalmer break; 879 1.39 mbalmer } 880 1.39 mbalmer if (!error) 881 1.39 mbalmer sc->sc_attach_busy = 1; 882 1.39 mbalmer mutex_exit(&sc->sc_mtx); 883 1.39 mbalmer if (error) 884 1.39 mbalmer return EBUSY; 885 1.39 mbalmer 886 1.19 mbalmer ga.ga_gpio = sc; 887 1.42 mbalmer /* Don't access attach->ga_flags here. */ 888 1.19 mbalmer ga.ga_dvname = attach->ga_dvname; 889 1.19 mbalmer ga.ga_offset = attach->ga_offset; 890 1.19 mbalmer ga.ga_mask = attach->ga_mask; 891 1.42 mbalmer DPRINTF(("%s: attach %s with offset %d, mask " 892 1.42 mbalmer "0x%02x, and flags 0x%02x\n", device_xname(sc->sc_dev), 893 1.42 mbalmer ga.ga_dvname, ga.ga_offset, ga.ga_mask, ga.ga_flags)); 894 1.19 mbalmer 895 1.19 mbalmer locs[GPIOCF_OFFSET] = ga.ga_offset; 896 1.19 mbalmer locs[GPIOCF_MASK] = ga.ga_mask; 897 1.42 mbalmer locs[GPIOCF_FLAG] = ga.ga_flags; 898 1.19 mbalmer 899 1.71 brad KERNEL_LOCK(1, NULL); 900 1.65 thorpej cf = config_search(sc->sc_dev, &ga, 901 1.66 thorpej CFARGS(.locators = locs)); 902 1.24 mbalmer if (cf != NULL) { 903 1.65 thorpej dv = config_attach(sc->sc_dev, cf, &ga, 904 1.65 thorpej gpiobus_print, 905 1.66 thorpej CFARGS(.locators = locs)); 906 1.45 mbalmer #ifdef COMPAT_50 907 1.24 mbalmer if (dv != NULL) { 908 1.24 mbalmer gdev = kmem_alloc(sizeof(struct gpio_dev), 909 1.24 mbalmer KM_SLEEP); 910 1.24 mbalmer gdev->sc_dev = dv; 911 1.24 mbalmer LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next); 912 1.24 mbalmer } else 913 1.39 mbalmer error = EINVAL; 914 1.45 mbalmer #else 915 1.45 mbalmer if (dv == NULL) 916 1.45 mbalmer error = EINVAL; 917 1.45 mbalmer #endif 918 1.19 mbalmer } else 919 1.39 mbalmer error = EINVAL; 920 1.71 brad KERNEL_UNLOCK_ONE(NULL); 921 1.71 brad 922 1.39 mbalmer mutex_enter(&sc->sc_mtx); 923 1.39 mbalmer sc->sc_attach_busy = 0; 924 1.39 mbalmer cv_signal(&sc->sc_attach); 925 1.39 mbalmer mutex_exit(&sc->sc_mtx); 926 1.39 mbalmer return error; 927 1.19 mbalmer case GPIOSET: 928 1.68 christos if (kauth_authorize_device(l->l_cred, 929 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 930 1.19 mbalmer return EPERM; 931 1.19 mbalmer 932 1.43 mbalmer set = data; 933 1.19 mbalmer 934 1.36 mbalmer if (set->gp_name[0] != '\0') 935 1.19 mbalmer pin = gpio_pinbyname(sc, set->gp_name); 936 1.36 mbalmer else 937 1.19 mbalmer pin = set->gp_pin; 938 1.36 mbalmer 939 1.19 mbalmer if (pin < 0 || pin >= sc->sc_npins) 940 1.19 mbalmer return EINVAL; 941 1.19 mbalmer flags = set->gp_flags; 942 1.19 mbalmer 943 1.19 mbalmer /* check that the controller supports all requested flags */ 944 1.19 mbalmer if ((flags & sc->sc_pins[pin].pin_caps) != flags) 945 1.19 mbalmer return ENODEV; 946 1.56 kardel flags = set->gp_flags; 947 1.19 mbalmer 948 1.19 mbalmer set->gp_caps = sc->sc_pins[pin].pin_caps; 949 1.19 mbalmer /* return old value */ 950 1.19 mbalmer set->gp_flags = sc->sc_pins[pin].pin_flags; 951 1.56 kardel 952 1.19 mbalmer if (flags > 0) { 953 1.56 kardel flags |= GPIO_PIN_SET; 954 1.19 mbalmer gpiobus_pin_ctl(gc, pin, flags); 955 1.19 mbalmer /* update current value */ 956 1.19 mbalmer sc->sc_pins[pin].pin_flags = flags; 957 1.19 mbalmer } 958 1.19 mbalmer 959 1.19 mbalmer /* rename pin or new pin? */ 960 1.19 mbalmer if (set->gp_name2[0] != '\0') { 961 1.28 mbalmer struct gpio_name *gnm; 962 1.28 mbalmer 963 1.28 mbalmer gnm = NULL; 964 1.28 mbalmer LIST_FOREACH(nm, &sc->sc_names, gp_next) { 965 1.28 mbalmer if (!strcmp(nm->gp_name, set->gp_name2) && 966 1.28 mbalmer nm->gp_pin != pin) 967 1.28 mbalmer return EINVAL; /* duplicate name */ 968 1.28 mbalmer if (nm->gp_pin == pin) 969 1.28 mbalmer gnm = nm; 970 1.28 mbalmer } 971 1.28 mbalmer if (gnm != NULL) 972 1.28 mbalmer strlcpy(gnm->gp_name, set->gp_name2, 973 1.28 mbalmer sizeof(gnm->gp_name)); 974 1.28 mbalmer else { 975 1.19 mbalmer nm = kmem_alloc(sizeof(struct gpio_name), 976 1.19 mbalmer KM_SLEEP); 977 1.19 mbalmer strlcpy(nm->gp_name, set->gp_name2, 978 1.19 mbalmer sizeof(nm->gp_name)); 979 1.19 mbalmer nm->gp_pin = set->gp_pin; 980 1.19 mbalmer LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next); 981 1.19 mbalmer } 982 1.19 mbalmer } 983 1.19 mbalmer break; 984 1.19 mbalmer case GPIOUNSET: 985 1.68 christos if (kauth_authorize_device(l->l_cred, 986 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 987 1.19 mbalmer return EPERM; 988 1.19 mbalmer 989 1.43 mbalmer set = data; 990 1.36 mbalmer if (set->gp_name[0] != '\0') 991 1.19 mbalmer pin = gpio_pinbyname(sc, set->gp_name); 992 1.36 mbalmer else 993 1.19 mbalmer pin = set->gp_pin; 994 1.35 mbalmer 995 1.19 mbalmer if (pin < 0 || pin >= sc->sc_npins) 996 1.19 mbalmer return EINVAL; 997 1.19 mbalmer if (sc->sc_pins[pin].pin_mapped) 998 1.19 mbalmer return EBUSY; 999 1.19 mbalmer if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET)) 1000 1.19 mbalmer return EINVAL; 1001 1.19 mbalmer 1002 1.19 mbalmer LIST_FOREACH(nm, &sc->sc_names, gp_next) { 1003 1.19 mbalmer if (nm->gp_pin == pin) { 1004 1.19 mbalmer LIST_REMOVE(nm, gp_next); 1005 1.19 mbalmer kmem_free(nm, sizeof(struct gpio_name)); 1006 1.19 mbalmer break; 1007 1.19 mbalmer } 1008 1.19 mbalmer } 1009 1.19 mbalmer sc->sc_pins[pin].pin_flags &= ~GPIO_PIN_SET; 1010 1.19 mbalmer break; 1011 1.19 mbalmer default: 1012 1.42 mbalmer #ifdef COMPAT_50 1013 1.19 mbalmer /* Try the old API */ 1014 1.22 cegger DPRINTF(("%s: trying the old API\n", device_xname(sc->sc_dev))); 1015 1.68 christos return gpio_ioctl_oapi(sc, cmd, data, flag, l); 1016 1.42 mbalmer #else 1017 1.42 mbalmer return ENOTTY; 1018 1.42 mbalmer #endif 1019 1.19 mbalmer } 1020 1.19 mbalmer return 0; 1021 1.19 mbalmer } 1022 1.19 mbalmer 1023 1.42 mbalmer #ifdef COMPAT_50 1024 1.35 mbalmer static int 1025 1.19 mbalmer gpio_ioctl_oapi(struct gpio_softc *sc, u_long cmd, void *data, int flag, 1026 1.68 christos struct lwp *l) 1027 1.19 mbalmer { 1028 1.19 mbalmer gpio_chipset_tag_t gc; 1029 1.19 mbalmer struct gpio_pin_op *op; 1030 1.19 mbalmer struct gpio_pin_ctl *ctl; 1031 1.45 mbalmer struct gpio_attach *attach; 1032 1.45 mbalmer struct gpio_dev *gdev; 1033 1.45 mbalmer 1034 1.45 mbalmer int error, pin, value, flags; 1035 1.19 mbalmer 1036 1.19 mbalmer gc = sc->sc_gc; 1037 1.19 mbalmer 1038 1.19 mbalmer switch (cmd) { 1039 1.1 jmcneill case GPIOPINREAD: 1040 1.43 mbalmer op = data; 1041 1.1 jmcneill 1042 1.1 jmcneill pin = op->gp_pin; 1043 1.19 mbalmer 1044 1.1 jmcneill if (pin < 0 || pin >= sc->sc_npins) 1045 1.19 mbalmer return EINVAL; 1046 1.19 mbalmer 1047 1.19 mbalmer if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && 1048 1.68 christos kauth_authorize_device(l->l_cred, 1049 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 1050 1.19 mbalmer return EPERM; 1051 1.1 jmcneill 1052 1.1 jmcneill /* return read value */ 1053 1.1 jmcneill op->gp_value = gpiobus_pin_read(gc, pin); 1054 1.1 jmcneill break; 1055 1.1 jmcneill case GPIOPINWRITE: 1056 1.19 mbalmer if ((flag & FWRITE) == 0) 1057 1.19 mbalmer return EBADF; 1058 1.19 mbalmer 1059 1.43 mbalmer op = data; 1060 1.1 jmcneill 1061 1.1 jmcneill pin = op->gp_pin; 1062 1.19 mbalmer 1063 1.1 jmcneill if (pin < 0 || pin >= sc->sc_npins) 1064 1.19 mbalmer return EINVAL; 1065 1.19 mbalmer 1066 1.5 riz if (sc->sc_pins[pin].pin_mapped) 1067 1.19 mbalmer return EBUSY; 1068 1.19 mbalmer 1069 1.19 mbalmer if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && 1070 1.68 christos kauth_authorize_device(l->l_cred, 1071 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 1072 1.19 mbalmer return EPERM; 1073 1.1 jmcneill 1074 1.1 jmcneill value = op->gp_value; 1075 1.1 jmcneill if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH) 1076 1.19 mbalmer return EINVAL; 1077 1.1 jmcneill 1078 1.1 jmcneill gpiobus_pin_write(gc, pin, value); 1079 1.1 jmcneill /* return old value */ 1080 1.1 jmcneill op->gp_value = sc->sc_pins[pin].pin_state; 1081 1.1 jmcneill /* update current value */ 1082 1.1 jmcneill sc->sc_pins[pin].pin_state = value; 1083 1.1 jmcneill break; 1084 1.1 jmcneill case GPIOPINTOGGLE: 1085 1.19 mbalmer if ((flag & FWRITE) == 0) 1086 1.19 mbalmer return EBADF; 1087 1.19 mbalmer 1088 1.43 mbalmer op = data; 1089 1.1 jmcneill 1090 1.1 jmcneill pin = op->gp_pin; 1091 1.19 mbalmer 1092 1.1 jmcneill if (pin < 0 || pin >= sc->sc_npins) 1093 1.19 mbalmer return EINVAL; 1094 1.19 mbalmer 1095 1.5 riz if (sc->sc_pins[pin].pin_mapped) 1096 1.19 mbalmer return EBUSY; 1097 1.19 mbalmer 1098 1.19 mbalmer if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) && 1099 1.68 christos kauth_authorize_device(l->l_cred, 1100 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 1101 1.19 mbalmer return EPERM; 1102 1.1 jmcneill 1103 1.1 jmcneill value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ? 1104 1.1 jmcneill GPIO_PIN_HIGH : GPIO_PIN_LOW); 1105 1.1 jmcneill gpiobus_pin_write(gc, pin, value); 1106 1.1 jmcneill /* return old value */ 1107 1.1 jmcneill op->gp_value = sc->sc_pins[pin].pin_state; 1108 1.1 jmcneill /* update current value */ 1109 1.1 jmcneill sc->sc_pins[pin].pin_state = value; 1110 1.1 jmcneill break; 1111 1.1 jmcneill case GPIOPINCTL: 1112 1.43 mbalmer ctl = data; 1113 1.19 mbalmer 1114 1.68 christos if (kauth_authorize_device(l->l_cred, 1115 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 1116 1.19 mbalmer return EPERM; 1117 1.1 jmcneill 1118 1.1 jmcneill pin = ctl->gp_pin; 1119 1.19 mbalmer 1120 1.1 jmcneill if (pin < 0 || pin >= sc->sc_npins) 1121 1.19 mbalmer return EINVAL; 1122 1.5 riz if (sc->sc_pins[pin].pin_mapped) 1123 1.19 mbalmer return EBUSY; 1124 1.19 mbalmer flags = ctl->gp_flags; 1125 1.1 jmcneill 1126 1.1 jmcneill /* check that the controller supports all requested flags */ 1127 1.1 jmcneill if ((flags & sc->sc_pins[pin].pin_caps) != flags) 1128 1.19 mbalmer return ENODEV; 1129 1.1 jmcneill 1130 1.1 jmcneill ctl->gp_caps = sc->sc_pins[pin].pin_caps; 1131 1.1 jmcneill /* return old value */ 1132 1.1 jmcneill ctl->gp_flags = sc->sc_pins[pin].pin_flags; 1133 1.1 jmcneill if (flags > 0) { 1134 1.1 jmcneill gpiobus_pin_ctl(gc, pin, flags); 1135 1.1 jmcneill /* update current value */ 1136 1.1 jmcneill sc->sc_pins[pin].pin_flags = flags; 1137 1.1 jmcneill } 1138 1.1 jmcneill break; 1139 1.44 mbalmer case GPIODETACH50: 1140 1.44 mbalmer /* FALLTHOUGH */ 1141 1.44 mbalmer case GPIODETACH: 1142 1.68 christos if (kauth_authorize_device(l->l_cred, 1143 1.68 christos KAUTH_DEVICE_GPIO_PINSET, NULL, NULL, NULL, NULL)) 1144 1.44 mbalmer return EPERM; 1145 1.44 mbalmer 1146 1.44 mbalmer error = 0; 1147 1.44 mbalmer mutex_enter(&sc->sc_mtx); 1148 1.44 mbalmer while (sc->sc_attach_busy) { 1149 1.44 mbalmer error = cv_wait_sig(&sc->sc_attach, &sc->sc_mtx); 1150 1.44 mbalmer if (error) 1151 1.44 mbalmer break; 1152 1.44 mbalmer } 1153 1.44 mbalmer if (!error) 1154 1.44 mbalmer sc->sc_attach_busy = 1; 1155 1.44 mbalmer mutex_exit(&sc->sc_mtx); 1156 1.44 mbalmer if (error) 1157 1.44 mbalmer return EBUSY; 1158 1.44 mbalmer 1159 1.71 brad KERNEL_LOCK(1, NULL); 1160 1.44 mbalmer attach = data; 1161 1.44 mbalmer LIST_FOREACH(gdev, &sc->sc_devs, sc_next) { 1162 1.44 mbalmer if (strcmp(device_xname(gdev->sc_dev), 1163 1.44 mbalmer attach->ga_dvname) == 0) { 1164 1.44 mbalmer mutex_enter(&sc->sc_mtx); 1165 1.44 mbalmer sc->sc_attach_busy = 0; 1166 1.44 mbalmer cv_signal(&sc->sc_attach); 1167 1.44 mbalmer mutex_exit(&sc->sc_mtx); 1168 1.44 mbalmer 1169 1.71 brad if (config_detach(gdev->sc_dev, 0) == 0) { 1170 1.71 brad KERNEL_UNLOCK_ONE(NULL); 1171 1.44 mbalmer return 0; 1172 1.71 brad } 1173 1.44 mbalmer break; 1174 1.44 mbalmer } 1175 1.44 mbalmer } 1176 1.71 brad KERNEL_UNLOCK_ONE(NULL); 1177 1.71 brad 1178 1.44 mbalmer if (gdev == NULL) { 1179 1.44 mbalmer mutex_enter(&sc->sc_mtx); 1180 1.44 mbalmer sc->sc_attach_busy = 0; 1181 1.44 mbalmer cv_signal(&sc->sc_attach); 1182 1.44 mbalmer mutex_exit(&sc->sc_mtx); 1183 1.44 mbalmer } 1184 1.44 mbalmer return EINVAL; 1185 1.44 mbalmer 1186 1.1 jmcneill default: 1187 1.19 mbalmer return ENOTTY; 1188 1.1 jmcneill } 1189 1.19 mbalmer return 0; 1190 1.1 jmcneill } 1191 1.42 mbalmer #endif /* COMPAT_50 */ 1192 1.35 mbalmer 1193 1.35 mbalmer MODULE(MODULE_CLASS_DRIVER, gpio, NULL); 1194 1.35 mbalmer 1195 1.37 mbalmer #ifdef _MODULE 1196 1.35 mbalmer #include "ioconf.c" 1197 1.37 mbalmer #endif 1198 1.35 mbalmer 1199 1.35 mbalmer static int 1200 1.35 mbalmer gpio_modcmd(modcmd_t cmd, void *opaque) 1201 1.35 mbalmer { 1202 1.37 mbalmer #ifdef _MODULE 1203 1.35 mbalmer devmajor_t cmajor = NODEVMAJOR, bmajor = NODEVMAJOR; 1204 1.35 mbalmer int error; 1205 1.37 mbalmer #endif 1206 1.35 mbalmer switch (cmd) { 1207 1.35 mbalmer case MODULE_CMD_INIT: 1208 1.37 mbalmer #ifdef _MODULE 1209 1.70 pgoyette error = devsw_attach(gpio_cd.cd_name, NULL, &bmajor, 1210 1.70 pgoyette &gpio_cdevsw, &cmajor); 1211 1.70 pgoyette if (error) { 1212 1.70 pgoyette aprint_error("%s: unable to register devsw\n", 1213 1.70 pgoyette gpio_cd.cd_name); 1214 1.70 pgoyette return error; 1215 1.70 pgoyette } 1216 1.35 mbalmer error = config_init_component(cfdriver_ioconf_gpio, 1217 1.35 mbalmer cfattach_ioconf_gpio, cfdata_ioconf_gpio); 1218 1.35 mbalmer if (error) { 1219 1.35 mbalmer aprint_error("%s: unable to init component\n", 1220 1.35 mbalmer gpio_cd.cd_name); 1221 1.70 pgoyette devsw_detach(NULL, &gpio_cdevsw); 1222 1.35 mbalmer return error; 1223 1.35 mbalmer } 1224 1.37 mbalmer #endif 1225 1.35 mbalmer return 0; 1226 1.35 mbalmer case MODULE_CMD_FINI: 1227 1.37 mbalmer #ifdef _MODULE 1228 1.35 mbalmer config_fini_component(cfdriver_ioconf_gpio, 1229 1.35 mbalmer cfattach_ioconf_gpio, cfdata_ioconf_gpio); 1230 1.35 mbalmer devsw_detach(NULL, &gpio_cdevsw); 1231 1.37 mbalmer #endif 1232 1.35 mbalmer return 0; 1233 1.35 mbalmer default: 1234 1.35 mbalmer return ENOTTY; 1235 1.35 mbalmer } 1236 1.35 mbalmer } 1237