static int ak09911c_i2c_read_block(struct i2c_client *client,
		unsigned char reg_addr, unsigned char *buf, unsigned char len)
{
#if defined(CONFIG_SEC_BERLUTI_PROJECT)
	int ret;
	struct i2c_msg msg[2];

	msg[0].addr = client->addr;
	msg[0].flags = I2C_M_WR;
	msg[0].len = 1;
	msg[0].buf = &reg_addr;

	msg[1].addr = client->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len = len;
	msg[1].buf = buf;

	ret = i2c_transfer(client->adapter, msg, 2);
	if (ret < 0) {
		pr_err("[SENSOR]: %s - i2c bus read error %d\n",
			__func__, ret);
		return ret;
	}

	return 0;
#else
	int i, ret = 0;

	for (i = 0; i < len; i++)
		ret += ak09911c_i2c_read(client, reg_addr + i, &buf[i]);

	return ret;
#endif
}
static int ak09911c_read_mag_xyz(struct ak09911c_p *data,
		struct ak09911c_v *mag)
{
	u8 temp[SENSOR_DATA_SIZE] = {0, };
	int ret = 0, retries = 0;

	mutex_lock(&data->lock);
	ret = ak09911c_ecs_set_mode(data, AK09911C_MODE_SNG_MEASURE);
	if (ret < 0)
		goto exit_i2c_read_err;

again:
	ret = ak09911c_i2c_read(data->client, AK09911C_REG_ST1, &temp[0]);
	if (ret < 0)
		goto exit_i2c_read_err;

	/* Check ST bit */
	if (!(temp[0] & 0x01)) {
		if ((retries++ < 5) && (temp[0] == 0)) {
#if !defined(CONFIG_SEC_BERLUTI_PROJECT)
			mdelay(2);
#endif
			goto again;
		} else {
			ret = -EAGAIN;
			goto exit_i2c_read_fail;
		}
	}

	ret = ak09911c_i2c_read_block(data->client, AK09911C_REG_ST1 + 1,
			&temp[1], SENSOR_DATA_SIZE - 1);
	if (ret < 0)
		goto exit_i2c_read_err;
#if 0
	/* Check ST2 bit */
	if ((temp[8] & 0x08)) {
		ret = -EAGAIN;
		goto exit_i2c_read_fail;
	}
#endif
	mag->x = temp[1] | (temp[2] << 8);
	mag->y = temp[3] | (temp[4] << 8);
	mag->z = temp[5] | (temp[6] << 8);

	remap_sensor_data(mag->v, data->chip_pos);

	goto exit;

exit_i2c_read_fail:
exit_i2c_read_err:
	pr_err("[SENSOR]: %s - ST1 = %u, ST2 = %u\n",
		__func__, temp[0], temp[8]);
exit:
	mutex_unlock(&data->lock);
	return ret;
}
예제 #3
0
static int ak09911c_i2c_read_block(struct i2c_client *client,
		unsigned char reg_addr, unsigned char *buf, unsigned char len)
{
	int i, ret = 0;

	for (i = 0; i < len; i++)
		ret += ak09911c_i2c_read(client, reg_addr + i, &buf[i]);

	return ret;
}
static ssize_t ak09911c_check_cntl(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	u8 reg;
	int ret = 0;
	struct ak09911c_p *data = dev_get_drvdata(dev);

	mutex_lock(&data->lock);
	/* power down */
	reg = AK09911C_MODE_POWERDOWN;

	ret = ak09911c_i2c_write(data->client, AK09911C_REG_CNTL2, reg);
	udelay(100);
	ret += ak09911c_i2c_read(data->client, AK09911C_REG_CNTL2, &reg);
	mutex_unlock(&data->lock);

	return snprintf(buf, PAGE_SIZE, "%s\n",
			(((reg == AK09911C_MODE_POWERDOWN) &&
			(ret == 0)) ? "OK" : "NG"));
}
static int ak09911c_selftest(struct ak09911c_p *data, int *dac_ret, int *sf)
{
	u8 temp[6], reg;
	s16 x, y, z;
	int retry_count = 0;
	int ready_count = 0;
	int ret;
retry:
	mutex_lock(&data->lock);
	/* power down */
	reg = AK09911C_MODE_POWERDOWN;
	*dac_ret = ak09911c_i2c_write(data->client, AK09911C_REG_CNTL2, reg);
	udelay(100);
	*dac_ret += ak09911c_i2c_read(data->client, AK09911C_REG_CNTL2, &reg);

	/* read device info */
	ak09911c_i2c_read_block(data->client, AK09911C_REG_WIA1, temp, 2);
	pr_info("[SENSOR]: %s - device id = 0x%x, info = 0x%x\n",
		__func__, temp[0], temp[1]);

	/* start self test */
	reg = AK09911C_MODE_SELF_TEST;
	ak09911c_i2c_write(data->client, AK09911C_REG_CNTL2, reg);

	/* wait for data ready */
	while (ready_count < 10) {
		msleep(20);
		ret = ak09911c_i2c_read(data->client, AK09911C_REG_ST1, &reg);
		if ((reg == 1) && (ret == 0))
			break;
		ready_count++;
	}

	ak09911c_i2c_read_block(data->client, AK09911C_REG_HXL,
		temp, sizeof(temp));
	mutex_unlock(&data->lock);

	x = temp[0] | (temp[1] << 8);
	y = temp[2] | (temp[3] << 8);
	z = temp[4] | (temp[5] << 8);

	/* Hadj = (H*(Asa+128))/128 */
	x = (x * (data->asa[0] + 128)) >> 7;
	y = (y * (data->asa[1] + 128)) >> 7;
	z = (z * (data->asa[2] + 128)) >> 7;

	pr_info("[SENSOR]: %s - self test x = %d, y = %d, z = %d\n",
		__func__, x, y, z);
	if ((x >= -30) && (x <= 30))
		pr_info("[SENSOR]: %s - x passed self test, -30<=x<=30\n",
			__func__);
	else
		pr_info("[SENSOR]: %s - x failed self test, -30<=x<=30\n",
			__func__);
	if ((y >= -30) && (y <= 30))
		pr_info("[SENSOR]: %s - y passed self test, -30<=y<=30\n",
			__func__);
	else
		pr_info("[SENSOR]: %s - y failed self test, -30<=y<=30\n",
			__func__);
	if ((z >= -400) && (z <= -50))
		pr_info("[SENSOR]: %s - z passed self test, -400<=z<=-50\n",
			__func__);
	else
		pr_info("[SENSOR]: %s - z failed self test, -400<=z<=-50\n",
			__func__);

	sf[0] = x;
	sf[1] = y;
	sf[2] = z;

	if (((x >= -30) && (x <= 30)) &&
		((y >= -30) && (y <= 30)) &&
		((z >= -400) && (z <= -50))) {
		pr_info("%s, Selftest is successful.\n", __func__);
		return 0;
	} else {
		if (retry_count < 5) {
			retry_count++;
			pr_warn("############################################");
			pr_warn("%s, retry_count=%d\n", __func__, retry_count);
			pr_warn("############################################");
			goto retry;
		} else {
			pr_err("[SENSOR]: %s - Selftest is failed.\n",
				__func__);
			return -1;
		}
	}
}