Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
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 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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
0
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
}
Esempio n. 7
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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
int charger_get_input_current(int *input_current)
{
	int rv;
	int reg;

#ifdef CONFIG_CHARGER_BQ24770
	rv = raw_read16(REG_INPUT_CURRENT, &reg);
#elif defined(CONFIG_CHARGER_BQ24773)
	rv = raw_read8(REG_INPUT_CURRENT, &reg);
#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;
}
Esempio n. 16
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 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;
}
Esempio n. 17
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;
}
Esempio n. 18
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;
}
Esempio n. 19
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;
}
Esempio n. 20
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;
}
Esempio n. 21
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;
}