/* * Only slave mode supported, disregard [old]addr */ static int twsi_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) { struct twsi_softc *sc; uint32_t param; sc = device_get_softc(dev); switch (speed) { case IIC_SLOW: case IIC_FAST: param = sc->baud_rate[speed].param; break; case IIC_FASTEST: case IIC_UNKNOWN: default: param = sc->baud_rate[IIC_FAST].param; break; } mtx_lock(&sc->mutex); TWSI_WRITE(sc, sc->reg_soft_reset, 0x0); DELAY(2000); TWSI_WRITE(sc, sc->reg_baud_rate, param); TWSI_WRITE(sc, sc->reg_control, TWSI_CONTROL_TWSIEN); DELAY(1000); mtx_unlock(&sc->mutex); return (0); }
/* * Only slave mode supported, disregard [old]addr */ static int mv_twsi_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) { struct mv_twsi_softc *sc; uint32_t param; sc = device_get_softc(dev); switch (speed) { case IIC_SLOW: case IIC_FAST: param = baud_rate[speed].param; break; case IIC_FASTEST: case IIC_UNKNOWN: default: param = baud_rate[IIC_FAST].param; break; } mtx_lock(&sc->mutex); TWSI_WRITE(sc, TWSI_SOFT_RESET, 0x0); DELAY(2000); TWSI_WRITE(sc, TWSI_BAUD_RATE, param); TWSI_WRITE(sc, TWSI_CONTROL, TWSI_CONTROL_TWSIEN | TWSI_CONTROL_ACK); DELAY(1000); mtx_unlock(&sc->mutex); return (0); }
static int twsi_write(device_t dev, const char *buf, int len, int *sent, int timeout) { struct twsi_softc *sc; uint32_t status; int rv; sc = device_get_softc(dev); mtx_lock(&sc->mutex); *sent = 0; while (*sent < len) { TWSI_WRITE(sc, sc->reg_data, *buf++); twsi_clear_iflg(sc); DELAY(1000); if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) { debugf("timeout writing data\n"); rv = IIC_ETIMEOUT; goto out; } status = TWSI_READ(sc, sc->reg_status); if (status != TWSI_STATUS_DATA_WR_ACK) { debugf("wrong status (%02x) while writing\n", status); rv = IIC_ESTATUS; goto out; } (*sent)++; } rv = IIC_NOERR; out: mtx_unlock(&sc->mutex); return (rv); }
/* * 'timeout' is given in us. Note also that timeout handling is not exact -- * twsi_locked_start() total wait can be more than 2 x timeout * (twsi_poll_ctrl() is called twice). 'mask' can be either TWSI_STATUS_START * or TWSI_STATUS_RPTD_START */ static int twsi_locked_start(device_t dev, struct twsi_softc *sc, int32_t mask, u_char slave, int timeout) { int read_access, iflg_set = 0; uint32_t status; mtx_assert(&sc->mutex, MA_OWNED); if (mask == TWSI_STATUS_RPTD_START) /* read IFLG to know if it should be cleared later; from NBSD */ iflg_set = TWSI_READ(sc, sc->reg_control) & TWSI_CONTROL_IFLG; twsi_control_set(sc, TWSI_CONTROL_START); if (mask == TWSI_STATUS_RPTD_START && iflg_set) { debugf("IFLG set, clearing\n"); twsi_clear_iflg(sc); } /* * Without this delay we timeout checking IFLG if the timeout is 0. * NBSD driver always waits here too. */ DELAY(1000); if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) { debugf("timeout sending %sSTART condition\n", mask == TWSI_STATUS_START ? "" : "repeated "); return (IIC_ETIMEOUT); } status = TWSI_READ(sc, sc->reg_status); if (status != mask) { debugf("wrong status (%02x) after sending %sSTART condition\n", status, mask == TWSI_STATUS_START ? "" : "repeated "); return (IIC_ESTATUS); } TWSI_WRITE(sc, sc->reg_data, slave); twsi_clear_iflg(sc); DELAY(1000); if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) { debugf("timeout sending slave address\n"); return (IIC_ETIMEOUT); } read_access = (slave & 0x1) ? 1 : 0; status = TWSI_READ(sc, sc->reg_status); if (status != (read_access ? TWSI_STATUS_ADDR_R_ACK : TWSI_STATUS_ADDR_W_ACK)) { debugf("no ACK (status: %02x) after sending slave address\n", status); return (IIC_ENOACK); } return (IIC_NOERR); }
static __inline void twsi_control_set(struct mv_twsi_softc *sc, uint32_t mask) { uint32_t val; val = TWSI_READ(sc, TWSI_CONTROL); val |= mask; TWSI_WRITE(sc, TWSI_CONTROL, val); }
static __inline void twsi_control_set(struct twsi_softc *sc, uint32_t mask) { uint32_t val; val = TWSI_READ(sc, sc->reg_control); val &= ~(TWSI_CONTROL_STOP | TWSI_CONTROL_START); val |= mask; TWSI_WRITE(sc, sc->reg_control, val); }