static ssize_t ak09911c_get_selftest(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0, dac_ret, adc_ret; int sf_ret, sf[3] = {0,}; struct ak09911c_v mag; struct ak09911c_p *data = dev_get_drvdata(dev); if (atomic_read(&data->enable) == 1) { ak09911c_ecs_set_mode(data, AK09911C_MODE_POWERDOWN); cancel_delayed_work_sync(&data->work); } sf_ret = ak09911c_selftest(data, &dac_ret, sf); adc_ret = ak09911c_read_mag_xyz(data, &mag); if (atomic_read(&data->enable) == 1) { ak09911c_ecs_set_mode(data, AK09911C_MODE_SNG_MEASURE); schedule_delayed_work(&data->work, nsecs_to_jiffies(atomic_read(&data->delay))); } ret = sf_ret + dac_ret + adc_ret; return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", ret, sf_ret, sf[0], sf[1], sf[2], dac_ret, adc_ret, mag.x, mag.y, mag.z); }
static ssize_t ak09911c_get_selftest(struct device *dev, struct device_attribute *attr, char *buf) { int status, dac_ret = -1, adc_ret = -1; int sf_ret, sf[3] = {0,}, retries; struct ak09911c_v mag; struct ak09911c_p *data = dev_get_drvdata(dev); /* STATUS */ if ((data->asa[0] == 0) | (data->asa[0] == 0xff) | (data->asa[1] == 0) | (data->asa[1] == 0xff) | (data->asa[2] == 0) | (data->asa[2] == 0xff)) status = -1; else status = 0; if (atomic_read(&data->enable) == 1) { ak09911c_ecs_set_mode(data, AK09911C_MODE_POWERDOWN); cancel_delayed_work_sync(&data->work); } sf_ret = ak09911c_selftest(data, &dac_ret, sf); for (retries = 0; retries < 5; retries++) { if (ak09911c_read_mag_xyz(data, &mag) == 0) { if ((mag.x < 1600) && (mag.x > -1600) && (mag.y < 1600) && (mag.y > -1600) && (mag.z < 1600) && (mag.z > -1600)) adc_ret = 0; else pr_err("[SENSOR]: %s adc specout %d, %d, %d\n", __func__, mag.x, mag.y, mag.z); break; } msleep(20); pr_err("%s adc retries %d", __func__, retries); } if (atomic_read(&data->enable) == 1) { ak09911c_ecs_set_mode(data, AK09911C_MODE_SNG_MEASURE); schedule_delayed_work(&data->work, nsecs_to_jiffies(atomic_read(&data->delay))); } return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", status, sf_ret, sf[0], sf[1], sf[2], dac_ret, adc_ret, mag.x, mag.y, mag.z); }
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; }
static void ak09911c_shutdown(struct i2c_client *client) { struct ak09911c_p *data = i2c_get_clientdata(client); pr_info("%s\n", __func__); if (atomic_read(&data->enable) == 1) { ak09911c_ecs_set_mode(data, AK09911C_MODE_POWERDOWN); cancel_delayed_work_sync(&data->work); } }
static void ak09911c_set_enable(struct ak09911c_p *data, int enable) { int pre_enable = atomic_read(&data->enable); if (enable) { if (pre_enable == 0) { ak09911c_ecs_set_mode(data, AK09911C_MODE_SNG_MEASURE); schedule_delayed_work(&data->work, nsecs_to_jiffies(atomic_read(&data->delay))); atomic_set(&data->enable, 1); } } else { if (pre_enable == 1) { ak09911c_ecs_set_mode(data, AK09911C_MODE_POWERDOWN); cancel_delayed_work_sync(&data->work); atomic_set(&data->enable, 0); } } }
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; retry: ret = ak09911c_smbus_read_byte(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)) { mdelay(2); goto retry; } else { ret = -EAGAIN; goto exit_i2c_read_fail; } } ret = ak09911c_smbus_read_byte_block(data->client, AK09911C_REG_ST1 + 1, &temp[1], SENSOR_DATA_SIZE - 1); if (ret < 0) goto exit_i2c_read_err; /* Check ST2 bit */ if ((temp[8] & 0x01)) { ret = -EAGAIN; goto exit_i2c_read_fail; } 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->pdata->chip_pos); goto exit; exit_i2c_read_fail: exit_i2c_read_err: pr_err("%s failed. ret = %d, ST1 = %u, ST2 = %u\n", __func__, ret, temp[0], temp[8]); exit: mutex_unlock(&data->lock); return ret; }
static int ak09911c_suspend(struct device *dev) { struct ak09911c_p *data = dev_get_drvdata(dev); if (atomic_read(&data->enable) == 1) { ak09911c_ecs_set_mode(data, AK09911C_MODE_POWERDOWN); cancel_delayed_work_sync(&data->work); } return 0; }
static int ak09911c_resume(struct device *dev) { struct ak09911c_p *data = dev_get_drvdata(dev); if (atomic_read(&data->enable) == 1) { ak09911c_ecs_set_mode(data, AK09911C_MODE_SNG_MEASURE); schedule_delayed_work(&data->work, nsecs_to_jiffies(atomic_read(&data->delay))); } return 0; }