Annotation of sys/arch/arm/xscale/pxa2x0_i2c.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pxa2x0_i2c.c,v 1.2 2005/05/26 03:52:07 pascoe Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 Christopher Pascoe <pascoe@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: #include <sys/param.h>
! 20: #include <sys/systm.h>
! 21:
! 22: #include <arm/xscale/pxa2x0reg.h>
! 23: #include <arm/xscale/pxa2x0var.h>
! 24: #include <arm/xscale/pxa2x0_i2c.h>
! 25: #include <arm/xscale/pxa2x0_gpio.h>
! 26:
! 27: #define I2C_RETRY_COUNT 10
! 28:
! 29: int
! 30: pxa2x0_i2c_attach_sub(struct pxa2x0_i2c_softc *sc)
! 31: {
! 32: if (bus_space_map(sc->sc_iot, PXA2X0_I2C_BASE,
! 33: PXA2X0_I2C_SIZE, 0, &sc->sc_ioh)) {
! 34: sc->sc_size = 0;
! 35: return EIO;
! 36: }
! 37: bus_space_barrier(sc->sc_iot, sc->sc_ioh, 0, sc->sc_size,
! 38: BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
! 39:
! 40: /*
! 41: * Configure the alternate functions. The _IN is arbitrary, as the
! 42: * direction is managed by the I2C unit when comms are in progress.
! 43: */
! 44: pxa2x0_gpio_set_function(117, GPIO_ALT_FN_1_IN); /* SCL */
! 45: pxa2x0_gpio_set_function(118, GPIO_ALT_FN_1_IN); /* SDA */
! 46:
! 47: pxa2x0_i2c_init(sc);
! 48:
! 49: return 0;
! 50: }
! 51:
! 52: int
! 53: pxa2x0_i2c_detach_sub(struct pxa2x0_i2c_softc *sc)
! 54: {
! 55: if (sc->sc_size) {
! 56: bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
! 57: sc->sc_size = 0;
! 58: }
! 59: pxa2x0_clkman_config(CKEN_I2C, 0);
! 60:
! 61: return 0;
! 62: }
! 63:
! 64: void
! 65: pxa2x0_i2c_init(struct pxa2x0_i2c_softc *sc)
! 66: {
! 67: pxa2x0_i2c_open(sc);
! 68: pxa2x0_i2c_close(sc);
! 69: }
! 70:
! 71: void
! 72: pxa2x0_i2c_open(struct pxa2x0_i2c_softc *sc)
! 73: {
! 74: /* Enable the clock to the standard I2C unit. */
! 75: pxa2x0_clkman_config(CKEN_I2C, 1);
! 76: }
! 77:
! 78: void
! 79: pxa2x0_i2c_close(struct pxa2x0_i2c_softc *sc)
! 80: {
! 81: /* Reset and disable the standard I2C unit. */
! 82: bus_space_write_4(sc->sc_iot, sc->sc_ioh, I2C_ICR, ICR_UR);
! 83: bus_space_write_4(sc->sc_iot, sc->sc_ioh, I2C_ISAR, 0);
! 84: delay(1);
! 85: pxa2x0_clkman_config(CKEN_I2C, 0);
! 86: }
! 87:
! 88: int
! 89: pxa2x0_i2c_read(struct pxa2x0_i2c_softc *sc, u_char slave, u_char *valuep)
! 90: {
! 91: u_int32_t rv;
! 92: int timeout;
! 93: int tries = I2C_RETRY_COUNT;
! 94: bus_space_tag_t iot = sc->sc_iot;
! 95: bus_space_handle_t ioh = sc->sc_ioh;
! 96:
! 97: retry:
! 98: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
! 99: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
! 100: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE | ISR_IRF);
! 101: delay(1);
! 102: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
! 103:
! 104: /* Write slave device address. */
! 105: bus_space_write_4(iot, ioh, I2C_IDBR, (slave<<1) | 0x1);
! 106: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 107: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_START);
! 108: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 109: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
! 110: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 111: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
! 112:
! 113: timeout = 10000;
! 114: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
! 115: if (timeout-- == 0)
! 116: goto err;
! 117: delay(1);
! 118: }
! 119:
! 120: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 121:
! 122: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 123: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_START);
! 124:
! 125: /* Read data value. */
! 126: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 127: bus_space_write_4(iot, ioh, I2C_ICR, rv |
! 128: (ICR_STOP | ICR_ACKNAK));
! 129: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 130: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
! 131:
! 132: timeout = 10000;
! 133: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_IRF) == 0) {
! 134: if (timeout-- == 0)
! 135: goto err;
! 136: delay(1);
! 137: }
! 138:
! 139: bus_space_write_4(iot, ioh, I2C_ISR, ISR_IRF);
! 140:
! 141: rv = bus_space_read_4(iot, ioh, I2C_IDBR);
! 142: *valuep = (u_char)rv;
! 143: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 144: bus_space_write_4(iot, ioh, I2C_ICR, rv &
! 145: ~(ICR_STOP | ICR_ACKNAK));
! 146:
! 147: return (0);
! 148: err:
! 149: if (tries-- >= 0)
! 150: goto retry;
! 151:
! 152: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
! 153: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
! 154: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE | ISR_IRF);
! 155: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
! 156:
! 157: return (-EIO);
! 158: }
! 159:
! 160: int
! 161: pxa2x0_i2c_write(struct pxa2x0_i2c_softc *sc, u_char slave, u_char value)
! 162: {
! 163: u_int32_t rv;
! 164: int timeout;
! 165: int tries = I2C_RETRY_COUNT;
! 166: bus_space_tag_t iot = sc->sc_iot;
! 167: bus_space_handle_t ioh = sc->sc_ioh;
! 168:
! 169: retry:
! 170: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
! 171: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
! 172: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 173: delay(1);
! 174: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
! 175:
! 176: /* Write slave device address. */
! 177: bus_space_write_4(iot, ioh, I2C_IDBR, (slave<<1));
! 178: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 179: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_START);
! 180: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 181: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
! 182: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 183: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
! 184:
! 185: timeout = 10000;
! 186: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
! 187: if (timeout-- == 0)
! 188: goto err;
! 189: delay(1);
! 190: }
! 191: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
! 192: goto err;
! 193:
! 194: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 195:
! 196: /* Write data. */
! 197: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 198: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_START);
! 199: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 200: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_STOP);
! 201: bus_space_write_4(iot, ioh, I2C_IDBR, value);
! 202: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 203: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
! 204:
! 205: timeout = 10000;
! 206: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
! 207: if (timeout-- == 0)
! 208: goto err;
! 209: delay(1);
! 210: }
! 211: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
! 212: goto err;
! 213:
! 214: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 215:
! 216: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 217: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
! 218:
! 219: return (0);
! 220: err:
! 221: if (tries-- >= 0)
! 222: goto retry;
! 223:
! 224: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
! 225: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
! 226: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 227: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
! 228:
! 229: return (-EIO);
! 230: }
! 231:
! 232: int
! 233: pxa2x0_i2c_write_2(struct pxa2x0_i2c_softc *sc, u_char slave, u_short value)
! 234: {
! 235: u_int32_t rv;
! 236: int timeout;
! 237: int tries = I2C_RETRY_COUNT;
! 238: bus_space_tag_t iot = sc->sc_iot;
! 239: bus_space_handle_t ioh = sc->sc_ioh;
! 240:
! 241: retry:
! 242: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
! 243: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
! 244: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 245: delay(1);
! 246: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
! 247:
! 248: /* Write slave device address. */
! 249: bus_space_write_4(iot, ioh, I2C_IDBR, (slave<<1));
! 250: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 251: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_START);
! 252: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 253: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
! 254: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 255: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
! 256:
! 257: timeout = 10000;
! 258: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
! 259: if (timeout-- == 0)
! 260: goto err;
! 261: delay(1);
! 262: }
! 263: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
! 264: goto err;
! 265:
! 266: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 267:
! 268: /* Write upper 8 bits of data. */
! 269: bus_space_write_4(iot, ioh, I2C_IDBR, (value >> 8) & 0xff);
! 270: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 271: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_START);
! 272: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 273: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
! 274: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 275: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
! 276:
! 277: timeout = 10000;
! 278: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
! 279: if (timeout-- == 0)
! 280: goto err;
! 281: delay(1);
! 282: }
! 283: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
! 284: goto err;
! 285:
! 286: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 287:
! 288: /* Write lower 8 bits of data. */
! 289: bus_space_write_4(iot, ioh, I2C_IDBR, value & 0xff);
! 290: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 291: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_START);
! 292: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 293: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_STOP);
! 294: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 295: bus_space_write_4(iot, ioh, I2C_ICR, rv | ICR_TB);
! 296:
! 297: timeout = 10000;
! 298: while ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ITE) == 0) {
! 299: if (timeout-- == 0)
! 300: goto err;
! 301: delay(1);
! 302: }
! 303: if ((bus_space_read_4(iot, ioh, I2C_ISR) & ISR_ACKNAK) != 0)
! 304: goto err;
! 305:
! 306: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 307:
! 308: rv = bus_space_read_4(iot, ioh, I2C_ICR);
! 309: bus_space_write_4(iot, ioh, I2C_ICR, rv & ~ICR_STOP);
! 310:
! 311: return (0);
! 312: err:
! 313: if (tries-- >= 0)
! 314: goto retry;
! 315:
! 316: bus_space_write_4(iot, ioh, I2C_ICR, ICR_UR);
! 317: bus_space_write_4(iot, ioh, I2C_ISAR, 0x00);
! 318: bus_space_write_4(iot, ioh, I2C_ISR, ISR_ITE);
! 319: bus_space_write_4(iot, ioh, I2C_ICR, ICR_IUE | ICR_SCLE);
! 320:
! 321: return (-EIO);
! 322: }
CVSweb