/* Turn off device regulators etc after 5 seconds of inactivity */
 #define YAS5XX_AUTOSUSPEND_DELAY_MS    5000
 
+enum chip_ids {
+       yas530,
+       yas532,
+       yas533,
+};
+
 struct yas5xx_calibration {
        /* Linearization calibration x, y1, y2 */
        s32 r[3];
        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_names: version letters or namings
+ */
+struct yas5xx_chip_info {
+       unsigned int devid;
+       char *product_name;
+       char *version_names[2];
+};
+
 /**
  * struct yas5xx - state container for the YAS5xx driver
  * @dev: parent device pointer
- * @devid: device ID number
+ * @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
  */
 struct yas5xx {
        struct device *dev;
-       unsigned int devid;
+       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;
  */
 static int yas530_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y2)
 {
+       const struct yas5xx_chip_info *ci = yas5xx->chip_info;
        unsigned int busy;
        u8 data[8];
        int ret;
 
        mutex_unlock(&yas5xx->lock);
 
-       switch (yas5xx->devid) {
+       switch (ci->devid) {
        case YAS530_DEVICE_ID:
                /*
                 * The t value is 9 bits in big endian format
 /* Used by YAS530, YAS532 and YAS533 */
 static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis)
 {
+       const struct yas5xx_chip_info *ci = yas5xx->chip_info;
        struct yas5xx_calibration *c = &yas5xx->calibration;
        static const s32 yas532ac_coef[] = {
                YAS532_VERSION_AC_COEF_X,
        s32 coef;
 
        /* Select coefficients */
-       switch (yas5xx->devid) {
+       switch (ci->devid) {
        case YAS530_DEVICE_ID:
                if (yas5xx->version == YAS530_VERSION_A)
                        coef = YAS530_VERSION_A_COEF;
  */
 static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo)
 {
+       const struct yas5xx_chip_info *ci = yas5xx->chip_info;
        struct yas5xx_calibration *c = &yas5xx->calibration;
        u16 t_ref, t, x, y1, y2;
        /* These are signed x, signed y1 etc */
        sy2 = yas530_linearize(yas5xx, y2, 2);
 
        /* Set the temperature reference value (unit: counts) */
-       switch (yas5xx->devid) {
+       switch (ci->devid) {
        case YAS530_DEVICE_ID:
                t_ref = YAS530_20DEGREES;
                break;
        }
 
        /* Temperature compensation for x, y1, y2 respectively */
-       if (yas5xx->devid == YAS532_DEVICE_ID &&
+       if (ci->devid == YAS532_DEVICE_ID &&
            yas5xx->version == YAS532_VERSION_AC) {
                /*
                 * YAS532 version AC uses the temperature deviation as a
        sz = -sy1 - sy2;
 
        /* Process temperature readout */
-       switch (yas5xx->devid) {
+       switch (ci->devid) {
        case YAS530_DEVICE_ID:
                /*
                 * Raw temperature value t is the number of counts starting
                           long mask)
 {
        struct yas5xx *yas5xx = iio_priv(indio_dev);
+       const struct yas5xx_chip_info *ci = yas5xx->chip_info;
        s32 t, x, y, z;
        int ret;
 
                }
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_SCALE:
-               switch (yas5xx->devid) {
+               switch (ci->devid) {
                case YAS530_DEVICE_ID:
                        /*
                         * Raw values of YAS530 are in picotesla. Divide by
 /* Used by YAS530, YAS532 and YAS533 */
 static int yas530_measure_offsets(struct yas5xx *yas5xx)
 {
+       const struct yas5xx_chip_info *ci = yas5xx->chip_info;
        int ret;
        u16 center;
        u16 t, x, y1, y2;
                return ret;
 
        /* When the initcoil is active this should be around the center */
-       switch (yas5xx->devid) {
+       switch (ci->devid) {
        case YAS530_DEVICE_ID:
                center = YAS530_DATA_CENTER;
                break;
        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 = "YAS530 MS-3E",
+               .version_names = { "A", "B" },
+       },
+       [yas532] = {
+               .devid = YAS532_DEVICE_ID,
+               .product_name = "YAS532 MS-3R",
+               .version_names = { "AB", "AC" },
+       },
+       [yas533] = {
+               .devid = YAS532_DEVICE_ID,
+               .product_name = "YAS533 MS-3F",
+               .version_names = { "AB", "AC" },
+       },
+};
+
 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;
+       const struct yas5xx_chip_info *ci;
+       int id_check;
        int ret;
 
        indio_dev = devm_iio_device_alloc(dev, sizeof(*yas5xx));
                goto assert_reset;
        }
 
-       ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &yas5xx->devid);
+       yas5xx->chip_info = &yas5xx_chip_info_tbl[id->driver_data];
+       ci = yas5xx->chip_info;
+
+       ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &id_check);
        if (ret)
                goto assert_reset;
 
-       switch (yas5xx->devid) {
+       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;
+       }
+
+       switch (ci->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", ci->devid);
                goto assert_reset;
        }
 
+       dev_info(dev, "detected %s %s\n", ci->product_name,
+                ci->version_names[yas5xx->version]);
+
        yas530_dump_calibration(yas5xx);
        ret = yas530_power_on(yas5xx);
        if (ret)
        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);
 
                                 yas5xx_runtime_resume, NULL);
 
 static const struct i2c_device_id yas5xx_id[] = {
-       {"yas530", },
-       {"yas532", },
-       {"yas533", },
+       {"yas530", yas530 },
+       {"yas532", yas532 },
+       {"yas533", yas533 },
        {}
 };
 MODULE_DEVICE_TABLE(i2c, yas5xx_id);