Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");