109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27c94a8b2SLinus Walleij /*
37c94a8b2SLinus Walleij * Driver for the Asahi Kasei EMD Corporation AK8974
47c94a8b2SLinus Walleij * and Aichi Steel AMI305 magnetometer chips.
57c94a8b2SLinus Walleij * Based on a patch from Samu Onkalo and the AK8975 IIO driver.
67c94a8b2SLinus Walleij *
77c94a8b2SLinus Walleij * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
87c94a8b2SLinus Walleij * Copyright (c) 2010 NVIDIA Corporation.
97c94a8b2SLinus Walleij * Copyright (C) 2016 Linaro Ltd.
107c94a8b2SLinus Walleij *
117c94a8b2SLinus Walleij * Author: Samu Onkalo <samu.p.onkalo@nokia.com>
127c94a8b2SLinus Walleij * Author: Linus Walleij <linus.walleij@linaro.org>
137c94a8b2SLinus Walleij */
147c94a8b2SLinus Walleij #include <linux/module.h>
152b4f0172SJonathan Cameron #include <linux/mod_devicetable.h>
167c94a8b2SLinus Walleij #include <linux/kernel.h>
177c94a8b2SLinus Walleij #include <linux/i2c.h>
187c94a8b2SLinus Walleij #include <linux/interrupt.h>
197c94a8b2SLinus Walleij #include <linux/irq.h> /* For irq_get_irq_data() */
207c94a8b2SLinus Walleij #include <linux/completion.h>
217c94a8b2SLinus Walleij #include <linux/err.h>
227c94a8b2SLinus Walleij #include <linux/mutex.h>
237c94a8b2SLinus Walleij #include <linux/delay.h>
247c94a8b2SLinus Walleij #include <linux/bitops.h>
25408cc6ebSMichał Mirosław #include <linux/random.h>
267c94a8b2SLinus Walleij #include <linux/regmap.h>
277c94a8b2SLinus Walleij #include <linux/regulator/consumer.h>
287c94a8b2SLinus Walleij #include <linux/pm_runtime.h>
297c94a8b2SLinus Walleij
307c94a8b2SLinus Walleij #include <linux/iio/iio.h>
317c94a8b2SLinus Walleij #include <linux/iio/sysfs.h>
327c94a8b2SLinus Walleij #include <linux/iio/buffer.h>
337c94a8b2SLinus Walleij #include <linux/iio/trigger.h>
347c94a8b2SLinus Walleij #include <linux/iio/trigger_consumer.h>
357c94a8b2SLinus Walleij #include <linux/iio/triggered_buffer.h>
367c94a8b2SLinus Walleij
377c94a8b2SLinus Walleij /*
387c94a8b2SLinus Walleij * 16-bit registers are little-endian. LSB is at the address defined below
397c94a8b2SLinus Walleij * and MSB is at the next higher address.
407c94a8b2SLinus Walleij */
417c94a8b2SLinus Walleij
4221be26fcSMichał Mirosław /* These registers are common for AK8974 and AMI30x */
437c94a8b2SLinus Walleij #define AK8974_SELFTEST 0x0C
447c94a8b2SLinus Walleij #define AK8974_SELFTEST_IDLE 0x55
457c94a8b2SLinus Walleij #define AK8974_SELFTEST_OK 0xAA
467c94a8b2SLinus Walleij
477c94a8b2SLinus Walleij #define AK8974_INFO 0x0D
487c94a8b2SLinus Walleij
497c94a8b2SLinus Walleij #define AK8974_WHOAMI 0x0F
5021be26fcSMichał Mirosław #define AK8974_WHOAMI_VALUE_AMI306 0x46
517c94a8b2SLinus Walleij #define AK8974_WHOAMI_VALUE_AMI305 0x47
527c94a8b2SLinus Walleij #define AK8974_WHOAMI_VALUE_AK8974 0x48
53525530afSNick Reitemeyer #define AK8974_WHOAMI_VALUE_HSCDTD008A 0x49
547c94a8b2SLinus Walleij
557c94a8b2SLinus Walleij #define AK8974_DATA_X 0x10
567c94a8b2SLinus Walleij #define AK8974_DATA_Y 0x12
577c94a8b2SLinus Walleij #define AK8974_DATA_Z 0x14
587c94a8b2SLinus Walleij #define AK8974_INT_SRC 0x16
597c94a8b2SLinus Walleij #define AK8974_STATUS 0x18
607c94a8b2SLinus Walleij #define AK8974_INT_CLEAR 0x1A
617c94a8b2SLinus Walleij #define AK8974_CTRL1 0x1B
627c94a8b2SLinus Walleij #define AK8974_CTRL2 0x1C
637c94a8b2SLinus Walleij #define AK8974_CTRL3 0x1D
647c94a8b2SLinus Walleij #define AK8974_INT_CTRL 0x1E
657c94a8b2SLinus Walleij #define AK8974_INT_THRES 0x26 /* Absolute any axis value threshold */
667c94a8b2SLinus Walleij #define AK8974_PRESET 0x30
677c94a8b2SLinus Walleij
687c94a8b2SLinus Walleij /* AK8974-specific offsets */
697c94a8b2SLinus Walleij #define AK8974_OFFSET_X 0x20
707c94a8b2SLinus Walleij #define AK8974_OFFSET_Y 0x22
717c94a8b2SLinus Walleij #define AK8974_OFFSET_Z 0x24
727c94a8b2SLinus Walleij /* AMI305-specific offsets */
737c94a8b2SLinus Walleij #define AMI305_OFFSET_X 0x6C
747c94a8b2SLinus Walleij #define AMI305_OFFSET_Y 0x72
757c94a8b2SLinus Walleij #define AMI305_OFFSET_Z 0x78
767c94a8b2SLinus Walleij
777c94a8b2SLinus Walleij /* Different temperature registers */
787c94a8b2SLinus Walleij #define AK8974_TEMP 0x31
797c94a8b2SLinus Walleij #define AMI305_TEMP 0x60
807c94a8b2SLinus Walleij
8121be26fcSMichał Mirosław /* AMI306-specific control register */
8221be26fcSMichał Mirosław #define AMI306_CTRL4 0x5C
8321be26fcSMichał Mirosław
8421be26fcSMichał Mirosław /* AMI306 factory calibration data */
8521be26fcSMichał Mirosław
8621be26fcSMichał Mirosław /* fine axis sensitivity */
8721be26fcSMichał Mirosław #define AMI306_FINEOUTPUT_X 0x90
8821be26fcSMichał Mirosław #define AMI306_FINEOUTPUT_Y 0x92
8921be26fcSMichał Mirosław #define AMI306_FINEOUTPUT_Z 0x94
9021be26fcSMichał Mirosław
9121be26fcSMichał Mirosław /* axis sensitivity */
9221be26fcSMichał Mirosław #define AMI306_SENS_X 0x96
9321be26fcSMichał Mirosław #define AMI306_SENS_Y 0x98
9421be26fcSMichał Mirosław #define AMI306_SENS_Z 0x9A
9521be26fcSMichał Mirosław
9621be26fcSMichał Mirosław /* axis cross-interference */
9721be26fcSMichał Mirosław #define AMI306_GAIN_PARA_XZ 0x9C
9821be26fcSMichał Mirosław #define AMI306_GAIN_PARA_XY 0x9D
9921be26fcSMichał Mirosław #define AMI306_GAIN_PARA_YZ 0x9E
10021be26fcSMichał Mirosław #define AMI306_GAIN_PARA_YX 0x9F
10121be26fcSMichał Mirosław #define AMI306_GAIN_PARA_ZY 0xA0
10221be26fcSMichał Mirosław #define AMI306_GAIN_PARA_ZX 0xA1
10321be26fcSMichał Mirosław
10421be26fcSMichał Mirosław /* offset at ZERO magnetic field */
10521be26fcSMichał Mirosław #define AMI306_OFFZERO_X 0xF8
10621be26fcSMichał Mirosław #define AMI306_OFFZERO_Y 0xFA
10721be26fcSMichał Mirosław #define AMI306_OFFZERO_Z 0xFC
10821be26fcSMichał Mirosław
10921be26fcSMichał Mirosław
1107c94a8b2SLinus Walleij #define AK8974_INT_X_HIGH BIT(7) /* Axis over +threshold */
1117c94a8b2SLinus Walleij #define AK8974_INT_Y_HIGH BIT(6)
1127c94a8b2SLinus Walleij #define AK8974_INT_Z_HIGH BIT(5)
1137c94a8b2SLinus Walleij #define AK8974_INT_X_LOW BIT(4) /* Axis below -threshold */
1147c94a8b2SLinus Walleij #define AK8974_INT_Y_LOW BIT(3)
1157c94a8b2SLinus Walleij #define AK8974_INT_Z_LOW BIT(2)
1167c94a8b2SLinus Walleij #define AK8974_INT_RANGE BIT(1) /* Range overflow (any axis) */
1177c94a8b2SLinus Walleij
1187c94a8b2SLinus Walleij #define AK8974_STATUS_DRDY BIT(6) /* Data ready */
1197c94a8b2SLinus Walleij #define AK8974_STATUS_OVERRUN BIT(5) /* Data overrun */
1207c94a8b2SLinus Walleij #define AK8974_STATUS_INT BIT(4) /* Interrupt occurred */
1217c94a8b2SLinus Walleij
1227c94a8b2SLinus Walleij #define AK8974_CTRL1_POWER BIT(7) /* 0 = standby; 1 = active */
1237c94a8b2SLinus Walleij #define AK8974_CTRL1_RATE BIT(4) /* 0 = 10 Hz; 1 = 20 Hz */
1247c94a8b2SLinus Walleij #define AK8974_CTRL1_FORCE_EN BIT(1) /* 0 = normal; 1 = force */
1257c94a8b2SLinus Walleij #define AK8974_CTRL1_MODE2 BIT(0) /* 0 */
1267c94a8b2SLinus Walleij
1277c94a8b2SLinus Walleij #define AK8974_CTRL2_INT_EN BIT(4) /* 1 = enable interrupts */
1287c94a8b2SLinus Walleij #define AK8974_CTRL2_DRDY_EN BIT(3) /* 1 = enable data ready signal */
1297c94a8b2SLinus Walleij #define AK8974_CTRL2_DRDY_POL BIT(2) /* 1 = data ready active high */
1307c94a8b2SLinus Walleij #define AK8974_CTRL2_RESDEF (AK8974_CTRL2_DRDY_POL)
1317c94a8b2SLinus Walleij
1327c94a8b2SLinus Walleij #define AK8974_CTRL3_RESET BIT(7) /* Software reset */
1337c94a8b2SLinus Walleij #define AK8974_CTRL3_FORCE BIT(6) /* Start forced measurement */
1347c94a8b2SLinus Walleij #define AK8974_CTRL3_SELFTEST BIT(4) /* Set selftest register */
1357c94a8b2SLinus Walleij #define AK8974_CTRL3_RESDEF 0x00
1367c94a8b2SLinus Walleij
1377c94a8b2SLinus Walleij #define AK8974_INT_CTRL_XEN BIT(7) /* Enable interrupt for this axis */
1387c94a8b2SLinus Walleij #define AK8974_INT_CTRL_YEN BIT(6)
1397c94a8b2SLinus Walleij #define AK8974_INT_CTRL_ZEN BIT(5)
1407c94a8b2SLinus Walleij #define AK8974_INT_CTRL_XYZEN (BIT(7)|BIT(6)|BIT(5))
1417c94a8b2SLinus Walleij #define AK8974_INT_CTRL_POL BIT(3) /* 0 = active low; 1 = active high */
1427c94a8b2SLinus Walleij #define AK8974_INT_CTRL_PULSE BIT(1) /* 0 = latched; 1 = pulse (50 usec) */
1437c94a8b2SLinus Walleij #define AK8974_INT_CTRL_RESDEF (AK8974_INT_CTRL_XYZEN | AK8974_INT_CTRL_POL)
1447c94a8b2SLinus Walleij
145525530afSNick Reitemeyer /* HSCDTD008A-specific control register */
146525530afSNick Reitemeyer #define HSCDTD008A_CTRL4 0x1E
147525530afSNick Reitemeyer #define HSCDTD008A_CTRL4_MMD BIT(7) /* must be set to 1 */
148525530afSNick Reitemeyer #define HSCDTD008A_CTRL4_RANGE BIT(4) /* 0 = 14-bit output; 1 = 15-bit output */
149525530afSNick Reitemeyer #define HSCDTD008A_CTRL4_RESDEF (HSCDTD008A_CTRL4_MMD | HSCDTD008A_CTRL4_RANGE)
150525530afSNick Reitemeyer
1517c94a8b2SLinus Walleij /* The AMI305 has elaborate FW version and serial number registers */
1527c94a8b2SLinus Walleij #define AMI305_VER 0xE8
1537c94a8b2SLinus Walleij #define AMI305_SN 0xEA
1547c94a8b2SLinus Walleij
1557c94a8b2SLinus Walleij #define AK8974_MAX_RANGE 2048
1567c94a8b2SLinus Walleij
1577c94a8b2SLinus Walleij #define AK8974_POWERON_DELAY 50
1587c94a8b2SLinus Walleij #define AK8974_ACTIVATE_DELAY 1
1597c94a8b2SLinus Walleij #define AK8974_SELFTEST_DELAY 1
1607c94a8b2SLinus Walleij /*
1617c94a8b2SLinus Walleij * Set the autosuspend to two orders of magnitude larger than the poweron
1627c94a8b2SLinus Walleij * delay to make sane reasonable power tradeoff savings (5 seconds in
1637c94a8b2SLinus Walleij * this case).
1647c94a8b2SLinus Walleij */
1657c94a8b2SLinus Walleij #define AK8974_AUTOSUSPEND_DELAY 5000
1667c94a8b2SLinus Walleij
1677c94a8b2SLinus Walleij #define AK8974_MEASTIME 3
1687c94a8b2SLinus Walleij
1697c94a8b2SLinus Walleij #define AK8974_PWR_ON 1
1707c94a8b2SLinus Walleij #define AK8974_PWR_OFF 0
1717c94a8b2SLinus Walleij
1727c94a8b2SLinus Walleij /**
1737c94a8b2SLinus Walleij * struct ak8974 - state container for the AK8974 driver
1747c94a8b2SLinus Walleij * @i2c: parent I2C client
1757c94a8b2SLinus Walleij * @orientation: mounting matrix, flipped axis etc
1767c94a8b2SLinus Walleij * @map: regmap to access the AK8974 registers over I2C
1777c94a8b2SLinus Walleij * @regs: the avdd and dvdd power regulators
1787c94a8b2SLinus Walleij * @name: the name of the part
1797c94a8b2SLinus Walleij * @variant: the whoami ID value (for selecting code paths)
1807c94a8b2SLinus Walleij * @lock: locks the magnetometer for exclusive use during a measurement
1817c94a8b2SLinus Walleij * @drdy_irq: uses the DRDY IRQ line
1827c94a8b2SLinus Walleij * @drdy_complete: completion for DRDY
1837c94a8b2SLinus Walleij * @drdy_active_low: the DRDY IRQ is active low
1845497523eSLee Jones * @scan: timestamps
1857c94a8b2SLinus Walleij */
1867c94a8b2SLinus Walleij struct ak8974 {
1877c94a8b2SLinus Walleij struct i2c_client *i2c;
1887c94a8b2SLinus Walleij struct iio_mount_matrix orientation;
1897c94a8b2SLinus Walleij struct regmap *map;
1907c94a8b2SLinus Walleij struct regulator_bulk_data regs[2];
1917c94a8b2SLinus Walleij const char *name;
1927c94a8b2SLinus Walleij u8 variant;
1937c94a8b2SLinus Walleij struct mutex lock;
1947c94a8b2SLinus Walleij bool drdy_irq;
1957c94a8b2SLinus Walleij struct completion drdy_complete;
1967c94a8b2SLinus Walleij bool drdy_active_low;
197838e00b1SJonathan Cameron /* Ensure timestamp is naturally aligned */
198838e00b1SJonathan Cameron struct {
199838e00b1SJonathan Cameron __le16 channels[3];
200838e00b1SJonathan Cameron s64 ts __aligned(8);
201838e00b1SJonathan Cameron } scan;
2027c94a8b2SLinus Walleij };
2037c94a8b2SLinus Walleij
2047c94a8b2SLinus Walleij static const char ak8974_reg_avdd[] = "avdd";
2057c94a8b2SLinus Walleij static const char ak8974_reg_dvdd[] = "dvdd";
2067c94a8b2SLinus Walleij
ak8974_get_u16_val(struct ak8974 * ak8974,u8 reg,u16 * val)20721be26fcSMichał Mirosław static int ak8974_get_u16_val(struct ak8974 *ak8974, u8 reg, u16 *val)
20821be26fcSMichał Mirosław {
20921be26fcSMichał Mirosław int ret;
21021be26fcSMichał Mirosław __le16 bulk;
21121be26fcSMichał Mirosław
21221be26fcSMichał Mirosław ret = regmap_bulk_read(ak8974->map, reg, &bulk, 2);
21321be26fcSMichał Mirosław if (ret)
21421be26fcSMichał Mirosław return ret;
21521be26fcSMichał Mirosław *val = le16_to_cpu(bulk);
21621be26fcSMichał Mirosław
21721be26fcSMichał Mirosław return 0;
21821be26fcSMichał Mirosław }
21921be26fcSMichał Mirosław
ak8974_set_u16_val(struct ak8974 * ak8974,u8 reg,u16 val)22021be26fcSMichał Mirosław static int ak8974_set_u16_val(struct ak8974 *ak8974, u8 reg, u16 val)
22121be26fcSMichał Mirosław {
22221be26fcSMichał Mirosław __le16 bulk = cpu_to_le16(val);
22321be26fcSMichał Mirosław
22421be26fcSMichał Mirosław return regmap_bulk_write(ak8974->map, reg, &bulk, 2);
22521be26fcSMichał Mirosław }
22621be26fcSMichał Mirosław
ak8974_set_power(struct ak8974 * ak8974,bool mode)2277c94a8b2SLinus Walleij static int ak8974_set_power(struct ak8974 *ak8974, bool mode)
2287c94a8b2SLinus Walleij {
2297c94a8b2SLinus Walleij int ret;
2307c94a8b2SLinus Walleij u8 val;
2317c94a8b2SLinus Walleij
2327c94a8b2SLinus Walleij val = mode ? AK8974_CTRL1_POWER : 0;
2337c94a8b2SLinus Walleij val |= AK8974_CTRL1_FORCE_EN;
2347c94a8b2SLinus Walleij ret = regmap_write(ak8974->map, AK8974_CTRL1, val);
2357c94a8b2SLinus Walleij if (ret < 0)
2367c94a8b2SLinus Walleij return ret;
2377c94a8b2SLinus Walleij
2387c94a8b2SLinus Walleij if (mode)
2397c94a8b2SLinus Walleij msleep(AK8974_ACTIVATE_DELAY);
2407c94a8b2SLinus Walleij
2417c94a8b2SLinus Walleij return 0;
2427c94a8b2SLinus Walleij }
2437c94a8b2SLinus Walleij
ak8974_reset(struct ak8974 * ak8974)2447c94a8b2SLinus Walleij static int ak8974_reset(struct ak8974 *ak8974)
2457c94a8b2SLinus Walleij {
2467c94a8b2SLinus Walleij int ret;
2477c94a8b2SLinus Walleij
2487c94a8b2SLinus Walleij /* Power on to get register access. Sets CTRL1 reg to reset state */
2497c94a8b2SLinus Walleij ret = ak8974_set_power(ak8974, AK8974_PWR_ON);
2507c94a8b2SLinus Walleij if (ret)
2517c94a8b2SLinus Walleij return ret;
2527c94a8b2SLinus Walleij ret = regmap_write(ak8974->map, AK8974_CTRL2, AK8974_CTRL2_RESDEF);
2537c94a8b2SLinus Walleij if (ret)
2547c94a8b2SLinus Walleij return ret;
2557c94a8b2SLinus Walleij ret = regmap_write(ak8974->map, AK8974_CTRL3, AK8974_CTRL3_RESDEF);
2567c94a8b2SLinus Walleij if (ret)
2577c94a8b2SLinus Walleij return ret;
258525530afSNick Reitemeyer if (ak8974->variant != AK8974_WHOAMI_VALUE_HSCDTD008A) {
2597c94a8b2SLinus Walleij ret = regmap_write(ak8974->map, AK8974_INT_CTRL,
2607c94a8b2SLinus Walleij AK8974_INT_CTRL_RESDEF);
2617c94a8b2SLinus Walleij if (ret)
2627c94a8b2SLinus Walleij return ret;
263525530afSNick Reitemeyer } else {
264525530afSNick Reitemeyer ret = regmap_write(ak8974->map, HSCDTD008A_CTRL4,
265525530afSNick Reitemeyer HSCDTD008A_CTRL4_RESDEF);
266525530afSNick Reitemeyer if (ret)
267525530afSNick Reitemeyer return ret;
268525530afSNick Reitemeyer }
2697c94a8b2SLinus Walleij
2707c94a8b2SLinus Walleij /* After reset, power off is default state */
2717c94a8b2SLinus Walleij return ak8974_set_power(ak8974, AK8974_PWR_OFF);
2727c94a8b2SLinus Walleij }
2737c94a8b2SLinus Walleij
ak8974_configure(struct ak8974 * ak8974)2747c94a8b2SLinus Walleij static int ak8974_configure(struct ak8974 *ak8974)
2757c94a8b2SLinus Walleij {
2767c94a8b2SLinus Walleij int ret;
2777c94a8b2SLinus Walleij
2787c94a8b2SLinus Walleij ret = regmap_write(ak8974->map, AK8974_CTRL2, AK8974_CTRL2_DRDY_EN |
2797c94a8b2SLinus Walleij AK8974_CTRL2_INT_EN);
2807c94a8b2SLinus Walleij if (ret)
2817c94a8b2SLinus Walleij return ret;
2827c94a8b2SLinus Walleij ret = regmap_write(ak8974->map, AK8974_CTRL3, 0);
2837c94a8b2SLinus Walleij if (ret)
2847c94a8b2SLinus Walleij return ret;
28521be26fcSMichał Mirosław if (ak8974->variant == AK8974_WHOAMI_VALUE_AMI306) {
28621be26fcSMichał Mirosław /* magic from datasheet: set high-speed measurement mode */
28721be26fcSMichał Mirosław ret = ak8974_set_u16_val(ak8974, AMI306_CTRL4, 0xA07E);
28821be26fcSMichał Mirosław if (ret)
28921be26fcSMichał Mirosław return ret;
29021be26fcSMichał Mirosław }
291525530afSNick Reitemeyer if (ak8974->variant == AK8974_WHOAMI_VALUE_HSCDTD008A)
292525530afSNick Reitemeyer return 0;
2937c94a8b2SLinus Walleij ret = regmap_write(ak8974->map, AK8974_INT_CTRL, AK8974_INT_CTRL_POL);
2947c94a8b2SLinus Walleij if (ret)
2957c94a8b2SLinus Walleij return ret;
2967c94a8b2SLinus Walleij
2977c94a8b2SLinus Walleij return regmap_write(ak8974->map, AK8974_PRESET, 0);
2987c94a8b2SLinus Walleij }
2997c94a8b2SLinus Walleij
ak8974_trigmeas(struct ak8974 * ak8974)3007c94a8b2SLinus Walleij static int ak8974_trigmeas(struct ak8974 *ak8974)
3017c94a8b2SLinus Walleij {
3027c94a8b2SLinus Walleij unsigned int clear;
3037c94a8b2SLinus Walleij u8 mask;
3047c94a8b2SLinus Walleij u8 val;
3057c94a8b2SLinus Walleij int ret;
3067c94a8b2SLinus Walleij
3077c94a8b2SLinus Walleij /* Clear any previous measurement overflow status */
3087c94a8b2SLinus Walleij ret = regmap_read(ak8974->map, AK8974_INT_CLEAR, &clear);
3097c94a8b2SLinus Walleij if (ret)
3107c94a8b2SLinus Walleij return ret;
3117c94a8b2SLinus Walleij
3127c94a8b2SLinus Walleij /* If we have a DRDY IRQ line, use it */
3137c94a8b2SLinus Walleij if (ak8974->drdy_irq) {
3147c94a8b2SLinus Walleij mask = AK8974_CTRL2_INT_EN |
3157c94a8b2SLinus Walleij AK8974_CTRL2_DRDY_EN |
3167c94a8b2SLinus Walleij AK8974_CTRL2_DRDY_POL;
3177c94a8b2SLinus Walleij val = AK8974_CTRL2_DRDY_EN;
3187c94a8b2SLinus Walleij
3197c94a8b2SLinus Walleij if (!ak8974->drdy_active_low)
3207c94a8b2SLinus Walleij val |= AK8974_CTRL2_DRDY_POL;
3217c94a8b2SLinus Walleij
3227c94a8b2SLinus Walleij init_completion(&ak8974->drdy_complete);
3237c94a8b2SLinus Walleij ret = regmap_update_bits(ak8974->map, AK8974_CTRL2,
3247c94a8b2SLinus Walleij mask, val);
3257c94a8b2SLinus Walleij if (ret)
3267c94a8b2SLinus Walleij return ret;
3277c94a8b2SLinus Walleij }
3287c94a8b2SLinus Walleij
3297c94a8b2SLinus Walleij /* Force a measurement */
3307c94a8b2SLinus Walleij return regmap_update_bits(ak8974->map,
3317c94a8b2SLinus Walleij AK8974_CTRL3,
3327c94a8b2SLinus Walleij AK8974_CTRL3_FORCE,
3337c94a8b2SLinus Walleij AK8974_CTRL3_FORCE);
3347c94a8b2SLinus Walleij }
3357c94a8b2SLinus Walleij
ak8974_await_drdy(struct ak8974 * ak8974)3367c94a8b2SLinus Walleij static int ak8974_await_drdy(struct ak8974 *ak8974)
3377c94a8b2SLinus Walleij {
3387c94a8b2SLinus Walleij int timeout = 2;
3397c94a8b2SLinus Walleij unsigned int val;
3407c94a8b2SLinus Walleij int ret;
3417c94a8b2SLinus Walleij
3427c94a8b2SLinus Walleij if (ak8974->drdy_irq) {
3437c94a8b2SLinus Walleij ret = wait_for_completion_timeout(&ak8974->drdy_complete,
3447c94a8b2SLinus Walleij 1 + msecs_to_jiffies(1000));
3457c94a8b2SLinus Walleij if (!ret) {
3467c94a8b2SLinus Walleij dev_err(&ak8974->i2c->dev,
3477c94a8b2SLinus Walleij "timeout waiting for DRDY IRQ\n");
3487c94a8b2SLinus Walleij return -ETIMEDOUT;
3497c94a8b2SLinus Walleij }
3507c94a8b2SLinus Walleij return 0;
3517c94a8b2SLinus Walleij }
3527c94a8b2SLinus Walleij
3537c94a8b2SLinus Walleij /* Default delay-based poll loop */
3547c94a8b2SLinus Walleij do {
3557c94a8b2SLinus Walleij msleep(AK8974_MEASTIME);
3567c94a8b2SLinus Walleij ret = regmap_read(ak8974->map, AK8974_STATUS, &val);
3577c94a8b2SLinus Walleij if (ret < 0)
3587c94a8b2SLinus Walleij return ret;
3597c94a8b2SLinus Walleij if (val & AK8974_STATUS_DRDY)
3607c94a8b2SLinus Walleij return 0;
3617c94a8b2SLinus Walleij } while (--timeout);
3627c94a8b2SLinus Walleij
363e2eb179cSColin Ian King dev_err(&ak8974->i2c->dev, "timeout waiting for DRDY\n");
364e2eb179cSColin Ian King return -ETIMEDOUT;
3657c94a8b2SLinus Walleij }
3667c94a8b2SLinus Walleij
ak8974_getresult(struct ak8974 * ak8974,__le16 * result)3677f709dcdSIco Doornekamp static int ak8974_getresult(struct ak8974 *ak8974, __le16 *result)
3687c94a8b2SLinus Walleij {
3697c94a8b2SLinus Walleij unsigned int src;
3707c94a8b2SLinus Walleij int ret;
3717c94a8b2SLinus Walleij
3727c94a8b2SLinus Walleij ret = ak8974_await_drdy(ak8974);
3737c94a8b2SLinus Walleij if (ret)
3747c94a8b2SLinus Walleij return ret;
3757c94a8b2SLinus Walleij ret = regmap_read(ak8974->map, AK8974_INT_SRC, &src);
3767c94a8b2SLinus Walleij if (ret < 0)
3777c94a8b2SLinus Walleij return ret;
3787c94a8b2SLinus Walleij
3797c94a8b2SLinus Walleij /* Out of range overflow! Strong magnet close? */
3807c94a8b2SLinus Walleij if (src & AK8974_INT_RANGE) {
3817c94a8b2SLinus Walleij dev_err(&ak8974->i2c->dev,
3827c94a8b2SLinus Walleij "range overflow in sensor\n");
3837c94a8b2SLinus Walleij return -ERANGE;
3847c94a8b2SLinus Walleij }
3857c94a8b2SLinus Walleij
3867c94a8b2SLinus Walleij ret = regmap_bulk_read(ak8974->map, AK8974_DATA_X, result, 6);
3877c94a8b2SLinus Walleij if (ret)
3887c94a8b2SLinus Walleij return ret;
3897c94a8b2SLinus Walleij
3907c94a8b2SLinus Walleij return ret;
3917c94a8b2SLinus Walleij }
3927c94a8b2SLinus Walleij
ak8974_drdy_irq(int irq,void * d)3937c94a8b2SLinus Walleij static irqreturn_t ak8974_drdy_irq(int irq, void *d)
3947c94a8b2SLinus Walleij {
3957c94a8b2SLinus Walleij struct ak8974 *ak8974 = d;
3967c94a8b2SLinus Walleij
3977c94a8b2SLinus Walleij if (!ak8974->drdy_irq)
3987c94a8b2SLinus Walleij return IRQ_NONE;
3997c94a8b2SLinus Walleij
4007c94a8b2SLinus Walleij /* TODO: timestamp here to get good measurement stamps */
4017c94a8b2SLinus Walleij return IRQ_WAKE_THREAD;
4027c94a8b2SLinus Walleij }
4037c94a8b2SLinus Walleij
ak8974_drdy_irq_thread(int irq,void * d)4047c94a8b2SLinus Walleij static irqreturn_t ak8974_drdy_irq_thread(int irq, void *d)
4057c94a8b2SLinus Walleij {
4067c94a8b2SLinus Walleij struct ak8974 *ak8974 = d;
4077c94a8b2SLinus Walleij unsigned int val;
4087c94a8b2SLinus Walleij int ret;
4097c94a8b2SLinus Walleij
4107c94a8b2SLinus Walleij /* Check if this was a DRDY from us */
4117c94a8b2SLinus Walleij ret = regmap_read(ak8974->map, AK8974_STATUS, &val);
4127c94a8b2SLinus Walleij if (ret < 0) {
4137c94a8b2SLinus Walleij dev_err(&ak8974->i2c->dev, "error reading DRDY status\n");
4147c94a8b2SLinus Walleij return IRQ_HANDLED;
4157c94a8b2SLinus Walleij }
4167c94a8b2SLinus Walleij if (val & AK8974_STATUS_DRDY) {
4177c94a8b2SLinus Walleij /* Yes this was our IRQ */
4187c94a8b2SLinus Walleij complete(&ak8974->drdy_complete);
4197c94a8b2SLinus Walleij return IRQ_HANDLED;
4207c94a8b2SLinus Walleij }
4217c94a8b2SLinus Walleij
4227c94a8b2SLinus Walleij /* We may be on a shared IRQ, let the next client check */
4237c94a8b2SLinus Walleij return IRQ_NONE;
4247c94a8b2SLinus Walleij }
4257c94a8b2SLinus Walleij
ak8974_selftest(struct ak8974 * ak8974)4267c94a8b2SLinus Walleij static int ak8974_selftest(struct ak8974 *ak8974)
4277c94a8b2SLinus Walleij {
4287c94a8b2SLinus Walleij struct device *dev = &ak8974->i2c->dev;
4297c94a8b2SLinus Walleij unsigned int val;
4307c94a8b2SLinus Walleij int ret;
4317c94a8b2SLinus Walleij
4327c94a8b2SLinus Walleij ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val);
4337c94a8b2SLinus Walleij if (ret)
4347c94a8b2SLinus Walleij return ret;
4357c94a8b2SLinus Walleij if (val != AK8974_SELFTEST_IDLE) {
4367c94a8b2SLinus Walleij dev_err(dev, "selftest not idle before test\n");
4377c94a8b2SLinus Walleij return -EIO;
4387c94a8b2SLinus Walleij }
4397c94a8b2SLinus Walleij
4407c94a8b2SLinus Walleij /* Trigger self-test */
4417c94a8b2SLinus Walleij ret = regmap_update_bits(ak8974->map,
4427c94a8b2SLinus Walleij AK8974_CTRL3,
4437c94a8b2SLinus Walleij AK8974_CTRL3_SELFTEST,
4447c94a8b2SLinus Walleij AK8974_CTRL3_SELFTEST);
4457c94a8b2SLinus Walleij if (ret) {
4467c94a8b2SLinus Walleij dev_err(dev, "could not write CTRL3\n");
4477c94a8b2SLinus Walleij return ret;
4487c94a8b2SLinus Walleij }
4497c94a8b2SLinus Walleij
4507c94a8b2SLinus Walleij msleep(AK8974_SELFTEST_DELAY);
4517c94a8b2SLinus Walleij
4527c94a8b2SLinus Walleij ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val);
4537c94a8b2SLinus Walleij if (ret)
4547c94a8b2SLinus Walleij return ret;
4557c94a8b2SLinus Walleij if (val != AK8974_SELFTEST_OK) {
4567c94a8b2SLinus Walleij dev_err(dev, "selftest result NOT OK (%02x)\n", val);
4577c94a8b2SLinus Walleij return -EIO;
4587c94a8b2SLinus Walleij }
4597c94a8b2SLinus Walleij
4607c94a8b2SLinus Walleij ret = regmap_read(ak8974->map, AK8974_SELFTEST, &val);
4617c94a8b2SLinus Walleij if (ret)
4627c94a8b2SLinus Walleij return ret;
4637c94a8b2SLinus Walleij if (val != AK8974_SELFTEST_IDLE) {
4647c94a8b2SLinus Walleij dev_err(dev, "selftest not idle after test (%02x)\n", val);
4657c94a8b2SLinus Walleij return -EIO;
4667c94a8b2SLinus Walleij }
4677c94a8b2SLinus Walleij dev_dbg(dev, "passed self-test\n");
4687c94a8b2SLinus Walleij
4697c94a8b2SLinus Walleij return 0;
4707c94a8b2SLinus Walleij }
4717c94a8b2SLinus Walleij
ak8974_read_calib_data(struct ak8974 * ak8974,unsigned int reg,__le16 * tab,size_t tab_size)4720a60340fSMichał Mirosław static void ak8974_read_calib_data(struct ak8974 *ak8974, unsigned int reg,
4730a60340fSMichał Mirosław __le16 *tab, size_t tab_size)
4740a60340fSMichał Mirosław {
4750a60340fSMichał Mirosław int ret = regmap_bulk_read(ak8974->map, reg, tab, tab_size);
4760a60340fSMichał Mirosław if (ret) {
4770a60340fSMichał Mirosław memset(tab, 0xFF, tab_size);
4780a60340fSMichał Mirosław dev_warn(&ak8974->i2c->dev,
4790a60340fSMichał Mirosław "can't read calibration data (regs %u..%zu): %d\n",
4800a60340fSMichał Mirosław reg, reg + tab_size - 1, ret);
4810a60340fSMichał Mirosław } else {
4820a60340fSMichał Mirosław add_device_randomness(tab, tab_size);
4830a60340fSMichał Mirosław }
4840a60340fSMichał Mirosław }
4850a60340fSMichał Mirosław
ak8974_detect(struct ak8974 * ak8974)4867c94a8b2SLinus Walleij static int ak8974_detect(struct ak8974 *ak8974)
4877c94a8b2SLinus Walleij {
4887c94a8b2SLinus Walleij unsigned int whoami;
4897c94a8b2SLinus Walleij const char *name;
4907c94a8b2SLinus Walleij int ret;
4917c94a8b2SLinus Walleij unsigned int fw;
4927c94a8b2SLinus Walleij u16 sn;
4937c94a8b2SLinus Walleij
4947c94a8b2SLinus Walleij ret = regmap_read(ak8974->map, AK8974_WHOAMI, &whoami);
4957c94a8b2SLinus Walleij if (ret)
4967c94a8b2SLinus Walleij return ret;
4977c94a8b2SLinus Walleij
4987c94a8b2SLinus Walleij name = "ami305";
49921be26fcSMichał Mirosław
50021be26fcSMichał Mirosław switch (whoami) {
50121be26fcSMichał Mirosław case AK8974_WHOAMI_VALUE_AMI306:
50221be26fcSMichał Mirosław name = "ami306";
503df561f66SGustavo A. R. Silva fallthrough;
50421be26fcSMichał Mirosław case AK8974_WHOAMI_VALUE_AMI305:
5057c94a8b2SLinus Walleij ret = regmap_read(ak8974->map, AMI305_VER, &fw);
5067c94a8b2SLinus Walleij if (ret)
5077c94a8b2SLinus Walleij return ret;
5087c94a8b2SLinus Walleij fw &= 0x7f; /* only bits 0 thru 6 valid */
5097c94a8b2SLinus Walleij ret = ak8974_get_u16_val(ak8974, AMI305_SN, &sn);
5107c94a8b2SLinus Walleij if (ret)
5117c94a8b2SLinus Walleij return ret;
512408cc6ebSMichał Mirosław add_device_randomness(&sn, sizeof(sn));
5137c94a8b2SLinus Walleij dev_info(&ak8974->i2c->dev,
5147c94a8b2SLinus Walleij "detected %s, FW ver %02x, S/N: %04x\n",
5157c94a8b2SLinus Walleij name, fw, sn);
5167c94a8b2SLinus Walleij break;
5177c94a8b2SLinus Walleij case AK8974_WHOAMI_VALUE_AK8974:
5187c94a8b2SLinus Walleij name = "ak8974";
5197c94a8b2SLinus Walleij dev_info(&ak8974->i2c->dev, "detected AK8974\n");
5207c94a8b2SLinus Walleij break;
521525530afSNick Reitemeyer case AK8974_WHOAMI_VALUE_HSCDTD008A:
522525530afSNick Reitemeyer name = "hscdtd008a";
523525530afSNick Reitemeyer dev_info(&ak8974->i2c->dev, "detected hscdtd008a\n");
524525530afSNick Reitemeyer break;
5257c94a8b2SLinus Walleij default:
5267c94a8b2SLinus Walleij dev_err(&ak8974->i2c->dev, "unsupported device (%02x) ",
5277c94a8b2SLinus Walleij whoami);
5287c94a8b2SLinus Walleij return -ENODEV;
5297c94a8b2SLinus Walleij }
5307c94a8b2SLinus Walleij
5317c94a8b2SLinus Walleij ak8974->name = name;
5327c94a8b2SLinus Walleij ak8974->variant = whoami;
5337c94a8b2SLinus Walleij
5340a60340fSMichał Mirosław if (whoami == AK8974_WHOAMI_VALUE_AMI306) {
5350a60340fSMichał Mirosław __le16 fab_data1[9], fab_data2[3];
5360a60340fSMichał Mirosław int i;
5370a60340fSMichał Mirosław
5380a60340fSMichał Mirosław ak8974_read_calib_data(ak8974, AMI306_FINEOUTPUT_X,
5390a60340fSMichał Mirosław fab_data1, sizeof(fab_data1));
5400a60340fSMichał Mirosław ak8974_read_calib_data(ak8974, AMI306_OFFZERO_X,
5410a60340fSMichał Mirosław fab_data2, sizeof(fab_data2));
5420a60340fSMichał Mirosław
5430a60340fSMichał Mirosław for (i = 0; i < 3; ++i) {
5440a60340fSMichał Mirosław static const char axis[3] = "XYZ";
5450a60340fSMichał Mirosław static const char pgaxis[6] = "ZYZXYX";
5460a60340fSMichał Mirosław unsigned offz = le16_to_cpu(fab_data2[i]) & 0x7F;
5470a60340fSMichał Mirosław unsigned fine = le16_to_cpu(fab_data1[i]);
5480a60340fSMichał Mirosław unsigned sens = le16_to_cpu(fab_data1[i + 3]);
5490a60340fSMichał Mirosław unsigned pgain1 = le16_to_cpu(fab_data1[i + 6]);
5500a60340fSMichał Mirosław unsigned pgain2 = pgain1 >> 8;
5510a60340fSMichał Mirosław
5520a60340fSMichał Mirosław pgain1 &= 0xFF;
5530a60340fSMichał Mirosław
5540a60340fSMichał Mirosław dev_info(&ak8974->i2c->dev,
5550a60340fSMichał Mirosław "factory calibration for axis %c: offz=%u sens=%u fine=%u pga%c=%u pga%c=%u\n",
5560a60340fSMichał Mirosław axis[i], offz, sens, fine, pgaxis[i * 2],
5570a60340fSMichał Mirosław pgain1, pgaxis[i * 2 + 1], pgain2);
5580a60340fSMichał Mirosław }
5590a60340fSMichał Mirosław }
5600a60340fSMichał Mirosław
5617c94a8b2SLinus Walleij return 0;
5627c94a8b2SLinus Walleij }
5637c94a8b2SLinus Walleij
ak8974_measure_channel(struct ak8974 * ak8974,unsigned long address,int * val)56455ecaf17SLinus Walleij static int ak8974_measure_channel(struct ak8974 *ak8974, unsigned long address,
56555ecaf17SLinus Walleij int *val)
5667c94a8b2SLinus Walleij {
5677f709dcdSIco Doornekamp __le16 hw_values[3];
56855ecaf17SLinus Walleij int ret;
5697c94a8b2SLinus Walleij
5707c94a8b2SLinus Walleij pm_runtime_get_sync(&ak8974->i2c->dev);
5717c94a8b2SLinus Walleij mutex_lock(&ak8974->lock);
5727c94a8b2SLinus Walleij
57355ecaf17SLinus Walleij /*
57455ecaf17SLinus Walleij * We read all axes and discard all but one, for optimized
57555ecaf17SLinus Walleij * reading, use the triggered buffer.
57655ecaf17SLinus Walleij */
5777c94a8b2SLinus Walleij ret = ak8974_trigmeas(ak8974);
5787c94a8b2SLinus Walleij if (ret)
5797c94a8b2SLinus Walleij goto out_unlock;
5807c94a8b2SLinus Walleij ret = ak8974_getresult(ak8974, hw_values);
5817c94a8b2SLinus Walleij if (ret)
5827c94a8b2SLinus Walleij goto out_unlock;
5837c94a8b2SLinus Walleij /*
58455ecaf17SLinus Walleij * This explicit cast to (s16) is necessary as the measurement
58555ecaf17SLinus Walleij * is done in 2's complement with positive and negative values.
58655ecaf17SLinus Walleij * The follwing assignment to *val will then convert the signed
58755ecaf17SLinus Walleij * s16 value to a signed int value.
5887c94a8b2SLinus Walleij */
58955ecaf17SLinus Walleij *val = (s16)le16_to_cpu(hw_values[address]);
5907c94a8b2SLinus Walleij out_unlock:
5917c94a8b2SLinus Walleij mutex_unlock(&ak8974->lock);
5927c94a8b2SLinus Walleij pm_runtime_mark_last_busy(&ak8974->i2c->dev);
5937c94a8b2SLinus Walleij pm_runtime_put_autosuspend(&ak8974->i2c->dev);
5947c94a8b2SLinus Walleij
5957c94a8b2SLinus Walleij return ret;
5967c94a8b2SLinus Walleij }
5977c94a8b2SLinus Walleij
ak8974_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)59855ecaf17SLinus Walleij static int ak8974_read_raw(struct iio_dev *indio_dev,
59955ecaf17SLinus Walleij struct iio_chan_spec const *chan,
60055ecaf17SLinus Walleij int *val, int *val2,
60155ecaf17SLinus Walleij long mask)
60255ecaf17SLinus Walleij {
60355ecaf17SLinus Walleij struct ak8974 *ak8974 = iio_priv(indio_dev);
60455ecaf17SLinus Walleij int ret;
60555ecaf17SLinus Walleij
60655ecaf17SLinus Walleij switch (mask) {
60755ecaf17SLinus Walleij case IIO_CHAN_INFO_RAW:
60855ecaf17SLinus Walleij if (chan->address > 2) {
60955ecaf17SLinus Walleij dev_err(&ak8974->i2c->dev, "faulty channel address\n");
61055ecaf17SLinus Walleij return -EIO;
61155ecaf17SLinus Walleij }
61255ecaf17SLinus Walleij ret = ak8974_measure_channel(ak8974, chan->address, val);
61355ecaf17SLinus Walleij if (ret)
61455ecaf17SLinus Walleij return ret;
61555ecaf17SLinus Walleij return IIO_VAL_INT;
61616636527SLinus Walleij case IIO_CHAN_INFO_SCALE:
61716636527SLinus Walleij switch (ak8974->variant) {
61816636527SLinus Walleij case AK8974_WHOAMI_VALUE_AMI306:
61916636527SLinus Walleij case AK8974_WHOAMI_VALUE_AMI305:
62016636527SLinus Walleij /*
62116636527SLinus Walleij * The datasheet for AMI305 and AMI306, page 6
62216636527SLinus Walleij * specifies the range of the sensor to be
62316636527SLinus Walleij * +/- 12 Gauss.
62416636527SLinus Walleij */
62516636527SLinus Walleij *val = 12;
62616636527SLinus Walleij /*
62716636527SLinus Walleij * 12 bits are used, +/- 2^11
62816636527SLinus Walleij * [ -2048 .. 2047 ] (manual page 20)
62916636527SLinus Walleij * [ 0xf800 .. 0x07ff ]
63016636527SLinus Walleij */
63116636527SLinus Walleij *val2 = 11;
63216636527SLinus Walleij return IIO_VAL_FRACTIONAL_LOG2;
63316636527SLinus Walleij case AK8974_WHOAMI_VALUE_HSCDTD008A:
63416636527SLinus Walleij /*
63516636527SLinus Walleij * The datasheet for HSCDTF008A, page 3 specifies the
63616636527SLinus Walleij * range of the sensor as +/- 2.4 mT per axis, which
63716636527SLinus Walleij * corresponds to +/- 2400 uT = +/- 24 Gauss.
63816636527SLinus Walleij */
63916636527SLinus Walleij *val = 24;
64016636527SLinus Walleij /*
64116636527SLinus Walleij * 15 bits are used (set up in CTRL4), +/- 2^14
64216636527SLinus Walleij * [ -16384 .. 16383 ] (manual page 24)
64316636527SLinus Walleij * [ 0xc000 .. 0x3fff ]
64416636527SLinus Walleij */
64516636527SLinus Walleij *val2 = 14;
64616636527SLinus Walleij return IIO_VAL_FRACTIONAL_LOG2;
64716636527SLinus Walleij default:
64816636527SLinus Walleij /* GUESSING +/- 12 Gauss */
64916636527SLinus Walleij *val = 12;
65016636527SLinus Walleij /* GUESSING 12 bits ADC +/- 2^11 */
65116636527SLinus Walleij *val2 = 11;
65216636527SLinus Walleij return IIO_VAL_FRACTIONAL_LOG2;
65316636527SLinus Walleij }
65416636527SLinus Walleij break;
65516636527SLinus Walleij default:
65616636527SLinus Walleij /* Unknown request */
65716636527SLinus Walleij break;
65855ecaf17SLinus Walleij }
65955ecaf17SLinus Walleij
66055ecaf17SLinus Walleij return -EINVAL;
66155ecaf17SLinus Walleij }
66255ecaf17SLinus Walleij
ak8974_fill_buffer(struct iio_dev * indio_dev)6637c94a8b2SLinus Walleij static void ak8974_fill_buffer(struct iio_dev *indio_dev)
6647c94a8b2SLinus Walleij {
6657c94a8b2SLinus Walleij struct ak8974 *ak8974 = iio_priv(indio_dev);
6667c94a8b2SLinus Walleij int ret;
6677c94a8b2SLinus Walleij
6687c94a8b2SLinus Walleij pm_runtime_get_sync(&ak8974->i2c->dev);
6697c94a8b2SLinus Walleij mutex_lock(&ak8974->lock);
6707c94a8b2SLinus Walleij
6717c94a8b2SLinus Walleij ret = ak8974_trigmeas(ak8974);
6727c94a8b2SLinus Walleij if (ret) {
6737c94a8b2SLinus Walleij dev_err(&ak8974->i2c->dev, "error triggering measure\n");
6747c94a8b2SLinus Walleij goto out_unlock;
6757c94a8b2SLinus Walleij }
676838e00b1SJonathan Cameron ret = ak8974_getresult(ak8974, ak8974->scan.channels);
6777c94a8b2SLinus Walleij if (ret) {
6787c94a8b2SLinus Walleij dev_err(&ak8974->i2c->dev, "error getting measures\n");
6797c94a8b2SLinus Walleij goto out_unlock;
6807c94a8b2SLinus Walleij }
6817c94a8b2SLinus Walleij
682838e00b1SJonathan Cameron iio_push_to_buffers_with_timestamp(indio_dev, &ak8974->scan,
6837c94a8b2SLinus Walleij iio_get_time_ns(indio_dev));
6847c94a8b2SLinus Walleij
6857c94a8b2SLinus Walleij out_unlock:
6867c94a8b2SLinus Walleij mutex_unlock(&ak8974->lock);
6877c94a8b2SLinus Walleij pm_runtime_mark_last_busy(&ak8974->i2c->dev);
6887c94a8b2SLinus Walleij pm_runtime_put_autosuspend(&ak8974->i2c->dev);
6897c94a8b2SLinus Walleij }
6907c94a8b2SLinus Walleij
ak8974_handle_trigger(int irq,void * p)6917c94a8b2SLinus Walleij static irqreturn_t ak8974_handle_trigger(int irq, void *p)
6927c94a8b2SLinus Walleij {
6937c94a8b2SLinus Walleij const struct iio_poll_func *pf = p;
6947c94a8b2SLinus Walleij struct iio_dev *indio_dev = pf->indio_dev;
6957c94a8b2SLinus Walleij
6967c94a8b2SLinus Walleij ak8974_fill_buffer(indio_dev);
6977c94a8b2SLinus Walleij iio_trigger_notify_done(indio_dev->trig);
6987c94a8b2SLinus Walleij
6997c94a8b2SLinus Walleij return IRQ_HANDLED;
7007c94a8b2SLinus Walleij }
7017c94a8b2SLinus Walleij
7027c94a8b2SLinus Walleij static const struct iio_mount_matrix *
ak8974_get_mount_matrix(const struct iio_dev * indio_dev,const struct iio_chan_spec * chan)7037c94a8b2SLinus Walleij ak8974_get_mount_matrix(const struct iio_dev *indio_dev,
7047c94a8b2SLinus Walleij const struct iio_chan_spec *chan)
7057c94a8b2SLinus Walleij {
7067c94a8b2SLinus Walleij struct ak8974 *ak8974 = iio_priv(indio_dev);
7077c94a8b2SLinus Walleij
7087c94a8b2SLinus Walleij return &ak8974->orientation;
7097c94a8b2SLinus Walleij }
7107c94a8b2SLinus Walleij
7117c94a8b2SLinus Walleij static const struct iio_chan_spec_ext_info ak8974_ext_info[] = {
7127c94a8b2SLinus Walleij IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, ak8974_get_mount_matrix),
7137c94a8b2SLinus Walleij { },
7147c94a8b2SLinus Walleij };
7157c94a8b2SLinus Walleij
716b67959ebSLinus Walleij #define AK8974_AXIS_CHANNEL(axis, index, bits) \
7177c94a8b2SLinus Walleij { \
7187c94a8b2SLinus Walleij .type = IIO_MAGN, \
7197c94a8b2SLinus Walleij .modified = 1, \
7207c94a8b2SLinus Walleij .channel2 = IIO_MOD_##axis, \
72116636527SLinus Walleij .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
72216636527SLinus Walleij BIT(IIO_CHAN_INFO_SCALE), \
7237c94a8b2SLinus Walleij .ext_info = ak8974_ext_info, \
7247c94a8b2SLinus Walleij .address = index, \
7257c94a8b2SLinus Walleij .scan_index = index, \
7267c94a8b2SLinus Walleij .scan_type = { \
7277c94a8b2SLinus Walleij .sign = 's', \
728b67959ebSLinus Walleij .realbits = bits, \
7297c94a8b2SLinus Walleij .storagebits = 16, \
7307c94a8b2SLinus Walleij .endianness = IIO_LE \
7317c94a8b2SLinus Walleij }, \
7327c94a8b2SLinus Walleij }
7337c94a8b2SLinus Walleij
734b67959ebSLinus Walleij /*
735b67959ebSLinus Walleij * We have no datasheet for the AK8974 but we guess that its
736b67959ebSLinus Walleij * ADC is 12 bits. The AMI305 and AMI306 certainly has 12bit
737b67959ebSLinus Walleij * ADC.
738b67959ebSLinus Walleij */
739b67959ebSLinus Walleij static const struct iio_chan_spec ak8974_12_bits_channels[] = {
740b67959ebSLinus Walleij AK8974_AXIS_CHANNEL(X, 0, 12),
741b67959ebSLinus Walleij AK8974_AXIS_CHANNEL(Y, 1, 12),
742b67959ebSLinus Walleij AK8974_AXIS_CHANNEL(Z, 2, 12),
743b67959ebSLinus Walleij IIO_CHAN_SOFT_TIMESTAMP(3),
744b67959ebSLinus Walleij };
745b67959ebSLinus Walleij
746b67959ebSLinus Walleij /*
747b67959ebSLinus Walleij * The HSCDTD008A has 15 bits resolution the way we set it up
748b67959ebSLinus Walleij * in CTRL4.
749b67959ebSLinus Walleij */
750b67959ebSLinus Walleij static const struct iio_chan_spec ak8974_15_bits_channels[] = {
751b67959ebSLinus Walleij AK8974_AXIS_CHANNEL(X, 0, 15),
752b67959ebSLinus Walleij AK8974_AXIS_CHANNEL(Y, 1, 15),
753b67959ebSLinus Walleij AK8974_AXIS_CHANNEL(Z, 2, 15),
7547c94a8b2SLinus Walleij IIO_CHAN_SOFT_TIMESTAMP(3),
7557c94a8b2SLinus Walleij };
7567c94a8b2SLinus Walleij
7577c94a8b2SLinus Walleij static const unsigned long ak8974_scan_masks[] = { 0x7, 0 };
7587c94a8b2SLinus Walleij
7597c94a8b2SLinus Walleij static const struct iio_info ak8974_info = {
7607c94a8b2SLinus Walleij .read_raw = &ak8974_read_raw,
7617c94a8b2SLinus Walleij };
7627c94a8b2SLinus Walleij
ak8974_writeable_reg(struct device * dev,unsigned int reg)7637c94a8b2SLinus Walleij static bool ak8974_writeable_reg(struct device *dev, unsigned int reg)
7647c94a8b2SLinus Walleij {
7657c94a8b2SLinus Walleij struct i2c_client *i2c = to_i2c_client(dev);
7667c94a8b2SLinus Walleij struct iio_dev *indio_dev = i2c_get_clientdata(i2c);
7677c94a8b2SLinus Walleij struct ak8974 *ak8974 = iio_priv(indio_dev);
7687c94a8b2SLinus Walleij
7697c94a8b2SLinus Walleij switch (reg) {
7707c94a8b2SLinus Walleij case AK8974_CTRL1:
7717c94a8b2SLinus Walleij case AK8974_CTRL2:
7727c94a8b2SLinus Walleij case AK8974_CTRL3:
7737c94a8b2SLinus Walleij case AK8974_INT_CTRL:
7747c94a8b2SLinus Walleij case AK8974_INT_THRES:
7757c94a8b2SLinus Walleij case AK8974_INT_THRES + 1:
776525530afSNick Reitemeyer return true;
7777c94a8b2SLinus Walleij case AK8974_PRESET:
7787c94a8b2SLinus Walleij case AK8974_PRESET + 1:
779525530afSNick Reitemeyer return ak8974->variant != AK8974_WHOAMI_VALUE_HSCDTD008A;
7807c94a8b2SLinus Walleij case AK8974_OFFSET_X:
7817c94a8b2SLinus Walleij case AK8974_OFFSET_X + 1:
7827c94a8b2SLinus Walleij case AK8974_OFFSET_Y:
7837c94a8b2SLinus Walleij case AK8974_OFFSET_Y + 1:
7847c94a8b2SLinus Walleij case AK8974_OFFSET_Z:
7857c94a8b2SLinus Walleij case AK8974_OFFSET_Z + 1:
786525530afSNick Reitemeyer return ak8974->variant == AK8974_WHOAMI_VALUE_AK8974 ||
787525530afSNick Reitemeyer ak8974->variant == AK8974_WHOAMI_VALUE_HSCDTD008A;
7887c94a8b2SLinus Walleij case AMI305_OFFSET_X:
7897c94a8b2SLinus Walleij case AMI305_OFFSET_X + 1:
7907c94a8b2SLinus Walleij case AMI305_OFFSET_Y:
7917c94a8b2SLinus Walleij case AMI305_OFFSET_Y + 1:
7927c94a8b2SLinus Walleij case AMI305_OFFSET_Z:
7937c94a8b2SLinus Walleij case AMI305_OFFSET_Z + 1:
79421be26fcSMichał Mirosław return ak8974->variant == AK8974_WHOAMI_VALUE_AMI305 ||
79521be26fcSMichał Mirosław ak8974->variant == AK8974_WHOAMI_VALUE_AMI306;
79621be26fcSMichał Mirosław case AMI306_CTRL4:
79721be26fcSMichał Mirosław case AMI306_CTRL4 + 1:
79821be26fcSMichał Mirosław return ak8974->variant == AK8974_WHOAMI_VALUE_AMI306;
7997c94a8b2SLinus Walleij default:
8007c94a8b2SLinus Walleij return false;
8017c94a8b2SLinus Walleij }
8027c94a8b2SLinus Walleij }
8037c94a8b2SLinus Walleij
ak8974_precious_reg(struct device * dev,unsigned int reg)8049991f99eSMichał Mirosław static bool ak8974_precious_reg(struct device *dev, unsigned int reg)
8059991f99eSMichał Mirosław {
8069991f99eSMichał Mirosław return reg == AK8974_INT_CLEAR;
8079991f99eSMichał Mirosław }
8089991f99eSMichał Mirosław
8097c94a8b2SLinus Walleij static const struct regmap_config ak8974_regmap_config = {
8107c94a8b2SLinus Walleij .reg_bits = 8,
8117c94a8b2SLinus Walleij .val_bits = 8,
8127c94a8b2SLinus Walleij .max_register = 0xff,
8137c94a8b2SLinus Walleij .writeable_reg = ak8974_writeable_reg,
8149991f99eSMichał Mirosław .precious_reg = ak8974_precious_reg,
8157c94a8b2SLinus Walleij };
8167c94a8b2SLinus Walleij
ak8974_probe(struct i2c_client * i2c)817149a5043SUwe Kleine-König static int ak8974_probe(struct i2c_client *i2c)
8187c94a8b2SLinus Walleij {
8197c94a8b2SLinus Walleij struct iio_dev *indio_dev;
8207c94a8b2SLinus Walleij struct ak8974 *ak8974;
8217c94a8b2SLinus Walleij unsigned long irq_trig;
8227c94a8b2SLinus Walleij int irq = i2c->irq;
8237c94a8b2SLinus Walleij int ret;
8247c94a8b2SLinus Walleij
8257c94a8b2SLinus Walleij /* Register with IIO */
8267c94a8b2SLinus Walleij indio_dev = devm_iio_device_alloc(&i2c->dev, sizeof(*ak8974));
8277c94a8b2SLinus Walleij if (indio_dev == NULL)
8287c94a8b2SLinus Walleij return -ENOMEM;
8297c94a8b2SLinus Walleij
8307c94a8b2SLinus Walleij ak8974 = iio_priv(indio_dev);
8317c94a8b2SLinus Walleij i2c_set_clientdata(i2c, indio_dev);
8327c94a8b2SLinus Walleij ak8974->i2c = i2c;
8337c94a8b2SLinus Walleij mutex_init(&ak8974->lock);
8347c94a8b2SLinus Walleij
835b892770aSAndy Shevchenko ret = iio_read_mount_matrix(&i2c->dev, &ak8974->orientation);
8367c94a8b2SLinus Walleij if (ret)
8377c94a8b2SLinus Walleij return ret;
8387c94a8b2SLinus Walleij
8397c94a8b2SLinus Walleij ak8974->regs[0].supply = ak8974_reg_avdd;
8407c94a8b2SLinus Walleij ak8974->regs[1].supply = ak8974_reg_dvdd;
8417c94a8b2SLinus Walleij
8427c94a8b2SLinus Walleij ret = devm_regulator_bulk_get(&i2c->dev,
8437c94a8b2SLinus Walleij ARRAY_SIZE(ak8974->regs),
8447c94a8b2SLinus Walleij ak8974->regs);
8455d2180ceSKrzysztof Kozlowski if (ret < 0)
8465d2180ceSKrzysztof Kozlowski return dev_err_probe(&i2c->dev, ret, "cannot get regulators\n");
8477c94a8b2SLinus Walleij
8487c94a8b2SLinus Walleij ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
8497c94a8b2SLinus Walleij if (ret < 0) {
8507c94a8b2SLinus Walleij dev_err(&i2c->dev, "cannot enable regulators\n");
8517c94a8b2SLinus Walleij return ret;
8527c94a8b2SLinus Walleij }
8537c94a8b2SLinus Walleij
8547c94a8b2SLinus Walleij /* Take runtime PM online */
8557c94a8b2SLinus Walleij pm_runtime_get_noresume(&i2c->dev);
8567c94a8b2SLinus Walleij pm_runtime_set_active(&i2c->dev);
8577c94a8b2SLinus Walleij pm_runtime_enable(&i2c->dev);
8587c94a8b2SLinus Walleij
8597c94a8b2SLinus Walleij ak8974->map = devm_regmap_init_i2c(i2c, &ak8974_regmap_config);
8607c94a8b2SLinus Walleij if (IS_ERR(ak8974->map)) {
8617c94a8b2SLinus Walleij dev_err(&i2c->dev, "failed to allocate register map\n");
8620187294dSDinghao Liu pm_runtime_put_noidle(&i2c->dev);
8630187294dSDinghao Liu pm_runtime_disable(&i2c->dev);
8647c94a8b2SLinus Walleij return PTR_ERR(ak8974->map);
8657c94a8b2SLinus Walleij }
8667c94a8b2SLinus Walleij
8677c94a8b2SLinus Walleij ret = ak8974_set_power(ak8974, AK8974_PWR_ON);
8687c94a8b2SLinus Walleij if (ret) {
8697c94a8b2SLinus Walleij dev_err(&i2c->dev, "could not power on\n");
8700187294dSDinghao Liu goto disable_pm;
8717c94a8b2SLinus Walleij }
8727c94a8b2SLinus Walleij
8737c94a8b2SLinus Walleij ret = ak8974_detect(ak8974);
8747c94a8b2SLinus Walleij if (ret) {
87521be26fcSMichał Mirosław dev_err(&i2c->dev, "neither AK8974 nor AMI30x found\n");
8760187294dSDinghao Liu goto disable_pm;
8777c94a8b2SLinus Walleij }
8787c94a8b2SLinus Walleij
8797c94a8b2SLinus Walleij ret = ak8974_selftest(ak8974);
8807c94a8b2SLinus Walleij if (ret)
8817c94a8b2SLinus Walleij dev_err(&i2c->dev, "selftest failed (continuing anyway)\n");
8827c94a8b2SLinus Walleij
8837c94a8b2SLinus Walleij ret = ak8974_reset(ak8974);
8847c94a8b2SLinus Walleij if (ret) {
8857c94a8b2SLinus Walleij dev_err(&i2c->dev, "AK8974 reset failed\n");
8860187294dSDinghao Liu goto disable_pm;
8877c94a8b2SLinus Walleij }
8887c94a8b2SLinus Walleij
889b67959ebSLinus Walleij switch (ak8974->variant) {
890b67959ebSLinus Walleij case AK8974_WHOAMI_VALUE_AMI306:
891b67959ebSLinus Walleij case AK8974_WHOAMI_VALUE_AMI305:
892b67959ebSLinus Walleij indio_dev->channels = ak8974_12_bits_channels;
893b67959ebSLinus Walleij indio_dev->num_channels = ARRAY_SIZE(ak8974_12_bits_channels);
894b67959ebSLinus Walleij break;
895b67959ebSLinus Walleij case AK8974_WHOAMI_VALUE_HSCDTD008A:
896b67959ebSLinus Walleij indio_dev->channels = ak8974_15_bits_channels;
897b67959ebSLinus Walleij indio_dev->num_channels = ARRAY_SIZE(ak8974_15_bits_channels);
898b67959ebSLinus Walleij break;
899b67959ebSLinus Walleij default:
900b67959ebSLinus Walleij indio_dev->channels = ak8974_12_bits_channels;
901b67959ebSLinus Walleij indio_dev->num_channels = ARRAY_SIZE(ak8974_12_bits_channels);
902b67959ebSLinus Walleij break;
903b67959ebSLinus Walleij }
9047c94a8b2SLinus Walleij indio_dev->info = &ak8974_info;
9057c94a8b2SLinus Walleij indio_dev->available_scan_masks = ak8974_scan_masks;
9067c94a8b2SLinus Walleij indio_dev->modes = INDIO_DIRECT_MODE;
9077c94a8b2SLinus Walleij indio_dev->name = ak8974->name;
9087c94a8b2SLinus Walleij
9097c94a8b2SLinus Walleij ret = iio_triggered_buffer_setup(indio_dev, NULL,
9107c94a8b2SLinus Walleij ak8974_handle_trigger,
9117c94a8b2SLinus Walleij NULL);
9127c94a8b2SLinus Walleij if (ret) {
9137c94a8b2SLinus Walleij dev_err(&i2c->dev, "triggered buffer setup failed\n");
9147c94a8b2SLinus Walleij goto disable_pm;
9157c94a8b2SLinus Walleij }
9167c94a8b2SLinus Walleij
9177c94a8b2SLinus Walleij /* If we have a valid DRDY IRQ, make use of it */
9187c94a8b2SLinus Walleij if (irq > 0) {
9197c94a8b2SLinus Walleij irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
9207c94a8b2SLinus Walleij if (irq_trig == IRQF_TRIGGER_RISING) {
9217c94a8b2SLinus Walleij dev_info(&i2c->dev, "enable rising edge DRDY IRQ\n");
9227c94a8b2SLinus Walleij } else if (irq_trig == IRQF_TRIGGER_FALLING) {
9237c94a8b2SLinus Walleij ak8974->drdy_active_low = true;
9247c94a8b2SLinus Walleij dev_info(&i2c->dev, "enable falling edge DRDY IRQ\n");
9257c94a8b2SLinus Walleij } else {
9267c94a8b2SLinus Walleij irq_trig = IRQF_TRIGGER_RISING;
9277c94a8b2SLinus Walleij }
9287c94a8b2SLinus Walleij irq_trig |= IRQF_ONESHOT;
9297c94a8b2SLinus Walleij irq_trig |= IRQF_SHARED;
9307c94a8b2SLinus Walleij
9317c94a8b2SLinus Walleij ret = devm_request_threaded_irq(&i2c->dev,
9327c94a8b2SLinus Walleij irq,
9337c94a8b2SLinus Walleij ak8974_drdy_irq,
9347c94a8b2SLinus Walleij ak8974_drdy_irq_thread,
9357c94a8b2SLinus Walleij irq_trig,
9367c94a8b2SLinus Walleij ak8974->name,
9377c94a8b2SLinus Walleij ak8974);
9387c94a8b2SLinus Walleij if (ret) {
9397c94a8b2SLinus Walleij dev_err(&i2c->dev, "unable to request DRDY IRQ "
9407c94a8b2SLinus Walleij "- proceeding without IRQ\n");
9417c94a8b2SLinus Walleij goto no_irq;
9427c94a8b2SLinus Walleij }
9437c94a8b2SLinus Walleij ak8974->drdy_irq = true;
9447c94a8b2SLinus Walleij }
9457c94a8b2SLinus Walleij
9467c94a8b2SLinus Walleij no_irq:
9477c94a8b2SLinus Walleij ret = iio_device_register(indio_dev);
9487c94a8b2SLinus Walleij if (ret) {
9497c94a8b2SLinus Walleij dev_err(&i2c->dev, "device register failed\n");
9507c94a8b2SLinus Walleij goto cleanup_buffer;
9517c94a8b2SLinus Walleij }
9527c94a8b2SLinus Walleij
9530187294dSDinghao Liu pm_runtime_set_autosuspend_delay(&i2c->dev,
9540187294dSDinghao Liu AK8974_AUTOSUSPEND_DELAY);
9550187294dSDinghao Liu pm_runtime_use_autosuspend(&i2c->dev);
9560187294dSDinghao Liu pm_runtime_put(&i2c->dev);
9570187294dSDinghao Liu
9587c94a8b2SLinus Walleij return 0;
9597c94a8b2SLinus Walleij
9607c94a8b2SLinus Walleij cleanup_buffer:
9617c94a8b2SLinus Walleij iio_triggered_buffer_cleanup(indio_dev);
9627c94a8b2SLinus Walleij disable_pm:
9637c94a8b2SLinus Walleij pm_runtime_put_noidle(&i2c->dev);
9647c94a8b2SLinus Walleij pm_runtime_disable(&i2c->dev);
9657c94a8b2SLinus Walleij ak8974_set_power(ak8974, AK8974_PWR_OFF);
9667c94a8b2SLinus Walleij regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
9677c94a8b2SLinus Walleij
9687c94a8b2SLinus Walleij return ret;
9697c94a8b2SLinus Walleij }
9707c94a8b2SLinus Walleij
ak8974_remove(struct i2c_client * i2c)971ed5c2f5fSUwe Kleine-König static void ak8974_remove(struct i2c_client *i2c)
9727c94a8b2SLinus Walleij {
9737c94a8b2SLinus Walleij struct iio_dev *indio_dev = i2c_get_clientdata(i2c);
9747c94a8b2SLinus Walleij struct ak8974 *ak8974 = iio_priv(indio_dev);
9757c94a8b2SLinus Walleij
9767c94a8b2SLinus Walleij iio_device_unregister(indio_dev);
9777c94a8b2SLinus Walleij iio_triggered_buffer_cleanup(indio_dev);
9787c94a8b2SLinus Walleij pm_runtime_get_sync(&i2c->dev);
9797c94a8b2SLinus Walleij pm_runtime_put_noidle(&i2c->dev);
9807c94a8b2SLinus Walleij pm_runtime_disable(&i2c->dev);
9817c94a8b2SLinus Walleij ak8974_set_power(ak8974, AK8974_PWR_OFF);
9827c94a8b2SLinus Walleij regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
9837c94a8b2SLinus Walleij }
9847c94a8b2SLinus Walleij
ak8974_runtime_suspend(struct device * dev)98574f4595aSJonathan Cameron static int ak8974_runtime_suspend(struct device *dev)
9867c94a8b2SLinus Walleij {
9877c94a8b2SLinus Walleij struct ak8974 *ak8974 =
9887c94a8b2SLinus Walleij iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
9897c94a8b2SLinus Walleij
9907c94a8b2SLinus Walleij ak8974_set_power(ak8974, AK8974_PWR_OFF);
9917c94a8b2SLinus Walleij regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
9927c94a8b2SLinus Walleij
9937c94a8b2SLinus Walleij return 0;
9947c94a8b2SLinus Walleij }
9957c94a8b2SLinus Walleij
ak8974_runtime_resume(struct device * dev)99674f4595aSJonathan Cameron static int ak8974_runtime_resume(struct device *dev)
9977c94a8b2SLinus Walleij {
9987c94a8b2SLinus Walleij struct ak8974 *ak8974 =
9997c94a8b2SLinus Walleij iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
10007c94a8b2SLinus Walleij int ret;
10017c94a8b2SLinus Walleij
10027c94a8b2SLinus Walleij ret = regulator_bulk_enable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
10037c94a8b2SLinus Walleij if (ret)
10047c94a8b2SLinus Walleij return ret;
10057c94a8b2SLinus Walleij msleep(AK8974_POWERON_DELAY);
10067c94a8b2SLinus Walleij ret = ak8974_set_power(ak8974, AK8974_PWR_ON);
10077c94a8b2SLinus Walleij if (ret)
10087c94a8b2SLinus Walleij goto out_regulator_disable;
10097c94a8b2SLinus Walleij
10107c94a8b2SLinus Walleij ret = ak8974_configure(ak8974);
10117c94a8b2SLinus Walleij if (ret)
10127c94a8b2SLinus Walleij goto out_disable_power;
10137c94a8b2SLinus Walleij
10147c94a8b2SLinus Walleij return 0;
10157c94a8b2SLinus Walleij
10167c94a8b2SLinus Walleij out_disable_power:
10177c94a8b2SLinus Walleij ak8974_set_power(ak8974, AK8974_PWR_OFF);
10187c94a8b2SLinus Walleij out_regulator_disable:
10197c94a8b2SLinus Walleij regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
10207c94a8b2SLinus Walleij
10217c94a8b2SLinus Walleij return ret;
10227c94a8b2SLinus Walleij }
10237c94a8b2SLinus Walleij
102474f4595aSJonathan Cameron static DEFINE_RUNTIME_DEV_PM_OPS(ak8974_dev_pm_ops, ak8974_runtime_suspend,
102574f4595aSJonathan Cameron ak8974_runtime_resume, NULL);
10267c94a8b2SLinus Walleij
10277c94a8b2SLinus Walleij static const struct i2c_device_id ak8974_id[] = {
10287c94a8b2SLinus Walleij {"ami305", 0 },
102921be26fcSMichał Mirosław {"ami306", 0 },
10307c94a8b2SLinus Walleij {"ak8974", 0 },
1031525530afSNick Reitemeyer {"hscdtd008a", 0 },
10327c94a8b2SLinus Walleij {}
10337c94a8b2SLinus Walleij };
10347c94a8b2SLinus Walleij MODULE_DEVICE_TABLE(i2c, ak8974_id);
10357c94a8b2SLinus Walleij
10367c94a8b2SLinus Walleij static const struct of_device_id ak8974_of_match[] = {
10377c94a8b2SLinus Walleij { .compatible = "asahi-kasei,ak8974", },
1038525530afSNick Reitemeyer { .compatible = "alps,hscdtd008a", },
10397c94a8b2SLinus Walleij {}
10407c94a8b2SLinus Walleij };
10417c94a8b2SLinus Walleij MODULE_DEVICE_TABLE(of, ak8974_of_match);
10427c94a8b2SLinus Walleij
10437c94a8b2SLinus Walleij static struct i2c_driver ak8974_driver = {
10447c94a8b2SLinus Walleij .driver = {
10457c94a8b2SLinus Walleij .name = "ak8974",
104674f4595aSJonathan Cameron .pm = pm_ptr(&ak8974_dev_pm_ops),
10472b4f0172SJonathan Cameron .of_match_table = ak8974_of_match,
10487c94a8b2SLinus Walleij },
1049*7cf15f42SUwe Kleine-König .probe = ak8974_probe,
10503ff861f5SDmitry Torokhov .remove = ak8974_remove,
10517c94a8b2SLinus Walleij .id_table = ak8974_id,
10527c94a8b2SLinus Walleij };
10537c94a8b2SLinus Walleij module_i2c_driver(ak8974_driver);
10547c94a8b2SLinus Walleij
105521be26fcSMichał Mirosław MODULE_DESCRIPTION("AK8974 and AMI30x 3-axis magnetometer driver");
10567c94a8b2SLinus Walleij MODULE_AUTHOR("Samu Onkalo");
10577c94a8b2SLinus Walleij MODULE_AUTHOR("Linus Walleij");
10587c94a8b2SLinus Walleij MODULE_LICENSE("GPL v2");
1059