int tcpm_transmit(int port, enum tcpm_transmit_type type, uint16_t header, const uint32_t *data) { int reg = TCPC_REG_TX_DATA; int rv, cnt = 4*PD_HEADER_CNT(header); rv = i2c_write8(I2C_PORT_TCPC, I2C_ADDR_TCPC(port), TCPC_REG_TX_BYTE_CNT, cnt); rv |= i2c_write16(I2C_PORT_TCPC, I2C_ADDR_TCPC(port), TCPC_REG_TX_HDR, header); /* If i2c read fails, return error */ if (rv) return rv; if (cnt > 0) { i2c_lock(I2C_PORT_TCPC, 1); rv = i2c_xfer(I2C_PORT_TCPC, I2C_ADDR_TCPC(port), (uint8_t *)®, 1, NULL, 0, I2C_XFER_START); rv |= i2c_xfer(I2C_PORT_TCPC, I2C_ADDR_TCPC(port), (uint8_t *)data, cnt, NULL, 0, I2C_XFER_STOP); i2c_lock(I2C_PORT_TCPC, 0); } /* If i2c read fails, return error */ if (rv) return rv; rv = i2c_write8(I2C_PORT_TCPC, I2C_ADDR_TCPC(port), TCPC_REG_TRANSMIT, TCPC_REG_TRANSMIT_SET(type)); return rv; }
int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data, int len) { int rv; uint8_t reg, block_length; /* * TODO(crosbug.com/p/23569): when i2c_xfer() supports start/stop bits, * merge this with the LM4 implementation and move to i2c_common.c. */ if ((len <= 0) || (len > SMBUS_MAX_BLOCK)) return EC_ERROR_INVAL; i2c_lock(port, 1); /* Read the counted string into the output buffer */ reg = offset; rv = i2c_xfer(port, slave_addr, ®, 1, data, len, I2C_XFER_SINGLE); if (rv == EC_SUCCESS) { /* Block length is the first byte of the returned buffer */ block_length = MIN(data[0], len - 1); /* Move data down, then null-terminate it */ memmove(data, data + 1, block_length); data[block_length] = 0; } i2c_lock(port, 0); return rv; }
/* Come out of standby mode. */ void lb_on(void) { CPRINTS("LB_on"); i2c_lock(I2C_PORT_LIGHTBAR, 1); controller_write(0, 0x01, 0x20); controller_write(1, 0x01, 0x20); i2c_lock(I2C_PORT_LIGHTBAR, 0); }
/* Helper function to set one LED color and remember it for later */ static void setrgb(int led, int red, int green, int blue) { int ctrl, bank; current[led][0] = red; current[led][1] = green; current[led][2] = blue; ctrl = led_to_ctrl[led]; bank = led_to_isc[led]; i2c_lock(I2C_PORT_LIGHTBAR, 1); controller_write(ctrl, bank, scale(blue, MAX_BLUE)); controller_write(ctrl, bank+1, scale(red, MAX_RED)); controller_write(ctrl, bank+2, scale(green, MAX_GREEN)); i2c_lock(I2C_PORT_LIGHTBAR, 0); }
static int read(const struct motion_sensor_t *s, vector_3_t v) { uint8_t raw[6]; uint8_t xyz_reg; int ret, range, i, tmp = 0; struct l3gd20_data *data = s->drv_data; ret = is_data_ready(s, &tmp); if (ret != EC_SUCCESS) return ret; /* * If sensor data is not ready, return the previous read data. * Note: return success so that motion senor task can read again * to get the latest updated sensor data quickly. */ if (!tmp) { if (v != s->raw_xyz) memcpy(v, s->raw_xyz, sizeof(s->raw_xyz)); return EC_SUCCESS; } xyz_reg = get_xyz_reg(s->type); /* Read 6 bytes starting at xyz_reg */ i2c_lock(s->port, 1); ret = i2c_xfer(s->port, s->addr, &xyz_reg, 1, raw, 6, I2C_XFER_SINGLE); i2c_lock(s->port, 0); if (ret != EC_SUCCESS) { CPRINTF("[%T %s type:0x%X RD XYZ Error]", s->name, s->type); return ret; } for (i = X; i <= Z; i++) v[i] = ((int16_t)((raw[i * 2 + 1] << 8) | raw[i * 2])); if (s->rot_standard_ref) rotate(v, *s->rot_standard_ref, v); /* apply offset in the device coordinates */ range = get_range(s); for (i = X; i <= Z; i++) v[i] += (data->offset[i] << 5) / range; return EC_SUCCESS; }
static int elan_tp_read_cmd(uint16_t reg, uint16_t *val) { uint8_t buf[2]; int rv; buf[0] = reg; buf[1] = reg >> 8; i2c_lock(CONFIG_TOUCHPAD_I2C_PORT, 1); rv = i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, CONFIG_TOUCHPAD_I2C_ADDR, buf, sizeof(buf), (uint8_t *)val, sizeof(*val), I2C_XFER_SINGLE); i2c_lock(CONFIG_TOUCHPAD_I2C_PORT, 0); return rv; }
static void update(struct sensor *sensor) { if (!i2c_lock()) { struct state *state = (struct state *) sensor; uint8_t cmd[4]; int r = 0; int v; cmd[0] = state->level ? CMD_SAMP_HIRES2 : CMD_SAMP_LORES; r = i2c_write(state->slave, cmd, 1); if (!r) { i2c_sleep(state->level ? SPEED_HIRES2 : SPEED_LORES); r = i2c_read(state->slave, cmd, 2); } if (!r) { v = (cmd[0] << 8) | cmd[1]; // Scale is 0.1 but we need to convert to the correct value // So datasheet says / 1.2 but we use 0.12 as thats 10/1.2 giving // us the correct unit v = (int) ((double) v / 0.12); } // log the value if (!r) { sensor_log(sensor, v, "%s %.1f", state->format, ((double) v) * UNIT); } i2c_unlock(); } }
static int elan_tp_write_cmd(uint16_t reg, uint16_t val) { uint8_t buf[4]; int rv; buf[0] = reg; buf[1] = reg >> 8; buf[2] = val; buf[3] = val >> 8; i2c_lock(CONFIG_TOUCHPAD_I2C_PORT, 1); rv = i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, CONFIG_TOUCHPAD_I2C_ADDR, buf, sizeof(buf), NULL, 0, I2C_XFER_SINGLE); i2c_lock(CONFIG_TOUCHPAD_I2C_PORT, 0); return rv; }
/* Helper for host command to dump controller registers */ void lb_hc_cmd_dump(struct ec_response_lightbar *out) { int i; uint8_t reg; BUILD_ASSERT(ARRAY_SIZE(dump_reglist) == ARRAY_SIZE(out->dump.vals)); for (i = 0; i < ARRAY_SIZE(dump_reglist); i++) { reg = dump_reglist[i]; out->dump.vals[i].reg = reg; i2c_lock(I2C_PORT_LIGHTBAR, 1); out->dump.vals[i].ic0 = controller_read(0, reg); out->dump.vals[i].ic1 = controller_read(1, reg); i2c_lock(I2C_PORT_LIGHTBAR, 0); } }
/* Initialize the controller ICs after reset */ void lb_init(int use_lock) { int i; CPRINTF("[%T LB_init_vals "); for (i = 0; i < ARRAY_SIZE(init_vals); i++) { CPRINTF("%c", '0' + i % 10); if (use_lock) i2c_lock(I2C_PORT_LIGHTBAR, 1); controller_write(0, init_vals[i].reg, init_vals[i].val); controller_write(1, init_vals[i].reg, init_vals[i].val); if (use_lock) i2c_lock(I2C_PORT_LIGHTBAR, 0); } CPRINTF("]\n"); memset(current, 0, sizeof(current)); }
int board_cut_off_battery(void) { int rv; uint8_t buf[3]; buf[0] = SB_MANUFACTURER_ACCESS & 0xff; buf[1] = PARAM_CUT_OFF_LOW; buf[2] = PARAM_CUT_OFF_HIGH; i2c_lock(I2C_PORT_BATTERY, 1); rv = i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR, buf, 3, NULL, 0, I2C_XFER_SINGLE); rv |= i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR, buf, 3, NULL, 0, I2C_XFER_SINGLE); i2c_lock(I2C_PORT_BATTERY, 0); return rv; }
static void i2c_pre_freq_change_hook(void) { const struct i2c_port_t *p = i2c_ports; int i; /* Lock I2C ports so freq change can't interrupt an I2C transaction */ for (i = 0; i < i2c_ports_used; i++, p++) i2c_lock(p->port, 1); }
static int cutoff(void) { int rv; uint8_t buf[3]; /* Ship mode command must be sent twice to take effect */ buf[0] = SB_MANUFACTURER_ACCESS & 0xff; buf[1] = PARAM_CUT_OFF_LOW; buf[2] = PARAM_CUT_OFF_HIGH; i2c_lock(I2C_PORT_BATTERY, 1); rv = i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR, buf, 3, NULL, 0, I2C_XFER_SINGLE); rv |= i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR, buf, 3, NULL, 0, I2C_XFER_SINGLE); i2c_lock(I2C_PORT_BATTERY, 0); return rv; }
static void i2c_freq_change_hook(void) { const struct i2c_port_t *p = i2c_ports; int i; i2c_freq_change(); /* Unlock I2C ports we locked in pre-freq change hook */ for (i = 0; i < i2c_ports_used; i++, p++) i2c_lock(p->port, 0); }
int i2c_read16(int port, int slave_addr, int offset, int *data) { int rv; uint8_t reg, buf[2]; reg = offset & 0xff; /* I2C read 16-bit word: transmit 8-bit offset, and read 16bits */ i2c_lock(port, 1); rv = i2c_xfer(port, slave_addr, ®, 1, buf, 2, I2C_XFER_SINGLE); i2c_lock(port, 0); if (rv) return rv; if (slave_addr & I2C_FLAG_BIG_ENDIAN) *data = ((int)buf[0] << 8) | buf[1]; else *data = ((int)buf[1] << 8) | buf[0]; return EC_SUCCESS; }
int pcf50605_write_multiple(int address, const unsigned char* buf, int count) { int i; i2c_lock(); for (i = 0; i < count; i++) pp_i2c_send(0x8, address + i, buf[i]); i2c_unlock(); return 0; }
void GSensor_I2C_WriteReg(UINT32 uiAddr, UINT32 uiValue) { UINT erReturn; UINT32 ulWriteAddr, ulReg1, ulData; UINT32 ulReg2 = 0; i2c_lock(g_GsensorInfo.I2C_Channel); ulWriteAddr = g_GsensorInfo.I2C_Slave_WAddr; if (g_GsensorInfo.I2C_RegBytes == GSENSOR_I2C_REGISTER_2BYTE) { ulReg1 = (uiAddr>>8); ulReg2 = ((uiAddr)&(0x000000ff)); } else {
int tcpm_get_message(int port, uint32_t *payload, int *head) { int rv, cnt, reg = TCPC_REG_RX_DATA; rv = i2c_read8(I2C_PORT_TCPC, I2C_ADDR_TCPC(port), TCPC_REG_RX_BYTE_CNT, &cnt); rv |= i2c_read16(I2C_PORT_TCPC, I2C_ADDR_TCPC(port), TCPC_REG_RX_HDR, (int *)head); if (rv == EC_SUCCESS && cnt > 0) { i2c_lock(I2C_PORT_TCPC, 1); rv = i2c_xfer(I2C_PORT_TCPC, I2C_ADDR_TCPC(port), (uint8_t *)®, 1, (uint8_t *)payload, cnt, I2C_XFER_SINGLE); i2c_lock(I2C_PORT_TCPC, 0); } /* Read complete, clear RX status alert bit */ i2c_write16(I2C_PORT_TCPC, I2C_ADDR_TCPC(port), TCPC_REG_ALERT, TCPC_REG_ALERT_RX_STATUS); return rv; }
RET_CODE i2c_raw_stop(i2c_bus_t *p_dev) { RET_CODE ret = ERR_NOFEATURE; lld_i2c_t *p_lld = (lld_i2c_t *)p_dev->p_priv; device_base_t *p_base = (device_base_t *)p_dev->p_base; if(drv_check_cond(p_dev) == SUCCESS) { MT_ASSERT(p_lld->std_read != NULL); i2c_lock(p_base); ret = p_lld->raw_stop(p_lld); i2c_unlock(p_base); } return ret; }
RET_CODE i2c_read(i2c_bus_t *p_dev, u8 slv_addr, u8 *p_buf, u32 len, u32 param) { RET_CODE ret = ERR_NOFEATURE; lld_i2c_t *p_lld = (lld_i2c_t *)p_dev->p_priv; device_base_t *p_base = (device_base_t *)p_dev->p_base; if(drv_check_cond(p_dev) == SUCCESS) { MT_ASSERT(p_lld->read != NULL); i2c_lock(p_base); ret = p_lld->read(p_lld, slv_addr, p_buf, len, param); i2c_unlock(p_base); } return ret; }
/* Initialize the controller ICs after reset */ static int elan_tp_init(void) { int rv; uint8_t val[2]; CPRINTS("%s", __func__); elan_tp_write_cmd(ETP_I2C_STAND_CMD, ETP_I2C_RESET); msleep(100); i2c_lock(CONFIG_TOUCHPAD_I2C_PORT, 1); rv = i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, CONFIG_TOUCHPAD_I2C_ADDR, NULL, 0, val, sizeof(val), I2C_XFER_SINGLE); i2c_lock(CONFIG_TOUCHPAD_I2C_PORT, 0); CPRINTS("reset rv %d buf=%04x", rv, *((uint16_t *)val)); if (rv) goto out; /* Read min/max */ rv = elan_tp_read_cmd(ETP_I2C_MAX_X_AXIS_CMD, &elan_tp_params.max_x); if (rv) goto out; rv = elan_tp_read_cmd(ETP_I2C_MAX_Y_AXIS_CMD, &elan_tp_params.max_y); if (rv) goto out; /* Read min/max */ rv = elan_tp_read_cmd(ETP_I2C_XY_TRACENUM_CMD, (uint16_t *)val); if (rv) goto out; if (val[0] == 0 || val[1] == 0) { CPRINTS("Invalid XY_TRACENUM"); goto out; } /* ETP_FWIDTH_REDUCE reduces the apparent width to avoid treating large * finger as palm. Multiply value by 2 as HID multitouch divides it. */ elan_tp_params.width_x = 2 * ((elan_tp_params.max_x / val[0]) - ETP_FWIDTH_REDUCE); elan_tp_params.width_y = 2 * ((elan_tp_params.max_y / val[1]) - ETP_FWIDTH_REDUCE); rv = elan_tp_read_cmd(ETP_I2C_PRESSURE_CMD, (uint16_t *)val); if (rv) goto out; elan_tp_params.pressure_adj = (val[0] & 0x10) ? 0 : ETP_PRESSURE_OFFSET; CPRINTS("max=%d/%d width=%d/%d adj=%d", elan_tp_params.max_x, elan_tp_params.max_y, elan_tp_params.width_x, elan_tp_params.width_y, elan_tp_params.pressure_adj); /* Switch to absolute mode */ rv = elan_tp_write_cmd(ETP_I2C_SET_CMD, ETP_ENABLE_ABS); if (rv) goto out; /* Sleep control off */ rv = elan_tp_write_cmd(ETP_I2C_STAND_CMD, ETP_I2C_WAKE_UP); out: CPRINTS("%s:%d", __func__, rv); return rv; }
/* Helper for host command to write controller registers directly */ void lb_hc_cmd_reg(const struct ec_params_lightbar *in) { i2c_lock(I2C_PORT_LIGHTBAR, 1); controller_write(in->reg.ctrl, in->reg.reg, in->reg.value); i2c_lock(I2C_PORT_LIGHTBAR, 0); }
static UINT32 GSensor_DA380_ReadReg_2Byte(UINT32 uiAddr, UINT32 uidata) { UINT32 ulWriteAddr, ulReadAddr, ulReg1; static UINT32 ulData1,ulData2; ulWriteAddr =0x30; ulReadAddr =0x31; ulReg1 =(uiAddr&0x000000ff); ulData1 = 0; ulData2 = 0; //debug_err((">>> read register\r\n")); if(i2c_lock(g_GsensorInfo.I2C_Channel) != E_OK) { debug_err(("GSensor: readReg I2C Lock Fail\r\n")); return ulData1; } if (GSensor_I2C_Transmit(ulWriteAddr, 1, 0) != I2C_STS_OK) { debug_err(("Error transmit data1!!\r\n")); i2c_unlock(g_GsensorInfo.I2C_Channel); return ulData1; } if (GSensor_I2C_Transmit(ulReg1, 0, 0) != I2C_STS_OK) { debug_err(("Error transmit data2!!\r\n")); i2c_unlock(g_GsensorInfo.I2C_Channel); return ulData1; } if (GSensor_I2C_Transmit(ulReadAddr, 1, 0) != I2C_STS_OK) { debug_err(("Error transmit data3!!\r\n")); i2c_unlock(g_GsensorInfo.I2C_Channel); return ulData1; } if (GSensor_I2C_Receive(&ulData1, 0, 0) != I2C_STS_OK) { debug_err(("Error Receive data!!\r\n")); i2c_unlock(g_GsensorInfo.I2C_Channel); return ulData1; } if (GSensor_I2C_Receive(&ulData2, 1, 1) != I2C_STS_OK) { debug_err(("Error Receive data!!\r\n")); i2c_unlock(g_GsensorInfo.I2C_Channel); return ulData1; } if(i2c_unlock(g_GsensorInfo.I2C_Channel) != E_OK) { debug_err(("GSensor: readReg I2C UnLock Fail\r\n")); return ulData1; } // debug_err((">>>>>uidata = %d %d\r\n",ulData1,ulData2)); uidata = (ulData1<<8) + ulData2; //debug_err((">>>uidata = %d\r\n",uidata)); return uidata; }
static int elan_tp_read_report(void) { int rv; uint8_t tp_buf[ETP_I2C_REPORT_LEN]; int i; uint8_t touch_info; uint8_t hover_info; uint8_t *finger = tp_buf+ETP_FINGER_DATA_OFFSET; i2c_lock(CONFIG_TOUCHPAD_I2C_PORT, 1); rv = i2c_xfer(CONFIG_TOUCHPAD_I2C_PORT, CONFIG_TOUCHPAD_I2C_ADDR, NULL, 0, tp_buf, ETP_I2C_REPORT_LEN, I2C_XFER_SINGLE); i2c_lock(CONFIG_TOUCHPAD_I2C_PORT, 0); if (rv) { CPRINTS("read report error"); return rv; } CPRINTF("[%T "); #if 0 for (i = 0; i < ETP_I2C_REPORT_LEN; i++) CPRINTF("%02x", tp_buf[i]); CPRINTF(" || "); #endif if (tp_buf[ETP_REPORT_ID_OFFSET] != ETP_REPORT_ID) { CPRINTS("Invalid report id (%x)", tp_buf[ETP_REPORT_ID_OFFSET]); return -1; } touch_info = tp_buf[ETP_TOUCH_INFO_OFFSET]; hover_info = tp_buf[ETP_HOVER_INFO_OFFSET]; if (touch_info & 0x01) CPRINTF("click|"); if (hover_info & 0x40) CPRINTF("hover|"); for (i = 0; i < ETP_MAX_FINGERS; i++) { int valid = touch_info & (1 << (3+i)); if (valid) { int x = ((finger[0] & 0xf0) << 4) | finger[1]; int y = ((finger[0] & 0x0f) << 8) | finger[2]; int width = (finger[3] & 0xf0) >> 4; int height = finger[3] & 0x0f; int pressure = finger[4]; y = elan_tp_params.max_y - y; width = width * elan_tp_params.width_x; height = height * elan_tp_params.width_y; pressure = pressure + elan_tp_params.pressure_adj; if (1) CPRINTF("i=%d %d/%d %d/%d %d|", i, x, y, width, height, pressure); finger += ETP_FINGER_DATA_LEN; } } CPRINTF("]\n"); return 0; }