136edc939SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2abeb6b1eSDaniel Baluta /* 3abeb6b1eSDaniel Baluta * MMC35240 - MEMSIC 3-axis Magnetic Sensor 4abeb6b1eSDaniel Baluta * 5abeb6b1eSDaniel Baluta * Copyright (c) 2015, Intel Corporation. 6abeb6b1eSDaniel Baluta * 7abeb6b1eSDaniel Baluta * IIO driver for MMC35240 (7-bit I2C slave address 0x30). 8abeb6b1eSDaniel Baluta * 9abeb6b1eSDaniel Baluta * TODO: offset, ACPI, continuous measurement mode, PM 10abeb6b1eSDaniel Baluta */ 11abeb6b1eSDaniel Baluta 12abeb6b1eSDaniel Baluta #include <linux/module.h> 13abeb6b1eSDaniel Baluta #include <linux/init.h> 14abeb6b1eSDaniel Baluta #include <linux/i2c.h> 15abeb6b1eSDaniel Baluta #include <linux/delay.h> 16abeb6b1eSDaniel Baluta #include <linux/regmap.h> 17d11715f0SDaniel Baluta #include <linux/acpi.h> 18553a776bSDaniel Baluta #include <linux/pm.h> 19abeb6b1eSDaniel Baluta 20abeb6b1eSDaniel Baluta #include <linux/iio/iio.h> 21abeb6b1eSDaniel Baluta #include <linux/iio/sysfs.h> 22abeb6b1eSDaniel Baluta 23abeb6b1eSDaniel Baluta #define MMC35240_DRV_NAME "mmc35240" 24abeb6b1eSDaniel Baluta #define MMC35240_REGMAP_NAME "mmc35240_regmap" 25abeb6b1eSDaniel Baluta 26abeb6b1eSDaniel Baluta #define MMC35240_REG_XOUT_L 0x00 27abeb6b1eSDaniel Baluta #define MMC35240_REG_XOUT_H 0x01 28abeb6b1eSDaniel Baluta #define MMC35240_REG_YOUT_L 0x02 29abeb6b1eSDaniel Baluta #define MMC35240_REG_YOUT_H 0x03 30abeb6b1eSDaniel Baluta #define MMC35240_REG_ZOUT_L 0x04 31abeb6b1eSDaniel Baluta #define MMC35240_REG_ZOUT_H 0x05 32abeb6b1eSDaniel Baluta 33abeb6b1eSDaniel Baluta #define MMC35240_REG_STATUS 0x06 34abeb6b1eSDaniel Baluta #define MMC35240_REG_CTRL0 0x07 35abeb6b1eSDaniel Baluta #define MMC35240_REG_CTRL1 0x08 36abeb6b1eSDaniel Baluta 37abeb6b1eSDaniel Baluta #define MMC35240_REG_ID 0x20 38abeb6b1eSDaniel Baluta 39abeb6b1eSDaniel Baluta #define MMC35240_STATUS_MEAS_DONE_BIT BIT(0) 40abeb6b1eSDaniel Baluta 41abeb6b1eSDaniel Baluta #define MMC35240_CTRL0_REFILL_BIT BIT(7) 42abeb6b1eSDaniel Baluta #define MMC35240_CTRL0_RESET_BIT BIT(6) 43abeb6b1eSDaniel Baluta #define MMC35240_CTRL0_SET_BIT BIT(5) 44abeb6b1eSDaniel Baluta #define MMC35240_CTRL0_CMM_BIT BIT(1) 45abeb6b1eSDaniel Baluta #define MMC35240_CTRL0_TM_BIT BIT(0) 46abeb6b1eSDaniel Baluta 47abeb6b1eSDaniel Baluta /* output resolution bits */ 48abeb6b1eSDaniel Baluta #define MMC35240_CTRL1_BW0_BIT BIT(0) 49abeb6b1eSDaniel Baluta #define MMC35240_CTRL1_BW1_BIT BIT(1) 50abeb6b1eSDaniel Baluta 51abeb6b1eSDaniel Baluta #define MMC35240_CTRL1_BW_MASK (MMC35240_CTRL1_BW0_BIT | \ 52abeb6b1eSDaniel Baluta MMC35240_CTRL1_BW1_BIT) 53abeb6b1eSDaniel Baluta #define MMC35240_CTRL1_BW_SHIFT 0 54abeb6b1eSDaniel Baluta 55abeb6b1eSDaniel Baluta #define MMC35240_WAIT_CHARGE_PUMP 50000 /* us */ 56abeb6b1eSDaniel Baluta #define MMC53240_WAIT_SET_RESET 1000 /* us */ 57abeb6b1eSDaniel Baluta 584892688dSDaniel Baluta /* 594892688dSDaniel Baluta * Memsic OTP process code piece is put here for reference: 604892688dSDaniel Baluta * 614892688dSDaniel Baluta * #define OTP_CONVERT(REG) ((float)((REG) >=32 ? (32 - (REG)) : (REG)) * 0.006 624892688dSDaniel Baluta * 1) For X axis, the COEFFICIENT is always 1. 634892688dSDaniel Baluta * 2) For Y axis, the COEFFICIENT is as below: 644892688dSDaniel Baluta * f_OTP_matrix[4] = OTP_CONVERT(((reg_data[1] & 0x03) << 4) | 654892688dSDaniel Baluta * (reg_data[2] >> 4)) + 1.0; 664892688dSDaniel Baluta * 3) For Z axis, the COEFFICIENT is as below: 674892688dSDaniel Baluta * f_OTP_matrix[8] = (OTP_CONVERT(reg_data[3] & 0x3f) + 1) * 1.35; 684892688dSDaniel Baluta * We implemented the OTP logic into driver. 694892688dSDaniel Baluta */ 704892688dSDaniel Baluta 714892688dSDaniel Baluta /* scale = 1000 here for Y otp */ 724892688dSDaniel Baluta #define MMC35240_OTP_CONVERT_Y(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 6) 734892688dSDaniel Baluta 744892688dSDaniel Baluta /* 0.6 * 1.35 = 0.81, scale 10000 for Z otp */ 754892688dSDaniel Baluta #define MMC35240_OTP_CONVERT_Z(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 81) 764892688dSDaniel Baluta 774892688dSDaniel Baluta #define MMC35240_X_COEFF(x) (x) 784892688dSDaniel Baluta #define MMC35240_Y_COEFF(y) (y + 1000) 794892688dSDaniel Baluta #define MMC35240_Z_COEFF(z) (z + 13500) 804892688dSDaniel Baluta 814892688dSDaniel Baluta #define MMC35240_OTP_START_ADDR 0x1B 824892688dSDaniel Baluta 83abeb6b1eSDaniel Baluta enum mmc35240_resolution { 84c99389adSTeodora Baluta MMC35240_16_BITS_SLOW = 0, /* 7.92 ms */ 85c99389adSTeodora Baluta MMC35240_16_BITS_FAST, /* 4.08 ms */ 86c99389adSTeodora Baluta MMC35240_14_BITS, /* 2.16 ms */ 87c99389adSTeodora Baluta MMC35240_12_BITS, /* 1.20 ms */ 88abeb6b1eSDaniel Baluta }; 89abeb6b1eSDaniel Baluta 90abeb6b1eSDaniel Baluta enum mmc35240_axis { 91abeb6b1eSDaniel Baluta AXIS_X = 0, 92abeb6b1eSDaniel Baluta AXIS_Y, 93abeb6b1eSDaniel Baluta AXIS_Z, 94abeb6b1eSDaniel Baluta }; 95abeb6b1eSDaniel Baluta 96abeb6b1eSDaniel Baluta static const struct { 97abeb6b1eSDaniel Baluta int sens[3]; /* sensitivity per X, Y, Z axis */ 98abeb6b1eSDaniel Baluta int nfo; /* null field output */ 99abeb6b1eSDaniel Baluta } mmc35240_props_table[] = { 100c99389adSTeodora Baluta /* 16 bits, 125Hz ODR */ 101abeb6b1eSDaniel Baluta { 1026b90da4bSDaniel Baluta {1024, 1024, 1024}, 103abeb6b1eSDaniel Baluta 32768, 104abeb6b1eSDaniel Baluta }, 105c99389adSTeodora Baluta /* 16 bits, 250Hz ODR */ 106abeb6b1eSDaniel Baluta { 107abeb6b1eSDaniel Baluta {1024, 1024, 770}, 108abeb6b1eSDaniel Baluta 32768, 109abeb6b1eSDaniel Baluta }, 110c99389adSTeodora Baluta /* 14 bits, 450Hz ODR */ 111abeb6b1eSDaniel Baluta { 112abeb6b1eSDaniel Baluta {256, 256, 193}, 113abeb6b1eSDaniel Baluta 8192, 114abeb6b1eSDaniel Baluta }, 115c99389adSTeodora Baluta /* 12 bits, 800Hz ODR */ 116abeb6b1eSDaniel Baluta { 117abeb6b1eSDaniel Baluta {64, 64, 48}, 118abeb6b1eSDaniel Baluta 2048, 119abeb6b1eSDaniel Baluta }, 120abeb6b1eSDaniel Baluta }; 121abeb6b1eSDaniel Baluta 122abeb6b1eSDaniel Baluta struct mmc35240_data { 123abeb6b1eSDaniel Baluta struct i2c_client *client; 124abeb6b1eSDaniel Baluta struct mutex mutex; 125abeb6b1eSDaniel Baluta struct regmap *regmap; 126abeb6b1eSDaniel Baluta enum mmc35240_resolution res; 1274892688dSDaniel Baluta 1284892688dSDaniel Baluta /* OTP compensation */ 1294892688dSDaniel Baluta int axis_coef[3]; 1304892688dSDaniel Baluta int axis_scale[3]; 131abeb6b1eSDaniel Baluta }; 132abeb6b1eSDaniel Baluta 133c99389adSTeodora Baluta static const struct { 134c99389adSTeodora Baluta int val; 135c99389adSTeodora Baluta int val2; 136c99389adSTeodora Baluta } mmc35240_samp_freq[] = { {1, 500000}, 137c99389adSTeodora Baluta {13, 0}, 138c99389adSTeodora Baluta {25, 0}, 139c99389adSTeodora Baluta {50, 0} }; 140abeb6b1eSDaniel Baluta 141c99389adSTeodora Baluta static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1.5 13 25 50"); 142abeb6b1eSDaniel Baluta 143abeb6b1eSDaniel Baluta #define MMC35240_CHANNEL(_axis) { \ 144abeb6b1eSDaniel Baluta .type = IIO_MAGN, \ 145abeb6b1eSDaniel Baluta .modified = 1, \ 146abeb6b1eSDaniel Baluta .channel2 = IIO_MOD_ ## _axis, \ 147abeb6b1eSDaniel Baluta .address = AXIS_ ## _axis, \ 148c2890547SDaniel Baluta .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 149c2890547SDaniel Baluta .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 150c2890547SDaniel Baluta BIT(IIO_CHAN_INFO_SCALE), \ 151abeb6b1eSDaniel Baluta } 152abeb6b1eSDaniel Baluta 153abeb6b1eSDaniel Baluta static const struct iio_chan_spec mmc35240_channels[] = { 154abeb6b1eSDaniel Baluta MMC35240_CHANNEL(X), 155abeb6b1eSDaniel Baluta MMC35240_CHANNEL(Y), 156abeb6b1eSDaniel Baluta MMC35240_CHANNEL(Z), 157abeb6b1eSDaniel Baluta }; 158abeb6b1eSDaniel Baluta 159abeb6b1eSDaniel Baluta static struct attribute *mmc35240_attributes[] = { 160abeb6b1eSDaniel Baluta &iio_const_attr_sampling_frequency_available.dev_attr.attr, 161bd35a214SDaniel Baluta NULL 162abeb6b1eSDaniel Baluta }; 163abeb6b1eSDaniel Baluta 164abeb6b1eSDaniel Baluta static const struct attribute_group mmc35240_attribute_group = { 165abeb6b1eSDaniel Baluta .attrs = mmc35240_attributes, 166abeb6b1eSDaniel Baluta }; 167abeb6b1eSDaniel Baluta 168abeb6b1eSDaniel Baluta static int mmc35240_get_samp_freq_index(struct mmc35240_data *data, 169abeb6b1eSDaniel Baluta int val, int val2) 170abeb6b1eSDaniel Baluta { 171abeb6b1eSDaniel Baluta int i; 172abeb6b1eSDaniel Baluta 173abeb6b1eSDaniel Baluta for (i = 0; i < ARRAY_SIZE(mmc35240_samp_freq); i++) 174c99389adSTeodora Baluta if (mmc35240_samp_freq[i].val == val && 175c99389adSTeodora Baluta mmc35240_samp_freq[i].val2 == val2) 176abeb6b1eSDaniel Baluta return i; 177abeb6b1eSDaniel Baluta return -EINVAL; 178abeb6b1eSDaniel Baluta } 179abeb6b1eSDaniel Baluta 180abeb6b1eSDaniel Baluta static int mmc35240_hw_set(struct mmc35240_data *data, bool set) 181abeb6b1eSDaniel Baluta { 182abeb6b1eSDaniel Baluta int ret; 183abeb6b1eSDaniel Baluta u8 coil_bit; 184abeb6b1eSDaniel Baluta 185abeb6b1eSDaniel Baluta /* 186abeb6b1eSDaniel Baluta * Recharge the capacitor at VCAP pin, requested to be issued 187abeb6b1eSDaniel Baluta * before a SET/RESET command. 188abeb6b1eSDaniel Baluta */ 189abeb6b1eSDaniel Baluta ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, 190abeb6b1eSDaniel Baluta MMC35240_CTRL0_REFILL_BIT, 191abeb6b1eSDaniel Baluta MMC35240_CTRL0_REFILL_BIT); 192abeb6b1eSDaniel Baluta if (ret < 0) 193abeb6b1eSDaniel Baluta return ret; 194abeb6b1eSDaniel Baluta usleep_range(MMC35240_WAIT_CHARGE_PUMP, MMC35240_WAIT_CHARGE_PUMP + 1); 195abeb6b1eSDaniel Baluta 196abeb6b1eSDaniel Baluta if (set) 197abeb6b1eSDaniel Baluta coil_bit = MMC35240_CTRL0_SET_BIT; 198abeb6b1eSDaniel Baluta else 199abeb6b1eSDaniel Baluta coil_bit = MMC35240_CTRL0_RESET_BIT; 200abeb6b1eSDaniel Baluta 201abeb6b1eSDaniel Baluta return regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, 2023ceaa2c2SDaniel Baluta coil_bit, coil_bit); 2033ceaa2c2SDaniel Baluta 204abeb6b1eSDaniel Baluta } 205abeb6b1eSDaniel Baluta 206abeb6b1eSDaniel Baluta static int mmc35240_init(struct mmc35240_data *data) 207abeb6b1eSDaniel Baluta { 2084892688dSDaniel Baluta int ret, y_convert, z_convert; 209abeb6b1eSDaniel Baluta unsigned int reg_id; 2104892688dSDaniel Baluta u8 otp_data[6]; 211abeb6b1eSDaniel Baluta 212abeb6b1eSDaniel Baluta ret = regmap_read(data->regmap, MMC35240_REG_ID, ®_id); 213abeb6b1eSDaniel Baluta if (ret < 0) { 214abeb6b1eSDaniel Baluta dev_err(&data->client->dev, "Error reading product id\n"); 215abeb6b1eSDaniel Baluta return ret; 216abeb6b1eSDaniel Baluta } 217abeb6b1eSDaniel Baluta 218abeb6b1eSDaniel Baluta dev_dbg(&data->client->dev, "MMC35240 chip id %x\n", reg_id); 219abeb6b1eSDaniel Baluta 220abeb6b1eSDaniel Baluta /* 221abeb6b1eSDaniel Baluta * make sure we restore sensor characteristics, by doing 222354c879dSViorel Suman * a SET/RESET sequence, the axis polarity being naturally 223354c879dSViorel Suman * aligned after RESET 224abeb6b1eSDaniel Baluta */ 225354c879dSViorel Suman ret = mmc35240_hw_set(data, true); 226abeb6b1eSDaniel Baluta if (ret < 0) 227abeb6b1eSDaniel Baluta return ret; 228abeb6b1eSDaniel Baluta usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1); 229abeb6b1eSDaniel Baluta 230354c879dSViorel Suman ret = mmc35240_hw_set(data, false); 231abeb6b1eSDaniel Baluta if (ret < 0) 232abeb6b1eSDaniel Baluta return ret; 233abeb6b1eSDaniel Baluta 234abeb6b1eSDaniel Baluta /* set default sampling frequency */ 2354892688dSDaniel Baluta ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1, 236abeb6b1eSDaniel Baluta MMC35240_CTRL1_BW_MASK, 237abeb6b1eSDaniel Baluta data->res << MMC35240_CTRL1_BW_SHIFT); 2384892688dSDaniel Baluta if (ret < 0) 2394892688dSDaniel Baluta return ret; 2404892688dSDaniel Baluta 2414892688dSDaniel Baluta ret = regmap_bulk_read(data->regmap, MMC35240_OTP_START_ADDR, 2424892688dSDaniel Baluta (u8 *)otp_data, sizeof(otp_data)); 2434892688dSDaniel Baluta if (ret < 0) 2444892688dSDaniel Baluta return ret; 2454892688dSDaniel Baluta 2464892688dSDaniel Baluta y_convert = MMC35240_OTP_CONVERT_Y(((otp_data[1] & 0x03) << 4) | 2474892688dSDaniel Baluta (otp_data[2] >> 4)); 2484892688dSDaniel Baluta z_convert = MMC35240_OTP_CONVERT_Z(otp_data[3] & 0x3f); 2494892688dSDaniel Baluta 2504892688dSDaniel Baluta data->axis_coef[0] = MMC35240_X_COEFF(1); 2514892688dSDaniel Baluta data->axis_coef[1] = MMC35240_Y_COEFF(y_convert); 2524892688dSDaniel Baluta data->axis_coef[2] = MMC35240_Z_COEFF(z_convert); 2534892688dSDaniel Baluta 2544892688dSDaniel Baluta data->axis_scale[0] = 1; 2554892688dSDaniel Baluta data->axis_scale[1] = 1000; 2564892688dSDaniel Baluta data->axis_scale[2] = 10000; 2574892688dSDaniel Baluta 2584892688dSDaniel Baluta return 0; 259abeb6b1eSDaniel Baluta } 260abeb6b1eSDaniel Baluta 261abeb6b1eSDaniel Baluta static int mmc35240_take_measurement(struct mmc35240_data *data) 262abeb6b1eSDaniel Baluta { 263abeb6b1eSDaniel Baluta int ret, tries = 100; 264abeb6b1eSDaniel Baluta unsigned int reg_status; 265abeb6b1eSDaniel Baluta 266abeb6b1eSDaniel Baluta ret = regmap_write(data->regmap, MMC35240_REG_CTRL0, 267abeb6b1eSDaniel Baluta MMC35240_CTRL0_TM_BIT); 268abeb6b1eSDaniel Baluta if (ret < 0) 269abeb6b1eSDaniel Baluta return ret; 270abeb6b1eSDaniel Baluta 271abeb6b1eSDaniel Baluta while (tries-- > 0) { 272abeb6b1eSDaniel Baluta ret = regmap_read(data->regmap, MMC35240_REG_STATUS, 273abeb6b1eSDaniel Baluta ®_status); 274abeb6b1eSDaniel Baluta if (ret < 0) 275abeb6b1eSDaniel Baluta return ret; 276abeb6b1eSDaniel Baluta if (reg_status & MMC35240_STATUS_MEAS_DONE_BIT) 277abeb6b1eSDaniel Baluta break; 278787f55c4SDaniel Baluta /* minimum wait time to complete measurement is 10 ms */ 279787f55c4SDaniel Baluta usleep_range(10000, 11000); 280abeb6b1eSDaniel Baluta } 281abeb6b1eSDaniel Baluta 282abeb6b1eSDaniel Baluta if (tries < 0) { 283abeb6b1eSDaniel Baluta dev_err(&data->client->dev, "data not ready\n"); 284abeb6b1eSDaniel Baluta return -EIO; 285abeb6b1eSDaniel Baluta } 286abeb6b1eSDaniel Baluta 287abeb6b1eSDaniel Baluta return 0; 288abeb6b1eSDaniel Baluta } 289abeb6b1eSDaniel Baluta 290abeb6b1eSDaniel Baluta static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3]) 291abeb6b1eSDaniel Baluta { 292abeb6b1eSDaniel Baluta int ret; 293abeb6b1eSDaniel Baluta 294abeb6b1eSDaniel Baluta ret = mmc35240_take_measurement(data); 295abeb6b1eSDaniel Baluta if (ret < 0) 296abeb6b1eSDaniel Baluta return ret; 297abeb6b1eSDaniel Baluta 298abeb6b1eSDaniel Baluta return regmap_bulk_read(data->regmap, MMC35240_REG_XOUT_L, (u8 *)buf, 299abeb6b1eSDaniel Baluta 3 * sizeof(__le16)); 300abeb6b1eSDaniel Baluta } 301abeb6b1eSDaniel Baluta 302c2890547SDaniel Baluta /** 303c2890547SDaniel Baluta * mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply 304c2890547SDaniel Baluta compensation for output value. 305c2890547SDaniel Baluta * 306c2890547SDaniel Baluta * @data: device private data 307c2890547SDaniel Baluta * @index: axis index for which we want the conversion 308c2890547SDaniel Baluta * @buf: raw data to be converted, 2 bytes in little endian format 309c2890547SDaniel Baluta * @val: compensated output reading (unit is milli gauss) 310c2890547SDaniel Baluta * 311c2890547SDaniel Baluta * Returns: 0 in case of success, -EINVAL when @index is not valid 312c2890547SDaniel Baluta */ 313c2890547SDaniel Baluta static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index, 314c2890547SDaniel Baluta __le16 buf[], int *val) 315abeb6b1eSDaniel Baluta { 3169e35d366STeodora Baluta int raw[3]; 3179e35d366STeodora Baluta int sens[3]; 318abeb6b1eSDaniel Baluta int nfo; 319abeb6b1eSDaniel Baluta 3209e35d366STeodora Baluta raw[AXIS_X] = le16_to_cpu(buf[AXIS_X]); 3219e35d366STeodora Baluta raw[AXIS_Y] = le16_to_cpu(buf[AXIS_Y]); 3229e35d366STeodora Baluta raw[AXIS_Z] = le16_to_cpu(buf[AXIS_Z]); 323abeb6b1eSDaniel Baluta 3249e35d366STeodora Baluta sens[AXIS_X] = mmc35240_props_table[data->res].sens[AXIS_X]; 3259e35d366STeodora Baluta sens[AXIS_Y] = mmc35240_props_table[data->res].sens[AXIS_Y]; 3269e35d366STeodora Baluta sens[AXIS_Z] = mmc35240_props_table[data->res].sens[AXIS_Z]; 327abeb6b1eSDaniel Baluta 328abeb6b1eSDaniel Baluta nfo = mmc35240_props_table[data->res].nfo; 329abeb6b1eSDaniel Baluta 330abeb6b1eSDaniel Baluta switch (index) { 331abeb6b1eSDaniel Baluta case AXIS_X: 3329e35d366STeodora Baluta *val = (raw[AXIS_X] - nfo) * 1000 / sens[AXIS_X]; 333abeb6b1eSDaniel Baluta break; 334abeb6b1eSDaniel Baluta case AXIS_Y: 3359e35d366STeodora Baluta *val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] - 3369e35d366STeodora Baluta (raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z]; 337abeb6b1eSDaniel Baluta break; 338abeb6b1eSDaniel Baluta case AXIS_Z: 3399e35d366STeodora Baluta *val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] + 3409e35d366STeodora Baluta (raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z]; 341abeb6b1eSDaniel Baluta break; 342abeb6b1eSDaniel Baluta default: 343abeb6b1eSDaniel Baluta return -EINVAL; 344abeb6b1eSDaniel Baluta } 3454892688dSDaniel Baluta /* apply OTP compensation */ 3464892688dSDaniel Baluta *val = (*val) * data->axis_coef[index] / data->axis_scale[index]; 3474892688dSDaniel Baluta 348abeb6b1eSDaniel Baluta return 0; 349abeb6b1eSDaniel Baluta } 350abeb6b1eSDaniel Baluta 351abeb6b1eSDaniel Baluta static int mmc35240_read_raw(struct iio_dev *indio_dev, 352abeb6b1eSDaniel Baluta struct iio_chan_spec const *chan, int *val, 353abeb6b1eSDaniel Baluta int *val2, long mask) 354abeb6b1eSDaniel Baluta { 355abeb6b1eSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 356abeb6b1eSDaniel Baluta int ret, i; 357abeb6b1eSDaniel Baluta unsigned int reg; 358abeb6b1eSDaniel Baluta __le16 buf[3]; 359abeb6b1eSDaniel Baluta 360abeb6b1eSDaniel Baluta switch (mask) { 361c2890547SDaniel Baluta case IIO_CHAN_INFO_RAW: 362abeb6b1eSDaniel Baluta mutex_lock(&data->mutex); 363abeb6b1eSDaniel Baluta ret = mmc35240_read_measurement(data, buf); 364abeb6b1eSDaniel Baluta mutex_unlock(&data->mutex); 365abeb6b1eSDaniel Baluta if (ret < 0) 366abeb6b1eSDaniel Baluta return ret; 367c2890547SDaniel Baluta ret = mmc35240_raw_to_mgauss(data, chan->address, buf, val); 368abeb6b1eSDaniel Baluta if (ret < 0) 369abeb6b1eSDaniel Baluta return ret; 370c2890547SDaniel Baluta return IIO_VAL_INT; 371c2890547SDaniel Baluta case IIO_CHAN_INFO_SCALE: 372c2890547SDaniel Baluta *val = 0; 373c2890547SDaniel Baluta *val2 = 1000; 374abeb6b1eSDaniel Baluta return IIO_VAL_INT_PLUS_MICRO; 375abeb6b1eSDaniel Baluta case IIO_CHAN_INFO_SAMP_FREQ: 376abeb6b1eSDaniel Baluta mutex_lock(&data->mutex); 377abeb6b1eSDaniel Baluta ret = regmap_read(data->regmap, MMC35240_REG_CTRL1, ®); 378abeb6b1eSDaniel Baluta mutex_unlock(&data->mutex); 379abeb6b1eSDaniel Baluta if (ret < 0) 380abeb6b1eSDaniel Baluta return ret; 381abeb6b1eSDaniel Baluta 382abeb6b1eSDaniel Baluta i = (reg & MMC35240_CTRL1_BW_MASK) >> MMC35240_CTRL1_BW_SHIFT; 3835517547bSDan Carpenter if (i < 0 || i >= ARRAY_SIZE(mmc35240_samp_freq)) 384abeb6b1eSDaniel Baluta return -EINVAL; 385abeb6b1eSDaniel Baluta 386c99389adSTeodora Baluta *val = mmc35240_samp_freq[i].val; 387c99389adSTeodora Baluta *val2 = mmc35240_samp_freq[i].val2; 388c99389adSTeodora Baluta return IIO_VAL_INT_PLUS_MICRO; 389abeb6b1eSDaniel Baluta default: 390abeb6b1eSDaniel Baluta return -EINVAL; 391abeb6b1eSDaniel Baluta } 392abeb6b1eSDaniel Baluta } 393abeb6b1eSDaniel Baluta 394abeb6b1eSDaniel Baluta static int mmc35240_write_raw(struct iio_dev *indio_dev, 395abeb6b1eSDaniel Baluta struct iio_chan_spec const *chan, int val, 396abeb6b1eSDaniel Baluta int val2, long mask) 397abeb6b1eSDaniel Baluta { 398abeb6b1eSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 399abeb6b1eSDaniel Baluta int i, ret; 400abeb6b1eSDaniel Baluta 401abeb6b1eSDaniel Baluta switch (mask) { 402abeb6b1eSDaniel Baluta case IIO_CHAN_INFO_SAMP_FREQ: 403abeb6b1eSDaniel Baluta i = mmc35240_get_samp_freq_index(data, val, val2); 404abeb6b1eSDaniel Baluta if (i < 0) 405abeb6b1eSDaniel Baluta return -EINVAL; 406abeb6b1eSDaniel Baluta mutex_lock(&data->mutex); 407abeb6b1eSDaniel Baluta ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1, 408abeb6b1eSDaniel Baluta MMC35240_CTRL1_BW_MASK, 409abeb6b1eSDaniel Baluta i << MMC35240_CTRL1_BW_SHIFT); 410abeb6b1eSDaniel Baluta mutex_unlock(&data->mutex); 411abeb6b1eSDaniel Baluta return ret; 412abeb6b1eSDaniel Baluta default: 413abeb6b1eSDaniel Baluta return -EINVAL; 414abeb6b1eSDaniel Baluta } 415abeb6b1eSDaniel Baluta } 416abeb6b1eSDaniel Baluta 417abeb6b1eSDaniel Baluta static const struct iio_info mmc35240_info = { 418abeb6b1eSDaniel Baluta .read_raw = mmc35240_read_raw, 419abeb6b1eSDaniel Baluta .write_raw = mmc35240_write_raw, 420abeb6b1eSDaniel Baluta .attrs = &mmc35240_attribute_group, 421abeb6b1eSDaniel Baluta }; 422abeb6b1eSDaniel Baluta 423abeb6b1eSDaniel Baluta static bool mmc35240_is_writeable_reg(struct device *dev, unsigned int reg) 424abeb6b1eSDaniel Baluta { 425abeb6b1eSDaniel Baluta switch (reg) { 426abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL0: 427abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL1: 428abeb6b1eSDaniel Baluta return true; 429abeb6b1eSDaniel Baluta default: 430abeb6b1eSDaniel Baluta return false; 431abeb6b1eSDaniel Baluta } 432abeb6b1eSDaniel Baluta } 433abeb6b1eSDaniel Baluta 434abeb6b1eSDaniel Baluta static bool mmc35240_is_readable_reg(struct device *dev, unsigned int reg) 435abeb6b1eSDaniel Baluta { 436abeb6b1eSDaniel Baluta switch (reg) { 437abeb6b1eSDaniel Baluta case MMC35240_REG_XOUT_L: 438abeb6b1eSDaniel Baluta case MMC35240_REG_XOUT_H: 439abeb6b1eSDaniel Baluta case MMC35240_REG_YOUT_L: 440abeb6b1eSDaniel Baluta case MMC35240_REG_YOUT_H: 441abeb6b1eSDaniel Baluta case MMC35240_REG_ZOUT_L: 442abeb6b1eSDaniel Baluta case MMC35240_REG_ZOUT_H: 443abeb6b1eSDaniel Baluta case MMC35240_REG_STATUS: 444abeb6b1eSDaniel Baluta case MMC35240_REG_ID: 445abeb6b1eSDaniel Baluta return true; 446abeb6b1eSDaniel Baluta default: 447abeb6b1eSDaniel Baluta return false; 448abeb6b1eSDaniel Baluta } 449abeb6b1eSDaniel Baluta } 450abeb6b1eSDaniel Baluta 451abeb6b1eSDaniel Baluta static bool mmc35240_is_volatile_reg(struct device *dev, unsigned int reg) 452abeb6b1eSDaniel Baluta { 453abeb6b1eSDaniel Baluta switch (reg) { 454abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL0: 455abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL1: 456abeb6b1eSDaniel Baluta return false; 457abeb6b1eSDaniel Baluta default: 458abeb6b1eSDaniel Baluta return true; 459abeb6b1eSDaniel Baluta } 460abeb6b1eSDaniel Baluta } 461abeb6b1eSDaniel Baluta 462abeb6b1eSDaniel Baluta static struct reg_default mmc35240_reg_defaults[] = { 463abeb6b1eSDaniel Baluta { MMC35240_REG_CTRL0, 0x00 }, 464abeb6b1eSDaniel Baluta { MMC35240_REG_CTRL1, 0x00 }, 465abeb6b1eSDaniel Baluta }; 466abeb6b1eSDaniel Baluta 467abeb6b1eSDaniel Baluta static const struct regmap_config mmc35240_regmap_config = { 468abeb6b1eSDaniel Baluta .name = MMC35240_REGMAP_NAME, 469abeb6b1eSDaniel Baluta 470abeb6b1eSDaniel Baluta .reg_bits = 8, 471abeb6b1eSDaniel Baluta .val_bits = 8, 472abeb6b1eSDaniel Baluta 473abeb6b1eSDaniel Baluta .max_register = MMC35240_REG_ID, 474abeb6b1eSDaniel Baluta .cache_type = REGCACHE_FLAT, 475abeb6b1eSDaniel Baluta 476abeb6b1eSDaniel Baluta .writeable_reg = mmc35240_is_writeable_reg, 477abeb6b1eSDaniel Baluta .readable_reg = mmc35240_is_readable_reg, 478abeb6b1eSDaniel Baluta .volatile_reg = mmc35240_is_volatile_reg, 479abeb6b1eSDaniel Baluta 480abeb6b1eSDaniel Baluta .reg_defaults = mmc35240_reg_defaults, 481abeb6b1eSDaniel Baluta .num_reg_defaults = ARRAY_SIZE(mmc35240_reg_defaults), 482abeb6b1eSDaniel Baluta }; 483abeb6b1eSDaniel Baluta 484abeb6b1eSDaniel Baluta static int mmc35240_probe(struct i2c_client *client, 485abeb6b1eSDaniel Baluta const struct i2c_device_id *id) 486abeb6b1eSDaniel Baluta { 487abeb6b1eSDaniel Baluta struct mmc35240_data *data; 488abeb6b1eSDaniel Baluta struct iio_dev *indio_dev; 489abeb6b1eSDaniel Baluta struct regmap *regmap; 490abeb6b1eSDaniel Baluta int ret; 491abeb6b1eSDaniel Baluta 492abeb6b1eSDaniel Baluta indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 493abeb6b1eSDaniel Baluta if (!indio_dev) 494abeb6b1eSDaniel Baluta return -ENOMEM; 495abeb6b1eSDaniel Baluta 496abeb6b1eSDaniel Baluta regmap = devm_regmap_init_i2c(client, &mmc35240_regmap_config); 497abeb6b1eSDaniel Baluta if (IS_ERR(regmap)) { 498abeb6b1eSDaniel Baluta dev_err(&client->dev, "regmap initialization failed\n"); 499abeb6b1eSDaniel Baluta return PTR_ERR(regmap); 500abeb6b1eSDaniel Baluta } 501abeb6b1eSDaniel Baluta 502abeb6b1eSDaniel Baluta data = iio_priv(indio_dev); 5038b14821aSDaniel Baluta i2c_set_clientdata(client, indio_dev); 504abeb6b1eSDaniel Baluta data->client = client; 505abeb6b1eSDaniel Baluta data->regmap = regmap; 506abeb6b1eSDaniel Baluta data->res = MMC35240_16_BITS_SLOW; 507abeb6b1eSDaniel Baluta 508abeb6b1eSDaniel Baluta mutex_init(&data->mutex); 509abeb6b1eSDaniel Baluta 510abeb6b1eSDaniel Baluta indio_dev->dev.parent = &client->dev; 511abeb6b1eSDaniel Baluta indio_dev->info = &mmc35240_info; 512abeb6b1eSDaniel Baluta indio_dev->name = MMC35240_DRV_NAME; 513abeb6b1eSDaniel Baluta indio_dev->channels = mmc35240_channels; 514abeb6b1eSDaniel Baluta indio_dev->num_channels = ARRAY_SIZE(mmc35240_channels); 515abeb6b1eSDaniel Baluta indio_dev->modes = INDIO_DIRECT_MODE; 516abeb6b1eSDaniel Baluta 517abeb6b1eSDaniel Baluta ret = mmc35240_init(data); 518abeb6b1eSDaniel Baluta if (ret < 0) { 519abeb6b1eSDaniel Baluta dev_err(&client->dev, "mmc35240 chip init failed\n"); 520abeb6b1eSDaniel Baluta return ret; 521abeb6b1eSDaniel Baluta } 522abeb6b1eSDaniel Baluta return devm_iio_device_register(&client->dev, indio_dev); 523abeb6b1eSDaniel Baluta } 524abeb6b1eSDaniel Baluta 525553a776bSDaniel Baluta #ifdef CONFIG_PM_SLEEP 526553a776bSDaniel Baluta static int mmc35240_suspend(struct device *dev) 527553a776bSDaniel Baluta { 528553a776bSDaniel Baluta struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 529553a776bSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 530553a776bSDaniel Baluta 531553a776bSDaniel Baluta regcache_cache_only(data->regmap, true); 532553a776bSDaniel Baluta 533553a776bSDaniel Baluta return 0; 534553a776bSDaniel Baluta } 535553a776bSDaniel Baluta 536553a776bSDaniel Baluta static int mmc35240_resume(struct device *dev) 537553a776bSDaniel Baluta { 538553a776bSDaniel Baluta struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 539553a776bSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 540553a776bSDaniel Baluta int ret; 541553a776bSDaniel Baluta 542553a776bSDaniel Baluta regcache_mark_dirty(data->regmap); 543553a776bSDaniel Baluta ret = regcache_sync_region(data->regmap, MMC35240_REG_CTRL0, 544553a776bSDaniel Baluta MMC35240_REG_CTRL1); 545553a776bSDaniel Baluta if (ret < 0) 546553a776bSDaniel Baluta dev_err(dev, "Failed to restore control registers\n"); 547553a776bSDaniel Baluta 548553a776bSDaniel Baluta regcache_cache_only(data->regmap, false); 549553a776bSDaniel Baluta 550553a776bSDaniel Baluta return 0; 551553a776bSDaniel Baluta } 552553a776bSDaniel Baluta #endif 553553a776bSDaniel Baluta 554553a776bSDaniel Baluta static const struct dev_pm_ops mmc35240_pm_ops = { 555553a776bSDaniel Baluta SET_SYSTEM_SLEEP_PM_OPS(mmc35240_suspend, mmc35240_resume) 556553a776bSDaniel Baluta }; 557553a776bSDaniel Baluta 5587dbf1ea8SJandy Gou static const struct of_device_id mmc35240_of_match[] = { 5597dbf1ea8SJandy Gou { .compatible = "memsic,mmc35240", }, 5607dbf1ea8SJandy Gou { } 5617dbf1ea8SJandy Gou }; 5627dbf1ea8SJandy Gou MODULE_DEVICE_TABLE(of, mmc35240_of_match); 5637dbf1ea8SJandy Gou 564d11715f0SDaniel Baluta static const struct acpi_device_id mmc35240_acpi_match[] = { 565d11715f0SDaniel Baluta {"MMC35240", 0}, 566d11715f0SDaniel Baluta { }, 567d11715f0SDaniel Baluta }; 568d11715f0SDaniel Baluta MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match); 569d11715f0SDaniel Baluta 570abeb6b1eSDaniel Baluta static const struct i2c_device_id mmc35240_id[] = { 571a52ffebcSDaniel Baluta {"mmc35240", 0}, 572abeb6b1eSDaniel Baluta {} 573abeb6b1eSDaniel Baluta }; 574abeb6b1eSDaniel Baluta MODULE_DEVICE_TABLE(i2c, mmc35240_id); 575abeb6b1eSDaniel Baluta 576abeb6b1eSDaniel Baluta static struct i2c_driver mmc35240_driver = { 577abeb6b1eSDaniel Baluta .driver = { 578abeb6b1eSDaniel Baluta .name = MMC35240_DRV_NAME, 5797dbf1ea8SJandy Gou .of_match_table = mmc35240_of_match, 580553a776bSDaniel Baluta .pm = &mmc35240_pm_ops, 581d11715f0SDaniel Baluta .acpi_match_table = ACPI_PTR(mmc35240_acpi_match), 582abeb6b1eSDaniel Baluta }, 583abeb6b1eSDaniel Baluta .probe = mmc35240_probe, 584abeb6b1eSDaniel Baluta .id_table = mmc35240_id, 585abeb6b1eSDaniel Baluta }; 586abeb6b1eSDaniel Baluta 587abeb6b1eSDaniel Baluta module_i2c_driver(mmc35240_driver); 588abeb6b1eSDaniel Baluta 589abeb6b1eSDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 590abeb6b1eSDaniel Baluta MODULE_DESCRIPTION("MEMSIC MMC35240 magnetic sensor driver"); 591abeb6b1eSDaniel Baluta MODULE_LICENSE("GPL v2"); 592