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 61abeb6b1eSDaniel Baluta enum mmc35240_resolution { 62abeb6b1eSDaniel Baluta MMC35240_16_BITS_SLOW = 0, /* 100 Hz */ 63abeb6b1eSDaniel Baluta MMC35240_16_BITS_FAST, /* 200 Hz */ 64abeb6b1eSDaniel Baluta MMC35240_14_BITS, /* 333 Hz */ 65abeb6b1eSDaniel Baluta MMC35240_12_BITS, /* 666 Hz */ 66abeb6b1eSDaniel Baluta }; 67abeb6b1eSDaniel Baluta 68abeb6b1eSDaniel Baluta enum mmc35240_axis { 69abeb6b1eSDaniel Baluta AXIS_X = 0, 70abeb6b1eSDaniel Baluta AXIS_Y, 71abeb6b1eSDaniel Baluta AXIS_Z, 72abeb6b1eSDaniel Baluta }; 73abeb6b1eSDaniel Baluta 74abeb6b1eSDaniel Baluta static const struct { 75abeb6b1eSDaniel Baluta int sens[3]; /* sensitivity per X, Y, Z axis */ 76abeb6b1eSDaniel Baluta int nfo; /* null field output */ 77abeb6b1eSDaniel Baluta } mmc35240_props_table[] = { 78abeb6b1eSDaniel Baluta /* 16 bits, 100Hz ODR */ 79abeb6b1eSDaniel Baluta { 80abeb6b1eSDaniel Baluta {1024, 1024, 770}, 81abeb6b1eSDaniel Baluta 32768, 82abeb6b1eSDaniel Baluta }, 83abeb6b1eSDaniel Baluta /* 16 bits, 200Hz ODR */ 84abeb6b1eSDaniel Baluta { 85abeb6b1eSDaniel Baluta {1024, 1024, 770}, 86abeb6b1eSDaniel Baluta 32768, 87abeb6b1eSDaniel Baluta }, 88abeb6b1eSDaniel Baluta /* 14 bits, 333Hz ODR */ 89abeb6b1eSDaniel Baluta { 90abeb6b1eSDaniel Baluta {256, 256, 193}, 91abeb6b1eSDaniel Baluta 8192, 92abeb6b1eSDaniel Baluta }, 93abeb6b1eSDaniel Baluta /* 12 bits, 666Hz ODR */ 94abeb6b1eSDaniel Baluta { 95abeb6b1eSDaniel Baluta {64, 64, 48}, 96abeb6b1eSDaniel Baluta 2048, 97abeb6b1eSDaniel Baluta }, 98abeb6b1eSDaniel Baluta }; 99abeb6b1eSDaniel Baluta 100abeb6b1eSDaniel Baluta struct mmc35240_data { 101abeb6b1eSDaniel Baluta struct i2c_client *client; 102abeb6b1eSDaniel Baluta struct mutex mutex; 103abeb6b1eSDaniel Baluta struct regmap *regmap; 104abeb6b1eSDaniel Baluta enum mmc35240_resolution res; 105abeb6b1eSDaniel Baluta }; 106abeb6b1eSDaniel Baluta 107abeb6b1eSDaniel Baluta static const int mmc35240_samp_freq[] = {100, 200, 333, 666}; 108abeb6b1eSDaniel Baluta 109abeb6b1eSDaniel Baluta static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 333 666"); 110abeb6b1eSDaniel Baluta 111abeb6b1eSDaniel Baluta #define MMC35240_CHANNEL(_axis) { \ 112abeb6b1eSDaniel Baluta .type = IIO_MAGN, \ 113abeb6b1eSDaniel Baluta .modified = 1, \ 114abeb6b1eSDaniel Baluta .channel2 = IIO_MOD_ ## _axis, \ 115abeb6b1eSDaniel Baluta .address = AXIS_ ## _axis, \ 116c2890547SDaniel Baluta .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 117c2890547SDaniel Baluta .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ 118c2890547SDaniel Baluta BIT(IIO_CHAN_INFO_SCALE), \ 119abeb6b1eSDaniel Baluta } 120abeb6b1eSDaniel Baluta 121abeb6b1eSDaniel Baluta static const struct iio_chan_spec mmc35240_channels[] = { 122abeb6b1eSDaniel Baluta MMC35240_CHANNEL(X), 123abeb6b1eSDaniel Baluta MMC35240_CHANNEL(Y), 124abeb6b1eSDaniel Baluta MMC35240_CHANNEL(Z), 125abeb6b1eSDaniel Baluta }; 126abeb6b1eSDaniel Baluta 127abeb6b1eSDaniel Baluta static struct attribute *mmc35240_attributes[] = { 128abeb6b1eSDaniel Baluta &iio_const_attr_sampling_frequency_available.dev_attr.attr, 129bd35a214SDaniel Baluta NULL 130abeb6b1eSDaniel Baluta }; 131abeb6b1eSDaniel Baluta 132abeb6b1eSDaniel Baluta static const struct attribute_group mmc35240_attribute_group = { 133abeb6b1eSDaniel Baluta .attrs = mmc35240_attributes, 134abeb6b1eSDaniel Baluta }; 135abeb6b1eSDaniel Baluta 136abeb6b1eSDaniel Baluta static int mmc35240_get_samp_freq_index(struct mmc35240_data *data, 137abeb6b1eSDaniel Baluta int val, int val2) 138abeb6b1eSDaniel Baluta { 139abeb6b1eSDaniel Baluta int i; 140abeb6b1eSDaniel Baluta 141abeb6b1eSDaniel Baluta for (i = 0; i < ARRAY_SIZE(mmc35240_samp_freq); i++) 142abeb6b1eSDaniel Baluta if (mmc35240_samp_freq[i] == val) 143abeb6b1eSDaniel Baluta return i; 144abeb6b1eSDaniel Baluta return -EINVAL; 145abeb6b1eSDaniel Baluta } 146abeb6b1eSDaniel Baluta 147abeb6b1eSDaniel Baluta static int mmc35240_hw_set(struct mmc35240_data *data, bool set) 148abeb6b1eSDaniel Baluta { 149abeb6b1eSDaniel Baluta int ret; 150abeb6b1eSDaniel Baluta u8 coil_bit; 151abeb6b1eSDaniel Baluta 152abeb6b1eSDaniel Baluta /* 153abeb6b1eSDaniel Baluta * Recharge the capacitor at VCAP pin, requested to be issued 154abeb6b1eSDaniel Baluta * before a SET/RESET command. 155abeb6b1eSDaniel Baluta */ 156abeb6b1eSDaniel Baluta ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, 157abeb6b1eSDaniel Baluta MMC35240_CTRL0_REFILL_BIT, 158abeb6b1eSDaniel Baluta MMC35240_CTRL0_REFILL_BIT); 159abeb6b1eSDaniel Baluta if (ret < 0) 160abeb6b1eSDaniel Baluta return ret; 161abeb6b1eSDaniel Baluta usleep_range(MMC35240_WAIT_CHARGE_PUMP, MMC35240_WAIT_CHARGE_PUMP + 1); 162abeb6b1eSDaniel Baluta 163abeb6b1eSDaniel Baluta if (set) 164abeb6b1eSDaniel Baluta coil_bit = MMC35240_CTRL0_SET_BIT; 165abeb6b1eSDaniel Baluta else 166abeb6b1eSDaniel Baluta coil_bit = MMC35240_CTRL0_RESET_BIT; 167abeb6b1eSDaniel Baluta 168abeb6b1eSDaniel Baluta return regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, 169abeb6b1eSDaniel Baluta MMC35240_CTRL0_REFILL_BIT, 170abeb6b1eSDaniel Baluta coil_bit); 171abeb6b1eSDaniel Baluta } 172abeb6b1eSDaniel Baluta 173abeb6b1eSDaniel Baluta static int mmc35240_init(struct mmc35240_data *data) 174abeb6b1eSDaniel Baluta { 175abeb6b1eSDaniel Baluta int ret; 176abeb6b1eSDaniel Baluta unsigned int reg_id; 177abeb6b1eSDaniel Baluta 178abeb6b1eSDaniel Baluta ret = regmap_read(data->regmap, MMC35240_REG_ID, ®_id); 179abeb6b1eSDaniel Baluta if (ret < 0) { 180abeb6b1eSDaniel Baluta dev_err(&data->client->dev, "Error reading product id\n"); 181abeb6b1eSDaniel Baluta return ret; 182abeb6b1eSDaniel Baluta } 183abeb6b1eSDaniel Baluta 184abeb6b1eSDaniel Baluta dev_dbg(&data->client->dev, "MMC35240 chip id %x\n", reg_id); 185abeb6b1eSDaniel Baluta 186abeb6b1eSDaniel Baluta /* 187abeb6b1eSDaniel Baluta * make sure we restore sensor characteristics, by doing 188abeb6b1eSDaniel Baluta * a RESET/SET sequence 189abeb6b1eSDaniel Baluta */ 190abeb6b1eSDaniel Baluta ret = mmc35240_hw_set(data, false); 191abeb6b1eSDaniel Baluta if (ret < 0) 192abeb6b1eSDaniel Baluta return ret; 193abeb6b1eSDaniel Baluta usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1); 194abeb6b1eSDaniel Baluta 195abeb6b1eSDaniel Baluta ret = mmc35240_hw_set(data, true); 196abeb6b1eSDaniel Baluta if (ret < 0) 197abeb6b1eSDaniel Baluta return ret; 198abeb6b1eSDaniel Baluta 199abeb6b1eSDaniel Baluta /* set default sampling frequency */ 200abeb6b1eSDaniel Baluta return regmap_update_bits(data->regmap, MMC35240_REG_CTRL1, 201abeb6b1eSDaniel Baluta MMC35240_CTRL1_BW_MASK, 202abeb6b1eSDaniel Baluta data->res << MMC35240_CTRL1_BW_SHIFT); 203abeb6b1eSDaniel Baluta } 204abeb6b1eSDaniel Baluta 205abeb6b1eSDaniel Baluta static int mmc35240_take_measurement(struct mmc35240_data *data) 206abeb6b1eSDaniel Baluta { 207abeb6b1eSDaniel Baluta int ret, tries = 100; 208abeb6b1eSDaniel Baluta unsigned int reg_status; 209abeb6b1eSDaniel Baluta 210abeb6b1eSDaniel Baluta ret = regmap_write(data->regmap, MMC35240_REG_CTRL0, 211abeb6b1eSDaniel Baluta MMC35240_CTRL0_TM_BIT); 212abeb6b1eSDaniel Baluta if (ret < 0) 213abeb6b1eSDaniel Baluta return ret; 214abeb6b1eSDaniel Baluta 215abeb6b1eSDaniel Baluta while (tries-- > 0) { 216abeb6b1eSDaniel Baluta ret = regmap_read(data->regmap, MMC35240_REG_STATUS, 217abeb6b1eSDaniel Baluta ®_status); 218abeb6b1eSDaniel Baluta if (ret < 0) 219abeb6b1eSDaniel Baluta return ret; 220abeb6b1eSDaniel Baluta if (reg_status & MMC35240_STATUS_MEAS_DONE_BIT) 221abeb6b1eSDaniel Baluta break; 222abeb6b1eSDaniel Baluta msleep(20); 223abeb6b1eSDaniel Baluta } 224abeb6b1eSDaniel Baluta 225abeb6b1eSDaniel Baluta if (tries < 0) { 226abeb6b1eSDaniel Baluta dev_err(&data->client->dev, "data not ready\n"); 227abeb6b1eSDaniel Baluta return -EIO; 228abeb6b1eSDaniel Baluta } 229abeb6b1eSDaniel Baluta 230abeb6b1eSDaniel Baluta return 0; 231abeb6b1eSDaniel Baluta } 232abeb6b1eSDaniel Baluta 233abeb6b1eSDaniel Baluta static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3]) 234abeb6b1eSDaniel Baluta { 235abeb6b1eSDaniel Baluta int ret; 236abeb6b1eSDaniel Baluta 237abeb6b1eSDaniel Baluta ret = mmc35240_take_measurement(data); 238abeb6b1eSDaniel Baluta if (ret < 0) 239abeb6b1eSDaniel Baluta return ret; 240abeb6b1eSDaniel Baluta 241abeb6b1eSDaniel Baluta return regmap_bulk_read(data->regmap, MMC35240_REG_XOUT_L, (u8 *)buf, 242abeb6b1eSDaniel Baluta 3 * sizeof(__le16)); 243abeb6b1eSDaniel Baluta } 244abeb6b1eSDaniel Baluta 245c2890547SDaniel Baluta /** 246c2890547SDaniel Baluta * mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply 247c2890547SDaniel Baluta compensation for output value. 248c2890547SDaniel Baluta * 249c2890547SDaniel Baluta * @data: device private data 250c2890547SDaniel Baluta * @index: axis index for which we want the conversion 251c2890547SDaniel Baluta * @buf: raw data to be converted, 2 bytes in little endian format 252c2890547SDaniel Baluta * @val: compensated output reading (unit is milli gauss) 253c2890547SDaniel Baluta * 254c2890547SDaniel Baluta * Returns: 0 in case of success, -EINVAL when @index is not valid 255c2890547SDaniel Baluta */ 256c2890547SDaniel Baluta static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index, 257c2890547SDaniel Baluta __le16 buf[], int *val) 258abeb6b1eSDaniel Baluta { 259abeb6b1eSDaniel Baluta int raw_x, raw_y, raw_z; 260abeb6b1eSDaniel Baluta int sens_x, sens_y, sens_z; 261abeb6b1eSDaniel Baluta int nfo; 262abeb6b1eSDaniel Baluta 263abeb6b1eSDaniel Baluta raw_x = le16_to_cpu(buf[AXIS_X]); 264abeb6b1eSDaniel Baluta raw_y = le16_to_cpu(buf[AXIS_Y]); 265abeb6b1eSDaniel Baluta raw_z = le16_to_cpu(buf[AXIS_Z]); 266abeb6b1eSDaniel Baluta 267abeb6b1eSDaniel Baluta sens_x = mmc35240_props_table[data->res].sens[AXIS_X]; 268abeb6b1eSDaniel Baluta sens_y = mmc35240_props_table[data->res].sens[AXIS_Y]; 269abeb6b1eSDaniel Baluta sens_z = mmc35240_props_table[data->res].sens[AXIS_Z]; 270abeb6b1eSDaniel Baluta 271abeb6b1eSDaniel Baluta nfo = mmc35240_props_table[data->res].nfo; 272abeb6b1eSDaniel Baluta 273abeb6b1eSDaniel Baluta switch (index) { 274abeb6b1eSDaniel Baluta case AXIS_X: 275c2890547SDaniel Baluta *val = (raw_x - nfo) * 1000 / sens_x; 276abeb6b1eSDaniel Baluta break; 277abeb6b1eSDaniel Baluta case AXIS_Y: 278c2890547SDaniel Baluta *val = (raw_y - nfo) * 1000 / sens_y - 279c2890547SDaniel Baluta (raw_z - nfo) * 1000 / sens_z; 280abeb6b1eSDaniel Baluta break; 281abeb6b1eSDaniel Baluta case AXIS_Z: 282c2890547SDaniel Baluta *val = (raw_y - nfo) * 1000 / sens_y + 283c2890547SDaniel Baluta (raw_z - nfo) * 1000 / sens_z; 284abeb6b1eSDaniel Baluta break; 285abeb6b1eSDaniel Baluta default: 286abeb6b1eSDaniel Baluta return -EINVAL; 287abeb6b1eSDaniel Baluta } 288abeb6b1eSDaniel Baluta return 0; 289abeb6b1eSDaniel Baluta } 290abeb6b1eSDaniel Baluta 291abeb6b1eSDaniel Baluta static int mmc35240_read_raw(struct iio_dev *indio_dev, 292abeb6b1eSDaniel Baluta struct iio_chan_spec const *chan, int *val, 293abeb6b1eSDaniel Baluta int *val2, long mask) 294abeb6b1eSDaniel Baluta { 295abeb6b1eSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 296abeb6b1eSDaniel Baluta int ret, i; 297abeb6b1eSDaniel Baluta unsigned int reg; 298abeb6b1eSDaniel Baluta __le16 buf[3]; 299abeb6b1eSDaniel Baluta 300abeb6b1eSDaniel Baluta switch (mask) { 301c2890547SDaniel Baluta case IIO_CHAN_INFO_RAW: 302abeb6b1eSDaniel Baluta mutex_lock(&data->mutex); 303abeb6b1eSDaniel Baluta ret = mmc35240_read_measurement(data, buf); 304abeb6b1eSDaniel Baluta mutex_unlock(&data->mutex); 305abeb6b1eSDaniel Baluta if (ret < 0) 306abeb6b1eSDaniel Baluta return ret; 307c2890547SDaniel Baluta ret = mmc35240_raw_to_mgauss(data, chan->address, buf, val); 308abeb6b1eSDaniel Baluta if (ret < 0) 309abeb6b1eSDaniel Baluta return ret; 310c2890547SDaniel Baluta return IIO_VAL_INT; 311c2890547SDaniel Baluta case IIO_CHAN_INFO_SCALE: 312c2890547SDaniel Baluta *val = 0; 313c2890547SDaniel Baluta *val2 = 1000; 314abeb6b1eSDaniel Baluta return IIO_VAL_INT_PLUS_MICRO; 315abeb6b1eSDaniel Baluta case IIO_CHAN_INFO_SAMP_FREQ: 316abeb6b1eSDaniel Baluta mutex_lock(&data->mutex); 317abeb6b1eSDaniel Baluta ret = regmap_read(data->regmap, MMC35240_REG_CTRL1, ®); 318abeb6b1eSDaniel Baluta mutex_unlock(&data->mutex); 319abeb6b1eSDaniel Baluta if (ret < 0) 320abeb6b1eSDaniel Baluta return ret; 321abeb6b1eSDaniel Baluta 322abeb6b1eSDaniel Baluta i = (reg & MMC35240_CTRL1_BW_MASK) >> MMC35240_CTRL1_BW_SHIFT; 3235517547bSDan Carpenter if (i < 0 || i >= ARRAY_SIZE(mmc35240_samp_freq)) 324abeb6b1eSDaniel Baluta return -EINVAL; 325abeb6b1eSDaniel Baluta 326abeb6b1eSDaniel Baluta *val = mmc35240_samp_freq[i]; 327abeb6b1eSDaniel Baluta *val2 = 0; 328abeb6b1eSDaniel Baluta return IIO_VAL_INT; 329abeb6b1eSDaniel Baluta default: 330abeb6b1eSDaniel Baluta return -EINVAL; 331abeb6b1eSDaniel Baluta } 332abeb6b1eSDaniel Baluta } 333abeb6b1eSDaniel Baluta 334abeb6b1eSDaniel Baluta static int mmc35240_write_raw(struct iio_dev *indio_dev, 335abeb6b1eSDaniel Baluta struct iio_chan_spec const *chan, int val, 336abeb6b1eSDaniel Baluta int val2, long mask) 337abeb6b1eSDaniel Baluta { 338abeb6b1eSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 339abeb6b1eSDaniel Baluta int i, ret; 340abeb6b1eSDaniel Baluta 341abeb6b1eSDaniel Baluta switch (mask) { 342abeb6b1eSDaniel Baluta case IIO_CHAN_INFO_SAMP_FREQ: 343abeb6b1eSDaniel Baluta i = mmc35240_get_samp_freq_index(data, val, val2); 344abeb6b1eSDaniel Baluta if (i < 0) 345abeb6b1eSDaniel Baluta return -EINVAL; 346abeb6b1eSDaniel Baluta mutex_lock(&data->mutex); 347abeb6b1eSDaniel Baluta ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1, 348abeb6b1eSDaniel Baluta MMC35240_CTRL1_BW_MASK, 349abeb6b1eSDaniel Baluta i << MMC35240_CTRL1_BW_SHIFT); 350abeb6b1eSDaniel Baluta mutex_unlock(&data->mutex); 351abeb6b1eSDaniel Baluta return ret; 352abeb6b1eSDaniel Baluta default: 353abeb6b1eSDaniel Baluta return -EINVAL; 354abeb6b1eSDaniel Baluta } 355abeb6b1eSDaniel Baluta } 356abeb6b1eSDaniel Baluta 357abeb6b1eSDaniel Baluta static const struct iio_info mmc35240_info = { 358abeb6b1eSDaniel Baluta .driver_module = THIS_MODULE, 359abeb6b1eSDaniel Baluta .read_raw = mmc35240_read_raw, 360abeb6b1eSDaniel Baluta .write_raw = mmc35240_write_raw, 361abeb6b1eSDaniel Baluta .attrs = &mmc35240_attribute_group, 362abeb6b1eSDaniel Baluta }; 363abeb6b1eSDaniel Baluta 364abeb6b1eSDaniel Baluta static bool mmc35240_is_writeable_reg(struct device *dev, unsigned int reg) 365abeb6b1eSDaniel Baluta { 366abeb6b1eSDaniel Baluta switch (reg) { 367abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL0: 368abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL1: 369abeb6b1eSDaniel Baluta return true; 370abeb6b1eSDaniel Baluta default: 371abeb6b1eSDaniel Baluta return false; 372abeb6b1eSDaniel Baluta } 373abeb6b1eSDaniel Baluta } 374abeb6b1eSDaniel Baluta 375abeb6b1eSDaniel Baluta static bool mmc35240_is_readable_reg(struct device *dev, unsigned int reg) 376abeb6b1eSDaniel Baluta { 377abeb6b1eSDaniel Baluta switch (reg) { 378abeb6b1eSDaniel Baluta case MMC35240_REG_XOUT_L: 379abeb6b1eSDaniel Baluta case MMC35240_REG_XOUT_H: 380abeb6b1eSDaniel Baluta case MMC35240_REG_YOUT_L: 381abeb6b1eSDaniel Baluta case MMC35240_REG_YOUT_H: 382abeb6b1eSDaniel Baluta case MMC35240_REG_ZOUT_L: 383abeb6b1eSDaniel Baluta case MMC35240_REG_ZOUT_H: 384abeb6b1eSDaniel Baluta case MMC35240_REG_STATUS: 385abeb6b1eSDaniel Baluta case MMC35240_REG_ID: 386abeb6b1eSDaniel Baluta return true; 387abeb6b1eSDaniel Baluta default: 388abeb6b1eSDaniel Baluta return false; 389abeb6b1eSDaniel Baluta } 390abeb6b1eSDaniel Baluta } 391abeb6b1eSDaniel Baluta 392abeb6b1eSDaniel Baluta static bool mmc35240_is_volatile_reg(struct device *dev, unsigned int reg) 393abeb6b1eSDaniel Baluta { 394abeb6b1eSDaniel Baluta switch (reg) { 395abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL0: 396abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL1: 397abeb6b1eSDaniel Baluta return false; 398abeb6b1eSDaniel Baluta default: 399abeb6b1eSDaniel Baluta return true; 400abeb6b1eSDaniel Baluta } 401abeb6b1eSDaniel Baluta } 402abeb6b1eSDaniel Baluta 403abeb6b1eSDaniel Baluta static struct reg_default mmc35240_reg_defaults[] = { 404abeb6b1eSDaniel Baluta { MMC35240_REG_CTRL0, 0x00 }, 405abeb6b1eSDaniel Baluta { MMC35240_REG_CTRL1, 0x00 }, 406abeb6b1eSDaniel Baluta }; 407abeb6b1eSDaniel Baluta 408abeb6b1eSDaniel Baluta static const struct regmap_config mmc35240_regmap_config = { 409abeb6b1eSDaniel Baluta .name = MMC35240_REGMAP_NAME, 410abeb6b1eSDaniel Baluta 411abeb6b1eSDaniel Baluta .reg_bits = 8, 412abeb6b1eSDaniel Baluta .val_bits = 8, 413abeb6b1eSDaniel Baluta 414abeb6b1eSDaniel Baluta .max_register = MMC35240_REG_ID, 415abeb6b1eSDaniel Baluta .cache_type = REGCACHE_FLAT, 416abeb6b1eSDaniel Baluta 417abeb6b1eSDaniel Baluta .writeable_reg = mmc35240_is_writeable_reg, 418abeb6b1eSDaniel Baluta .readable_reg = mmc35240_is_readable_reg, 419abeb6b1eSDaniel Baluta .volatile_reg = mmc35240_is_volatile_reg, 420abeb6b1eSDaniel Baluta 421abeb6b1eSDaniel Baluta .reg_defaults = mmc35240_reg_defaults, 422abeb6b1eSDaniel Baluta .num_reg_defaults = ARRAY_SIZE(mmc35240_reg_defaults), 423abeb6b1eSDaniel Baluta }; 424abeb6b1eSDaniel Baluta 425abeb6b1eSDaniel Baluta static int mmc35240_probe(struct i2c_client *client, 426abeb6b1eSDaniel Baluta const struct i2c_device_id *id) 427abeb6b1eSDaniel Baluta { 428abeb6b1eSDaniel Baluta struct mmc35240_data *data; 429abeb6b1eSDaniel Baluta struct iio_dev *indio_dev; 430abeb6b1eSDaniel Baluta struct regmap *regmap; 431abeb6b1eSDaniel Baluta int ret; 432abeb6b1eSDaniel Baluta 433abeb6b1eSDaniel Baluta indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 434abeb6b1eSDaniel Baluta if (!indio_dev) 435abeb6b1eSDaniel Baluta return -ENOMEM; 436abeb6b1eSDaniel Baluta 437abeb6b1eSDaniel Baluta regmap = devm_regmap_init_i2c(client, &mmc35240_regmap_config); 438abeb6b1eSDaniel Baluta if (IS_ERR(regmap)) { 439abeb6b1eSDaniel Baluta dev_err(&client->dev, "regmap initialization failed\n"); 440abeb6b1eSDaniel Baluta return PTR_ERR(regmap); 441abeb6b1eSDaniel Baluta } 442abeb6b1eSDaniel Baluta 443abeb6b1eSDaniel Baluta data = iio_priv(indio_dev); 444abeb6b1eSDaniel Baluta data->client = client; 445abeb6b1eSDaniel Baluta data->regmap = regmap; 446abeb6b1eSDaniel Baluta data->res = MMC35240_16_BITS_SLOW; 447abeb6b1eSDaniel Baluta 448abeb6b1eSDaniel Baluta mutex_init(&data->mutex); 449abeb6b1eSDaniel Baluta 450abeb6b1eSDaniel Baluta indio_dev->dev.parent = &client->dev; 451abeb6b1eSDaniel Baluta indio_dev->info = &mmc35240_info; 452abeb6b1eSDaniel Baluta indio_dev->name = MMC35240_DRV_NAME; 453abeb6b1eSDaniel Baluta indio_dev->channels = mmc35240_channels; 454abeb6b1eSDaniel Baluta indio_dev->num_channels = ARRAY_SIZE(mmc35240_channels); 455abeb6b1eSDaniel Baluta indio_dev->modes = INDIO_DIRECT_MODE; 456abeb6b1eSDaniel Baluta 457abeb6b1eSDaniel Baluta ret = mmc35240_init(data); 458abeb6b1eSDaniel Baluta if (ret < 0) { 459abeb6b1eSDaniel Baluta dev_err(&client->dev, "mmc35240 chip init failed\n"); 460abeb6b1eSDaniel Baluta return ret; 461abeb6b1eSDaniel Baluta } 462abeb6b1eSDaniel Baluta return devm_iio_device_register(&client->dev, indio_dev); 463abeb6b1eSDaniel Baluta } 464abeb6b1eSDaniel Baluta 465553a776bSDaniel Baluta #ifdef CONFIG_PM_SLEEP 466553a776bSDaniel Baluta static int mmc35240_suspend(struct device *dev) 467553a776bSDaniel Baluta { 468553a776bSDaniel Baluta struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 469553a776bSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 470553a776bSDaniel Baluta 471553a776bSDaniel Baluta regcache_cache_only(data->regmap, true); 472553a776bSDaniel Baluta 473553a776bSDaniel Baluta return 0; 474553a776bSDaniel Baluta } 475553a776bSDaniel Baluta 476553a776bSDaniel Baluta static int mmc35240_resume(struct device *dev) 477553a776bSDaniel Baluta { 478553a776bSDaniel Baluta struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 479553a776bSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 480553a776bSDaniel Baluta int ret; 481553a776bSDaniel Baluta 482553a776bSDaniel Baluta regcache_mark_dirty(data->regmap); 483553a776bSDaniel Baluta ret = regcache_sync_region(data->regmap, MMC35240_REG_CTRL0, 484553a776bSDaniel Baluta MMC35240_REG_CTRL1); 485553a776bSDaniel Baluta if (ret < 0) 486553a776bSDaniel Baluta dev_err(dev, "Failed to restore control registers\n"); 487553a776bSDaniel Baluta 488553a776bSDaniel Baluta regcache_cache_only(data->regmap, false); 489553a776bSDaniel Baluta 490553a776bSDaniel Baluta return 0; 491553a776bSDaniel Baluta } 492553a776bSDaniel Baluta #endif 493553a776bSDaniel Baluta 494553a776bSDaniel Baluta static const struct dev_pm_ops mmc35240_pm_ops = { 495553a776bSDaniel Baluta SET_SYSTEM_SLEEP_PM_OPS(mmc35240_suspend, mmc35240_resume) 496553a776bSDaniel Baluta }; 497553a776bSDaniel Baluta 498d11715f0SDaniel Baluta static const struct acpi_device_id mmc35240_acpi_match[] = { 499d11715f0SDaniel Baluta {"MMC35240", 0}, 500d11715f0SDaniel Baluta { }, 501d11715f0SDaniel Baluta }; 502d11715f0SDaniel Baluta MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match); 503d11715f0SDaniel Baluta 504abeb6b1eSDaniel Baluta static const struct i2c_device_id mmc35240_id[] = { 505a52ffebcSDaniel Baluta {"mmc35240", 0}, 506abeb6b1eSDaniel Baluta {} 507abeb6b1eSDaniel Baluta }; 508abeb6b1eSDaniel Baluta MODULE_DEVICE_TABLE(i2c, mmc35240_id); 509abeb6b1eSDaniel Baluta 510abeb6b1eSDaniel Baluta static struct i2c_driver mmc35240_driver = { 511abeb6b1eSDaniel Baluta .driver = { 512abeb6b1eSDaniel Baluta .name = MMC35240_DRV_NAME, 513553a776bSDaniel Baluta .pm = &mmc35240_pm_ops, 514d11715f0SDaniel Baluta .acpi_match_table = ACPI_PTR(mmc35240_acpi_match), 515abeb6b1eSDaniel Baluta }, 516abeb6b1eSDaniel Baluta .probe = mmc35240_probe, 517abeb6b1eSDaniel Baluta .id_table = mmc35240_id, 518abeb6b1eSDaniel Baluta }; 519abeb6b1eSDaniel Baluta 520abeb6b1eSDaniel Baluta module_i2c_driver(mmc35240_driver); 521abeb6b1eSDaniel Baluta 522abeb6b1eSDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 523abeb6b1eSDaniel Baluta MODULE_DESCRIPTION("MEMSIC MMC35240 magnetic sensor driver"); 524abeb6b1eSDaniel Baluta MODULE_LICENSE("GPL v2"); 525