Skip to content

Commit

Permalink
iio: magnetometer: yas530: Introduce "chip_info" structure
Browse files Browse the repository at this point in the history
This commit introduces the "chip_info" structure approach for better variant
handling.

The variant to be used is now chosen by the Device Tree (enum "chip_ids"),
not by the chip ID in the register. However, there is a check to make sure
they match (using integer "id_check").

Signed-off-by: Jakob Hauser <jahau@rocketmail.com>
  • Loading branch information
Jakko3 authored and intel-lab-lkp committed Aug 8, 2022
1 parent 4299204 commit 2e5a660
Showing 1 changed file with 83 additions and 24 deletions.
107 changes: 83 additions & 24 deletions drivers/iio/magnetometer/yamaha-yas530.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,24 @@
/* Turn off device regulators etc after 5 seconds of inactivity */
#define YAS5XX_AUTOSUSPEND_DELAY_MS 5000

enum chip_ids {
yas530,
yas532,
yas533,
};

static const char * const yas5xx_product_name[] = {
"YAS530 MS-3E",
"YAS532 MS-3R",
"YAS533 MS-3F",
};

static const char * const yas5xx_version_names[][2] = {
[yas530] = { "A", "B" },
[yas532] = { "AB", "AC" },
[yas533] = { "AB", "AC" },
};

