Annotation of sys/dev/gpio/gpioow.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: gpioow.c,v 1.2 2006/06/23 06:27:11 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: /*
! 20: * 1-Wire bus bit-banging through GPIO pin.
! 21: */
! 22:
! 23: #include <sys/param.h>
! 24: #include <sys/systm.h>
! 25: #include <sys/device.h>
! 26: #include <sys/gpio.h>
! 27:
! 28: #include <dev/gpio/gpiovar.h>
! 29:
! 30: #include <dev/onewire/onewirevar.h>
! 31:
! 32: #define GPIOOW_NPINS 1
! 33: #define GPIOOW_PIN_DATA 0
! 34:
! 35: struct gpioow_softc {
! 36: struct device sc_dev;
! 37:
! 38: void * sc_gpio;
! 39: struct gpio_pinmap sc_map;
! 40: int __map[GPIOOW_NPINS];
! 41:
! 42: struct onewire_bus sc_ow_bus;
! 43: struct device * sc_ow_dev;
! 44:
! 45: int sc_data;
! 46: int sc_dying;
! 47: };
! 48:
! 49: int gpioow_match(struct device *, void *, void *);
! 50: void gpioow_attach(struct device *, struct device *, void *);
! 51: int gpioow_detach(struct device *, int);
! 52: int gpioow_activate(struct device *, enum devact);
! 53:
! 54: int gpioow_ow_reset(void *);
! 55: int gpioow_ow_bit(void *, int);
! 56:
! 57: void gpioow_bb_rx(void *);
! 58: void gpioow_bb_tx(void *);
! 59: int gpioow_bb_get(void *);
! 60: void gpioow_bb_set(void *, int);
! 61:
! 62: struct cfattach gpioow_ca = {
! 63: sizeof(struct gpioow_softc),
! 64: gpioow_match,
! 65: gpioow_attach,
! 66: gpioow_detach,
! 67: gpioow_activate
! 68: };
! 69:
! 70: struct cfdriver gpioow_cd = {
! 71: NULL, "gpioow", DV_DULL
! 72: };
! 73:
! 74: static const struct onewire_bbops gpioow_bbops = {
! 75: gpioow_bb_rx,
! 76: gpioow_bb_tx,
! 77: gpioow_bb_get,
! 78: gpioow_bb_set
! 79: };
! 80:
! 81: int
! 82: gpioow_match(struct device *parent, void *match, void *aux)
! 83: {
! 84: struct cfdata *cf = match;
! 85:
! 86: return (strcmp(cf->cf_driver->cd_name, "gpioow") == 0);
! 87: }
! 88:
! 89: void
! 90: gpioow_attach(struct device *parent, struct device *self, void *aux)
! 91: {
! 92: struct gpioow_softc *sc = (struct gpioow_softc *)self;
! 93: struct gpio_attach_args *ga = aux;
! 94: struct onewirebus_attach_args oba;
! 95: int caps;
! 96:
! 97: /* Check that we have enough pins */
! 98: if (gpio_npins(ga->ga_mask) != GPIOOW_NPINS) {
! 99: printf(": invalid pin mask\n");
! 100: return;
! 101: }
! 102:
! 103: /* Map pins */
! 104: sc->sc_gpio = ga->ga_gpio;
! 105: sc->sc_map.pm_map = sc->__map;
! 106: if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
! 107: &sc->sc_map)) {
! 108: printf(": can't map pins\n");
! 109: return;
! 110: }
! 111:
! 112: /* Configure data pin */
! 113: caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA);
! 114: if (!(caps & GPIO_PIN_OUTPUT)) {
! 115: printf(": data pin is unable to drive output\n");
! 116: goto fail;
! 117: }
! 118: if (!(caps & GPIO_PIN_INPUT)) {
! 119: printf(": data pin is unable to read input\n");
! 120: goto fail;
! 121: }
! 122: printf(": DATA[%d]", sc->sc_map.pm_map[GPIOOW_PIN_DATA]);
! 123: sc->sc_data = GPIO_PIN_OUTPUT;
! 124: if (caps & GPIO_PIN_OPENDRAIN) {
! 125: printf(" open-drain");
! 126: sc->sc_data |= GPIO_PIN_OPENDRAIN;
! 127: } else if ((caps & GPIO_PIN_PUSHPULL) && (caps & GPIO_PIN_TRISTATE)) {
! 128: printf(" push-pull tri-state");
! 129: sc->sc_data |= GPIO_PIN_PUSHPULL;
! 130: }
! 131: if (caps & GPIO_PIN_PULLUP) {
! 132: printf(" pull-up");
! 133: sc->sc_data |= GPIO_PIN_PULLUP;
! 134: }
! 135: gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA, sc->sc_data);
! 136:
! 137: printf("\n");
! 138:
! 139: /* Attach 1-Wire bus */
! 140: sc->sc_ow_bus.bus_cookie = sc;
! 141: sc->sc_ow_bus.bus_reset = gpioow_ow_reset;
! 142: sc->sc_ow_bus.bus_bit = gpioow_ow_bit;
! 143:
! 144: bzero(&oba, sizeof(oba));
! 145: oba.oba_bus = &sc->sc_ow_bus;
! 146: sc->sc_ow_dev = config_found(self, &oba, onewirebus_print);
! 147:
! 148: return;
! 149:
! 150: fail:
! 151: gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
! 152: }
! 153:
! 154: int
! 155: gpioow_detach(struct device *self, int flags)
! 156: {
! 157: struct gpioow_softc *sc = (struct gpioow_softc *)self;
! 158: int rv = 0;
! 159:
! 160: if (sc->sc_ow_dev != NULL)
! 161: rv = config_detach(sc->sc_ow_dev, flags);
! 162:
! 163: return (rv);
! 164: }
! 165:
! 166: int
! 167: gpioow_activate(struct device *self, enum devact act)
! 168: {
! 169: struct gpioow_softc *sc = (struct gpioow_softc *)self;
! 170: int rv = 0;
! 171:
! 172: switch (act) {
! 173: case DVACT_ACTIVATE:
! 174: break;
! 175: case DVACT_DEACTIVATE:
! 176: sc->sc_dying = 1;
! 177: if (sc->sc_ow_dev != NULL)
! 178: rv = config_deactivate(sc->sc_ow_dev);
! 179: break;
! 180: }
! 181:
! 182: return (rv);
! 183: }
! 184:
! 185: int
! 186: gpioow_ow_reset(void *arg)
! 187: {
! 188: return (onewire_bb_reset(&gpioow_bbops, arg));
! 189: }
! 190:
! 191: int
! 192: gpioow_ow_bit(void *arg, int value)
! 193: {
! 194: return (onewire_bb_bit(&gpioow_bbops, arg, value));
! 195: }
! 196:
! 197: void
! 198: gpioow_bb_rx(void *arg)
! 199: {
! 200: struct gpioow_softc *sc = arg;
! 201: int data = sc->sc_data;
! 202:
! 203: data &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
! 204: data |= GPIO_PIN_INPUT;
! 205: if (data & GPIO_PIN_PUSHPULL)
! 206: data |= GPIO_PIN_TRISTATE;
! 207: if (sc->sc_data != data) {
! 208: sc->sc_data = data;
! 209: gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA,
! 210: sc->sc_data);
! 211: }
! 212: }
! 213:
! 214: void
! 215: gpioow_bb_tx(void *arg)
! 216: {
! 217: struct gpioow_softc *sc = arg;
! 218: int data = sc->sc_data;
! 219:
! 220: data &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
! 221: data |= GPIO_PIN_OUTPUT;
! 222: if (sc->sc_data != data) {
! 223: sc->sc_data = data;
! 224: gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA,
! 225: sc->sc_data);
! 226: }
! 227: }
! 228:
! 229: int
! 230: gpioow_bb_get(void *arg)
! 231: {
! 232: struct gpioow_softc *sc = arg;
! 233:
! 234: return (gpio_pin_read(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA) ==
! 235: GPIO_PIN_HIGH ? 1 : 0);
! 236: }
! 237:
! 238: void
! 239: gpioow_bb_set(void *arg, int value)
! 240: {
! 241: struct gpioow_softc *sc = arg;
! 242:
! 243: gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA,
! 244: value ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
! 245: }
CVSweb