libi2cdriver: add functions for IC register access

Many i2c device drivers used similar code to access registers on
the ICs they drive. This commit implements that functionality in
libi2cdriver and updates the drivers to use the library instead of
their own register access functions. The net result is 375+ fewer
lines of code and less work for people developing new drivers.

The two exceptions were cat24c256 and parts of tda19988. They access
the bus in uncommon ways. It doesn't make sense at this time to
move their read/write functions into libi2cdriver.

Change-Id: Id8280b71af33b710a49944d7f20a7262be9f5988
This commit is contained in:
Thomas Cort
2013-09-16 13:33:00 -04:00
parent 43471c3110
commit 75bd3009d3
10 changed files with 274 additions and 656 deletions

View File

@@ -1,5 +1,6 @@
/* This file contains device independent i2c device driver helpers. */
#include <assert.h>
#include <minix/drivers.h>
#include <minix/endpoint.h>
#include <minix/i2c.h>
@@ -193,3 +194,174 @@ i2cdriver_exec(endpoint_t bus_endpoint, minix_i2c_ioctl_exec_t * ioctl_exec)
return m.REP_STATUS;
}
static int
__i2creg_read(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t raw,
uint8_t reg, uint32_t * val, size_t vallen)
{
int r, i;
minix_i2c_ioctl_exec_t ioctl_exec;
assert(val != NULL);
assert(vallen >= 1 && vallen <= 4);
memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t));
/* Read from chip */
ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP;
ioctl_exec.iie_addr = address;
if (!raw) {
/* write the register address */
ioctl_exec.iie_cmd[0] = reg;
ioctl_exec.iie_cmdlen = 1;
}
/* read vallen bytes */
ioctl_exec.iie_buflen = vallen;
r = i2cdriver_exec(bus_endpoint, &ioctl_exec);
if (r != OK) {
return -1;
}
for (*val = 0, i = 0; i < vallen; i++) {
*val = ((*val) << 8) | ioctl_exec.iie_buf[i];
}
return OK;
}
int
i2creg_raw_read8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t * val)
{
int r;
uint32_t val32;
r = __i2creg_read(bus_endpoint, address, 1, 0, &val32, 1);
*val = val32 & 0xff;
return r;
}
int
i2creg_read8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg,
uint8_t * val)
{
int r;
uint32_t val32;
r = __i2creg_read(bus_endpoint, address, 0, reg, &val32, 1);
*val = val32 & 0xff;
return r;
}
int
i2creg_read16(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg,
uint16_t * val)
{
int r;
uint32_t val32;
r = __i2creg_read(bus_endpoint, address, 0, reg, &val32, 2);
*val = val32 & 0xffff;
return r;
}
int
i2creg_read24(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg,
uint32_t * val)
{
return __i2creg_read(bus_endpoint, address, 0, reg, val, 3);
}
static int
__i2creg_write(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t raw,
uint8_t reg, uint8_t val)
{
int r;
minix_i2c_ioctl_exec_t ioctl_exec;
memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t));
/* Write to chip */
ioctl_exec.iie_op = I2C_OP_WRITE_WITH_STOP;
ioctl_exec.iie_addr = address;
if (raw) {
/* write just the value */
ioctl_exec.iie_buf[0] = val;
ioctl_exec.iie_buflen = 1;
} else {
/* write the register address and value */
ioctl_exec.iie_buf[0] = reg;
ioctl_exec.iie_buf[1] = val;
ioctl_exec.iie_buflen = 2;
}
r = i2cdriver_exec(bus_endpoint, &ioctl_exec);
if (r != OK) {
return -1;
}
return OK;
}
int
i2creg_write8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg,
uint8_t val)
{
return __i2creg_write(bus_endpoint, address, 0, reg, val);
}
int
i2creg_raw_write8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t val)
{
return __i2creg_write(bus_endpoint, address, 1, 0, val);
}
int
i2creg_set_bits8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg,
uint8_t bits)
{
int r;
uint8_t val;
r = i2creg_read8(bus_endpoint, address, reg, &val);
if (r != OK) {
return -1;
}
val |= bits;
r = i2creg_write8(bus_endpoint, address, reg, val);
if (r != OK) {
return -1;
}
return OK;
}
int
i2creg_clear_bits8(endpoint_t bus_endpoint, i2c_addr_t address, uint8_t reg,
uint8_t bits)
{
int r;
uint8_t val;
r = i2creg_read8(bus_endpoint, address, reg, &val);
if (r != OK) {
return -1;
}
val &= ~bits;
r = i2creg_write8(bus_endpoint, address, reg, val);
if (r != OK) {
return -1;
}
return OK;
}