Annotation of sys/arch/arm/sa11x0/sa1111_gpio.c, Revision 1.1
1.1 ! nbrk 1: /* $Id$ */
! 2: #include <sys/cdefs.h>
! 3:
! 4: #include <sys/param.h>
! 5: #include <sys/systm.h>
! 6: #include <sys/device.h>
! 7: #include <sys/malloc.h>
! 8: #include <sys/evcount.h>
! 9: #include <sys/queue.h>
! 10: #include <uvm/uvm_extern.h>
! 11:
! 12: #include <machine/bus.h>
! 13: #include <machine/intr.h>
! 14: #include <machine/lock.h>
! 15:
! 16: #include <arm/sa11x0/sa11x1_var.h>
! 17: #include <arm/sa11x0/sa1111_reg.h>
! 18: #include <arm/sa11x0/sa1111_intr.h>
! 19: #include <arm/sa11x0/sa1111_gpiovar.h>
! 20:
! 21: /*
! 22: * SA-1111 GPIO controller.
! 23: * It featurs three blocks:
! 24: * - GPIO_A[0:3]
! 25: * - GPIO_B[0:5]
! 26: * - GPIO_C[0:7]
! 27: * We can control data value (level) and direction individually for each pin.
! 28: */
! 29:
! 30: struct sacgpio_softc {
! 31: struct device sc_dev;
! 32: bus_space_tag_t sc_bust;
! 33: bus_space_handle_t sc_bush;
! 34: };
! 35:
! 36: /* autoconf glue */
! 37: int sacgpio_match(struct device *parent, void *cf, void *aux);
! 38: void sacgpio_attach(struct device *parent, struct device *self, void *aux);
! 39:
! 40: struct cfattach sacgpio_ca = {
! 41: sizeof(struct sacgpio_softc),
! 42: sacgpio_match,
! 43: sacgpio_attach,
! 44: NULL,
! 45: NULL
! 46: };
! 47: struct cfdriver sacgpio_cd = {
! 48: NULL,
! 49: "sacgpio",
! 50: DV_DULL
! 51: };
! 52:
! 53: struct sacgpio_softc *sacgpio_sc;
! 54:
! 55: int
! 56: sacgpio_match(struct device *parent, void *cf, void *aux)
! 57: {
! 58: struct sacc_attach_args *saa = aux;
! 59:
! 60: if (saa->sac_typecookie == SACC_TYPE_GPIO && sacgpio_sc == NULL)
! 61: return(1);
! 62:
! 63: return(0);
! 64: }
! 65:
! 66: void
! 67: sacgpio_attach(struct device *parent, struct device *self, void *aux)
! 68: {
! 69: struct sacgpio_softc *sc = (struct sacgpio_softc*)self;
! 70: struct sacc_attach_args *saa = aux;
! 71: sc->sc_bust = saa->sac_iot;
! 72: sc->sc_bush = saa->sac_bush;
! 73:
! 74: /*
! 75: * Nothing to do. Just register default sc and return.
! 76: */
! 77: printf(": SA-1111 GPIO controller\n");
! 78:
! 79: sacgpio_sc = sc;
! 80: }
! 81:
! 82: /*
! 83: * Read value of port x.
! 84: */
! 85: int
! 86: sa1111_gpio_get_bit(int gpiobank, uint8_t gpio)
! 87: {
! 88: struct sacgpio_softc *sc = sacgpio_sc;
! 89: bus_addr_t reg;
! 90:
! 91: if (sc == NULL)
! 92: panic("sa1111_gpio_get_bit: sacgpio not configured");
! 93:
! 94: /* select bank */
! 95: switch (gpiobank) {
! 96: case SACGPIO_BANKA:
! 97: /* block A has only 4 pins */
! 98: if (gpio > 3)
! 99: panic("%s: sa1111_gpio_get_bit: bogus gpio %d in bank A",
! 100: sc->sc_dev.dv_xname, gpio);
! 101: reg = SACCGPIOA_DVR;
! 102: break;
! 103: case SACGPIO_BANKB:
! 104: /* block B has only 6 pins */
! 105: if (gpio > 5)
! 106: panic("%s: sa1111_gpio_get_bit: bogus gpio %d in bank B",
! 107: sc->sc_dev.dv_xname, gpio);
! 108: reg = SACCGPIOB_DVR;
! 109: break;
! 110: case SACGPIO_BANKC:
! 111: reg = SACCGPIOC_DVR;
! 112: break;
! 113: default:
! 114: panic("%s: sa1111_gpio_get_bit: bogus gpio bank 0x%x",
! 115: sc->sc_dev.dv_xname, gpiobank);
! 116: }
! 117:
! 118: return( bus_space_read_4(sc->sc_bust, sc->sc_bush, reg) & (1 << gpio) );
! 119: }
! 120:
! 121: /*
! 122: * Set value of port x to 1.
! 123: */
! 124: void
! 125: sa1111_gpio_set_bit(int gpiobank, uint8_t gpio)
! 126: {
! 127: struct sacgpio_softc *sc = sacgpio_sc;
! 128: bus_addr_t reg;
! 129: uint32_t oldval;
! 130:
! 131: if (sc == NULL)
! 132: panic("sa1111_gpio_set_bit: sacgpio not configured");
! 133:
! 134: /* select bank */
! 135: switch (gpiobank) {
! 136: case SACGPIO_BANKA:
! 137: /* block A has only 4 pins */
! 138: if (gpio > 3)
! 139: panic("%s: sa1111_gpio_set_bit: bogus gpio %d in bank A",
! 140: sc->sc_dev.dv_xname, gpio);
! 141: reg = SACCGPIOA_DVR;
! 142: break;
! 143: case SACGPIO_BANKB:
! 144: /* block B has only 6 pins */
! 145: if (gpio > 5)
! 146: panic("%s: sa1111_gpio_set_bit: bogus gpio %d in bank B",
! 147: sc->sc_dev.dv_xname, gpio);
! 148: reg = SACCGPIOB_DVR;
! 149: break;
! 150: case SACGPIO_BANKC:
! 151: reg = SACCGPIOC_DVR;
! 152: break;
! 153: default:
! 154: panic("%s: sa1111_gpio_set_bit: bogus gpio bank 0x%x",
! 155: sc->sc_dev.dv_xname, gpiobank);
! 156: }
! 157: oldval = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
! 158: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldval | 1 << gpio);
! 159: }
! 160:
! 161: /*
! 162: * Set value of port x to 0.
! 163: */
! 164: void
! 165: sa1111_gpio_clear_bit(int gpiobank, uint8_t gpio)
! 166: {
! 167: struct sacgpio_softc *sc = sacgpio_sc;
! 168: bus_addr_t reg;
! 169: uint32_t oldval;
! 170:
! 171: if (sc == NULL)
! 172: panic("sa1111_gpio_glear_bit: sacgpio not configured");
! 173:
! 174: /* select bank */
! 175: switch (gpiobank) {
! 176: case SACGPIO_BANKA:
! 177: /* block A has only 4 pins */
! 178: if (gpio > 3)
! 179: panic("%s: sa1111_gpio_clear_bit: bogus gpio %d in bank A",
! 180: sc->sc_dev.dv_xname, gpio);
! 181: reg = SACCGPIOA_DVR;
! 182: break;
! 183: case SACGPIO_BANKB:
! 184: /* block B has only 6 pins */
! 185: if (gpio > 5)
! 186: panic("%s: sa1111_gpio_clear_bit: bogus gpio %d in bank B",
! 187: sc->sc_dev.dv_xname, gpio);
! 188: reg = SACCGPIOB_DVR;
! 189: break;
! 190: case SACGPIO_BANKC:
! 191: reg = SACCGPIOC_DVR;
! 192: break;
! 193: default:
! 194: panic("%s: sa1111_gpio_clear_sit: bogus gpio bank 0x%x",
! 195: sc->sc_dev.dv_xname, gpiobank);
! 196: }
! 197: oldval = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
! 198: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldval & ~(1 << gpio));
! 199: }
! 200:
! 201: /*
! 202: * Set port direction.
! 203: */
! 204: void
! 205: sa1111_gpio_set_dir(int gpiobank, uint8_t gpio, int dir)
! 206: {
! 207: struct sacgpio_softc *sc = sacgpio_sc;
! 208: bus_addr_t reg;
! 209: uint32_t olddir;
! 210:
! 211: if (sc == NULL)
! 212: panic("sa1111_gpio_set_dir: sacgpio not configured");
! 213:
! 214: /* select bank */
! 215: switch (gpiobank) {
! 216: case SACGPIO_BANKA:
! 217: /* block A has only 4 pins */
! 218: if (gpio > 3)
! 219: panic("%s: sa1111_gpio_set_dir: bogus gpio %d in bank A",
! 220: sc->sc_dev.dv_xname, gpio);
! 221: reg = SACCGPIOA_DDR;
! 222: break;
! 223: case SACGPIO_BANKB:
! 224: /* block B has only 6 pins */
! 225: if (gpio > 5)
! 226: panic("%s: sa1111_gpio_set_dir: bogus gpio %d in bank B",
! 227: sc->sc_dev.dv_xname, gpio);
! 228: reg = SACCGPIOB_DDR;
! 229: break;
! 230: case SACGPIO_BANKC:
! 231: reg = SACCGPIOC_DDR;
! 232: break;
! 233: default:
! 234: panic("%s: sa1111_gpio_set_dir: bogus gpio bank 0x%x",
! 235: sc->sc_dev.dv_xname, gpiobank);
! 236: }
! 237: /* direction */
! 238: olddir = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
! 239: switch (dir) {
! 240: case SACGPIO_DIR_INPUT:
! 241: olddir |= 1 << gpio;
! 242: break;
! 243: case SACGPIO_DIR_OUTPUT:
! 244: olddir &= ~(1 << gpio);
! 245: break;
! 246: default:
! 247: panic("%s: sa1111_gpio_set_dir: bogus direction 0x%x",
! 248: sc->sc_dev.dv_xname, dir);
! 249: }
! 250: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, olddir);
! 251: }
! 252:
! 253: /*
! 254: * Get port direction.
! 255: */
! 256: u_int
! 257: sa1111_gpio_get_dir(int gpiobank, uint8_t gpio)
! 258: {
! 259: struct sacgpio_softc *sc = sacgpio_sc;
! 260: bus_addr_t reg;
! 261: int dir;
! 262:
! 263: if (sc == NULL)
! 264: panic("sa1111_gpio_get_dir: sacgpio not configured");
! 265:
! 266: /* select bank */
! 267: switch (gpiobank) {
! 268: case SACGPIO_BANKA:
! 269: /* block A has only 4 pins */
! 270: if (gpio > 3)
! 271: panic("%s: sa1111_gpio_get_dir: bogus gpio %d in bank A",
! 272: sc->sc_dev.dv_xname, gpio);
! 273: reg = SACCGPIOA_DDR;
! 274: break;
! 275: case SACGPIO_BANKB:
! 276: /* block B has only 6 pins */
! 277: if (gpio > 5)
! 278: panic("%s: sa1111_gpio_get_dir: bogus gpio %d in bank B",
! 279: sc->sc_dev.dv_xname, gpio);
! 280: reg = SACCGPIOB_DDR;
! 281: break;
! 282: case SACGPIO_BANKC:
! 283: reg = SACCGPIOC_DDR;
! 284: break;
! 285: default:
! 286: panic("%s: sa1111_gpio_get_dir: bogus gpio bank 0x%x",
! 287: sc->sc_dev.dv_xname, gpiobank);
! 288: }
! 289:
! 290: dir = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg) & ~(1 << gpio);
! 291:
! 292: return (dir ? SACGPIO_DIR_INPUT : SACGPIO_DIR_OUTPUT);
! 293: }
! 294:
! 295:
CVSweb