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