/** * struct yas5xx_chip_info - device-specific data and function pointers * @devid: device ID number * @product_name: product name of the YAS variant * @version_names: version letters or namings * @volatile_reg: device-specific volatile registers * @volatile_reg_qty: quantity of device-specific volatile registers * @scaling_val2: scaling value for IIO_CHAN_INFO_SCALE * @t_ref: number of counts at reference temperature 20 °C * @min_temp_x10: starting point of temperature counting in 1/10:s degrees Celsius * @get_measure: function pointer to get a measurement * @get_calibration_data: function pointer to get calibration data * @dump_calibration: function pointer to dump calibration for debugging * @measure_offsets: function pointer to measure the offsets * @power_on: function pointer to power-on procedure * * The "t_ref" value for YAS532/533 is known from the Android driver. * For YAS530 and YAS537 it was approximately measured. * * The temperatures "min_temp_x10" are derived from the temperature resolutions * given in the data sheets.
*/ struct yas5xx_chip_info { unsignedint devid; constchar *product_name; constchar *version_names[2]; constint *volatile_reg; int volatile_reg_qty;
u32 scaling_val2;
u16 t_ref;
s16 min_temp_x10; int (*get_measure)(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo); int (*get_calibration_data)(struct yas5xx *yas5xx); void (*dump_calibration)(struct yas5xx *yas5xx); int (*measure_offsets)(struct yas5xx *yas5xx); int (*power_on)(struct yas5xx *yas5xx);
};
/** * struct yas5xx - state container for the YAS5xx driver * @dev: parent device pointer * @chip_info: device-specific data and function pointers * @version: device version * @calibration: calibration settings from the OTP storage * @hard_offsets: offsets for each axis measured with initcoil actuated * @orientation: mounting matrix, flipped axis etc * @map: regmap to access the YAX5xx registers over I2C * @regs: the vdd and vddio power regulators * @reset: optional GPIO line used for handling RESET * @lock: locks the magnetometer for exclusive use during a measurement (which * involves several register transactions so the regmap lock is not enough) * so that measurements get serialized in a first-come-first serve manner * @scan: naturally aligned measurements
*/ struct yas5xx { struct device *dev; conststruct yas5xx_chip_info *chip_info; unsignedint version; struct yas5xx_calibration calibration;
s8 hard_offsets[3]; struct iio_mount_matrix orientation; struct regmap *map; struct regulator_bulk_data regs[2]; struct gpio_desc *reset; struct mutex lock; /* * The scanout is 4 x 32 bits in CPU endianness. * Ensure timestamp is naturally aligned
*/ struct {
s32 channels[4];
aligned_s64 ts;
} scan;
};
/* On YAS530 the x, y1 and y2 values are 12 bits */ static u16 yas530_extract_axis(u8 *data)
{
u16 val;
/* * These are the bits used in a 16bit word: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 * x x x x x x x x x x x x
*/
val = get_unaligned_be16(&data[0]);
val = FIELD_GET(GENMASK(14, 3), val); return val;
}
/* On YAS532 the x, y1 and y2 values are 13 bits */ static u16 yas532_extract_axis(u8 *data)
{
u16 val;
/* * These are the bits used in a 16bit word: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 * x x x x x x x x x x x x x
*/
val = get_unaligned_be16(&data[0]);
val = FIELD_GET(GENMASK(14, 2), val); return val;
}
/** * yas530_measure() - Make a measure from the hardware * @yas5xx: The device state * @t: the raw temperature measurement * @x: the raw x axis measurement * @y1: the y1 axis measurement * @y2: the y2 axis measurement * @return: 0 on success or error code * * Used by YAS530, YAS532 and YAS533.
*/ staticint yas530_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y2)
{ conststruct yas5xx_chip_info *ci = yas5xx->chip_info; unsignedint busy;
u8 data[8]; int ret;
u16 val;
mutex_lock(&yas5xx->lock);
ret = regmap_write(yas5xx->map, YAS530_MEASURE, YAS5XX_MEASURE_START); if (ret < 0) goto out_unlock;
/* * Typical time to measure 1500 us, max 2000 us so wait min 500 us * and at most 20000 us (one magnitude more than the datsheet max) * before timeout.
*/
ret = regmap_read_poll_timeout(yas5xx->map, YAS5XX_MEASURE_DATA, busy,
!(busy & YAS5XX_MEASURE_DATA_BUSY),
500, 20000); if (ret) {
dev_err(yas5xx->dev, "timeout waiting for measurement\n"); goto out_unlock;
}
ret = regmap_bulk_read(yas5xx->map, YAS5XX_MEASURE_DATA,
data, sizeof(data)); if (ret) goto out_unlock;
mutex_unlock(&yas5xx->lock);
switch (ci->devid) { case YAS530_DEVICE_ID: /* * The t value is 9 bits in big endian format * These are the bits used in a 16bit word: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 * x x x x x x x x x
*/
val = get_unaligned_be16(&data[0]);
val = FIELD_GET(GENMASK(14, 6), val);
*t = val;
*x = yas530_extract_axis(&data[2]);
*y1 = yas530_extract_axis(&data[4]);
*y2 = yas530_extract_axis(&data[6]); break; case YAS532_DEVICE_ID: /* * The t value is 10 bits in big endian format * These are the bits used in a 16bit word: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 * x x x x x x x x x x
*/
val = get_unaligned_be16(&data[0]);
val = FIELD_GET(GENMASK(14, 5), val);
*t = val;
*x = yas532_extract_axis(&data[2]);
*y1 = yas532_extract_axis(&data[4]);
*y2 = yas532_extract_axis(&data[6]); break; default:
dev_err(yas5xx->dev, "unknown data format\n");
ret = -EINVAL; break;
}
/** * yas537_measure() - Make a measure from the hardware * @yas5xx: The device state * @t: the raw temperature measurement * @x: the raw x axis measurement * @y1: the y1 axis measurement * @y2: the y2 axis measurement * @return: 0 on success or error code
*/ staticint yas537_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y2)
{ struct yas5xx_calibration *c = &yas5xx->calibration; unsignedint busy;
u8 data[8];
u16 xy1y2[3];
s32 h[3], s[3]; int half_range = BIT(13); int i, ret;
mutex_lock(&yas5xx->lock);
/* Contrary to YAS530/532, also a "cont" bit is set, meaning unknown */
ret = regmap_write(yas5xx->map, YAS537_MEASURE, YAS5XX_MEASURE_START |
YAS5XX_MEASURE_CONT); if (ret < 0) goto out_unlock;
/* Use same timeout like YAS530/532 but the bit is in data row 2 */
ret = regmap_read_poll_timeout(yas5xx->map, YAS5XX_MEASURE_DATA + 2, busy,
!(busy & YAS5XX_MEASURE_DATA_BUSY),
500, 20000); if (ret) {
dev_err(yas5xx->dev, "timeout waiting for measurement\n"); goto out_unlock;
}
ret = regmap_bulk_read(yas5xx->map, YAS5XX_MEASURE_DATA,
data, sizeof(data)); if (ret) goto out_unlock;
to = (min_temp_x10 + ((ref_temp_x10 - min_temp_x10) * t / t_ref)) * 100; return to;
}
/** * yas530_get_measure() - Measure a sample of all axis and process * @yas5xx: The device state * @to: Temperature out * @xo: X axis out * @yo: Y axis out * @zo: Z axis out * @return: 0 on success or error code * * Used by YAS530, YAS532 and YAS533.
*/ staticint yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo)
{ conststruct yas5xx_chip_info *ci = yas5xx->chip_info; struct yas5xx_calibration *c = &yas5xx->calibration;
u16 t_ref, t_comp, t, x, y1, y2; /* These are signed x, signed y1 etc */
s32 sx, sy1, sy2, sy, sz; int ret;
/* We first get raw data that needs to be translated to [x,y,z] */
ret = yas530_measure(yas5xx, &t, &x, &y1, &y2); if (ret) return ret;
/* Do some linearization if available */
sx = yas530_linearize(yas5xx, x, 0);
sy1 = yas530_linearize(yas5xx, y1, 1);
sy2 = yas530_linearize(yas5xx, y2, 2);
/* * Set the temperature for compensation (unit: counts): * YAS532/YAS533 version AC uses the temperature deviation as a * multiplier. YAS530 and YAS532 version AB use solely the t value.
*/
t_ref = ci->t_ref; if (ci->devid == YAS532_DEVICE_ID &&
yas5xx->version == YAS532_VERSION_AC) {
t_comp = t - t_ref;
} else {
t_comp = t;
}
/* * Break y1 and y2 into y and z, y1 and y2 are apparently encoding * y and z.
*/
sy = sy1 - sy2;
sz = -sy1 - sy2;
/* Calculate temperature readout */
*to = yas5xx_calc_temperature(yas5xx, t);
/* * Calibrate [x,y,z] with some formulas like this: * * 100 * x + a_2 * y + a_3 * z * x' = k * --------------------------- * 10 * * a_4 * x + a_5 * y + a_6 * z * y' = k * --------------------------- * 10 * * a_7 * x + a_8 * y + a_9 * z * z' = k * --------------------------- * 10
*/
*xo = c->k * ((100 * sx + c->a2 * sy + c->a3 * sz) / 10);
*yo = c->k * ((c->a4 * sx + c->a5 * sy + c->a6 * sz) / 10);
*zo = c->k * ((c->a7 * sx + c->a8 * sy + c->a9 * sz) / 10);
return 0;
}
/** * yas537_get_measure() - Measure a sample of all axis and process * @yas5xx: The device state * @to: Temperature out * @xo: X axis out * @yo: Y axis out * @zo: Z axis out * @return: 0 on success or error code
*/ staticint yas537_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo)
{
u16 t, x, y1, y2; int ret;
/* We first get raw data that needs to be translated to [x,y,z] */
ret = yas537_measure(yas5xx, &t, &x, &y1, &y2); if (ret) return ret;
/* Calculate temperature readout */
*to = yas5xx_calc_temperature(yas5xx, t);
/* * Unfortunately, no linearization or temperature compensation formulas * are known for YAS537.
*/
/* * YAS versions share different registers on the same address, * need to differentiate.
*/
reg_qty = ci->volatile_reg_qty; for (i = 0; i < reg_qty; i++) { if (reg == ci->volatile_reg[i]) returntrue;
}
returnfalse;
}
/* TODO: enable regmap cache, using mark dirty and sync at runtime resume */ staticconststruct regmap_config yas5xx_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0xff,
.volatile_reg = yas5xx_volatile_reg,
};
/** * yas530_extract_calibration() - extracts the a2-a9 and k calibration * @data: the bitfield to use * @c: the calibration to populate * * Used by YAS530, YAS532 and YAS533.
*/ staticvoid yas530_extract_calibration(u8 *data, struct yas5xx_calibration *c)
{
u64 val = get_unaligned_be64(data);
/* * Extract linearization: * Linearization layout in the 32 bits at byte 10: * The r factors are 6 bit values where bit 5 is the sign * * n 7 6 5 4 3 2 1 0 * 0 [ xx r0 r0 r0 r0 r0 r0 f0 ] bits 31 .. 24 * 1 [ f0 r1 r1 r1 r1 r1 r1 f1 ] bits 23 .. 16 * 2 [ f1 r2 r2 r2 r2 r2 r2 f2 ] bits 15 .. 8 * 3 [ f2 xx xx xx xx xx xx xx ] bits 7 .. 0
*/
val = get_unaligned_be32(&data[10]);
c->f[0] = FIELD_GET(GENMASK(24, 23), val);
c->f[1] = FIELD_GET(GENMASK(16, 15), val);
c->f[2] = FIELD_GET(GENMASK(8, 7), val);
c->r[0] = sign_extend32(FIELD_GET(GENMASK(30, 25), val), 5);
c->r[1] = sign_extend32(FIELD_GET(GENMASK(22, 17), val), 5);
c->r[2] = sign_extend32(FIELD_GET(GENMASK(14, 7), val), 5);
return 0;
}
staticint yas537_get_calibration_data(struct yas5xx *yas5xx)
{ struct yas5xx_calibration *c = &yas5xx->calibration;
u8 data[17];
u32 val1, val2, val3, val4; int i, ret;
/* Writing SRST register */
ret = regmap_write(yas5xx->map, YAS537_SRST, BIT(1)); if (ret) return ret;
/* Calibration readout, YAS537 needs one readout only */
ret = regmap_bulk_read(yas5xx->map, YAS537_CAL, data, sizeof(data)); if (ret) return ret;
dev_dbg(yas5xx->dev, "calibration data: %17ph\n", data);
/* Sanity check, is this all zeroes? */ if (!memchr_inv(data, 0x00, 16) && !FIELD_GET(GENMASK(5, 0), data[16]))
dev_warn(yas5xx->dev, "calibration is blank!\n");
/* Contribute calibration data to the input pool for kernel entropy */
add_device_randomness(data, sizeof(data));
/* Extract version information */
yas5xx->version = FIELD_GET(GENMASK(7, 6), data[16]);
/* There are two versions of YAS537 behaving differently */ switch (yas5xx->version) { case YAS537_VERSION_0: /* * The first version simply writes data back into registers: * * data[0] YAS537_MTC 0x93 * data[1] 0x94 * data[2] 0x95 * data[3] 0x96 * data[4] 0x97 * data[5] 0x98 * data[6] 0x99 * data[7] 0x9a * data[8] 0x9b * data[9] 0x9c * data[10] 0x9d * data[11] YAS537_OC 0x9e * * data[12] YAS537_OFFSET_X 0x84 * data[13] YAS537_OFFSET_Y1 0x85 * data[14] YAS537_OFFSET_Y2 0x86 * * data[15] YAS537_HCK 0x88 * data[16] YAS537_LCK 0x89
*/ for (i = 0; i < 12; i++) {
ret = regmap_write(yas5xx->map, YAS537_MTC + i,
data[i]); if (ret) return ret;
} for (i = 0; i < 3; i++) {
ret = regmap_write(yas5xx->map, YAS537_OFFSET_X + i,
data[i + 12]); if (ret) return ret;
yas5xx->hard_offsets[i] = data[i + 12];
} for (i = 0; i < 2; i++) {
ret = regmap_write(yas5xx->map, YAS537_HCK + i,
data[i + 15]); if (ret) return ret;
} break; case YAS537_VERSION_1: /* * The second version writes some data into registers but also * extracts calibration coefficients. * * Registers being written: * * data[0] YAS537_MTC 0x93 * data[1] YAS537_MTC+1 0x94 * data[2] YAS537_MTC+2 0x95 * data[3] YAS537_MTC+3 (partially) 0x96 * * data[12] YAS537_OFFSET_X 0x84 * data[13] YAS537_OFFSET_Y1 0x85 * data[14] YAS537_OFFSET_Y2 0x86 * * data[15] YAS537_HCK (partially) 0x88 * YAS537_LCK (partially) 0x89 * data[16] YAS537_OC (partially) 0x9e
*/ for (i = 0; i < 3; i++) {
ret = regmap_write(yas5xx->map, YAS537_MTC + i,
data[i]); if (ret) return ret;
} for (i = 0; i < 3; i++) {
ret = regmap_write(yas5xx->map, YAS537_OFFSET_X + i,
data[i + 12]); if (ret) return ret;
yas5xx->hard_offsets[i] = data[i + 12];
} /* * Visualization of partially taken data: * * data[3] n 7 6 5 4 3 2 1 0 * YAS537_MTC+3 x x x 1 0 0 0 0 * * data[15] n 7 6 5 4 3 2 1 0 * YAS537_HCK x x x x 0 * * data[15] n 7 6 5 4 3 2 1 0 * YAS537_LCK x x x x 0 * * data[16] n 7 6 5 4 3 2 1 0 * YAS537_OC x x x x x x
*/
ret = regmap_write(yas5xx->map, YAS537_MTC + 3,
FIELD_PREP(YAS537_MTC3_MASK_PREP,
FIELD_GET(YAS537_MTC3_MASK_GET, data[3])) |
YAS537_MTC3_ADD_BIT); if (ret) return ret;
ret = regmap_write(yas5xx->map, YAS537_HCK,
FIELD_PREP(YAS537_HCK_MASK_PREP,
FIELD_GET(YAS537_HCK_MASK_GET, data[15]))); if (ret) return ret;
ret = regmap_write(yas5xx->map, YAS537_LCK,
FIELD_PREP(YAS537_LCK_MASK_PREP,
FIELD_GET(YAS537_LCK_MASK_GET, data[15]))); if (ret) return ret;
ret = regmap_write(yas5xx->map, YAS537_OC,
FIELD_GET(YAS537_OC_MASK_GET, data[16])); if (ret) return ret; /* * For data extraction, build some blocks. Four 32-bit blocks * look appropriate. * * n 7 6 5 4 3 2 1 0 * data[0] 0 [ Cx Cx Cx Cx Cx Cx Cx Cx ] bits 31 .. 24 * data[1] 1 [ Cx C1 C1 C1 C1 C1 C1 C1 ] bits 23 .. 16 * data[2] 2 [ C1 C1 C2 C2 C2 C2 C2 C2 ] bits 15 .. 8 * data[3] 3 [ C2 C2 C2 ] bits 7 .. 0 * * n 7 6 5 4 3 2 1 0 * data[3] 0 [ a2 a2 a2 a2 a2 ] bits 31 .. 24 * data[4] 1 [ a2 a2 a3 a3 a3 a3 a3 a3 ] bits 23 .. 16 * data[5] 2 [ a3 a4 a4 a4 a4 a4 a4 a4 ] bits 15 .. 8 * data[6] 3 [ a4 ] bits 7 .. 0 * * n 7 6 5 4 3 2 1 0 * data[6] 0 [ a5 a5 a5 a5 a5 a5 a5 ] bits 31 .. 24 * data[7] 1 [ a5 a5 a6 a6 a6 a6 a6 a6 ] bits 23 .. 16 * data[8] 2 [ a6 a7 a7 a7 a7 a7 a7 a7 ] bits 15 .. 8 * data[9] 3 [ a7 ] bits 7 .. 0 * * n 7 6 5 4 3 2 1 0 * data[9] 0 [ a8 a8 a8 a8 a8 a8 a8 ] bits 31 .. 24 * data[10] 1 [ a9 a9 a9 a9 a9 a9 a9 a9 ] bits 23 .. 16 * data[11] 2 [ a9 k k k k k k k ] bits 15 .. 8 * data[12] 3 [ ] bits 7 .. 0
*/
val1 = get_unaligned_be32(&data[0]);
val2 = get_unaligned_be32(&data[3]);
val3 = get_unaligned_be32(&data[6]);
val4 = get_unaligned_be32(&data[9]); /* Extract calibration coefficients and modify */
c->Cx = FIELD_GET(GENMASK(31, 23), val1) - 256;
c->Cy1 = FIELD_GET(GENMASK(22, 14), val1) - 256;
c->Cy2 = FIELD_GET(GENMASK(13, 5), val1) - 256;
c->a2 = FIELD_GET(GENMASK(28, 22), val2) - 64;
c->a3 = FIELD_GET(GENMASK(21, 15), val2) - 64;
c->a4 = FIELD_GET(GENMASK(14, 7), val2) - 128;
c->a5 = FIELD_GET(GENMASK(30, 22), val3) - 112;
c->a6 = FIELD_GET(GENMASK(21, 15), val3) - 64;
c->a7 = FIELD_GET(GENMASK(14, 7), val3) - 128;
c->a8 = FIELD_GET(GENMASK(30, 24), val4) - 64;
c->a9 = FIELD_GET(GENMASK(23, 15), val4) - 112;
c->k = FIELD_GET(GENMASK(14, 8), val4); break; default:
dev_err(yas5xx->dev, "unknown version of YAS537\n"); return -EINVAL;
}
return 0;
}
/* Used by YAS530, YAS532 and YAS533 */ staticvoid yas530_dump_calibration(struct yas5xx *yas5xx)
{ struct yas5xx_calibration *c = &yas5xx->calibration;
/* Used by YAS530, YAS532 and YAS533 */ staticint yas530_set_offsets(struct yas5xx *yas5xx, s8 ox, s8 oy1, s8 oy2)
{ int ret;
ret = regmap_write(yas5xx->map, YAS530_OFFSET_X, ox); if (ret) return ret;
ret = regmap_write(yas5xx->map, YAS530_OFFSET_Y1, oy1); if (ret) return ret; return regmap_write(yas5xx->map, YAS530_OFFSET_Y2, oy2);
}
/* Used by YAS530, YAS532 and YAS533 */ static s8 yas530_adjust_offset(s8 old, int bit, u16 center, u16 measure)
{ if (measure > center) return old + BIT(bit); if (measure < center) return old - BIT(bit); return old;
}
/* Used by YAS530, YAS532 and YAS533 */ staticint yas530_measure_offsets(struct yas5xx *yas5xx)
{ conststruct yas5xx_chip_info *ci = yas5xx->chip_info; int ret;
u16 center;
u16 t, x, y1, y2;
s8 ox, oy1, oy2; int i;
/* Actuate the init coil and measure offsets */
ret = regmap_write(yas5xx->map, YAS530_ACTUATE_INIT_COIL, 0); if (ret) return ret;
/* When the initcoil is active this should be around the center */ switch (ci->devid) { case YAS530_DEVICE_ID:
center = YAS530_DATA_CENTER; break; case YAS532_DEVICE_ID:
center = YAS532_DATA_CENTER; break; default:
dev_err(yas5xx->dev, "unknown device type\n"); return -EINVAL;
}
/* * We set offsets in the interval +-31 by iterating * +-16, +-8, +-4, +-2, +-1 adjusting the offsets each * time, then writing the final offsets into the * registers. * * NOTE: these offsets are NOT in the same unit or magnitude * as the values for [x, y1, y2]. The value is +/-31 * but the effect on the raw values is much larger. * The effect of the offset is to bring the measure * rougly to the center.
*/
ox = 0;
oy1 = 0;
oy2 = 0;
for (i = 4; i >= 0; i--) {
ret = yas530_set_offsets(yas5xx, ox, oy1, oy2); if (ret) return ret;
/* Used by YAS530, YAS532 and YAS533 */ staticint yas530_power_on(struct yas5xx *yas5xx)
{ unsignedint val; int ret;
/* Zero the test registers */
ret = regmap_write(yas5xx->map, YAS530_TEST1, 0); if (ret) return ret;
ret = regmap_write(yas5xx->map, YAS530_TEST2, 0); if (ret) return ret;
/* Set up for no interrupts, calibrated clock divider */
val = FIELD_PREP(YAS5XX_CONFIG_CCK_MASK, yas5xx->calibration.dck);
ret = regmap_write(yas5xx->map, YAS530_CONFIG, val); if (ret) return ret;
/* Writing ADCCAL and TRM registers */
buf = cpu_to_be16(GENMASK(9, 3));
ret = regmap_bulk_write(yas5xx->map, YAS537_ADCCAL, &buf, sizeof(buf)); if (ret) return ret;
ret = regmap_write(yas5xx->map, YAS537_TRM, GENMASK(7, 0)); if (ret) return ret;
/* The interval value is static in regular operation */
intrvl = (YAS537_DEFAULT_SENSOR_DELAY_MS * MILLI
- YAS537_MEASURE_TIME_WORST_US) / 4100;
ret = regmap_write(yas5xx->map, YAS537_MEASURE_INTERVAL, intrvl); if (ret) return ret;
/* The average value is also static in regular operation */
ret = regmap_write(yas5xx->map, YAS537_AVR, YAS537_MAG_AVERAGE_32_MASK); if (ret) return ret;
/* Perform the "rcoil" part but skip the "last_after_rcoil" read */
ret = regmap_write(yas5xx->map, YAS537_CONFIG, BIT(3)); if (ret) return ret;
/* Wait until the coil has ramped up */
usleep_range(YAS537_MAG_RCOIL_TIME_US, YAS537_MAG_RCOIL_TIME_US + 100);
ret = iio_read_mount_matrix(dev, &yas5xx->orientation); if (ret) return ret;
yas5xx->regs[0].supply = "vdd";
yas5xx->regs[1].supply = "iovdd";
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(yas5xx->regs),
yas5xx->regs); if (ret) return dev_err_probe(dev, ret, "cannot get regulators\n");
ret = regulator_bulk_enable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); if (ret) return dev_err_probe(dev, ret, "cannot enable regulators\n");
/* See comment in runtime resume callback */
usleep_range(31000, 40000);
/* This will take the device out of reset if need be */
yas5xx->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(yas5xx->reset)) {
ret = dev_err_probe(dev, PTR_ERR(yas5xx->reset), "failed to get reset line\n"); goto reg_off;
}
yas5xx->map = devm_regmap_init_i2c(i2c, &yas5xx_regmap_config); if (IS_ERR(yas5xx->map)) {
ret = dev_err_probe(dev, PTR_ERR(yas5xx->map), "failed to allocate register map\n"); goto assert_reset;
}
ci = i2c_get_match_data(i2c);
yas5xx->chip_info = ci;
ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &id_check); if (ret) goto assert_reset;
if (id_check != ci->devid) {
ret = dev_err_probe(dev, -ENODEV, "device ID %02x doesn't match %s\n",
id_check, id->name); goto assert_reset;
}
ret = ci->get_calibration_data(yas5xx); if (ret) goto assert_reset;
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev); /* * Now we can't get any more reads from the device, which would * also call pm_runtime* functions and race with our disable * code. Disable PM runtime in orderly fashion and power down.
*/
pm_runtime_get_sync(dev);
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
gpiod_set_value_cansleep(yas5xx->reset, 1);
regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs);
}
ret = regulator_bulk_enable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); if (ret) {
dev_err(dev, "cannot enable regulators\n"); return ret;
}
/* * The YAS530 datasheet says TVSKW is up to 30 ms, after that 1 ms * for all voltages to settle. The YAS532 is 10ms then 4ms for the * I2C to come online. Let's keep it safe and put this at 31ms.
*/
usleep_range(31000, 40000);
gpiod_set_value_cansleep(yas5xx->reset, 0);
ret = ci->power_on(yas5xx); if (ret) {
dev_err(dev, "cannot power on\n"); goto out_reset;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.