/* 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; }
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; }
/** * 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 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; }
static int tmp432_set_temp(const int offset, int temp) { if (temp < -127 || temp > 127) return EC_ERROR_INVAL; return raw_write8(offset, (uint8_t)temp); }
int charger_set_input_current(int input_current) { #ifdef CONFIG_CHARGER_BQ24770 return raw_write16(REG_INPUT_CURRENT, CURRENT_TO_REG(input_current, R_AC)); #elif defined(CONFIG_CHARGER_BQ24773) return raw_write8(REG_INPUT_CURRENT, CURRENT_TO_REG8(input_current, R_AC)); #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; }
static void bd99992gw_init(void) { int i; int active_channel_count = 0; uint8_t pointer_reg = BD99992GW_REG_ADC1ADDR0; /* Mark active channels from the board temp sensor table */ for (i = 0; i < TEMP_SENSOR_COUNT; ++i) if (temp_sensors[i].read == bd99992gw_get_val) active_channels[active_channel_count++] = temp_sensors[i].idx; /* Make sure we don't have too many active channels. */ ASSERT(active_channel_count <= ARRAY_SIZE(active_channels)); /* Mark the first unused channel so we know where to stop searching */ if (active_channel_count != ARRAY_SIZE(active_channels)) active_channels[active_channel_count] = BD99992GW_ADC_CHANNEL_NONE; /* Now write pointer regs with channel to monitor */ for (i = 0; i < active_channel_count; ++i) /* Write stop bit on last channel */ if (raw_write8(pointer_reg + i, active_channels[i] | ((i == active_channel_count - 1) ? BD99992GW_ADC1ADDR_STOP : 0))) return; /* Enable ADC interrupts */ if (raw_write8(BD99992GW_REG_MADC1INT, 0xf & ~BD99992GW_MADC1INT_RND)) return; if (raw_write8(BD99992GW_REG_IRQLVL1MSK, BD99992GW_IRQLVL1MSK_MADC)) return; /* Enable ADC sequencing */ if (raw_write8(BD99992GW_REG_ADC1CNTL2, BD99992GW_ADC1CNTL2_ADCTHERM)) return; /* Start round-robin conversions at 27ms period */ raw_write8(BD99992GW_REG_ADC1CNTL1, ADC_LOOP_PERIOD | BD99992GW_ADC1CNTL1_ADEN | BD99992GW_ADC1CNTL1_ADSTRT); }
int tmp432_set_therm_limit(int channel, int limit_c, int hysteresis) { int ret = 0; int reg = 0; if (channel >= TMP432_CHANNEL_COUNT) return EC_ERROR_INVAL; if (hysteresis > TMP432_HYSTERESIS_HIGH_LIMIT || hysteresis < TMP432_HYSTERESIS_LOW_LIMIT) return EC_ERROR_INVAL; /* hysteresis must be less than high limit */ if (hysteresis > limit_c) return EC_ERROR_INVAL; if (tmp432_set_therm_mode() != EC_SUCCESS) return EC_ERROR_UNKNOWN; switch (channel) { case TMP432_CHANNEL_LOCAL: reg = TMP432_LOCAL_HIGH_LIMIT_W; break; case TMP432_CHANNEL_REMOTE1: reg = TMP432_REMOTE1_HIGH_LIMIT_W; break; case TMP432_CHANNEL_REMOTE2: reg = TMP432_REMOTE2_HIGH_LIMIT_W; break; } ret = raw_write8(reg, limit_c); if (ret) return EC_ERROR_UNKNOWN; ret = raw_write8(TMP432_THERM_HYSTERESIS, hysteresis); if (ret) return EC_ERROR_UNKNOWN; return EC_SUCCESS; }
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 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 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 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; }
static int si114x_initialize(const struct motion_sensor_t *s) { int ret, val; /* send reset command */ ret = raw_write8(s->port, s->addr, SI114X_REG_COMMAND, SI114X_CMD_RESET); if (ret != EC_SUCCESS) return ret; msleep(20); /* hardware key, magic value */ ret = raw_write8(s->port, s->addr, SI114X_REG_HW_KEY, 0x17); if (ret != EC_SUCCESS) return ret; msleep(20); /* interrupt configuration, interrupt output enable */ ret = raw_write8(s->port, s->addr, SI114X_REG_INT_CFG, SI114X_INT_CFG_OE); if (ret != EC_SUCCESS) return ret; /* enable interrupt for certain activities */ ret = raw_write8(s->port, s->addr, SI114X_REG_IRQ_ENABLE, SI114X_PS3_IE | SI114X_PS2_IE | SI114X_PS1_IE | SI114X_ALS_INT0_IE); if (ret != EC_SUCCESS) return ret; /* Only forced mode */ ret = raw_write8(s->port, s->addr, SI114X_REG_MEAS_RATE, 0); if (ret != EC_SUCCESS) return ret; /* measure ALS every time device wakes up */ ret = raw_write8(s->port, s->addr, SI114X_REG_ALS_RATE, 0); if (ret != EC_SUCCESS) return ret; /* measure proximity every time device wakes up */ ret = raw_write8(s->port, s->addr, SI114X_REG_PS_RATE, 0); if (ret != EC_SUCCESS) return ret; /* set LED currents to maximum */ switch (SI114X_NUM_LEDS) { case 3: ret = raw_write8(s->port, s->addr, SI114X_REG_PS_LED3, 0x0f); if (ret != EC_SUCCESS) return ret; ret = raw_write8(s->port, s->addr, SI114X_REG_PS_LED21, 0xff); break; case 2: ret = raw_write8(s->port, s->addr, SI114X_REG_PS_LED21, 0xff); break; case 1: ret = raw_write8(s->port, s->addr, SI114X_REG_PS_LED21, 0x0f); break; } if (ret != EC_SUCCESS) return ret; ret = si114x_set_chlist(s); if (ret != EC_SUCCESS) return ret; /* set normal proximity measurement mode, set high signal range * PS measurement */ val = SI114X_PARAM_PS_ADC_MISC_NORMAL_MODE; ret = si114x_param_op(s, SI114X_CMD_PARAM_SET, SI114X_PARAM_PS_ADC_MISC, &val); return ret; }
/* 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; }
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; }