struct yas5xx_calibration {
/* Linearization calibration x, y1, y2 */
s32 r[3];
Expand All @@ -110,12 +128,26 @@ struct yas5xx_calibration {
u8 dck;
};

struct yas5xx;

/**
* struct yas5xx_chip_info - device-specific data and function pointers
* @devid: device ID number
* @product_name: product name of the YAS variant
* @version_name: version letter or naming
*/
struct yas5xx_chip_info {
unsigned int devid;
const char *product_name;
const char * const *version_name;
};

/**
* struct yas5xx - state container for the YAS5xx driver
* @dev: parent device pointer
* @devid: device ID number
* @chip: enumeration of the device variant
* @chip_info: device-specific data
* @version: device version
* @name: device name
* @calibration: calibration settings from the OTP storage
* @hard_offsets: offsets for each axis measured with initcoil actuated
* @orientation: mounting matrix, flipped axis etc
Expand All @@ -129,9 +161,9 @@ struct yas5xx_calibration {
*/
struct yas5xx {
struct device *dev;
unsigned int devid;
enum chip_ids chip;
const struct yas5xx_chip_info *chip_info;
unsigned int version;
char name[16];
struct yas5xx_calibration calibration;
s8 hard_offsets[3];
struct iio_mount_matrix orientation;
Expand Down Expand Up @@ -222,7 +254,7 @@ static int yas530_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y

mutex_unlock(&yas5xx->lock);

switch (yas5xx->devid) {
switch (yas5xx->chip_info->devid) {
case YAS530_DEVICE_ID:
/*
* The t value is 9 bits in big endian format
Expand Down Expand Up @@ -276,7 +308,7 @@ static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis)
s32 coef;

/* Select coefficients */
switch (yas5xx->devid) {
switch (yas5xx->chip_info->devid) {
case YAS530_DEVICE_ID:
if (yas5xx->version == YAS530_VERSION_A)
coef = YAS530_VERSION_A_COEF;
Expand Down Expand Up @@ -336,7 +368,7 @@ static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo,
sy2 = yas530_linearize(yas5xx, y2, 2);

/* Set the temperature reference value (unit: counts) */
switch (yas5xx->devid) {
switch (yas5xx->chip_info->devid) {
case YAS530_DEVICE_ID:
t_ref = YAS530_20DEGREES;
break;
Expand All @@ -349,7 +381,7 @@ static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo,
}

/* Temperature compensation for x, y1, y2 respectively */
if (yas5xx->devid == YAS532_DEVICE_ID &&
if (yas5xx->chip_info->devid == YAS532_DEVICE_ID &&
yas5xx->version == YAS532_VERSION_AC) {
/*
* YAS532 version AC uses the temperature deviation as a
Expand Down Expand Up @@ -384,7 +416,7 @@ static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo,
sz = -sy1 - sy2;

/* Process temperature readout */
switch (yas5xx->devid) {
switch (yas5xx->chip_info->devid) {
case YAS530_DEVICE_ID:
/*
* Raw temperature value t is the number of counts starting
Expand Down Expand Up @@ -473,7 +505,7 @@ static int yas5xx_read_raw(struct iio_dev *indio_dev,
}
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
switch (yas5xx->devid) {
switch (yas5xx->chip_info->devid) {
case YAS530_DEVICE_ID:
/*
* Raw values of YAS530 are in picotesla. Divide by
Expand Down Expand Up @@ -814,7 +846,7 @@ static int yas530_measure_offsets(struct yas5xx *yas5xx)
return ret;

/* When the initcoil is active this should be around the center */
switch (yas5xx->devid) {
switch (yas5xx->chip_info->devid) {
case YAS530_DEVICE_ID:
center = YAS530_DATA_CENTER;
break;
Expand Down Expand Up @@ -895,12 +927,31 @@ static int yas530_power_on(struct yas5xx *yas5xx)
return regmap_write(yas5xx->map, YAS530_MEASURE_INTERVAL, 0);
}

static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = {
[yas530] = {
.devid = YAS530_DEVICE_ID,
.product_name = yas5xx_product_name[yas530],
.version_name = yas5xx_version_names[yas530],
},
[yas532] = {
.devid = YAS532_DEVICE_ID,
.product_name = yas5xx_product_name[yas532],
.version_name = yas5xx_version_names[yas532],
},
[yas533] = {
.devid = YAS532_DEVICE_ID,
.product_name = yas5xx_product_name[yas533],
.version_name = yas5xx_version_names[yas533],
},
};

static int yas5xx_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct device *dev = &i2c->dev;
struct yas5xx *yas5xx;
int id_check;
int ret;

indio_dev = devm_iio_device_alloc(dev, sizeof(*yas5xx));
Expand Down Expand Up @@ -947,33 +998,41 @@ static int yas5xx_probe(struct i2c_client *i2c,
goto assert_reset;
}

ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &yas5xx->devid);
yas5xx->chip = id->driver_data;
yas5xx->chip_info = &yas5xx_chip_info_tbl[yas5xx->chip];

ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &id_check);
if (ret)
goto assert_reset;

switch (yas5xx->devid) {
if (id_check != yas5xx->chip_info->devid) {
ret = dev_err_probe(dev, -ENODEV,
"device ID %02x doesn't match %s\n",
id_check, id->name);
goto assert_reset;
}

switch (yas5xx->chip_info->devid) {
case YAS530_DEVICE_ID:
ret = yas530_get_calibration_data(yas5xx);
if (ret)
goto assert_reset;
dev_info(dev, "detected YAS530 MS-3E %s",
yas5xx->version ? "B" : "A");
strncpy(yas5xx->name, "yas530", sizeof(yas5xx->name));
break;
case YAS532_DEVICE_ID:
ret = yas532_get_calibration_data(yas5xx);
if (ret)
goto assert_reset;
dev_info(dev, "detected YAS532/YAS533 MS-3R/F %s",
yas5xx->version ? "AC" : "AB");
strncpy(yas5xx->name, "yas532", sizeof(yas5xx->name));
break;
default:
ret = -ENODEV;
dev_err(dev, "unhandled device ID %02x\n", yas5xx->devid);
dev_err(dev, "unhandled device ID %02x\n",
yas5xx->chip_info->devid);
goto assert_reset;
}

dev_info(dev, "detected %s %s\n", yas5xx->chip_info->product_name,
yas5xx->chip_info->version_name[yas5xx->version]);

yas530_dump_calibration(yas5xx);
ret = yas530_power_on(yas5xx);
if (ret)
Expand All @@ -985,7 +1044,7 @@ static int yas5xx_probe(struct i2c_client *i2c,
indio_dev->info = &yas5xx_info;
indio_dev->available_scan_masks = yas5xx_scan_masks;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->name = yas5xx->name;
indio_dev->name = id->name;
indio_dev->channels = yas5xx_channels;
indio_dev->num_channels = ARRAY_SIZE(yas5xx_channels);

Expand Down Expand Up @@ -1100,9 +1159,9 @@ static const struct dev_pm_ops yas5xx_dev_pm_ops = {
};

static const struct i2c_device_id yas5xx_id[] = {
{"yas530", },
{"yas532", },
{"yas533", },
{"yas530", yas530 },
{"yas532", yas532 },
{"yas533", yas533 },
{}
};
MODULE_DEVICE_TABLE(i2c, yas5xx_id);
Expand Down

0 comments on commit 2e5a660

Please sign in to comment.