/* * I2C read called by cmd_i2c when doing 'i2c read' and by cmd_eeprom.c * Begin write, send address byte(s), begin read, receive data bytes, end. * * NOTE: some EEPROMS want a stop right before the second start, while * some will choke if it is there. Deciding which we should do is eeprom * stuff, not i2c, but at the moment the APIs won't let us put it in * cmd_eeprom, so we have to choose here, and for the moment that'll be * a repeated start without a preceding stop. */ int i2c_read(u8 dev, uint addr, int alen, u8 *data, int length) { int status; /* begin i2c write to send the address bytes */ status = i2c_begin(MVTWSI_STATUS_START, (dev << 1)); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(addr >> (8*alen), MVTWSI_STATUS_DATA_W_ACK); /* begin i2c read to receive eeprom data bytes */ if (status == 0) status = i2c_begin( MVTWSI_STATUS_REPEATED_START, (dev << 1) | 1); /* prepare ACK if at least one byte must be received */ if (length > 0) twsi_control_flags |= MVTWSI_CONTROL_ACK; /* now receive actual bytes */ while ((status == 0) && length--) { /* reset NAK if we if no more to read now */ if (length == 0) twsi_control_flags &= ~MVTWSI_CONTROL_ACK; /* read current byte */ status = twsi_recv(data++); } /* Stop transaction */ status = twsi_stop(status); /* return 0 or status of first failure */ return status; }
/* * I2C probe called by cmd_i2c when doing 'i2c probe'. * Begin read, nak data byte, end. */ int i2c_probe(uchar chip) { u8 dummy_byte; int status; /* begin i2c read */ status = i2c_begin(MVTWSI_STATUS_START, (chip << 1) | 1); /* dummy read was accepted: receive byte but NAK it. */ if (status == 0) status = twsi_recv(&dummy_byte); /* Stop transaction */ twsi_stop(0); /* return 0 or status of first failure */ return status; }
/* * Reset controller. * Called at end of i2c_init unsuccessful i2c transactions. * Controller reset also resets the baud rate and slave address, so * re-establish them. */ static void twsi_reset(void) { /* ensure controller will be enabled by any twsi*() function */ twsi_control_flags = MVTWSI_CONTROL_TWSIEN; /* reset controller */ writel(0, &twsi->soft_reset); /* wait 2 ms -- this is what the Marvell LSP does */ udelay(20000); /* set baud rate */ writel(twsi_baud_rate, &twsi->baudrate); /* set slave address even though we don't use it */ writel(twsi_slave_address, &twsi->slave_address); writel(0, &twsi->xtnd_slave_addr); /* assert STOP but don't care for the result */ (void) twsi_stop(0); }
/* * I2C write called by cmd_i2c when doing 'i2c write' and by cmd_eeprom.c * Begin write, send address byte(s), send data bytes, end. */ int i2c_write(u8 dev, uint addr, int alen, u8 *data, int length) { int status; /* begin i2c write to send the eeprom adress bytes then data bytes */ status = i2c_begin(MVTWSI_STATUS_START, (dev << 1)); /* send addr bytes */ while ((status == 0) && alen--) status = twsi_send(addr >> (8*alen), MVTWSI_STATUS_DATA_W_ACK); /* send data bytes */ while ((status == 0) && (length-- > 0)) status = twsi_send(*(data++), MVTWSI_STATUS_DATA_W_ACK); /* Stop transaction */ status = twsi_stop(status); /* return 0 or status of first failure */ return status; }
/* * timeout is given in us */ static int twsi_start(device_t dev, u_char slave, int timeout) { struct twsi_softc *sc; int rv; sc = device_get_softc(dev); mtx_lock(&sc->mutex); rv = twsi_locked_start(dev, sc, TWSI_STATUS_START, slave, timeout); mtx_unlock(&sc->mutex); if (rv) { twsi_stop(dev); return (rv); } else return (IIC_NOERR); }