static int print_status(void) { int value; print_temps("Local", TMP432_LOCAL, TMP432_LOCAL_THERM_LIMIT, TMP432_LOCAL_HIGH_LIMIT_R, TMP432_LOCAL_LOW_LIMIT_R); print_temps("Remote1", TMP432_REMOTE1, TMP432_REMOTE1_THERM_LIMIT, TMP432_REMOTE1_HIGH_LIMIT_R, TMP432_REMOTE1_LOW_LIMIT_R); print_temps("Remote2", TMP432_REMOTE2, TMP432_REMOTE2_THERM_LIMIT, TMP432_REMOTE2_HIGH_LIMIT_R, TMP432_REMOTE2_LOW_LIMIT_R); ccprintf("\n"); if (raw_read8(TMP432_STATUS, &value) == EC_SUCCESS) ccprintf("STATUS: %08b\n", value); if (raw_read8(TMP432_CONFIGURATION1_R, &value) == EC_SUCCESS) ccprintf("CONFIG1: %08b\n", value); if (raw_read8(TMP432_CONFIGURATION2_R, &value) == EC_SUCCESS) ccprintf("CONFIG2: %08b\n", value); return EC_SUCCESS; }
static int init(const struct motion_sensor_t *s) { int ret = 0, tmp; ret = raw_read8(s->addr, LSM6DS0_WHO_AM_I_REG, &tmp); if (ret) return EC_ERROR_UNKNOWN; if (tmp != LSM6DS0_WHO_AM_I) return EC_ERROR_ACCESS_DENIED; /* * This sensor can be powered through an EC reboot, so the state of * the sensor is unknown here. Initiate software reset to restore * sensor to default. * [6] BDU Enable Block Data Update. * [0] SW_RESET software reset * * lsm6ds0 supports both accel & gyro features * Board will see two virtual sensor devices: accel & gyro. * Requirement: Accel need be init before gyro. * SW_RESET is down for accel only! */ if (MOTIONSENSE_TYPE_ACCEL == s->type) { mutex_lock(s->mutex); ret = raw_read8(s->addr, LSM6DS0_CTRL_REG8, &tmp); if (ret) { mutex_unlock(s->mutex); return EC_ERROR_UNKNOWN; } tmp |= (1 | LSM6DS0_BDU_ENABLE); ret = raw_write8(s->addr, LSM6DS0_CTRL_REG8, tmp); mutex_unlock(s->mutex); if (ret) return EC_ERROR_UNKNOWN; /* Power Down Gyro */ ret = raw_write8(s->addr, LSM6DS0_CTRL_REG1_G, 0x0); if (ret) return EC_ERROR_UNKNOWN; ret = set_range(s, s->default_range, 1); if (ret) return EC_ERROR_UNKNOWN; } if (MOTIONSENSE_TYPE_GYRO == s->type) { /* Config GYRO Range */ ret = set_range(s, s->default_range, 1); if (ret) return EC_ERROR_UNKNOWN; } CPRINTF("[%T %s: MS Done Init type:0x%X range:%d]\n", s->name, s->type, get_range(s)); return ret; }
static int set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) { int ret, val, odr_tbl_size; uint8_t ctrl_reg, reg_val; const struct accel_param_pair *data_rates; struct lsm6ds0_data *data = s->drv_data; ctrl_reg = get_ctrl_reg(s->type); data_rates = get_odr_table(s->type, &odr_tbl_size); reg_val = get_reg_val(rate, rnd, data_rates, odr_tbl_size); /* * Lock accel resource to prevent another task from attempting * to write accel parameters until we are done. */ mutex_lock(s->mutex); ret = raw_read8(s->addr, ctrl_reg, &val); if (ret != EC_SUCCESS) goto accel_cleanup; val = (val & ~LSM6DS0_ODR_MASK) | reg_val; ret = raw_write8(s->addr, ctrl_reg, val); /* Now that we have set the odr, update the driver's value. */ if (ret == EC_SUCCESS) data->base.odr = get_engineering_val(reg_val, data_rates, odr_tbl_size); /* CTRL_REG3_G 12h * [7] low-power mode = 0; * [6] high pass filter disabled; * [5:4] 0 keep const 0 * [3:0] HPCF_G * Table 48 Gyroscope high-pass filter cutoff frequency */ if (MOTIONSENSE_TYPE_GYRO == s->type) { ret = raw_read8(s->addr, LSM6DS0_CTRL_REG3_G, &val); if (ret != EC_SUCCESS) goto accel_cleanup; val &= ~(0x3 << 4); /* clear bit [5:4] */ val = (rate > 119000) ? (val | (1<<7)) /* set high-power mode */ : (val & ~(1<<7)); /* set low-power mode */ ret = raw_write8(s->addr, LSM6DS0_CTRL_REG3_G, val); } accel_cleanup: mutex_unlock(s->mutex); return ret; }
/* helper function to operate on parameter values: op can be query/set/or/and */ static int si114x_param_op(const struct motion_sensor_t *s, uint8_t op, uint8_t param, int *value) { int ret; mutex_lock(s->mutex); if (op != SI114X_CMD_PARAM_QUERY) { ret = raw_write8(s->port, s->addr, SI114X_REG_PARAM_WR, *value); if (ret != EC_SUCCESS) goto error; } ret = raw_write8(s->port, s->addr, SI114X_REG_COMMAND, op | (param & 0x1F)); if (ret != EC_SUCCESS) goto error; ret = raw_read8(s->port, s->addr, SI114X_REG_PARAM_RD, value); if (ret != EC_SUCCESS) goto error; mutex_unlock(s->mutex); *value &= 0xff; return EC_SUCCESS; error: mutex_unlock(s->mutex); return ret; }
static int tmp432_shutdown(uint8_t want_shutdown) { int ret, value; if (want_shutdown == is_sensor_shutdown) return EC_SUCCESS; ret = raw_read8(TMP432_CONFIGURATION1_R, &value); if (ret < 0) { ccprintf("ERROR: Temp sensor I2C read8 error.\n"); return ret; } if (want_shutdown && !(value & TMP432_CONFIG1_RUN_L)) { /* tmp432 is running, and want it to shutdown */ /* CONFIG REG1 BIT6: 0=Run, 1=Shutdown */ /* shut it down */ value |= TMP432_CONFIG1_RUN_L; ret = raw_write8(TMP432_CONFIGURATION1_R, value); } else if (!want_shutdown && (value & TMP432_CONFIG1_RUN_L)) { /* tmp432 is shutdown, and want turn it on */ value &= ~TMP432_CONFIG1_RUN_L; ret = raw_write8(TMP432_CONFIGURATION1_R, value); } /* else, the current setting is exactly what you want */ is_sensor_shutdown = want_shutdown; return ret; }
int charger_device_id(int *id) { #ifdef CONFIG_CHARGER_BQ24770 return raw_read16(REG_DEVICE_ADDRESS, id); #elif defined(CONFIG_CHARGER_BQ24773) return raw_read8(REG_DEVICE_ADDRESS, id); #endif }
static int init(const struct motion_sensor_t *s) { int ret = 0, tmp; ret = raw_read8(s->port, s->addr, L3GD20_WHO_AM_I_REG, &tmp); if (ret) return EC_ERROR_UNKNOWN; if (tmp != L3GD20_WHO_AM_I) return EC_ERROR_ACCESS_DENIED; /* All axes are enabled */ ret = raw_write8(s->port, s->addr, L3GD20_CTRL_REG1, 0x0f); if (ret) return EC_ERROR_UNKNOWN; mutex_lock(s->mutex); ret = raw_read8(s->port, s->addr, L3GD20_CTRL_REG4, &tmp); if (ret) { mutex_unlock(s->mutex); return EC_ERROR_UNKNOWN; } tmp |= L3GD20_BDU_ENABLE; ret = raw_write8(s->port, s->addr, L3GD20_CTRL_REG4, tmp); mutex_unlock(s->mutex); if (ret) return EC_ERROR_UNKNOWN; /* Config GYRO ODR */ ret = set_data_rate(s, s->default_range, 1); if (ret) return EC_ERROR_UNKNOWN; /* Config GYRO Range */ ret = set_range(s, s->default_range, 1); if (ret) return EC_ERROR_UNKNOWN; CPRINTF("[%T %s: MS Done Init type:0x%X range:%d]\n", s->name, s->type, get_range(s)); return ret; }
/** * irq_handler - bottom half of the interrupt stack. * Ran from the motion_sense task, finds the events that raised the interrupt. * * For now, we just print out. We should set a bitmask motion sense code will * act upon. */ static int irq_handler(struct motion_sensor_t *s, uint32_t *event) { int ret = EC_SUCCESS, val; struct si114x_drv_data_t *data = SI114X_GET_DATA(s); struct si114x_typed_data_t *type_data = SI114X_GET_TYPED_DATA(s); if (!(*event & CONFIG_ALS_SI114X_INT_EVENT)) return EC_ERROR_NOT_HANDLED; ret = raw_read8(s->port, s->addr, SI114X_REG_IRQ_STATUS, &val); if (ret) return ret; if (!(val & type_data->irq_flags)) return EC_ERROR_INVAL; /* clearing IRQ */ ret = raw_write8(s->port, s->addr, SI114X_REG_IRQ_STATUS, val & type_data->irq_flags); if (ret != EC_SUCCESS) CPRINTS("clearing irq failed"); switch (data->state) { case SI114X_ALS_IN_PROGRESS: case SI114X_ALS_IN_PROGRESS_PS_PENDING: /* We are only reading the visible light sensor */ ret = si114x_read_results(s, 1); /* Fire pending requests */ if (data->state == SI114X_ALS_IN_PROGRESS_PS_PENDING) { ret = raw_write8(s->port, s->addr, SI114X_REG_COMMAND, SI114X_CMD_PS_FORCE); data->state = SI114X_PS_IN_PROGRESS; } else { data->state = SI114X_IDLE; } break; case SI114X_PS_IN_PROGRESS: case SI114X_PS_IN_PROGRESS_ALS_PENDING: /* Read PS results */ ret = si114x_read_results(s, SI114X_NUM_LEDS); if (data->state == SI114X_PS_IN_PROGRESS_ALS_PENDING) { ret = raw_write8(s->port, s->addr, SI114X_REG_COMMAND, SI114X_CMD_ALS_FORCE); data->state = SI114X_ALS_IN_PROGRESS; } else { data->state = SI114X_IDLE; } break; case SI114X_IDLE: default: CPRINTS("Invalid state"); } return ret; }
static int get_temp(const int offset, int *temp_ptr) { int rv; int temp_raw = 0; rv = raw_read8(offset, &temp_raw); if (rv < 0) return rv; *temp_ptr = (int)(int8_t)temp_raw; return EC_SUCCESS; }
static int si114x_revisions(const struct motion_sensor_t *s) { int val; int ret = raw_read8(s->port, s->addr, SI114X_REG_PART_ID, &val); if (ret != EC_SUCCESS) return ret; if (val != CONFIG_ALS_SI114X) { CPRINTS("invalid part"); return EC_ERROR_ACCESS_DENIED; } ret = raw_read8(s->port, s->port, s->addr, SI114X_REG_SEQ_ID, &val); if (ret != EC_SUCCESS) return ret; if (val < SI114X_SEQ_REV_A03) CPRINTS("WARNING: old sequencer revision"); return 0; }
static int command_tmp432(int argc, char **argv) { char *command; char *e; int data; int offset; int rv; if (!has_power()) { ccprintf("ERROR: Temp sensor not powered.\n"); return EC_ERROR_NOT_POWERED; } /* If no args just print status */ if (argc == 1) return print_status(); if (argc < 3) return EC_ERROR_PARAM_COUNT; command = argv[1]; offset = strtoi(argv[2], &e, 0); if (*e || offset < 0 || offset > 255) return EC_ERROR_PARAM2; if (!strcasecmp(command, "getbyte")) { rv = raw_read8(offset, &data); if (rv < 0) return rv; ccprintf("Byte at offset 0x%02x is %08b\n", offset, data); return rv; } /* Remaining commands are "tmp432 set-command offset data" */ if (argc != 4) return EC_ERROR_PARAM_COUNT; data = strtoi(argv[3], &e, 0); if (*e) return EC_ERROR_PARAM3; if (!strcasecmp(command, "settemp")) { ccprintf("Setting 0x%02x to %dC\n", offset, data); rv = tmp432_set_temp(offset, data); } else if (!strcasecmp(command, "setbyte")) { ccprintf("Setting 0x%02x to 0x%02x\n", offset, data); rv = raw_write8(offset, data); } else return EC_ERROR_PARAM1; return rv; }
static int is_data_ready(const struct motion_sensor_t *s, int *ready) { int ret, tmp; ret = raw_read8(s->port, s->addr, L3GD20_STATUS_REG, &tmp); if (ret != EC_SUCCESS) { CPRINTF("[%T %s type:0x%X RS Error]", s->name, s->type); return ret; } *ready = (tmp & L3GD20_STS_ZYXDA_MASK) ? 1 : 0; return EC_SUCCESS; }
static int tmp432_set_therm_mode(void) { int ret = 0; int data = 0; ret = raw_read8(TMP432_CONFIGURATION1_R, &data); if (ret) return EC_ERROR_UNKNOWN; data |= TMP432_CONFIG1_MODE; ret = raw_write8(TMP432_CONFIGURATION1_W, data); if (ret) return EC_ERROR_UNKNOWN; return EC_SUCCESS; }
static int is_data_ready(const struct motion_sensor_t *s, int *ready) { int ret, tmp; ret = raw_read8(s->addr, LSM6DS0_STATUS_REG, &tmp); if (ret != EC_SUCCESS) { CPRINTF("[%T %s type:0x%X RS Error]", s->name, s->type); return ret; } if (MOTIONSENSE_TYPE_ACCEL == s->type) *ready = (LSM6DS0_STS_XLDA_UP == (tmp & LSM6DS0_STS_XLDA_MASK)); else *ready = (LSM6DS0_STS_GDA_UP == (tmp & LSM6DS0_STS_GDA_MASK)); return EC_SUCCESS; }
int charger_get_input_current(int *input_current) { int rv; int reg; #ifdef CONFIG_CHARGER_BQ24770 rv = raw_read16(REG_INPUT_CURRENT, ®); #elif defined(CONFIG_CHARGER_BQ24773) rv = raw_read8(REG_INPUT_CURRENT, ®); #endif if (rv) return rv; #ifdef CONFIG_CHARGER_BQ24770 *input_current = REG_TO_CURRENT(reg, R_AC); #elif defined(CONFIG_CHARGER_BQ24773) *input_current = REG8_TO_CURRENT(reg, R_AC); #endif return EC_SUCCESS; }
static int set_range(const struct motion_sensor_t *s, int range, int rnd) { int ret, ctrl_val, range_tbl_size; uint8_t ctrl_reg, reg_val; const struct accel_param_pair *ranges; struct lsm6ds0_data *data = s->drv_data; ctrl_reg = get_ctrl_reg(s->type); ranges = get_range_table(s->type, &range_tbl_size); reg_val = get_reg_val(range, rnd, ranges, range_tbl_size); /* * Lock accel resource to prevent another task from attempting * to write accel parameters until we are done. */ mutex_lock(s->mutex); ret = raw_read8(s->addr, ctrl_reg, &ctrl_val); if (ret != EC_SUCCESS) goto accel_cleanup; ctrl_val = (ctrl_val & ~LSM6DS0_RANGE_MASK) | reg_val; ret = raw_write8(s->addr, ctrl_reg, ctrl_val); /* Now that we have set the range, update the driver's value. */ if (ret == EC_SUCCESS) data->base.range = get_engineering_val(reg_val, ranges, range_tbl_size); accel_cleanup: mutex_unlock(s->mutex); return ret; }
static int set_range(const struct motion_sensor_t *s, int range, int rnd) { int ret, ctrl_val, range_tbl_size; uint8_t ctrl_reg, reg_val; const struct gyro_param_pair *ranges; struct l3gd20_data *data = (struct l3gd20_data *)s->drv_data; ctrl_reg = L3GD20_CTRL_REG4; ranges = get_range_table(s->type, &range_tbl_size); reg_val = get_reg_val(range, rnd, ranges, range_tbl_size); /* * Lock Gyro resource to prevent another task from attempting * to write Gyro parameters until we are done. */ mutex_lock(s->mutex); ret = raw_read8(s->port, s->addr, ctrl_reg, &ctrl_val); if (ret != EC_SUCCESS) goto gyro_cleanup; ctrl_val = (ctrl_val & ~L3GD20_RANGE_MASK) | reg_val; ret = raw_write8(s->port, s->addr, ctrl_reg, ctrl_val); /* Now that we have set the range, update the driver's value. */ if (ret == EC_SUCCESS) data->base.range = get_engineering_val(reg_val, ranges, range_tbl_size); gyro_cleanup: mutex_unlock(s->mutex); return EC_SUCCESS; }
static int command_tmp432(int argc, char **argv) { char *command; char *e; char *power; int data; int offset; int rv; /* handle "power" command before checking the power status. */ if ((argc == 3) && !strcasecmp(argv[1], "power")) { power = argv[2]; if (!strncasecmp(power, "on", sizeof("on"))) { rv = tmp432_set_power(TMP432_POWER_ON); if (!rv) print_status(); } else if (!strncasecmp(power, "off", sizeof("off"))) rv = tmp432_set_power(TMP432_POWER_OFF); else return EC_ERROR_PARAM2; ccprintf("Set TMP432 %s\n", power); return rv; } if (!has_power()) { ccprintf("ERROR: Temp sensor not powered.\n"); return EC_ERROR_NOT_POWERED; } /* If no args just print status */ if (argc == 1) return print_status(); if (argc < 3) return EC_ERROR_PARAM_COUNT; command = argv[1]; offset = strtoi(argv[2], &e, 0); if (*e || offset < 0 || offset > 255) return EC_ERROR_PARAM2; if (!strcasecmp(command, "getbyte")) { rv = raw_read8(offset, &data); if (rv < 0) return rv; ccprintf("Byte at offset 0x%02x is %08b\n", offset, data); return rv; } /* Remaining commands are "tmp432 set-command offset data" */ if (argc != 4) return EC_ERROR_PARAM_COUNT; data = strtoi(argv[3], &e, 0); if (*e) return EC_ERROR_PARAM3; if (!strcasecmp(command, "settemp")) { ccprintf("Setting 0x%02x to %dC\n", offset, data); rv = tmp432_set_temp(offset, data); } else if (!strcasecmp(command, "setbyte")) { ccprintf("Setting 0x%02x to 0x%02x\n", offset, data); rv = raw_write8(offset, data); } else return EC_ERROR_PARAM1; return rv; }
static int set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) { int ret, val, odr_tbl_size; uint8_t ctrl_reg, reg_val; const struct gyro_param_pair *data_rates; struct l3gd20_data *data = s->drv_data; ctrl_reg = get_ctrl_reg(s->type); data_rates = get_odr_table(s->type, &odr_tbl_size); reg_val = get_reg_val(rate, rnd, data_rates, odr_tbl_size); /* * Lock gyro resource to prevent another task from attempting * to write gyro parameters until we are done. */ mutex_lock(s->mutex); ret = raw_read8(s->port, s->addr, ctrl_reg, &val); if (ret != EC_SUCCESS) goto gyro_cleanup; val = (val & ~(L3GD20_ODR_MASK | L3GD20_ODR_PD_MASK)) | (reg_val & ~L3GD20_LOW_ODR_MASK); ret = raw_write8(s->port, s->addr, ctrl_reg, val); /* Now that we have set the odr, update the driver's value. */ if (ret == EC_SUCCESS) data->base.odr = get_engineering_val(reg_val, data_rates, odr_tbl_size); ret = raw_read8(s->port, s->addr, L3GD20_LOW_ODR, &val); if (ret != EC_SUCCESS) goto gyro_cleanup; /* We need to clear low_ODR bit for higher data rates */ if (reg_val & L3GD20_LOW_ODR_MASK) val |= 1; else val &= ~1; ret = raw_write8(s->port, s->addr, L3GD20_LOW_ODR, val); if (ret != EC_SUCCESS) goto gyro_cleanup; /* CTRL_REG5 24h * [7] low-power mode = 0; * [6] fifo disabled = 0; * [5] Stop on fth = 0; * [4] High pass filter enable = 1; * [3:2] int1_sel = 0; * [1:0] out_sel = 1; */ ret = raw_read8(s->port, s->addr, L3GD20_CTRL_REG5, &val); if (ret != EC_SUCCESS) goto gyro_cleanup; val |= (1 << 4); /* high-pass filter enabled */ val |= (1 << 0); /* data in data reg are high-pass filtered */ ret = raw_write8(s->port, s->addr, L3GD20_CTRL_REG5, val); if (ret != EC_SUCCESS) goto gyro_cleanup; ret = raw_read8(s->port, s->addr, L3GD20_CTRL_REG2, &val); if (ret != EC_SUCCESS) goto gyro_cleanup; /* * Table 25. High pass filter mode configuration * Table 26. High pass filter cut off frequency configuration */ val &= 0xf0; val |= 0x04; ret = raw_write8(s->port, s->addr, L3GD20_CTRL_REG2, val); gyro_cleanup: mutex_unlock(s->mutex); return ret; }
/* Get temperature from requested sensor */ int bd99992gw_get_val(int idx, int *temp_ptr) { uint16_t adc; int i, read, ret; enum bd99992gw_adc_channel channel; /* ADC unit is only functional in S0 */ if (!chipset_in_state(CHIPSET_STATE_ON)) return EC_ERROR_NOT_POWERED; /* Find requested channel */ for (i = 0; i < ARRAY_SIZE(active_channels); ++i) { channel = active_channels[i]; if (channel == idx || channel == BD99992GW_ADC_CHANNEL_NONE) break; } /* Make sure we found it */ if (i == ARRAY_SIZE(active_channels) || active_channels[i] != idx) { CPRINTS("Bad ADC channel %d\n", idx); return EC_ERROR_INVAL; } /* Pause conversions */ ret = raw_write8(0x80, ADC_LOOP_PERIOD | BD99992GW_ADC1CNTL1_ADEN | BD99992GW_ADC1CNTL1_ADSTRT | BD99992GW_ADC1CNTL1_ADPAUSE); if (ret) return ret; /* Read 10-bit ADC result */ ret = raw_read8(BD99992GW_REG_ADC1DATA0L + 2 * i, &read); if (ret) return ret; adc = read; ret = raw_read8(BD99992GW_REG_ADC1DATA0H + 2 * i, &read); if (ret) return ret; adc |= read << 2; /* Convert temperature to C / K */ *temp_ptr = C_TO_K(bd99992gw_get_temp(adc)); /* Clear interrupts */ ret = raw_write8(BD99992GW_REG_ADC1INT, BD99992GW_ADC1INT_RND); if (ret) return ret; ret = raw_write8(BD99992GW_REG_IRQLVL1, BD99992GW_IRQLVL1_ADC); if (ret) return ret; /* Resume conversions */ ret = raw_write8(BD99992GW_REG_ADC1CNTL1, ADC_LOOP_PERIOD | BD99992GW_ADC1CNTL1_ADEN | BD99992GW_ADC1CNTL1_ADSTRT); if (ret) return ret; return EC_SUCCESS; }
/* Just trigger a measurement */ static int read(const struct motion_sensor_t *s, vector_3_t v) { int ret = 0; uint8_t cmd; struct si114x_drv_data_t *data = SI114X_GET_DATA(s); switch (data->state) { case SI114X_ALS_IN_PROGRESS: if (s->type == MOTIONSENSE_TYPE_PROX) data->state = SI114X_ALS_IN_PROGRESS_PS_PENDING; #if 0 else CPRINTS("Invalid state"); #endif ret = EC_ERROR_BUSY; break; case SI114X_PS_IN_PROGRESS: if (s->type == MOTIONSENSE_TYPE_LIGHT) data->state = SI114X_PS_IN_PROGRESS_ALS_PENDING; #if 0 else CPRINTS("Invalid state"); #endif ret = EC_ERROR_BUSY; break; case SI114X_IDLE: switch (s->type) { case MOTIONSENSE_TYPE_LIGHT: cmd = SI114X_CMD_ALS_FORCE; data->state = SI114X_ALS_IN_PROGRESS; break; case MOTIONSENSE_TYPE_PROX: cmd = SI114X_CMD_PS_FORCE; data->state = SI114X_PS_IN_PROGRESS; break; default: CPRINTS("Invalid sensor type"); return EC_ERROR_INVAL; } ret = raw_write8(s->port, s->addr, SI114X_REG_COMMAND, cmd); ret = EC_RES_IN_PROGRESS; break; case SI114X_ALS_IN_PROGRESS_PS_PENDING: case SI114X_PS_IN_PROGRESS_ALS_PENDING: ret = EC_ERROR_ACCESS_DENIED; break; case SI114X_NOT_READY: ret = EC_ERROR_NOT_POWERED; } if (ret == EC_ERROR_ACCESS_DENIED && s->type == MOTIONSENSE_TYPE_LIGHT) { timestamp_t ts_now = get_time(); /* * We were unable to access the sensor for THRES time. * We should reset the sensor to clear the interrupt register * and the state machine. */ if (time_after(ts_now.le.lo, s->last_collection + SI114X_DENIED_THRESHOLD)) { int ret, val; ret = raw_read8(s->port, s->addr, SI114X_REG_IRQ_STATUS, &val); CPRINTS("%d stuck IRQ_STATUS 0x%02x - ret %d", s->name, val, ret); init(s); } } return ret; }