Exemple #1
0
/* 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;
}
Exemple #2
0
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;
}
Exemple #4
0
/**
 * 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;
}
Exemple #6
0
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);
}
Exemple #7
0
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
}
Exemple #8
0
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;
}
Exemple #9
0
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);
}
Exemple #10
0
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;
}
Exemple #11
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;
}
Exemple #12
0
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;
}
Exemple #14
0
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;
}
Exemple #15
0
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;
}
Exemple #16
0
/* 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;
}
Exemple #17
0
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;
}
Exemple #18
0
/* 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;
}
Exemple #19
0
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;
}