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, \ 116abeb6b1eSDaniel Baluta .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ 117abeb6b1eSDaniel Baluta .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ 118abeb6b1eSDaniel Baluta } 119abeb6b1eSDaniel Baluta 120abeb6b1eSDaniel Baluta static const struct iio_chan_spec mmc35240_channels[] = { 121abeb6b1eSDaniel Baluta MMC35240_CHANNEL(X), 122abeb6b1eSDaniel Baluta MMC35240_CHANNEL(Y), 123abeb6b1eSDaniel Baluta MMC35240_CHANNEL(Z), 124abeb6b1eSDaniel Baluta }; 125abeb6b1eSDaniel Baluta 126abeb6b1eSDaniel Baluta static struct attribute *mmc35240_attributes[] = { 127abeb6b1eSDaniel Baluta &iio_const_attr_sampling_frequency_available.dev_attr.attr, 128abeb6b1eSDaniel Baluta }; 129abeb6b1eSDaniel Baluta 130abeb6b1eSDaniel Baluta static const struct attribute_group mmc35240_attribute_group = { 131abeb6b1eSDaniel Baluta .attrs = mmc35240_attributes, 132abeb6b1eSDaniel Baluta }; 133abeb6b1eSDaniel Baluta 134abeb6b1eSDaniel Baluta static int mmc35240_get_samp_freq_index(struct mmc35240_data *data, 135abeb6b1eSDaniel Baluta int val, int val2) 136abeb6b1eSDaniel Baluta { 137abeb6b1eSDaniel Baluta int i; 138abeb6b1eSDaniel Baluta 139abeb6b1eSDaniel Baluta for (i = 0; i < ARRAY_SIZE(mmc35240_samp_freq); i++) 140abeb6b1eSDaniel Baluta if (mmc35240_samp_freq[i] == val) 141abeb6b1eSDaniel Baluta return i; 142abeb6b1eSDaniel Baluta return -EINVAL; 143abeb6b1eSDaniel Baluta } 144abeb6b1eSDaniel Baluta 145abeb6b1eSDaniel Baluta static int mmc35240_hw_set(struct mmc35240_data *data, bool set) 146abeb6b1eSDaniel Baluta { 147abeb6b1eSDaniel Baluta int ret; 148abeb6b1eSDaniel Baluta u8 coil_bit; 149abeb6b1eSDaniel Baluta 150abeb6b1eSDaniel Baluta /* 151abeb6b1eSDaniel Baluta * Recharge the capacitor at VCAP pin, requested to be issued 152abeb6b1eSDaniel Baluta * before a SET/RESET command. 153abeb6b1eSDaniel Baluta */ 154abeb6b1eSDaniel Baluta ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, 155abeb6b1eSDaniel Baluta MMC35240_CTRL0_REFILL_BIT, 156abeb6b1eSDaniel Baluta MMC35240_CTRL0_REFILL_BIT); 157abeb6b1eSDaniel Baluta if (ret < 0) 158abeb6b1eSDaniel Baluta return ret; 159abeb6b1eSDaniel Baluta usleep_range(MMC35240_WAIT_CHARGE_PUMP, MMC35240_WAIT_CHARGE_PUMP + 1); 160abeb6b1eSDaniel Baluta 161abeb6b1eSDaniel Baluta if (set) 162abeb6b1eSDaniel Baluta coil_bit = MMC35240_CTRL0_SET_BIT; 163abeb6b1eSDaniel Baluta else 164abeb6b1eSDaniel Baluta coil_bit = MMC35240_CTRL0_RESET_BIT; 165abeb6b1eSDaniel Baluta 166abeb6b1eSDaniel Baluta return regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, 167abeb6b1eSDaniel Baluta MMC35240_CTRL0_REFILL_BIT, 168abeb6b1eSDaniel Baluta coil_bit); 169abeb6b1eSDaniel Baluta } 170abeb6b1eSDaniel Baluta 171abeb6b1eSDaniel Baluta static int mmc35240_init(struct mmc35240_data *data) 172abeb6b1eSDaniel Baluta { 173abeb6b1eSDaniel Baluta int ret; 174abeb6b1eSDaniel Baluta unsigned int reg_id; 175abeb6b1eSDaniel Baluta 176abeb6b1eSDaniel Baluta ret = regmap_read(data->regmap, MMC35240_REG_ID, ®_id); 177abeb6b1eSDaniel Baluta if (ret < 0) { 178abeb6b1eSDaniel Baluta dev_err(&data->client->dev, "Error reading product id\n"); 179abeb6b1eSDaniel Baluta return ret; 180abeb6b1eSDaniel Baluta } 181abeb6b1eSDaniel Baluta 182abeb6b1eSDaniel Baluta dev_dbg(&data->client->dev, "MMC35240 chip id %x\n", reg_id); 183abeb6b1eSDaniel Baluta 184abeb6b1eSDaniel Baluta /* 185abeb6b1eSDaniel Baluta * make sure we restore sensor characteristics, by doing 186abeb6b1eSDaniel Baluta * a RESET/SET sequence 187abeb6b1eSDaniel Baluta */ 188abeb6b1eSDaniel Baluta ret = mmc35240_hw_set(data, false); 189abeb6b1eSDaniel Baluta if (ret < 0) 190abeb6b1eSDaniel Baluta return ret; 191abeb6b1eSDaniel Baluta usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1); 192abeb6b1eSDaniel Baluta 193abeb6b1eSDaniel Baluta ret = mmc35240_hw_set(data, true); 194abeb6b1eSDaniel Baluta if (ret < 0) 195abeb6b1eSDaniel Baluta return ret; 196abeb6b1eSDaniel Baluta 197abeb6b1eSDaniel Baluta /* set default sampling frequency */ 198abeb6b1eSDaniel Baluta return regmap_update_bits(data->regmap, MMC35240_REG_CTRL1, 199abeb6b1eSDaniel Baluta MMC35240_CTRL1_BW_MASK, 200abeb6b1eSDaniel Baluta data->res << MMC35240_CTRL1_BW_SHIFT); 201abeb6b1eSDaniel Baluta } 202abeb6b1eSDaniel Baluta 203abeb6b1eSDaniel Baluta static int mmc35240_take_measurement(struct mmc35240_data *data) 204abeb6b1eSDaniel Baluta { 205abeb6b1eSDaniel Baluta int ret, tries = 100; 206abeb6b1eSDaniel Baluta unsigned int reg_status; 207abeb6b1eSDaniel Baluta 208abeb6b1eSDaniel Baluta ret = regmap_write(data->regmap, MMC35240_REG_CTRL0, 209abeb6b1eSDaniel Baluta MMC35240_CTRL0_TM_BIT); 210abeb6b1eSDaniel Baluta if (ret < 0) 211abeb6b1eSDaniel Baluta return ret; 212abeb6b1eSDaniel Baluta 213abeb6b1eSDaniel Baluta while (tries-- > 0) { 214abeb6b1eSDaniel Baluta ret = regmap_read(data->regmap, MMC35240_REG_STATUS, 215abeb6b1eSDaniel Baluta ®_status); 216abeb6b1eSDaniel Baluta if (ret < 0) 217abeb6b1eSDaniel Baluta return ret; 218abeb6b1eSDaniel Baluta if (reg_status & MMC35240_STATUS_MEAS_DONE_BIT) 219abeb6b1eSDaniel Baluta break; 220abeb6b1eSDaniel Baluta msleep(20); 221abeb6b1eSDaniel Baluta } 222abeb6b1eSDaniel Baluta 223abeb6b1eSDaniel Baluta if (tries < 0) { 224abeb6b1eSDaniel Baluta dev_err(&data->client->dev, "data not ready\n"); 225abeb6b1eSDaniel Baluta return -EIO; 226abeb6b1eSDaniel Baluta } 227abeb6b1eSDaniel Baluta 228abeb6b1eSDaniel Baluta return 0; 229abeb6b1eSDaniel Baluta } 230abeb6b1eSDaniel Baluta 231abeb6b1eSDaniel Baluta static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3]) 232abeb6b1eSDaniel Baluta { 233abeb6b1eSDaniel Baluta int ret; 234abeb6b1eSDaniel Baluta 235abeb6b1eSDaniel Baluta ret = mmc35240_take_measurement(data); 236abeb6b1eSDaniel Baluta if (ret < 0) 237abeb6b1eSDaniel Baluta return ret; 238abeb6b1eSDaniel Baluta 239abeb6b1eSDaniel Baluta return regmap_bulk_read(data->regmap, MMC35240_REG_XOUT_L, (u8 *)buf, 240abeb6b1eSDaniel Baluta 3 * sizeof(__le16)); 241abeb6b1eSDaniel Baluta } 242abeb6b1eSDaniel Baluta 243abeb6b1eSDaniel Baluta static int mmc35240_raw_to_gauss(struct mmc35240_data *data, int index, 244abeb6b1eSDaniel Baluta __le16 buf[], 245abeb6b1eSDaniel Baluta int *val, int *val2) 246abeb6b1eSDaniel Baluta { 247abeb6b1eSDaniel Baluta int raw_x, raw_y, raw_z; 248abeb6b1eSDaniel Baluta int sens_x, sens_y, sens_z; 249abeb6b1eSDaniel Baluta int nfo; 250abeb6b1eSDaniel Baluta 251abeb6b1eSDaniel Baluta raw_x = le16_to_cpu(buf[AXIS_X]); 252abeb6b1eSDaniel Baluta raw_y = le16_to_cpu(buf[AXIS_Y]); 253abeb6b1eSDaniel Baluta raw_z = le16_to_cpu(buf[AXIS_Z]); 254abeb6b1eSDaniel Baluta 255abeb6b1eSDaniel Baluta sens_x = mmc35240_props_table[data->res].sens[AXIS_X]; 256abeb6b1eSDaniel Baluta sens_y = mmc35240_props_table[data->res].sens[AXIS_Y]; 257abeb6b1eSDaniel Baluta sens_z = mmc35240_props_table[data->res].sens[AXIS_Z]; 258abeb6b1eSDaniel Baluta 259abeb6b1eSDaniel Baluta nfo = mmc35240_props_table[data->res].nfo; 260abeb6b1eSDaniel Baluta 261abeb6b1eSDaniel Baluta switch (index) { 262abeb6b1eSDaniel Baluta case AXIS_X: 263abeb6b1eSDaniel Baluta *val = (raw_x - nfo) / sens_x; 264abeb6b1eSDaniel Baluta *val2 = ((raw_x - nfo) % sens_x) * 1000000; 265abeb6b1eSDaniel Baluta break; 266abeb6b1eSDaniel Baluta case AXIS_Y: 267abeb6b1eSDaniel Baluta *val = (raw_y - nfo) / sens_y - (raw_z - nfo) / sens_z; 268abeb6b1eSDaniel Baluta *val2 = (((raw_y - nfo) % sens_y - (raw_z - nfo) % sens_z)) 269abeb6b1eSDaniel Baluta * 1000000; 270abeb6b1eSDaniel Baluta break; 271abeb6b1eSDaniel Baluta case AXIS_Z: 272abeb6b1eSDaniel Baluta *val = (raw_y - nfo) / sens_y + (raw_z - nfo) / sens_z; 273abeb6b1eSDaniel Baluta *val2 = (((raw_y - nfo) % sens_y + (raw_z - nfo) % sens_z)) 274abeb6b1eSDaniel Baluta * 1000000; 275abeb6b1eSDaniel Baluta break; 276abeb6b1eSDaniel Baluta default: 277abeb6b1eSDaniel Baluta return -EINVAL; 278abeb6b1eSDaniel Baluta } 279abeb6b1eSDaniel Baluta return 0; 280abeb6b1eSDaniel Baluta } 281abeb6b1eSDaniel Baluta 282abeb6b1eSDaniel Baluta static int mmc35240_read_raw(struct iio_dev *indio_dev, 283abeb6b1eSDaniel Baluta struct iio_chan_spec const *chan, int *val, 284abeb6b1eSDaniel Baluta int *val2, long mask) 285abeb6b1eSDaniel Baluta { 286abeb6b1eSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 287abeb6b1eSDaniel Baluta int ret, i; 288abeb6b1eSDaniel Baluta unsigned int reg; 289abeb6b1eSDaniel Baluta __le16 buf[3]; 290abeb6b1eSDaniel Baluta 291abeb6b1eSDaniel Baluta switch (mask) { 292abeb6b1eSDaniel Baluta case IIO_CHAN_INFO_PROCESSED: 293abeb6b1eSDaniel Baluta mutex_lock(&data->mutex); 294abeb6b1eSDaniel Baluta ret = mmc35240_read_measurement(data, buf); 295abeb6b1eSDaniel Baluta mutex_unlock(&data->mutex); 296abeb6b1eSDaniel Baluta if (ret < 0) 297abeb6b1eSDaniel Baluta return ret; 298abeb6b1eSDaniel Baluta ret = mmc35240_raw_to_gauss(data, chan->address, 299abeb6b1eSDaniel Baluta buf, val, val2); 300abeb6b1eSDaniel Baluta if (ret < 0) 301abeb6b1eSDaniel Baluta return ret; 302abeb6b1eSDaniel Baluta return IIO_VAL_INT_PLUS_MICRO; 303abeb6b1eSDaniel Baluta case IIO_CHAN_INFO_SAMP_FREQ: 304abeb6b1eSDaniel Baluta mutex_lock(&data->mutex); 305abeb6b1eSDaniel Baluta ret = regmap_read(data->regmap, MMC35240_REG_CTRL1, ®); 306abeb6b1eSDaniel Baluta mutex_unlock(&data->mutex); 307abeb6b1eSDaniel Baluta if (ret < 0) 308abeb6b1eSDaniel Baluta return ret; 309abeb6b1eSDaniel Baluta 310abeb6b1eSDaniel Baluta i = (reg & MMC35240_CTRL1_BW_MASK) >> MMC35240_CTRL1_BW_SHIFT; 311abeb6b1eSDaniel Baluta if (i < 0 || i > ARRAY_SIZE(mmc35240_samp_freq)) 312abeb6b1eSDaniel Baluta return -EINVAL; 313abeb6b1eSDaniel Baluta 314abeb6b1eSDaniel Baluta *val = mmc35240_samp_freq[i]; 315abeb6b1eSDaniel Baluta *val2 = 0; 316abeb6b1eSDaniel Baluta return IIO_VAL_INT; 317abeb6b1eSDaniel Baluta default: 318abeb6b1eSDaniel Baluta return -EINVAL; 319abeb6b1eSDaniel Baluta } 320abeb6b1eSDaniel Baluta } 321abeb6b1eSDaniel Baluta 322abeb6b1eSDaniel Baluta static int mmc35240_write_raw(struct iio_dev *indio_dev, 323abeb6b1eSDaniel Baluta struct iio_chan_spec const *chan, int val, 324abeb6b1eSDaniel Baluta int val2, long mask) 325abeb6b1eSDaniel Baluta { 326abeb6b1eSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 327abeb6b1eSDaniel Baluta int i, ret; 328abeb6b1eSDaniel Baluta 329abeb6b1eSDaniel Baluta switch (mask) { 330abeb6b1eSDaniel Baluta case IIO_CHAN_INFO_SAMP_FREQ: 331abeb6b1eSDaniel Baluta i = mmc35240_get_samp_freq_index(data, val, val2); 332abeb6b1eSDaniel Baluta if (i < 0) 333abeb6b1eSDaniel Baluta return -EINVAL; 334abeb6b1eSDaniel Baluta mutex_lock(&data->mutex); 335abeb6b1eSDaniel Baluta ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1, 336abeb6b1eSDaniel Baluta MMC35240_CTRL1_BW_MASK, 337abeb6b1eSDaniel Baluta i << MMC35240_CTRL1_BW_SHIFT); 338abeb6b1eSDaniel Baluta mutex_unlock(&data->mutex); 339abeb6b1eSDaniel Baluta return ret; 340abeb6b1eSDaniel Baluta default: 341abeb6b1eSDaniel Baluta return -EINVAL; 342abeb6b1eSDaniel Baluta } 343abeb6b1eSDaniel Baluta } 344abeb6b1eSDaniel Baluta 345abeb6b1eSDaniel Baluta static const struct iio_info mmc35240_info = { 346abeb6b1eSDaniel Baluta .driver_module = THIS_MODULE, 347abeb6b1eSDaniel Baluta .read_raw = mmc35240_read_raw, 348abeb6b1eSDaniel Baluta .write_raw = mmc35240_write_raw, 349abeb6b1eSDaniel Baluta .attrs = &mmc35240_attribute_group, 350abeb6b1eSDaniel Baluta }; 351abeb6b1eSDaniel Baluta 352abeb6b1eSDaniel Baluta static bool mmc35240_is_writeable_reg(struct device *dev, unsigned int reg) 353abeb6b1eSDaniel Baluta { 354abeb6b1eSDaniel Baluta switch (reg) { 355abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL0: 356abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL1: 357abeb6b1eSDaniel Baluta return true; 358abeb6b1eSDaniel Baluta default: 359abeb6b1eSDaniel Baluta return false; 360abeb6b1eSDaniel Baluta } 361abeb6b1eSDaniel Baluta } 362abeb6b1eSDaniel Baluta 363abeb6b1eSDaniel Baluta static bool mmc35240_is_readable_reg(struct device *dev, unsigned int reg) 364abeb6b1eSDaniel Baluta { 365abeb6b1eSDaniel Baluta switch (reg) { 366abeb6b1eSDaniel Baluta case MMC35240_REG_XOUT_L: 367abeb6b1eSDaniel Baluta case MMC35240_REG_XOUT_H: 368abeb6b1eSDaniel Baluta case MMC35240_REG_YOUT_L: 369abeb6b1eSDaniel Baluta case MMC35240_REG_YOUT_H: 370abeb6b1eSDaniel Baluta case MMC35240_REG_ZOUT_L: 371abeb6b1eSDaniel Baluta case MMC35240_REG_ZOUT_H: 372abeb6b1eSDaniel Baluta case MMC35240_REG_STATUS: 373abeb6b1eSDaniel Baluta case MMC35240_REG_ID: 374abeb6b1eSDaniel Baluta return true; 375abeb6b1eSDaniel Baluta default: 376abeb6b1eSDaniel Baluta return false; 377abeb6b1eSDaniel Baluta } 378abeb6b1eSDaniel Baluta } 379abeb6b1eSDaniel Baluta 380abeb6b1eSDaniel Baluta static bool mmc35240_is_volatile_reg(struct device *dev, unsigned int reg) 381abeb6b1eSDaniel Baluta { 382abeb6b1eSDaniel Baluta switch (reg) { 383abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL0: 384abeb6b1eSDaniel Baluta case MMC35240_REG_CTRL1: 385abeb6b1eSDaniel Baluta return false; 386abeb6b1eSDaniel Baluta default: 387abeb6b1eSDaniel Baluta return true; 388abeb6b1eSDaniel Baluta } 389abeb6b1eSDaniel Baluta } 390abeb6b1eSDaniel Baluta 391abeb6b1eSDaniel Baluta static struct reg_default mmc35240_reg_defaults[] = { 392abeb6b1eSDaniel Baluta { MMC35240_REG_CTRL0, 0x00 }, 393abeb6b1eSDaniel Baluta { MMC35240_REG_CTRL1, 0x00 }, 394abeb6b1eSDaniel Baluta }; 395abeb6b1eSDaniel Baluta 396abeb6b1eSDaniel Baluta static const struct regmap_config mmc35240_regmap_config = { 397abeb6b1eSDaniel Baluta .name = MMC35240_REGMAP_NAME, 398abeb6b1eSDaniel Baluta 399abeb6b1eSDaniel Baluta .reg_bits = 8, 400abeb6b1eSDaniel Baluta .val_bits = 8, 401abeb6b1eSDaniel Baluta 402abeb6b1eSDaniel Baluta .max_register = MMC35240_REG_ID, 403abeb6b1eSDaniel Baluta .cache_type = REGCACHE_FLAT, 404abeb6b1eSDaniel Baluta 405abeb6b1eSDaniel Baluta .writeable_reg = mmc35240_is_writeable_reg, 406abeb6b1eSDaniel Baluta .readable_reg = mmc35240_is_readable_reg, 407abeb6b1eSDaniel Baluta .volatile_reg = mmc35240_is_volatile_reg, 408abeb6b1eSDaniel Baluta 409abeb6b1eSDaniel Baluta .reg_defaults = mmc35240_reg_defaults, 410abeb6b1eSDaniel Baluta .num_reg_defaults = ARRAY_SIZE(mmc35240_reg_defaults), 411abeb6b1eSDaniel Baluta }; 412abeb6b1eSDaniel Baluta 413abeb6b1eSDaniel Baluta static int mmc35240_probe(struct i2c_client *client, 414abeb6b1eSDaniel Baluta const struct i2c_device_id *id) 415abeb6b1eSDaniel Baluta { 416abeb6b1eSDaniel Baluta struct mmc35240_data *data; 417abeb6b1eSDaniel Baluta struct iio_dev *indio_dev; 418abeb6b1eSDaniel Baluta struct regmap *regmap; 419abeb6b1eSDaniel Baluta int ret; 420abeb6b1eSDaniel Baluta 421abeb6b1eSDaniel Baluta indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 422abeb6b1eSDaniel Baluta if (!indio_dev) 423abeb6b1eSDaniel Baluta return -ENOMEM; 424abeb6b1eSDaniel Baluta 425abeb6b1eSDaniel Baluta regmap = devm_regmap_init_i2c(client, &mmc35240_regmap_config); 426abeb6b1eSDaniel Baluta if (IS_ERR(regmap)) { 427abeb6b1eSDaniel Baluta dev_err(&client->dev, "regmap initialization failed\n"); 428abeb6b1eSDaniel Baluta return PTR_ERR(regmap); 429abeb6b1eSDaniel Baluta } 430abeb6b1eSDaniel Baluta 431abeb6b1eSDaniel Baluta data = iio_priv(indio_dev); 432abeb6b1eSDaniel Baluta data->client = client; 433abeb6b1eSDaniel Baluta data->regmap = regmap; 434abeb6b1eSDaniel Baluta data->res = MMC35240_16_BITS_SLOW; 435abeb6b1eSDaniel Baluta 436abeb6b1eSDaniel Baluta mutex_init(&data->mutex); 437abeb6b1eSDaniel Baluta 438abeb6b1eSDaniel Baluta indio_dev->dev.parent = &client->dev; 439abeb6b1eSDaniel Baluta indio_dev->info = &mmc35240_info; 440abeb6b1eSDaniel Baluta indio_dev->name = MMC35240_DRV_NAME; 441abeb6b1eSDaniel Baluta indio_dev->channels = mmc35240_channels; 442abeb6b1eSDaniel Baluta indio_dev->num_channels = ARRAY_SIZE(mmc35240_channels); 443abeb6b1eSDaniel Baluta indio_dev->modes = INDIO_DIRECT_MODE; 444abeb6b1eSDaniel Baluta 445abeb6b1eSDaniel Baluta ret = mmc35240_init(data); 446abeb6b1eSDaniel Baluta if (ret < 0) { 447abeb6b1eSDaniel Baluta dev_err(&client->dev, "mmc35240 chip init failed\n"); 448abeb6b1eSDaniel Baluta return ret; 449abeb6b1eSDaniel Baluta } 450abeb6b1eSDaniel Baluta return devm_iio_device_register(&client->dev, indio_dev); 451abeb6b1eSDaniel Baluta } 452abeb6b1eSDaniel Baluta 453553a776bSDaniel Baluta #ifdef CONFIG_PM_SLEEP 454553a776bSDaniel Baluta static int mmc35240_suspend(struct device *dev) 455553a776bSDaniel Baluta { 456553a776bSDaniel Baluta struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 457553a776bSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 458553a776bSDaniel Baluta 459553a776bSDaniel Baluta regcache_cache_only(data->regmap, true); 460553a776bSDaniel Baluta 461553a776bSDaniel Baluta return 0; 462553a776bSDaniel Baluta } 463553a776bSDaniel Baluta 464553a776bSDaniel Baluta static int mmc35240_resume(struct device *dev) 465553a776bSDaniel Baluta { 466553a776bSDaniel Baluta struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); 467553a776bSDaniel Baluta struct mmc35240_data *data = iio_priv(indio_dev); 468553a776bSDaniel Baluta int ret; 469553a776bSDaniel Baluta 470553a776bSDaniel Baluta regcache_mark_dirty(data->regmap); 471553a776bSDaniel Baluta ret = regcache_sync_region(data->regmap, MMC35240_REG_CTRL0, 472553a776bSDaniel Baluta MMC35240_REG_CTRL1); 473553a776bSDaniel Baluta if (ret < 0) 474553a776bSDaniel Baluta dev_err(dev, "Failed to restore control registers\n"); 475553a776bSDaniel Baluta 476553a776bSDaniel Baluta regcache_cache_only(data->regmap, false); 477553a776bSDaniel Baluta 478553a776bSDaniel Baluta return 0; 479553a776bSDaniel Baluta } 480553a776bSDaniel Baluta #endif 481553a776bSDaniel Baluta 482553a776bSDaniel Baluta static const struct dev_pm_ops mmc35240_pm_ops = { 483553a776bSDaniel Baluta SET_SYSTEM_SLEEP_PM_OPS(mmc35240_suspend, mmc35240_resume) 484553a776bSDaniel Baluta }; 485553a776bSDaniel Baluta 486d11715f0SDaniel Baluta static const struct acpi_device_id mmc35240_acpi_match[] = { 487d11715f0SDaniel Baluta {"MMC35240", 0}, 488d11715f0SDaniel Baluta { }, 489d11715f0SDaniel Baluta }; 490d11715f0SDaniel Baluta MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match); 491d11715f0SDaniel Baluta 492abeb6b1eSDaniel Baluta static const struct i2c_device_id mmc35240_id[] = { 493abeb6b1eSDaniel Baluta {"MMC35240", 0}, 494abeb6b1eSDaniel Baluta {} 495abeb6b1eSDaniel Baluta }; 496abeb6b1eSDaniel Baluta MODULE_DEVICE_TABLE(i2c, mmc35240_id); 497abeb6b1eSDaniel Baluta 498abeb6b1eSDaniel Baluta static struct i2c_driver mmc35240_driver = { 499abeb6b1eSDaniel Baluta .driver = { 500abeb6b1eSDaniel Baluta .name = MMC35240_DRV_NAME, 501553a776bSDaniel Baluta .pm = &mmc35240_pm_ops, 502d11715f0SDaniel Baluta .acpi_match_table = ACPI_PTR(mmc35240_acpi_match), 503abeb6b1eSDaniel Baluta }, 504abeb6b1eSDaniel Baluta .probe = mmc35240_probe, 505abeb6b1eSDaniel Baluta .id_table = mmc35240_id, 506abeb6b1eSDaniel Baluta }; 507abeb6b1eSDaniel Baluta 508abeb6b1eSDaniel Baluta module_i2c_driver(mmc35240_driver); 509abeb6b1eSDaniel Baluta 510abeb6b1eSDaniel Baluta MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); 511abeb6b1eSDaniel Baluta MODULE_DESCRIPTION("MEMSIC MMC35240 magnetic sensor driver"); 512abeb6b1eSDaniel Baluta MODULE_LICENSE("GPL v2"); 513