From 75bd3009d367388da31498c63a71b54eafaa2774 Mon Sep 17 00:00:00 2001 From: Thomas Cort Date: Mon, 16 Sep 2013 13:33:00 -0400 Subject: [PATCH] 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 --- drivers/bmp085/bmp085.c | 191 +++-------------------------------- drivers/sht21/sht21.c | 117 +++------------------ drivers/tda19988/tda19988.c | 70 ++----------- drivers/tps65217/tps65217.c | 88 +--------------- drivers/tps65950/rtc.c | 38 ++++--- drivers/tps65950/tps65950.c | 137 +++---------------------- drivers/tps65950/tps65950.h | 7 +- drivers/tsl2550/tsl2550.c | 97 ++---------------- include/minix/i2cdriver.h | 11 ++ lib/libi2cdriver/i2cdriver.c | 172 +++++++++++++++++++++++++++++++ 10 files changed, 273 insertions(+), 655 deletions(-) diff --git a/drivers/bmp085/bmp085.c b/drivers/bmp085/bmp085.c index 776558071..a7dddb244 100644 --- a/drivers/bmp085/bmp085.c +++ b/drivers/bmp085/bmp085.c @@ -157,12 +157,6 @@ static int bmp085_transfer(endpoint_t endpt, int opcode, u64_t position, unsigned int UNUSED(flags)); static int bmp085_other(message * m); -/* i2c bus access */ -static int reg_read(uint8_t reg, uint8_t * val); -static int reg_read16(uint8_t reg, uint16_t * val); -static int reg_read24(uint8_t reg, uint32_t * val); -static int reg_write(uint8_t reg, uint8_t val); - /* SEF Function */ static int sef_cb_lu_state_save(int); static int lu_state_restore(void); @@ -188,159 +182,6 @@ static struct device bmp085_device = { .dv_size = 0 }; -static int -reg_read(uint8_t reg, uint8_t * val) -{ - int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - if (val == NULL) { - log_warn(&log, "reg_read() called with NULL pointer\n"); - return -1; - } - - 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; - - /* write the register address */ - ioctl_exec.iie_cmd[0] = reg; - ioctl_exec.iie_cmdlen = 1; - - /* read 1 byte */ - ioctl_exec.iie_buflen = 1; - - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); - if (r != OK) { - log_warn(&log, "reg_read() failed (r=%d)\n", r); - return -1; - } - - *val = ioctl_exec.iie_buf[0]; - - log_trace(&log, "Read 0x%x from reg 0x%x\n", *val, reg); - - return OK; -} - -static int -reg_read16(uint8_t reg, uint16_t * val) -{ - int r; - uint8_t msb, lsb; - minix_i2c_ioctl_exec_t ioctl_exec; - - if (val == NULL) { - log_warn(&log, "reg_read16() called with NULL pointer\n"); - return -1; - } - - 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; - - /* write the register address */ - ioctl_exec.iie_cmd[0] = reg; - ioctl_exec.iie_cmdlen = 1; - - /* read 2 bytes */ - ioctl_exec.iie_buflen = 2; - - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); - if (r != OK) { - log_warn(&log, "reg_read16() failed (r=%d)\n", r); - return -1; - } - - msb = ioctl_exec.iie_buf[0]; - lsb = ioctl_exec.iie_buf[1]; - - *val = ((msb << 8) | lsb); - - log_trace(&log, "Read 0x%x from reg 0x%x\n", *val, reg); - - return OK; - -} - -static int -reg_read24(uint8_t reg, uint32_t * val) -{ - int r; - uint8_t msb, lsb, xlsb; - minix_i2c_ioctl_exec_t ioctl_exec; - - if (val == NULL) { - log_warn(&log, "reg_read24() called with NULL pointer\n"); - return -1; - } - - 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; - - /* write the register address */ - ioctl_exec.iie_cmd[0] = reg; - ioctl_exec.iie_cmdlen = 1; - - /* read 3 bytes */ - ioctl_exec.iie_buflen = 3; - - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); - if (r != OK) { - log_warn(&log, "reg_read24() failed (r=%d)\n", r); - return -1; - } - - msb = ioctl_exec.iie_buf[0]; - lsb = ioctl_exec.iie_buf[1]; - xlsb = ioctl_exec.iie_buf[2]; - - *val = ((msb << 16) | (lsb << 8) | xlsb); - - log_trace(&log, "Read 0x%x from reg 0x%x\n", *val, reg); - - return OK; - -} - -static int -reg_write(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)); - - /* Read from chip */ - ioctl_exec.iie_op = I2C_OP_WRITE_WITH_STOP; - ioctl_exec.iie_addr = address; - - /* no commands here */ - ioctl_exec.iie_cmdlen = 0; - - /* write register 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) { - log_warn(&log, "reg_write() failed (r=%d)\n", r); - return -1; - } - - log_trace(&log, "Wrote 0x%x to reg 0x%x\n", val, reg); - - return OK; -} - /* * Initialize the driver. Checks the CHIPID against a known value and * reads the calibration coefficients. @@ -373,7 +214,7 @@ version_check(void) int r; uint8_t chipid; - r = reg_read(CHIPID_REG, &chipid); + r = i2creg_read8(bus_endpoint, address, CHIPID_REG, &chipid); if (r != OK) { log_warn(&log, "Couldn't read CHIPID\n"); return -1; @@ -400,67 +241,67 @@ read_cal_coef(void) int r; /* Populate the calibration struct with values */ - r = reg_read16(AC1_MSB_REG, &cal.ac1); + r = i2creg_read16(bus_endpoint, address, AC1_MSB_REG, &cal.ac1); if (r != OK) { return -1; } log_debug(&log, "cal.ac1 = %d\n", cal.ac1); - r = reg_read16(AC2_MSB_REG, &cal.ac2); + r = i2creg_read16(bus_endpoint, address, AC2_MSB_REG, &cal.ac2); if (r != OK) { return -1; } log_debug(&log, "cal.ac2 = %d\n", cal.ac2); - r = reg_read16(AC3_MSB_REG, &cal.ac3); + r = i2creg_read16(bus_endpoint, address, AC3_MSB_REG, &cal.ac3); if (r != OK) { return -1; } log_debug(&log, "cal.ac3 = %d\n", cal.ac3); - r = reg_read16(AC4_MSB_REG, &cal.ac4); + r = i2creg_read16(bus_endpoint, address, AC4_MSB_REG, &cal.ac4); if (r != OK) { return -1; } log_debug(&log, "cal.ac4 = %u\n", cal.ac4); - r = reg_read16(AC5_MSB_REG, &cal.ac5); + r = i2creg_read16(bus_endpoint, address, AC5_MSB_REG, &cal.ac5); if (r != OK) { return -1; } log_debug(&log, "cal.ac5 = %u\n", cal.ac5); - r = reg_read16(AC6_MSB_REG, &cal.ac6); + r = i2creg_read16(bus_endpoint, address, AC6_MSB_REG, &cal.ac6); if (r != OK) { return -1; } log_debug(&log, "cal.ac6 = %u\n", cal.ac6); - r = reg_read16(B1_MSB_REG, &cal.b1); + r = i2creg_read16(bus_endpoint, address, B1_MSB_REG, &cal.b1); if (r != OK) { return -1; } log_debug(&log, "cal.b1 = %d\n", cal.b1); - r = reg_read16(B2_MSB_REG, &cal.b2); + r = i2creg_read16(bus_endpoint, address, B2_MSB_REG, &cal.b2); if (r != OK) { return -1; } log_debug(&log, "cal.b2 = %d\n", cal.b2); - r = reg_read16(MB_MSB_REG, &cal.mb); + r = i2creg_read16(bus_endpoint, address, MB_MSB_REG, &cal.mb); if (r != OK) { return -1; } log_debug(&log, "cal.mb = %d\n", cal.mb); - r = reg_read16(MC_MSB_REG, &cal.mc); + r = i2creg_read16(bus_endpoint, address, MC_MSB_REG, &cal.mc); if (r != OK) { return -1; } log_debug(&log, "cal.mc = %d\n", cal.mc); - r = reg_read16(MD_MSB_REG, &cal.md); + r = i2creg_read16(bus_endpoint, address, MD_MSB_REG, &cal.md); if (r != OK) { return -1; } @@ -516,7 +357,7 @@ measure(int32_t * temperature, int32_t * pressure) log_debug(&log, "Triggering Temp Reading...\n"); /* trigger temperature reading */ - r = reg_write(CTRL_REG, CMD_TRIG_T); + r = i2creg_write8(bus_endpoint, address, CTRL_REG, CMD_TRIG_T); if (r != OK) { log_warn(&log, "Failed to trigger temperature reading.\n"); return -1; @@ -526,7 +367,7 @@ measure(int32_t * temperature, int32_t * pressure) micro_delay(UDELAY_T); /* read the uncompensated temperature */ - r = reg_read16(SENSOR_VAL_MSB_REG, &ut); + r = i2creg_read16(bus_endpoint, address, SENSOR_VAL_MSB_REG, &ut); if (r != OK) { log_warn(&log, "Failed to read temperature.\n"); return -1; @@ -537,7 +378,7 @@ measure(int32_t * temperature, int32_t * pressure) log_debug(&log, "Triggering Pressure Reading...\n"); /* trigger pressure reading */ - r = reg_write(CTRL_REG, p_cmd->cmd); + r = i2creg_write8(bus_endpoint, address, CTRL_REG, p_cmd->cmd); if (r != OK) { log_warn(&log, "Failed to trigger pressure reading.\n"); return -1; @@ -547,7 +388,7 @@ measure(int32_t * temperature, int32_t * pressure) micro_delay(p_cmd->udelay); /* read the uncompensated pressure */ - r = reg_read24(SENSOR_VAL_MSB_REG, &up); + r = i2creg_read24(bus_endpoint, address, SENSOR_VAL_MSB_REG, &up); if (r != OK) { log_warn(&log, "Failed to read pressure.\n"); return -1; diff --git a/drivers/sht21/sht21.c b/drivers/sht21/sht21.c index cb9f327d2..4f96f6bfa 100644 --- a/drivers/sht21/sht21.c +++ b/drivers/sht21/sht21.c @@ -106,8 +106,6 @@ static int32_t cached_rh = 0.0; /* main driver functions */ static int sht21_init(void); -static int soft_reset(void); -static int usr_reg_read(uint8_t * usr_reg_val); static int sensor_read(enum sht21_sensors sensor, int32_t * measurement); static int measure(void); @@ -148,30 +146,18 @@ static struct device sht21_device = { }; /* - * Sends the chip a soft reset command and waits 15 ms for the chip to reset. + * Performs a soft reset and reads the contents of the user register to ensure + * that the chip is in a good state and working properly. */ static int -soft_reset(void) +sht21_init(void) { 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; - - /* No command bytes for writing to this chip */ - ioctl_exec.iie_cmdlen = 0; - - /* Set the byte to write */ - ioctl_exec.iie_buf[0] = CMD_SOFT_RESET; - ioctl_exec.iie_buflen = 1; + uint8_t usr_reg_val; - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); + /* Perform a soft-reset */ + r = i2creg_raw_write8(bus_endpoint, address, CMD_SOFT_RESET); if (r != OK) { - log_warn(&log, "soft_reset() failed (r=%d)\n", r); return -1; } @@ -180,65 +166,7 @@ soft_reset(void) log_debug(&log, "Soft Reset Complete\n"); - return OK; -} - -/* - * Obtain the contents of the usr register and store it in usr_reg_val. - */ -static int -usr_reg_read(uint8_t * usr_reg_val) -{ - int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - if (usr_reg_val == NULL) { - log_warn(&log, "usr_reg_read() called with NULL pointer\n"); - return -1; - } - - 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; - - /* Send the read from user register command */ - ioctl_exec.iie_cmd[0] = CMD_RD_USR_REG; - ioctl_exec.iie_cmdlen = 1; - - /* Read the register contents into iie_buf */ - ioctl_exec.iie_buflen = 1; - - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); - if (r != OK) { - log_warn(&log, "usr_reg_read() failed (r=%d)\n", r); - return -1; - } - - *usr_reg_val = ioctl_exec.iie_buf[0]; - - log_trace(&log, "Read 0x%x from USR_REG\n", *usr_reg_val); - - return OK; -} - -/* - * Performs a soft reset and reads the contents of the user register to ensure - * that the chip is in a good state and working properly. - */ -static int -sht21_init(void) -{ - int r; - uint8_t usr_reg_val; - - r = soft_reset(); - if (r != OK) { - return -1; - } - - r = usr_reg_read(&usr_reg_val); + r = i2creg_read8(bus_endpoint, address, CMD_RD_USR_REG, &usr_reg_val); if (r != OK) { return -1; } @@ -270,10 +198,10 @@ sensor_read(enum sht21_sensors sensor, int32_t * measurement) { int r; uint8_t cmd; - uint8_t val_hi, val_lo; uint16_t val; + uint8_t bytes[2]; + uint32_t val32; uint8_t expected_crc; - minix_i2c_ioctl_exec_t ioctl_exec; switch (sensor) { case SHT21_T: @@ -292,36 +220,23 @@ sensor_read(enum sht21_sensors sensor, int32_t * measurement) return -1; } - 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; - - /* Send the trigger command */ - ioctl_exec.iie_cmd[0] = cmd; - ioctl_exec.iie_cmdlen = 1; - - /* Read the results */ - ioctl_exec.iie_buflen = 3; - - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); + r = i2creg_read24(bus_endpoint, address, cmd, &val32); if (r != OK) { log_warn(&log, "sensor_read() failed (r=%d)\n", r); return -1; } - expected_crc = ioctl_exec.iie_buf[2]; + expected_crc = val32 & 0xff; + val = (val32 >> 8) & 0xffff; + + bytes[0] = (val >> 8) & 0xff; + bytes[1] = val & 0xff; - r = checksum(ioctl_exec.iie_buf, 2, expected_crc); + r = checksum(bytes, 2, expected_crc); if (r != OK) { return -1; } - val_hi = ioctl_exec.iie_buf[0]; - val_lo = ioctl_exec.iie_buf[1]; - val = ((val_hi << 8) | val_lo); - val &= ~STATUS_BITS_MASK; /* clear status bits */ log_debug(&log, "Read VAL:0x%x CRC:0x%x\n", val, expected_crc); diff --git a/drivers/tda19988/tda19988.c b/drivers/tda19988/tda19988.c index 81f40bcb5..c8bbeff9a 100644 --- a/drivers/tda19988/tda19988.c +++ b/drivers/tda19988/tda19988.c @@ -375,28 +375,15 @@ static int is_display_connected(void) { int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); - - /* Read from CEC */ - ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP; - ioctl_exec.iie_addr = cec_address; - - /* write the register address */ - ioctl_exec.iie_cmd[0] = CEC_STATUS_REG; - ioctl_exec.iie_cmdlen = 1; - - /* read 1 byte */ - ioctl_exec.iie_buflen = 1; + uint8_t val; - r = i2cdriver_exec(cec_bus_endpoint, &ioctl_exec); + r = i2creg_read8(cec_bus_endpoint, cec_address, CEC_STATUS_REG, &val); if (r != OK) { log_warn(&log, "Reading connection status failed (r=%d)\n", r); return -1; } - if ((CEC_STATUS_CONNECTED_MASK & ioctl_exec.iie_buf[0]) == 0) { + if ((CEC_STATUS_CONNECTED_MASK & val) == 0) { log_debug(&log, "No Display Detected\n"); return 0; } else { @@ -412,20 +399,9 @@ static int enable_hdmi_module(void) { int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); - - /* Write to CEC */ - ioctl_exec.iie_op = I2C_OP_WRITE_WITH_STOP; - ioctl_exec.iie_addr = cec_address; - - /* write the register address and value */ - ioctl_exec.iie_buf[0] = CEC_ENABLE_REG; - ioctl_exec.iie_buf[1] = CEC_ENABLE_ALL_MASK; - ioctl_exec.iie_buflen = 2; - r = i2cdriver_exec(cec_bus_endpoint, &ioctl_exec); + r = i2creg_write8(cec_bus_endpoint, cec_address, CEC_ENABLE_REG, + CEC_ENABLE_ALL_MASK); if (r != OK) { log_warn(&log, "Writing enable bits failed (r=%d)\n", r); return -1; @@ -444,7 +420,8 @@ set_page(uint8_t page) if (page != current_page) { - r = hdmi_write(HDMI_PAGELESS, HDMI_PAGE_SELECT_REG, page); + r = i2creg_write8(hdmi_bus_endpoint, hdmi_address, + HDMI_PAGE_SELECT_REG, page); if (r != OK) { return r; } @@ -508,7 +485,6 @@ hdmi_read(uint8_t page, uint8_t reg, uint8_t * val) { int r; - minix_i2c_ioctl_exec_t ioctl_exec; if (val == NULL) { log_warn(&log, "Read called with NULL pointer\n"); @@ -523,27 +499,12 @@ hdmi_read(uint8_t page, uint8_t reg, uint8_t * val) } } - memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); - - /* Read from HDMI */ - ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP; - ioctl_exec.iie_addr = hdmi_address; - - /* write the register address */ - ioctl_exec.iie_cmd[0] = reg; - ioctl_exec.iie_cmdlen = 1; - - /* read 1 byte */ - ioctl_exec.iie_buflen = 1; - - r = i2cdriver_exec(hdmi_bus_endpoint, &ioctl_exec); + r = i2creg_read8(hdmi_bus_endpoint, hdmi_address, reg, val); if (r != OK) { log_warn(&log, "hdmi_read() failed (r=%d)\n", r); return -1; } - *val = ioctl_exec.iie_buf[0]; - log_trace(&log, "Read 0x%x from reg 0x%x in page 0x%x\n", *val, reg, page); @@ -553,9 +514,7 @@ hdmi_read(uint8_t page, uint8_t reg, uint8_t * val) static int hdmi_write(uint8_t page, uint8_t reg, uint8_t val) { - int r; - minix_i2c_ioctl_exec_t ioctl_exec; if (page != HDMI_PAGELESS) { r = set_page(page); @@ -565,18 +524,7 @@ hdmi_write(uint8_t page, uint8_t reg, uint8_t val) } } - memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); - - /* Write to HDMI */ - ioctl_exec.iie_op = I2C_OP_WRITE_WITH_STOP; - ioctl_exec.iie_addr = hdmi_address; - - /* 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(hdmi_bus_endpoint, &ioctl_exec); + r = i2creg_write8(hdmi_bus_endpoint, hdmi_address, reg, val); if (r != OK) { log_warn(&log, "hdmi_write() failed (r=%d)\n", r); return -1; diff --git a/drivers/tps65217/tps65217.c b/drivers/tps65217/tps65217.c index 63d943f6a..eac833ae3 100644 --- a/drivers/tps65217/tps65217.c +++ b/drivers/tps65217/tps65217.c @@ -101,10 +101,6 @@ static struct log log = { .log_func = default_log }; -/* Register Access */ -static int reg_read(uint8_t reg, uint8_t * val); -static int reg_write(uint8_t reg, uint8_t val); - /* Device Specific Functions */ static int check_revision(void); static int enable_pwr_off(void); @@ -118,87 +114,13 @@ static int sef_cb_lu_state_save(int); static int lu_state_restore(void); static int sef_cb_init(int type, sef_init_info_t * info); -static int -reg_read(uint8_t reg, uint8_t * val) -{ - int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - if (val == NULL) { - log_warn(&log, "Read called with NULL pointer\n"); - return EINVAL; - } - - 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; - - /* write the register address */ - ioctl_exec.iie_cmd[0] = reg; - ioctl_exec.iie_cmdlen = 1; - - /* read 1 byte */ - ioctl_exec.iie_buflen = 1; - - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); - if (r != OK) { - log_warn(&log, "reg_read() failed (r=%d)\n", r); - return -1; - } - - *val = ioctl_exec.iie_buf[0]; - - log_trace(&log, "Read 0x%x from reg 0x%x", *val, reg); - - return OK; -} - -static int -reg_write(uint8_t reg, uint8_t val) -{ - int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - if (reg >= 0x0d) { - /* TODO: writes to password protected registers hasn't - * been implemented since nothing in this driver needs to - * write to them. When needed, it should be implemented. - */ - log_warn(&log, "Cannot write to protected registers."); - return -1; - } - - 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; - - /* 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) { - log_warn(&log, "reg_write() failed (r=%d)\n", r); - return -1; - } - - log_trace(&log, "Successfully wrote 0x%x to reg 0x%x\n", val, reg); - - return OK; -} - static int check_revision(void) { int r; uint8_t chipid; - r = reg_read(CHIPID_REG, &chipid); + r = i2creg_read8(bus_endpoint, address, CHIPID_REG, &chipid); if (r != OK) { log_warn(&log, "Failed to read CHIPID\n"); return -1; @@ -235,7 +157,7 @@ enable_pwr_off(void) * system is ready to be powered off. Should be called during startup * so that shutdown(8) can do power-off with reboot(RBT_POWEROFF). */ - r = reg_write(STATUS_REG, PWR_OFF_MASK); + r = i2creg_write8(bus_endpoint, address, STATUS_REG, PWR_OFF_MASK); if (r != OK) { log_warn(&log, "Cannot set power off mask."); return -1; @@ -274,14 +196,14 @@ intr_enable(void) } /* Enable/Disable interrupts in the TPS65217 */ - r = reg_write(INT_REG, DEFAULT_INT_MASK); + r = i2creg_write8(bus_endpoint, address, INT_REG, DEFAULT_INT_MASK); if (r != OK) { log_warn(&log, "Failed to set interrupt mask.\n"); return -1; } /* Read from the interrupt register to clear any pending interrupts */ - r = reg_read(INT_REG, &val); + r = i2creg_read8(bus_endpoint, address, INT_REG, &val); if (r != OK) { log_warn(&log, "Failed to read interrupt register.\n"); return -1; @@ -298,7 +220,7 @@ intr_handler(void) struct tm t; /* read interrupt register to get interrupt that fired and clear it */ - r = reg_read(INT_REG, &val); + r = i2creg_read8(bus_endpoint, address, INT_REG, &val); if (r != OK) { log_warn(&log, "Failed to read interrupt register.\n"); return -1; diff --git a/drivers/tps65950/rtc.c b/drivers/tps65950/rtc.c index c3a13f0d2..9a683556a 100644 --- a/drivers/tps65950/rtc.c +++ b/drivers/tps65950/rtc.c @@ -26,13 +26,14 @@ rtc_init(void) uint8_t val; struct tm t; - r = reg_set(ID4, RTC_CTRL_REG, (1 << STOP_RTC_BIT)); + r = i2creg_set_bits8(bus_endpoint, addresses[ID4], RTC_CTRL_REG, + (1 << STOP_RTC_BIT)); if (r != OK) { log_warn(&log, "Failed to start RTC\n"); return -1; } - r = reg_read(ID4, RTC_STATUS_REG, &val); + r = i2creg_read8(bus_endpoint, addresses[ID4], RTC_STATUS_REG, &val); if (r != OK) { log_warn(&log, "Failed to read RTC_STATUS_REG\n"); return -1; @@ -59,7 +60,8 @@ rtc_get_time(struct tm *t, int flags) /* Write GET_TIME_BIT to RTC_CTRL_REG to latch the RTC values into * the RTC registers. This is required before each read. */ - r = reg_set(ID4, RTC_CTRL_REG, (1 << GET_TIME_BIT)); + r = i2creg_set_bits8(bus_endpoint, addresses[ID4], RTC_CTRL_REG, + (1 << GET_TIME_BIT)); if (r != OK) { return -1; } @@ -67,42 +69,42 @@ rtc_get_time(struct tm *t, int flags) /* Read and Convert BCD to binary (default RTC mode). */ /* Seconds - 0 to 59 */ - r = reg_read(ID4, SECONDS_REG, &val); + r = i2creg_read8(bus_endpoint, addresses[ID4], SECONDS_REG, &val); if (r != OK) { return -1; } t->tm_sec = bcd_to_dec(val & 0x7f); /* Minutes - 0 to 59 */ - r = reg_read(ID4, MINUTES_REG, &val); + r = i2creg_read8(bus_endpoint, addresses[ID4], MINUTES_REG, &val); if (r != OK) { return -1; } t->tm_min = bcd_to_dec(val & 0x7f); /* Hours - 0 to 23 */ - r = reg_read(ID4, HOURS_REG, &val); + r = i2creg_read8(bus_endpoint, addresses[ID4], HOURS_REG, &val); if (r != OK) { return -1; } t->tm_hour = bcd_to_dec(val & 0x3f); /* Days - 1 to 31 */ - r = reg_read(ID4, DAYS_REG, &val); + r = i2creg_read8(bus_endpoint, addresses[ID4], DAYS_REG, &val); if (r != OK) { return -1; } t->tm_mday = bcd_to_dec(val & 0x3f); /* Months - Jan=1 to Dec=12 */ - r = reg_read(ID4, MONTHS_REG, &val); + r = i2creg_read8(bus_endpoint, addresses[ID4], MONTHS_REG, &val); if (r != OK) { return -1; } t->tm_mon = bcd_to_dec(val & 0x1f) - 1; /* Years - last 2 digits of year */ - r = reg_read(ID4, YEARS_REG, &val); + r = i2creg_read8(bus_endpoint, addresses[ID4], YEARS_REG, &val); if (r != OK) { return -1; } @@ -129,32 +131,38 @@ rtc_set_time(struct tm *t, int flags) int r; /* Write the date/time to the RTC registers. */ - r = reg_write(ID4, SECONDS_REG, (dec_to_bcd(t->tm_sec) & 0x7f)); + r = i2creg_write8(bus_endpoint, addresses[ID4], SECONDS_REG, + (dec_to_bcd(t->tm_sec) & 0x7f)); if (r != OK) { return -1; } - r = reg_write(ID4, MINUTES_REG, (dec_to_bcd(t->tm_min) & 0x7f)); + r = i2creg_write8(bus_endpoint, addresses[ID4], MINUTES_REG, + (dec_to_bcd(t->tm_min) & 0x7f)); if (r != OK) { return -1; } - r = reg_write(ID4, HOURS_REG, (dec_to_bcd(t->tm_hour) & 0x3f)); + r = i2creg_write8(bus_endpoint, addresses[ID4], HOURS_REG, + (dec_to_bcd(t->tm_hour) & 0x3f)); if (r != OK) { return -1; } - r = reg_write(ID4, DAYS_REG, (dec_to_bcd(t->tm_mday) & 0x3f)); + r = i2creg_write8(bus_endpoint, addresses[ID4], DAYS_REG, + (dec_to_bcd(t->tm_mday) & 0x3f)); if (r != OK) { return -1; } - r = reg_write(ID4, MONTHS_REG, (dec_to_bcd(t->tm_mon + 1) & 0x1f)); + r = i2creg_write8(bus_endpoint, addresses[ID4], MONTHS_REG, + (dec_to_bcd(t->tm_mon + 1) & 0x1f)); if (r != OK) { return -1; } - r = reg_write(ID4, YEARS_REG, (dec_to_bcd(t->tm_year % 100) & 0xff)); + r = i2creg_write8(bus_endpoint, addresses[ID4], YEARS_REG, + (dec_to_bcd(t->tm_year % 100) & 0xff)); if (r != OK) { return -1; } diff --git a/drivers/tps65950/tps65950.c b/drivers/tps65950/tps65950.c index 2f139e073..b6167c067 100644 --- a/drivers/tps65950/tps65950.c +++ b/drivers/tps65950/tps65950.c @@ -28,11 +28,10 @@ static i2c_addr_t valid_addrs[2] = { static uint32_t bus; /* endpoint for the driver for the bus itself. */ -static endpoint_t bus_endpoint; +endpoint_t bus_endpoint; /* slave addresses of the device */ -#define NADDRESSES 4 -static i2c_addr_t addresses[NADDRESSES] = { +i2c_addr_t addresses[NADDRESSES] = { 0x48, 0x49, 0x4a, 0x4b }; @@ -49,123 +48,6 @@ static int sef_cb_init(int type, sef_init_info_t * info); static int fetch_t(endpoint_t ep, cp_grant_id_t gid, struct tm *t); static int store_t(endpoint_t ep, cp_grant_id_t gid, struct tm *t); -int -reg_read(uint8_t id, uint8_t reg, uint8_t * val) -{ - int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - if (id < 0 || id >= NADDRESSES) { - log_warn(&log, "id parameter out of range.\n"); - return EINVAL; - } - - if (val == NULL) { - log_warn(&log, "Read called with NULL pointer\n"); - return EINVAL; - } - - 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 = addresses[id]; - - /* write the register address */ - ioctl_exec.iie_cmd[0] = reg; - ioctl_exec.iie_cmdlen = 1; - - /* read 1 byte */ - ioctl_exec.iie_buflen = 1; - - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); - if (r != OK) { - log_warn(&log, "reg_read() failed (r=%d)\n", r); - return -1; - } - - *val = ioctl_exec.iie_buf[0]; - - log_trace(&log, "Read 0x%x from reg 0x%x", *val, reg); - - return OK; -} - -int -reg_write(uint8_t id, uint8_t reg, uint8_t val) -{ - int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - if (id < 0 || id >= NADDRESSES) { - log_warn(&log, "id parameter out of range.\n"); - return EINVAL; - } - - 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 = addresses[id]; - - /* 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) { - log_warn(&log, "reg_write() failed (r=%d)\n", r); - return -1; - } - - log_trace(&log, "Successfully wrote 0x%x to reg 0x%x\n", val, reg); - - return OK; -} - -int -reg_set(uint8_t id, uint8_t reg, uint8_t mask) -{ - int r; - uint8_t val; - - r = reg_read(id, reg, &val); - if (r != OK) { - return -1; - } - - val |= mask; - - r = reg_write(id, reg, val); - if (r != OK) { - return -1; - } - - return OK; -} - -int -reg_clear(uint8_t id, uint8_t reg, uint8_t mask) -{ - int r; - uint8_t val; - - r = reg_read(id, reg, &val); - if (r != OK) { - return -1; - } - - val &= ~mask; - - r = reg_write(id, reg, val); - if (r != OK) { - return -1; - } - - return OK; -} - static int fetch_t(endpoint_t ep, cp_grant_id_t gid, struct tm *t) { @@ -204,7 +86,8 @@ check_revision(void) uint8_t idcode_7_0, idcode_15_8, idcode_23_16, idcode_31_24; /* need to write a special code to unlock read protect on IDCODE */ - r = reg_write(ID2, UNLOCK_TEST_REG, UNLOCK_TEST_CODE); + r = i2creg_write8(bus_endpoint, addresses[ID2], UNLOCK_TEST_REG, + UNLOCK_TEST_CODE); if (r != OK) { log_warn(&log, "Failed to write unlock code to UNLOCK_TEST\n"); return -1; @@ -213,22 +96,26 @@ check_revision(void) /* * read each part of the IDCODE */ - r = reg_read(ID2, IDCODE_7_0_REG, &idcode_7_0); + r = i2creg_read8(bus_endpoint, addresses[ID2], IDCODE_7_0_REG, + &idcode_7_0); if (r != OK) { log_warn(&log, "Failed to read IDCODE part 1\n"); } - r = reg_read(ID2, IDCODE_15_8_REG, &idcode_15_8); + r = i2creg_read8(bus_endpoint, addresses[ID2], IDCODE_15_8_REG, + &idcode_15_8); if (r != OK) { log_warn(&log, "Failed to read IDCODE part 2\n"); } - r = reg_read(ID2, IDCODE_23_16_REG, &idcode_23_16); + r = i2creg_read8(bus_endpoint, addresses[ID2], IDCODE_23_16_REG, + &idcode_23_16); if (r != OK) { log_warn(&log, "Failed to read IDCODE part 3\n"); } - r = reg_read(ID2, IDCODE_31_24_REG, &idcode_31_24); + r = i2creg_read8(bus_endpoint, addresses[ID2], IDCODE_31_24_REG, + &idcode_31_24); if (r != OK) { log_warn(&log, "Failed to read IDCODE part 4\n"); } diff --git a/drivers/tps65950/tps65950.h b/drivers/tps65950/tps65950.h index 1508f898a..d410873ef 100644 --- a/drivers/tps65950/tps65950.h +++ b/drivers/tps65950/tps65950.h @@ -63,10 +63,9 @@ #define RTC_STATUS_REG 0x0000002A #define RUN_BIT 1 +#define NADDRESSES 4 -int reg_read(uint8_t id, uint8_t reg, uint8_t * val); -int reg_write(uint8_t id, uint8_t reg, uint8_t val); -int reg_set(uint8_t id, uint8_t reg, uint8_t mask); -int reg_clear(uint8_t id, uint8_t reg, uint8_t mask); +extern endpoint_t bus_endpoint; +extern i2c_addr_t addresses[NADDRESSES]; #endif /* __TPS65950_H */ diff --git a/drivers/tsl2550/tsl2550.c b/drivers/tsl2550/tsl2550.c index 06cc31d7c..f2ba424d1 100644 --- a/drivers/tsl2550/tsl2550.c +++ b/drivers/tsl2550/tsl2550.c @@ -59,10 +59,6 @@ static i2c_addr_t address; /* endpoint for the driver for the bus itself. */ static endpoint_t bus_endpoint; -/* register access functions */ -static int reg_read(uint8_t * val); -static int reg_write(uint8_t val); - /* main driver functions */ static int tsl2550_init(void); static int adc_read(int adc, uint8_t * val); @@ -216,7 +212,7 @@ adc_read(int adc, uint8_t * val) *val = (adc == 0) ? CMD_READ_ADC0 : CMD_READ_ADC1; /* Select the ADC to read from */ - r = reg_write(*val); + r = i2creg_raw_write8(bus_endpoint, address, *val); if (r != OK) { log_warn(&log, "Failed to write ADC read command.\n"); return -1; @@ -230,7 +226,7 @@ adc_read(int adc, uint8_t * val) */ spin_init(&spin, 400000); do { - r = reg_read(val); + r = i2creg_raw_read8(bus_endpoint, address, val); if (r != OK) { log_warn(&log, "Failed to read ADC%d value.\n", adc); return -1; @@ -247,7 +243,7 @@ adc_read(int adc, uint8_t * val) * before 400 ms) and left the loop. To ensure there is a final read * at or after the 400 ms mark, we try one last time here. */ - r = reg_read(val); + r = i2creg_raw_read8(bus_endpoint, address, val); if (r != OK) { log_warn(&log, "Failed to read ADC%d value.\n", adc); return -1; @@ -261,87 +257,6 @@ adc_read(int adc, uint8_t * val) } } -static int -reg_read(uint8_t * val) -{ - int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - if (val == NULL) { - log_warn(&log, "Read called with a NULL pointer.\n"); - return EINVAL; - } - - 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; - - /* No register address to write */ - ioctl_exec.iie_cmdlen = 0; - - /* Read one byte */ - ioctl_exec.iie_buflen = 1; - - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); - if (r != OK) { - log_warn(&log, "reg_read() failed (r=%d)\n", r); - return -1; - } - - *val = ioctl_exec.iie_buf[0]; - - log_trace(&log, "Read 0x%x from reg\n", *val); - - return OK; -} - -static int -reg_write(uint8_t val) -{ - int r; - minix_i2c_ioctl_exec_t ioctl_exec; - - switch (val) { - case CMD_PWR_DOWN: - case CMD_PWR_UP: - case CMD_EXT_RANGE: - case CMD_NORM_RANGE: - case CMD_READ_ADC0: - case CMD_READ_ADC1: - /* Command is valid */ - break; - default: - log_warn(&log, - "reg_write() called with invalid command 0x%x\n", val); - return EINVAL; - } - - 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; - - /* No command bytes for writing to this chip */ - ioctl_exec.iie_cmdlen = 0; - - /* Set the byte to write */ - ioctl_exec.iie_buf[0] = val; - ioctl_exec.iie_buflen = 1; - - r = i2cdriver_exec(bus_endpoint, &ioctl_exec); - if (r != OK) { - log_warn(&log, "reg_write() failed (r=%d)\n", r); - return -1; - } - - log_trace(&log, "Wrote 0x%x to reg\n", val); - - return OK; -} - static int tsl2550_init(void) { @@ -349,14 +264,14 @@ tsl2550_init(void) uint8_t val; /* Power on the device */ - r = reg_write(CMD_PWR_UP); + r = i2creg_raw_write8(bus_endpoint, address, CMD_PWR_UP); if (r != OK) { log_warn(&log, "Power-up command failed.\n"); return -1; } /* Read power on test value */ - r = reg_read(&val); + r = i2creg_raw_read8(bus_endpoint, address, &val); if (r != OK) { log_warn(&log, "Failed to read power on test value.\n"); return -1; @@ -370,7 +285,7 @@ tsl2550_init(void) } /* Set range to normal */ - r = reg_write(CMD_NORM_RANGE); + r = i2creg_raw_write8(bus_endpoint, address, CMD_NORM_RANGE); if (r != OK) { log_warn(&log, "Normal range command failed.\n"); return -1; diff --git a/include/minix/i2cdriver.h b/include/minix/i2cdriver.h index 3dd902cd7..778513fe2 100644 --- a/include/minix/i2cdriver.h +++ b/include/minix/i2cdriver.h @@ -18,4 +18,15 @@ void i2cdriver_handle_bus_update(endpoint_t * bus_endpoint, uint32_t bus, int i2cdriver_reserve_device(endpoint_t bus_endpoint, i2c_addr_t address); int i2cdriver_exec(endpoint_t bus_endpoint, minix_i2c_ioctl_exec_t *ioctl_exec); +int i2creg_raw_read8(endpoint_t bus, i2c_addr_t addr, uint8_t * val); +int i2creg_read8(endpoint_t bus, i2c_addr_t addr, uint8_t reg, uint8_t * val); +int i2creg_read16(endpoint_t bus, i2c_addr_t addr, uint8_t reg, uint16_t * val); +int i2creg_read24(endpoint_t bus, i2c_addr_t addr, uint8_t reg, uint32_t * val); +int i2creg_raw_write8(endpoint_t bus, i2c_addr_t addr, uint8_t val); +int i2creg_write8(endpoint_t bus, i2c_addr_t addr, uint8_t reg, uint8_t val); +int i2creg_set_bits8(endpoint_t bus, i2c_addr_t addr, uint8_t reg, + uint8_t bits); +int i2creg_clear_bits8(endpoint_t bus, i2c_addr_t addr, uint8_t reg, + uint8_t bits); + #endif /* _MINIX_I2CDRIVER_H */ diff --git a/lib/libi2cdriver/i2cdriver.c b/lib/libi2cdriver/i2cdriver.c index 755bd8a1f..1a73ba7ed 100644 --- a/lib/libi2cdriver/i2cdriver.c +++ b/lib/libi2cdriver/i2cdriver.c @@ -1,5 +1,6 @@ /* This file contains device independent i2c device driver helpers. */ +#include #include #include #include @@ -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; +} -- 2.44.0