^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * mag3110.c - Support for Freescale MAG3110 magnetometer sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (7-bit I2C slave address 0x0e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * TODO: irq, user offset, oversampling, continuous mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/iio/trigger_consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/iio/buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/iio/triggered_buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define MAG3110_STATUS 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define MAG3110_OUT_X 0x01 /* MSB first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define MAG3110_OUT_Y 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define MAG3110_OUT_Z 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define MAG3110_WHO_AM_I 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define MAG3110_SYSMOD 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MAG3110_OFF_X 0x09 /* MSB first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MAG3110_OFF_Y 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define MAG3110_OFF_Z 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define MAG3110_DIE_TEMP 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MAG3110_CTRL_REG1 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define MAG3110_CTRL_REG2 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define MAG3110_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define MAG3110_CTRL_DR_MASK (BIT(7) | BIT(6) | BIT(5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MAG3110_CTRL_DR_SHIFT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MAG3110_CTRL_DR_DEFAULT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define MAG3110_SYSMOD_MODE_MASK GENMASK(1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define MAG3110_CTRL_TM BIT(1) /* trigger single measurement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define MAG3110_CTRL_AC BIT(0) /* continuous measurements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define MAG3110_CTRL_AUTO_MRST_EN BIT(7) /* magnetic auto-reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define MAG3110_CTRL_RAW BIT(5) /* measurements not user-offset corrected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define MAG3110_DEVICE_ID 0xc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Each client has this additional data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct mag3110_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u8 ctrl_reg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int sleep_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct regulator *vdd_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct regulator *vddio_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Ensure natural alignment of timestamp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) __be16 channels[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u8 temperature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) s64 ts __aligned(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) } scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static int mag3110_request(struct mag3110_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int ret, tries = 150;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if ((data->ctrl_reg1 & MAG3110_CTRL_AC) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* trigger measurement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ret = i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) data->ctrl_reg1 | MAG3110_CTRL_TM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) while (tries-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) ret = i2c_smbus_read_byte_data(data->client, MAG3110_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* wait for data ready */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if ((ret & MAG3110_STATUS_DRDY) == MAG3110_STATUS_DRDY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (data->sleep_val <= 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) usleep_range(data->sleep_val * 250, data->sleep_val * 500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (tries < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) dev_err(&data->client->dev, "data not ready\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int mag3110_read(struct mag3110_data *data, __be16 buf[3])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ret = mag3110_request(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ret = i2c_smbus_read_i2c_block_data(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) MAG3110_OUT_X, 3 * sizeof(__be16), (u8 *) buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static ssize_t mag3110_show_int_plus_micros(char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const int (*vals)[2], int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) size_t len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) while (n-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) len += scnprintf(buf + len, PAGE_SIZE - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) "%d.%06d ", vals[n][0], vals[n][1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* replace trailing space by newline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) buf[len - 1] = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int mag3110_get_int_plus_micros_index(const int (*vals)[2], int n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int val, int val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) while (n-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (val == vals[n][0] && val2 == vals[n][1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static const int mag3110_samp_freq[8][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {80, 0}, {40, 0}, {20, 0}, {10, 0}, {5, 0}, {2, 500000},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {1, 250000}, {0, 625000}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static ssize_t mag3110_show_samp_freq_avail(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return mag3110_show_int_plus_micros(buf, mag3110_samp_freq, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mag3110_show_samp_freq_avail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static int mag3110_get_samp_freq_index(struct mag3110_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int val, int val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return mag3110_get_int_plus_micros_index(mag3110_samp_freq, 8, val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int mag3110_calculate_sleep(struct mag3110_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int ret, i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (mag3110_samp_freq[i][0] > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ret = 1000 / mag3110_samp_freq[i][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ret = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return ret == 0 ? 1 : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static int mag3110_standby(struct mag3110_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) data->ctrl_reg1 & ~MAG3110_CTRL_AC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int mag3110_wait_standby(struct mag3110_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int ret, tries = 30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * Takes up to 1/ODR to come out of active mode into stby
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * Longest expected period is 12.5seconds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * We'll sleep for 500ms between checks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) while (tries-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ret = i2c_smbus_read_byte_data(data->client, MAG3110_SYSMOD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) dev_err(&data->client->dev, "i2c error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* wait for standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if ((ret & MAG3110_SYSMOD_MODE_MASK) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) msleep_interruptible(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (tries < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dev_err(&data->client->dev, "device not entering standby mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int mag3110_active(struct mag3110_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) data->ctrl_reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* returns >0 if active, 0 if in standby and <0 on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static int mag3110_is_active(struct mag3110_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) reg = i2c_smbus_read_byte_data(data->client, MAG3110_CTRL_REG1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (reg < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return reg & MAG3110_CTRL_AC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int mag3110_change_config(struct mag3110_data *data, u8 reg, u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int is_active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) is_active = mag3110_is_active(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (is_active < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ret = is_active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* config can only be changed when in standby */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (is_active > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ret = mag3110_standby(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * After coming out of active we must wait for the part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * to transition to STBY. This can take up to 1 /ODR to occur
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ret = mag3110_wait_standby(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ret = i2c_smbus_write_byte_data(data->client, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (is_active > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ret = mag3110_active(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static int mag3110_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct mag3110_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) __be16 buffer[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) ret = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) case IIO_MAGN: /* in 0.1 uT / LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ret = mag3110_read(data, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) goto release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *val = sign_extend32(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) be16_to_cpu(buffer[chan->scan_index]), 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ret = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) case IIO_TEMP: /* in 1 C / LSB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ret = mag3110_request(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) goto release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ret = i2c_smbus_read_byte_data(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) MAG3110_DIE_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) goto release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) *val = sign_extend32(ret, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case IIO_MAGN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) *val2 = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case IIO_TEMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) *val = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) case IIO_CHAN_INFO_SAMP_FREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) *val = mag3110_samp_freq[i][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) *val2 = mag3110_samp_freq[i][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) case IIO_CHAN_INFO_CALIBBIAS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ret = i2c_smbus_read_word_swapped(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) MAG3110_OFF_X + 2 * chan->scan_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) *val = sign_extend32(ret >> 1, 14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static int mag3110_write_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) int val, int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct mag3110_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) int rate, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) ret = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) case IIO_CHAN_INFO_SAMP_FREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) rate = mag3110_get_samp_freq_index(data, val, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (rate < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) data->ctrl_reg1 &= 0xff & ~MAG3110_CTRL_DR_MASK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) & ~MAG3110_CTRL_AC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) data->sleep_val = mag3110_calculate_sleep(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (data->sleep_val < 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) data->ctrl_reg1 |= MAG3110_CTRL_AC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) ret = mag3110_change_config(data, MAG3110_CTRL_REG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) data->ctrl_reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case IIO_CHAN_INFO_CALIBBIAS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (val < -10000 || val > 10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) ret = i2c_smbus_write_word_swapped(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) MAG3110_OFF_X + 2 * chan->scan_index, val << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static irqreturn_t mag3110_trigger_handler(int irq, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct iio_poll_func *pf = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct iio_dev *indio_dev = pf->indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct mag3110_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = mag3110_read(data, data->scan.channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (test_bit(3, indio_dev->active_scan_mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) ret = i2c_smbus_read_byte_data(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) MAG3110_DIE_TEMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) data->scan.temperature = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) iio_trigger_notify_done(indio_dev->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) #define MAG3110_CHANNEL(axis, idx) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .type = IIO_MAGN, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .modified = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .channel2 = IIO_MOD_##axis, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) BIT(IIO_CHAN_INFO_CALIBBIAS), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) BIT(IIO_CHAN_INFO_SCALE), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .scan_index = idx, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .scan_type = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) .sign = 's', \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .realbits = 16, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) .storagebits = 16, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) .endianness = IIO_BE, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static const struct iio_chan_spec mag3110_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) MAG3110_CHANNEL(X, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) MAG3110_CHANNEL(Y, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) MAG3110_CHANNEL(Z, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) .type = IIO_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) .scan_index = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) .scan_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) .sign = 's',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) .realbits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) .storagebits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) IIO_CHAN_SOFT_TIMESTAMP(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) static struct attribute *mag3110_attributes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static const struct attribute_group mag3110_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .attrs = mag3110_attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static const struct iio_info mag3110_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) .attrs = &mag3110_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .read_raw = &mag3110_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .write_raw = &mag3110_write_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static const unsigned long mag3110_scan_masks[] = {0x7, 0xf, 0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static int mag3110_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct mag3110_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (IS_ERR(data->vdd_reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return dev_err_probe(&client->dev, PTR_ERR(data->vdd_reg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) "failed to get VDD regulator!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) data->vddio_reg = devm_regulator_get(&client->dev, "vddio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (IS_ERR(data->vddio_reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return dev_err_probe(&client->dev, PTR_ERR(data->vddio_reg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) "failed to get VDDIO regulator!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ret = regulator_enable(data->vdd_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) dev_err(&client->dev, "failed to enable VDD regulator!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ret = regulator_enable(data->vddio_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) dev_err(&client->dev, "failed to enable VDDIO regulator!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) goto disable_regulator_vdd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) goto disable_regulators;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (ret != MAG3110_DEVICE_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) goto disable_regulators;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) mutex_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) indio_dev->info = &mag3110_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) indio_dev->name = id->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) indio_dev->channels = mag3110_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) indio_dev->num_channels = ARRAY_SIZE(mag3110_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) indio_dev->available_scan_masks = mag3110_scan_masks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) data->ctrl_reg1 = MAG3110_CTRL_DR_DEFAULT << MAG3110_CTRL_DR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) data->sleep_val = mag3110_calculate_sleep(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (data->sleep_val < 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) data->ctrl_reg1 |= MAG3110_CTRL_AC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) ret = mag3110_change_config(data, MAG3110_CTRL_REG1, data->ctrl_reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) goto disable_regulators;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) MAG3110_CTRL_AUTO_MRST_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) goto standby_on_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) ret = iio_triggered_buffer_setup(indio_dev, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) mag3110_trigger_handler, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) goto standby_on_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ret = iio_device_register(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) goto buffer_cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) buffer_cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) iio_triggered_buffer_cleanup(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) standby_on_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) mag3110_standby(iio_priv(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) disable_regulators:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) regulator_disable(data->vddio_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) disable_regulator_vdd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) regulator_disable(data->vdd_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static int mag3110_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) struct iio_dev *indio_dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) struct mag3110_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) iio_device_unregister(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) iio_triggered_buffer_cleanup(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) mag3110_standby(iio_priv(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) regulator_disable(data->vddio_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) regulator_disable(data->vdd_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static int mag3110_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct mag3110_data *data = iio_priv(i2c_get_clientdata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ret = mag3110_standby(iio_priv(i2c_get_clientdata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) to_i2c_client(dev))));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ret = regulator_disable(data->vddio_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) dev_err(dev, "failed to disable VDDIO regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ret = regulator_disable(data->vdd_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) dev_err(dev, "failed to disable VDD regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) static int mag3110_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct mag3110_data *data = iio_priv(i2c_get_clientdata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ret = regulator_enable(data->vdd_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) dev_err(dev, "failed to enable VDD regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) ret = regulator_enable(data->vddio_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) dev_err(dev, "failed to enable VDDIO regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) regulator_disable(data->vdd_reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) data->ctrl_reg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) static SIMPLE_DEV_PM_OPS(mag3110_pm_ops, mag3110_suspend, mag3110_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) #define MAG3110_PM_OPS (&mag3110_pm_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) #define MAG3110_PM_OPS NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static const struct i2c_device_id mag3110_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) { "mag3110", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) MODULE_DEVICE_TABLE(i2c, mag3110_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static const struct of_device_id mag3110_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) { .compatible = "fsl,mag3110" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) MODULE_DEVICE_TABLE(of, mag3110_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) static struct i2c_driver mag3110_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) .name = "mag3110",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) .of_match_table = mag3110_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) .pm = MAG3110_PM_OPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) .probe = mag3110_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) .remove = mag3110_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) .id_table = mag3110_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) module_i2c_driver(mag3110_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) MODULE_DESCRIPTION("Freescale MAG3110 magnetometer driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) MODULE_LICENSE("GPL");