staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
/*
|
|
|
|
* A sensor driver for the magnetometer AK8975.
|
|
|
|
*
|
|
|
|
* Magnetic compass sensor driver for monitoring magnetic flux information.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2010, NVIDIA Corporation.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/i2c.h>
|
2013-05-07 18:41:00 +08:00
|
|
|
#include <linux/interrupt.h>
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
#include <linux/err.h>
|
|
|
|
#include <linux/mutex.h>
|
|
|
|
#include <linux/delay.h>
|
2013-05-07 18:41:00 +08:00
|
|
|
#include <linux/bitops.h>
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
#include <linux/gpio.h>
|
2013-05-07 18:41:00 +08:00
|
|
|
#include <linux/of_gpio.h>
|
2014-03-20 00:56:00 +08:00
|
|
|
#include <linux/acpi.h>
|
2016-03-03 18:44:05 +08:00
|
|
|
#include <linux/regulator/consumer.h>
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
2012-04-25 22:54:58 +08:00
|
|
|
#include <linux/iio/iio.h>
|
|
|
|
#include <linux/iio/sysfs.h>
|
2016-04-08 23:09:08 +08:00
|
|
|
#include <linux/iio/buffer.h>
|
|
|
|
#include <linux/iio/trigger.h>
|
|
|
|
#include <linux/iio/trigger_consumer.h>
|
|
|
|
#include <linux/iio/triggered_buffer.h>
|
2016-04-21 01:23:44 +08:00
|
|
|
|
|
|
|
#include <linux/iio/magnetometer/ak8975.h>
|
2016-04-08 23:09:08 +08:00
|
|
|
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
/*
|
|
|
|
* Register definitions, as well as various shifts and masks to get at the
|
|
|
|
* individual fields of the registers.
|
|
|
|
*/
|
|
|
|
#define AK8975_REG_WIA 0x00
|
|
|
|
#define AK8975_DEVICE_ID 0x48
|
|
|
|
|
|
|
|
#define AK8975_REG_INFO 0x01
|
|
|
|
|
|
|
|
#define AK8975_REG_ST1 0x02
|
|
|
|
#define AK8975_REG_ST1_DRDY_SHIFT 0
|
|
|
|
#define AK8975_REG_ST1_DRDY_MASK (1 << AK8975_REG_ST1_DRDY_SHIFT)
|
|
|
|
|
|
|
|
#define AK8975_REG_HXL 0x03
|
|
|
|
#define AK8975_REG_HXH 0x04
|
|
|
|
#define AK8975_REG_HYL 0x05
|
|
|
|
#define AK8975_REG_HYH 0x06
|
|
|
|
#define AK8975_REG_HZL 0x07
|
|
|
|
#define AK8975_REG_HZH 0x08
|
|
|
|
#define AK8975_REG_ST2 0x09
|
|
|
|
#define AK8975_REG_ST2_DERR_SHIFT 2
|
|
|
|
#define AK8975_REG_ST2_DERR_MASK (1 << AK8975_REG_ST2_DERR_SHIFT)
|
|
|
|
|
|
|
|
#define AK8975_REG_ST2_HOFL_SHIFT 3
|
|
|
|
#define AK8975_REG_ST2_HOFL_MASK (1 << AK8975_REG_ST2_HOFL_SHIFT)
|
|
|
|
|
|
|
|
#define AK8975_REG_CNTL 0x0A
|
|
|
|
#define AK8975_REG_CNTL_MODE_SHIFT 0
|
|
|
|
#define AK8975_REG_CNTL_MODE_MASK (0xF << AK8975_REG_CNTL_MODE_SHIFT)
|
2014-11-22 02:45:47 +08:00
|
|
|
#define AK8975_REG_CNTL_MODE_POWER_DOWN 0x00
|
|
|
|
#define AK8975_REG_CNTL_MODE_ONCE 0x01
|
|
|
|
#define AK8975_REG_CNTL_MODE_SELF_TEST 0x08
|
|
|
|
#define AK8975_REG_CNTL_MODE_FUSE_ROM 0x0F
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
|
|
|
#define AK8975_REG_RSVC 0x0B
|
|
|
|
#define AK8975_REG_ASTC 0x0C
|
|
|
|
#define AK8975_REG_TS1 0x0D
|
|
|
|
#define AK8975_REG_TS2 0x0E
|
|
|
|
#define AK8975_REG_I2CDIS 0x0F
|
|
|
|
#define AK8975_REG_ASAX 0x10
|
|
|
|
#define AK8975_REG_ASAY 0x11
|
|
|
|
#define AK8975_REG_ASAZ 0x12
|
|
|
|
|
|
|
|
#define AK8975_MAX_REGS AK8975_REG_ASAZ
|
|
|
|
|
2014-11-22 02:45:49 +08:00
|
|
|
/*
|
|
|
|
* AK09912 Register definitions
|
|
|
|
*/
|
|
|
|
#define AK09912_REG_WIA1 0x00
|
|
|
|
#define AK09912_REG_WIA2 0x01
|
|
|
|
#define AK09912_DEVICE_ID 0x04
|
|
|
|
#define AK09911_DEVICE_ID 0x05
|
|
|
|
|
|
|
|
#define AK09911_REG_INFO1 0x02
|
|
|
|
#define AK09911_REG_INFO2 0x03
|
|
|
|
|
|
|
|
#define AK09912_REG_ST1 0x10
|
|
|
|
|
|
|
|
#define AK09912_REG_ST1_DRDY_SHIFT 0
|
|
|
|
#define AK09912_REG_ST1_DRDY_MASK (1 << AK09912_REG_ST1_DRDY_SHIFT)
|
|
|
|
|
|
|
|
#define AK09912_REG_HXL 0x11
|
|
|
|
#define AK09912_REG_HXH 0x12
|
|
|
|
#define AK09912_REG_HYL 0x13
|
|
|
|
#define AK09912_REG_HYH 0x14
|
|
|
|
#define AK09912_REG_HZL 0x15
|
|
|
|
#define AK09912_REG_HZH 0x16
|
|
|
|
#define AK09912_REG_TMPS 0x17
|
|
|
|
|
|
|
|
#define AK09912_REG_ST2 0x18
|
|
|
|
#define AK09912_REG_ST2_HOFL_SHIFT 3
|
|
|
|
#define AK09912_REG_ST2_HOFL_MASK (1 << AK09912_REG_ST2_HOFL_SHIFT)
|
|
|
|
|
|
|
|
#define AK09912_REG_CNTL1 0x30
|
|
|
|
|
|
|
|
#define AK09912_REG_CNTL2 0x31
|
|
|
|
#define AK09912_REG_CNTL_MODE_POWER_DOWN 0x00
|
|
|
|
#define AK09912_REG_CNTL_MODE_ONCE 0x01
|
|
|
|
#define AK09912_REG_CNTL_MODE_SELF_TEST 0x10
|
|
|
|
#define AK09912_REG_CNTL_MODE_FUSE_ROM 0x1F
|
|
|
|
#define AK09912_REG_CNTL2_MODE_SHIFT 0
|
|
|
|
#define AK09912_REG_CNTL2_MODE_MASK (0x1F << AK09912_REG_CNTL2_MODE_SHIFT)
|
|
|
|
|
|
|
|
#define AK09912_REG_CNTL3 0x32
|
|
|
|
|
|
|
|
#define AK09912_REG_TS1 0x33
|
|
|
|
#define AK09912_REG_TS2 0x34
|
|
|
|
#define AK09912_REG_TS3 0x35
|
|
|
|
#define AK09912_REG_I2CDIS 0x36
|
|
|
|
#define AK09912_REG_TS4 0x37
|
|
|
|
|
|
|
|
#define AK09912_REG_ASAX 0x60
|
|
|
|
#define AK09912_REG_ASAY 0x61
|
|
|
|
#define AK09912_REG_ASAZ 0x62
|
|
|
|
|
|
|
|
#define AK09912_MAX_REGS AK09912_REG_ASAZ
|
|
|
|
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
/*
|
|
|
|
* Miscellaneous values.
|
|
|
|
*/
|
|
|
|
#define AK8975_MAX_CONVERSION_TIMEOUT 500
|
|
|
|
#define AK8975_CONVERSION_DONE_POLL_TIME 10
|
2013-05-07 18:41:00 +08:00
|
|
|
#define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000)
|
2014-11-22 02:45:48 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Precalculate scale factor (in Gauss units) for each axis and
|
|
|
|
* store in the device data.
|
|
|
|
*
|
|
|
|
* This scale factor is axis-dependent, and is derived from 3 calibration
|
|
|
|
* factors ASA(x), ASA(y), and ASA(z).
|
|
|
|
*
|
|
|
|
* These ASA values are read from the sensor device at start of day, and
|
|
|
|
* cached in the device context struct.
|
|
|
|
*
|
|
|
|
* Adjusting the flux value with the sensitivity adjustment value should be
|
|
|
|
* done via the following formula:
|
|
|
|
*
|
|
|
|
* Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 )
|
|
|
|
* where H is the raw value, ASA is the sensitivity adjustment, and Hadj
|
|
|
|
* is the resultant adjusted value.
|
|
|
|
*
|
|
|
|
* We reduce the formula to:
|
|
|
|
*
|
|
|
|
* Hadj = H * (ASA + 128) / 256
|
|
|
|
*
|
|
|
|
* H is in the range of -4096 to 4095. The magnetometer has a range of
|
|
|
|
* +-1229uT. To go from the raw value to uT is:
|
|
|
|
*
|
|
|
|
* HuT = H * 1229/4096, or roughly, 3/10.
|
|
|
|
*
|
|
|
|
* Since 1uT = 0.01 gauss, our final scale factor becomes:
|
|
|
|
*
|
|
|
|
* Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100
|
|
|
|
* Hadj = H * ((ASA + 128) * 0.003) / 256
|
|
|
|
*
|
|
|
|
* Since ASA doesn't change, we cache the resultant scale factor into the
|
|
|
|
* device context in ak8975_setup().
|
|
|
|
*
|
|
|
|
* Given we use IIO_VAL_INT_PLUS_MICRO bit when displaying the scale, we
|
|
|
|
* multiply the stored scale value by 1e6.
|
|
|
|
*/
|
|
|
|
static long ak8975_raw_to_gauss(u16 data)
|
|
|
|
{
|
|
|
|
return (((long)data + 128) * 3000) / 256;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2014-11-22 02:45:49 +08:00
|
|
|
* For AK8963 and AK09911, same calculation, but the device is less sensitive:
|
2014-11-22 02:45:48 +08:00
|
|
|
*
|
|
|
|
* H is in the range of +-8190. The magnetometer has a range of
|
|
|
|
* +-4912uT. To go from the raw value to uT is:
|
|
|
|
*
|
|
|
|
* HuT = H * 4912/8190, or roughly, 6/10, instead of 3/10.
|
|
|
|
*/
|
2014-11-22 02:45:49 +08:00
|
|
|
|
|
|
|
static long ak8963_09911_raw_to_gauss(u16 data)
|
2014-11-22 02:45:48 +08:00
|
|
|
{
|
|
|
|
return (((long)data + 128) * 6000) / 256;
|
|
|
|
}
|
2014-03-20 00:56:00 +08:00
|
|
|
|
2014-11-22 02:45:49 +08:00
|
|
|
/*
|
|
|
|
* For AK09912, same calculation, except the device is more sensitive:
|
|
|
|
*
|
|
|
|
* H is in the range of -32752 to 32752. The magnetometer has a range of
|
|
|
|
* +-4912uT. To go from the raw value to uT is:
|
|
|
|
*
|
|
|
|
* HuT = H * 4912/32752, or roughly, 3/20, instead of 3/10.
|
|
|
|
*/
|
|
|
|
static long ak09912_raw_to_gauss(u16 data)
|
|
|
|
{
|
|
|
|
return (((long)data + 128) * 1500) / 256;
|
|
|
|
}
|
|
|
|
|
2014-03-20 00:56:00 +08:00
|
|
|
/* Compatible Asahi Kasei Compass parts */
|
|
|
|
enum asahi_compass_chipset {
|
|
|
|
AK8975,
|
|
|
|
AK8963,
|
2014-11-22 02:45:49 +08:00
|
|
|
AK09911,
|
|
|
|
AK09912,
|
2014-11-22 02:45:48 +08:00
|
|
|
AK_MAX_TYPE
|
|
|
|
};
|
|
|
|
|
|
|
|
enum ak_ctrl_reg_addr {
|
|
|
|
ST1,
|
|
|
|
ST2,
|
|
|
|
CNTL,
|
|
|
|
ASA_BASE,
|
|
|
|
MAX_REGS,
|
|
|
|
REGS_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum ak_ctrl_reg_mask {
|
|
|
|
ST1_DRDY,
|
|
|
|
ST2_HOFL,
|
|
|
|
ST2_DERR,
|
|
|
|
CNTL_MODE,
|
|
|
|
MASK_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum ak_ctrl_mode {
|
|
|
|
POWER_DOWN,
|
|
|
|
MODE_ONCE,
|
|
|
|
SELF_TEST,
|
|
|
|
FUSE_ROM,
|
|
|
|
MODE_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ak_def {
|
|
|
|
enum asahi_compass_chipset type;
|
|
|
|
long (*raw_to_gauss)(u16 data);
|
|
|
|
u16 range;
|
|
|
|
u8 ctrl_regs[REGS_END];
|
|
|
|
u8 ctrl_masks[MASK_END];
|
|
|
|
u8 ctrl_modes[MODE_END];
|
|
|
|
u8 data_regs[3];
|
|
|
|
};
|
|
|
|
|
2016-01-05 22:56:42 +08:00
|
|
|
static const struct ak_def ak_def_array[AK_MAX_TYPE] = {
|
2014-11-22 02:45:48 +08:00
|
|
|
{
|
|
|
|
.type = AK8975,
|
|
|
|
.raw_to_gauss = ak8975_raw_to_gauss,
|
|
|
|
.range = 4096,
|
|
|
|
.ctrl_regs = {
|
|
|
|
AK8975_REG_ST1,
|
|
|
|
AK8975_REG_ST2,
|
|
|
|
AK8975_REG_CNTL,
|
|
|
|
AK8975_REG_ASAX,
|
|
|
|
AK8975_MAX_REGS},
|
|
|
|
.ctrl_masks = {
|
|
|
|
AK8975_REG_ST1_DRDY_MASK,
|
|
|
|
AK8975_REG_ST2_HOFL_MASK,
|
|
|
|
AK8975_REG_ST2_DERR_MASK,
|
|
|
|
AK8975_REG_CNTL_MODE_MASK},
|
|
|
|
.ctrl_modes = {
|
|
|
|
AK8975_REG_CNTL_MODE_POWER_DOWN,
|
|
|
|
AK8975_REG_CNTL_MODE_ONCE,
|
|
|
|
AK8975_REG_CNTL_MODE_SELF_TEST,
|
|
|
|
AK8975_REG_CNTL_MODE_FUSE_ROM},
|
|
|
|
.data_regs = {
|
|
|
|
AK8975_REG_HXL,
|
|
|
|
AK8975_REG_HYL,
|
|
|
|
AK8975_REG_HZL},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.type = AK8963,
|
2014-11-22 02:45:49 +08:00
|
|
|
.raw_to_gauss = ak8963_09911_raw_to_gauss,
|
2014-11-22 02:45:48 +08:00
|
|
|
.range = 8190,
|
|
|
|
.ctrl_regs = {
|
|
|
|
AK8975_REG_ST1,
|
|
|
|
AK8975_REG_ST2,
|
|
|
|
AK8975_REG_CNTL,
|
|
|
|
AK8975_REG_ASAX,
|
|
|
|
AK8975_MAX_REGS},
|
|
|
|
.ctrl_masks = {
|
|
|
|
AK8975_REG_ST1_DRDY_MASK,
|
|
|
|
AK8975_REG_ST2_HOFL_MASK,
|
|
|
|
0,
|
|
|
|
AK8975_REG_CNTL_MODE_MASK},
|
|
|
|
.ctrl_modes = {
|
|
|
|
AK8975_REG_CNTL_MODE_POWER_DOWN,
|
|
|
|
AK8975_REG_CNTL_MODE_ONCE,
|
|
|
|
AK8975_REG_CNTL_MODE_SELF_TEST,
|
|
|
|
AK8975_REG_CNTL_MODE_FUSE_ROM},
|
|
|
|
.data_regs = {
|
|
|
|
AK8975_REG_HXL,
|
|
|
|
AK8975_REG_HYL,
|
|
|
|
AK8975_REG_HZL},
|
|
|
|
},
|
2014-11-22 02:45:49 +08:00
|
|
|
{
|
|
|
|
.type = AK09911,
|
|
|
|
.raw_to_gauss = ak8963_09911_raw_to_gauss,
|
|
|
|
.range = 8192,
|
|
|
|
.ctrl_regs = {
|
|
|
|
AK09912_REG_ST1,
|
|
|
|
AK09912_REG_ST2,
|
|
|
|
AK09912_REG_CNTL2,
|
|
|
|
AK09912_REG_ASAX,
|
|
|
|
AK09912_MAX_REGS},
|
|
|
|
.ctrl_masks = {
|
|
|
|
AK09912_REG_ST1_DRDY_MASK,
|
|
|
|
AK09912_REG_ST2_HOFL_MASK,
|
|
|
|
0,
|
|
|
|
AK09912_REG_CNTL2_MODE_MASK},
|
|
|
|
.ctrl_modes = {
|
|
|
|
AK09912_REG_CNTL_MODE_POWER_DOWN,
|
|
|
|
AK09912_REG_CNTL_MODE_ONCE,
|
|
|
|
AK09912_REG_CNTL_MODE_SELF_TEST,
|
|
|
|
AK09912_REG_CNTL_MODE_FUSE_ROM},
|
|
|
|
.data_regs = {
|
|
|
|
AK09912_REG_HXL,
|
|
|
|
AK09912_REG_HYL,
|
|
|
|
AK09912_REG_HZL},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.type = AK09912,
|
|
|
|
.raw_to_gauss = ak09912_raw_to_gauss,
|
|
|
|
.range = 32752,
|
|
|
|
.ctrl_regs = {
|
|
|
|
AK09912_REG_ST1,
|
|
|
|
AK09912_REG_ST2,
|
|
|
|
AK09912_REG_CNTL2,
|
|
|
|
AK09912_REG_ASAX,
|
|
|
|
AK09912_MAX_REGS},
|
|
|
|
.ctrl_masks = {
|
|
|
|
AK09912_REG_ST1_DRDY_MASK,
|
|
|
|
AK09912_REG_ST2_HOFL_MASK,
|
|
|
|
0,
|
|
|
|
AK09912_REG_CNTL2_MODE_MASK},
|
|
|
|
.ctrl_modes = {
|
|
|
|
AK09912_REG_CNTL_MODE_POWER_DOWN,
|
|
|
|
AK09912_REG_CNTL_MODE_ONCE,
|
|
|
|
AK09912_REG_CNTL_MODE_SELF_TEST,
|
|
|
|
AK09912_REG_CNTL_MODE_FUSE_ROM},
|
|
|
|
.data_regs = {
|
|
|
|
AK09912_REG_HXL,
|
|
|
|
AK09912_REG_HYL,
|
|
|
|
AK09912_REG_HZL},
|
|
|
|
}
|
2014-03-20 00:56:00 +08:00
|
|
|
};
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Per-instance context data for the device.
|
|
|
|
*/
|
|
|
|
struct ak8975_data {
|
|
|
|
struct i2c_client *client;
|
2016-01-05 22:56:42 +08:00
|
|
|
const struct ak_def *def;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
struct mutex lock;
|
|
|
|
u8 asa[3];
|
|
|
|
long raw_to_gauss[3];
|
|
|
|
int eoc_gpio;
|
2013-05-07 18:41:00 +08:00
|
|
|
int eoc_irq;
|
|
|
|
wait_queue_head_t data_ready_queue;
|
|
|
|
unsigned long flags;
|
2014-11-22 02:45:48 +08:00
|
|
|
u8 cntl_cache;
|
2016-04-21 01:23:44 +08:00
|
|
|
struct iio_mount_matrix orientation;
|
2016-03-18 00:43:26 +08:00
|
|
|
struct regulator *vdd;
|
2011-08-13 00:48:03 +08:00
|
|
|
};
|
|
|
|
|
2016-03-18 00:43:26 +08:00
|
|
|
/* Enable attached power regulator if any. */
|
|
|
|
static int ak8975_power_on(struct i2c_client *client)
|
|
|
|
{
|
|
|
|
const struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
|
|
|
struct ak8975_data *data = iio_priv(indio_dev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
data->vdd = devm_regulator_get(&client->dev, "vdd");
|
|
|
|
if (IS_ERR_OR_NULL(data->vdd)) {
|
|
|
|
ret = PTR_ERR(data->vdd);
|
|
|
|
if (ret == -ENODEV)
|
|
|
|
ret = 0;
|
|
|
|
} else {
|
|
|
|
ret = regulator_enable(data->vdd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
dev_err(&client->dev, "failed to enable Vdd supply: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Disable attached power regulator if any. */
|
|
|
|
static void ak8975_power_off(const struct i2c_client *client)
|
|
|
|
{
|
|
|
|
const struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
|
|
|
const struct ak8975_data *data = iio_priv(indio_dev);
|
|
|
|
|
|
|
|
if (!IS_ERR_OR_NULL(data->vdd))
|
|
|
|
regulator_disable(data->vdd);
|
|
|
|
}
|
|
|
|
|
2014-11-22 02:45:49 +08:00
|
|
|
/*
|
|
|
|
* Return 0 if the i2c device is the one we expect.
|
|
|
|
* return a negative error number otherwise
|
|
|
|
*/
|
|
|
|
static int ak8975_who_i_am(struct i2c_client *client,
|
|
|
|
enum asahi_compass_chipset type)
|
|
|
|
{
|
|
|
|
u8 wia_val[2];
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Signature for each device:
|
|
|
|
* Device | WIA1 | WIA2
|
|
|
|
* AK09912 | DEVICE_ID | AK09912_DEVICE_ID
|
|
|
|
* AK09911 | DEVICE_ID | AK09911_DEVICE_ID
|
|
|
|
* AK8975 | DEVICE_ID | NA
|
|
|
|
* AK8963 | DEVICE_ID | NA
|
|
|
|
*/
|
2016-04-30 03:05:32 +08:00
|
|
|
ret = i2c_smbus_read_i2c_block_data_or_emulated(
|
|
|
|
client, AK09912_REG_WIA1, 2, wia_val);
|
2014-11-22 02:45:49 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
dev_err(&client->dev, "Error reading WIA\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wia_val[0] != AK8975_DEVICE_ID)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case AK8975:
|
|
|
|
case AK8963:
|
|
|
|
return 0;
|
|
|
|
case AK09911:
|
|
|
|
if (wia_val[1] == AK09911_DEVICE_ID)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case AK09912:
|
|
|
|
if (wia_val[1] == AK09912_DEVICE_ID)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
dev_err(&client->dev, "Type %d unknown\n", type);
|
|
|
|
}
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
/*
|
2014-11-22 02:45:48 +08:00
|
|
|
* Helper function to write to CNTL register.
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
*/
|
2014-11-22 02:45:48 +08:00
|
|
|
static int ak8975_set_mode(struct ak8975_data *data, enum ak_ctrl_mode mode)
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
{
|
2011-08-13 00:48:03 +08:00
|
|
|
u8 regval;
|
|
|
|
int ret;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
2014-11-22 02:45:48 +08:00
|
|
|
regval = (data->cntl_cache & ~data->def->ctrl_masks[CNTL_MODE]) |
|
|
|
|
data->def->ctrl_modes[mode];
|
|
|
|
ret = i2c_smbus_write_byte_data(data->client,
|
|
|
|
data->def->ctrl_regs[CNTL], regval);
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
2014-11-22 02:45:48 +08:00
|
|
|
data->cntl_cache = regval;
|
|
|
|
/* After mode change wait atleast 100us */
|
|
|
|
usleep_range(100, 500);
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-05-07 18:41:00 +08:00
|
|
|
/*
|
|
|
|
* Handle data ready irq
|
|
|
|
*/
|
|
|
|
static irqreturn_t ak8975_irq_handler(int irq, void *data)
|
|
|
|
{
|
|
|
|
struct ak8975_data *ak8975 = data;
|
|
|
|
|
|
|
|
set_bit(0, &ak8975->flags);
|
|
|
|
wake_up(&ak8975->data_ready_queue);
|
|
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Install data ready interrupt handler
|
|
|
|
*/
|
|
|
|
static int ak8975_setup_irq(struct ak8975_data *data)
|
|
|
|
{
|
|
|
|
struct i2c_client *client = data->client;
|
|
|
|
int rc;
|
|
|
|
int irq;
|
|
|
|
|
2016-04-04 13:54:59 +08:00
|
|
|
init_waitqueue_head(&data->data_ready_queue);
|
|
|
|
clear_bit(0, &data->flags);
|
2013-05-07 18:41:00 +08:00
|
|
|
if (client->irq)
|
|
|
|
irq = client->irq;
|
|
|
|
else
|
|
|
|
irq = gpio_to_irq(data->eoc_gpio);
|
|
|
|
|
2014-06-23 20:34:00 +08:00
|
|
|
rc = devm_request_irq(&client->dev, irq, ak8975_irq_handler,
|
2014-11-22 02:45:47 +08:00
|
|
|
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
|
|
|
dev_name(&client->dev), data);
|
2013-05-07 18:41:00 +08:00
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(&client->dev,
|
|
|
|
"irq %d request failed, (gpio %d): %d\n",
|
|
|
|
irq, data->eoc_gpio, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->eoc_irq = irq;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
/*
|
|
|
|
* Perform some start-of-day setup, including reading the asa calibration
|
|
|
|
* values and caching them.
|
|
|
|
*/
|
|
|
|
static int ak8975_setup(struct i2c_client *client)
|
|
|
|
{
|
2012-04-09 20:35:01 +08:00
|
|
|
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
|
|
|
struct ak8975_data *data = iio_priv(indio_dev);
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Write the fused rom access mode. */
|
2014-11-22 02:45:48 +08:00
|
|
|
ret = ak8975_set_mode(data, FUSE_ROM);
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
dev_err(&client->dev, "Error in setting fuse access mode\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get asa data and store in the device data. */
|
2016-04-30 03:05:32 +08:00
|
|
|
ret = i2c_smbus_read_i2c_block_data_or_emulated(
|
|
|
|
client, data->def->ctrl_regs[ASA_BASE],
|
|
|
|
3, data->asa);
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
dev_err(&client->dev, "Not able to read asa data\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-06-07 04:14:56 +08:00
|
|
|
/* After reading fuse ROM data set power-down mode */
|
2014-11-22 02:45:48 +08:00
|
|
|
ret = ak8975_set_mode(data, POWER_DOWN);
|
2014-11-22 02:45:47 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
dev_err(&client->dev, "Error in setting power-down mode\n");
|
|
|
|
return ret;
|
|
|
|
}
|
2013-05-07 18:41:00 +08:00
|
|
|
|
2014-11-22 02:45:47 +08:00
|
|
|
if (data->eoc_gpio > 0 || client->irq > 0) {
|
2013-05-07 18:41:00 +08:00
|
|
|
ret = ak8975_setup_irq(data);
|
|
|
|
if (ret < 0) {
|
|
|
|
dev_err(&client->dev,
|
|
|
|
"Error setting data ready interrupt\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-22 02:45:48 +08:00
|
|
|
data->raw_to_gauss[0] = data->def->raw_to_gauss(data->asa[0]);
|
|
|
|
data->raw_to_gauss[1] = data->def->raw_to_gauss(data->asa[1]);
|
|
|
|
data->raw_to_gauss[2] = data->def->raw_to_gauss(data->asa[2]);
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-06 20:31:40 +08:00
|
|
|
static int wait_conversion_complete_gpio(struct ak8975_data *data)
|
|
|
|
{
|
|
|
|
struct i2c_client *client = data->client;
|
|
|
|
u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Wait for the conversion to complete. */
|
|
|
|
while (timeout_ms) {
|
|
|
|
msleep(AK8975_CONVERSION_DONE_POLL_TIME);
|
|
|
|
if (gpio_get_value(data->eoc_gpio))
|
|
|
|
break;
|
|
|
|
timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
|
|
|
|
}
|
|
|
|
if (!timeout_ms) {
|
|
|
|
dev_err(&client->dev, "Conversion timeout happened\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2014-11-22 02:45:48 +08:00
|
|
|
ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST1]);
|
2013-03-25 00:58:00 +08:00
|
|
|
if (ret < 0)
|
2011-04-06 20:31:40 +08:00
|
|
|
dev_err(&client->dev, "Error in reading ST1\n");
|
2013-03-25 00:58:00 +08:00
|
|
|
|
|
|
|
return ret;
|
2011-04-06 20:31:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int wait_conversion_complete_polled(struct ak8975_data *data)
|
|
|
|
{
|
|
|
|
struct i2c_client *client = data->client;
|
|
|
|
u8 read_status;
|
|
|
|
u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Wait for the conversion to complete. */
|
|
|
|
while (timeout_ms) {
|
|
|
|
msleep(AK8975_CONVERSION_DONE_POLL_TIME);
|
2014-11-22 02:45:48 +08:00
|
|
|
ret = i2c_smbus_read_byte_data(client,
|
|
|
|
data->def->ctrl_regs[ST1]);
|
2011-04-06 20:31:40 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
dev_err(&client->dev, "Error in reading ST1\n");
|
|
|
|
return ret;
|
|
|
|
}
|
2013-03-25 00:58:00 +08:00
|
|
|
read_status = ret;
|
2011-04-06 20:31:40 +08:00
|
|
|
if (read_status)
|
|
|
|
break;
|
|
|
|
timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
|
|
|
|
}
|
|
|
|
if (!timeout_ms) {
|
|
|
|
dev_err(&client->dev, "Conversion timeout happened\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2013-05-07 18:41:00 +08:00
|
|
|
|
2011-04-06 20:31:40 +08:00
|
|
|
return read_status;
|
|
|
|
}
|
|
|
|
|
2013-05-07 18:41:00 +08:00
|
|
|
/* Returns 0 if the end of conversion interrupt occured or -ETIME otherwise */
|
|
|
|
static int wait_conversion_complete_interrupt(struct ak8975_data *data)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = wait_event_timeout(data->data_ready_queue,
|
|
|
|
test_bit(0, &data->flags),
|
|
|
|
AK8975_DATA_READY_TIMEOUT);
|
|
|
|
clear_bit(0, &data->flags);
|
|
|
|
|
|
|
|
return ret > 0 ? 0 : -ETIME;
|
|
|
|
}
|
|
|
|
|
2016-04-08 23:09:08 +08:00
|
|
|
static int ak8975_start_read_axis(struct ak8975_data *data,
|
|
|
|
const struct i2c_client *client)
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
{
|
|
|
|
/* Set up the device for taking a sample. */
|
2016-04-08 23:09:08 +08:00
|
|
|
int ret = ak8975_set_mode(data, MODE_ONCE);
|
|
|
|
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
dev_err(&client->dev, "Error in setting operating mode\n");
|
2016-04-08 23:09:08 +08:00
|
|
|
return ret;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait for the conversion to complete. */
|
2013-05-07 18:41:00 +08:00
|
|
|
if (data->eoc_irq)
|
|
|
|
ret = wait_conversion_complete_interrupt(data);
|
|
|
|
else if (gpio_is_valid(data->eoc_gpio))
|
2011-04-06 20:31:40 +08:00
|
|
|
ret = wait_conversion_complete_gpio(data);
|
|
|
|
else
|
|
|
|
ret = wait_conversion_complete_polled(data);
|
|
|
|
if (ret < 0)
|
2016-04-08 23:09:08 +08:00
|
|
|
return ret;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
2013-05-07 18:41:00 +08:00
|
|
|
/* This will be executed only for non-interrupt based waiting case */
|
2014-11-22 02:45:48 +08:00
|
|
|
if (ret & data->def->ctrl_masks[ST1_DRDY]) {
|
|
|
|
ret = i2c_smbus_read_byte_data(client,
|
|
|
|
data->def->ctrl_regs[ST2]);
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
if (ret < 0) {
|
|
|
|
dev_err(&client->dev, "Error in reading ST2\n");
|
2016-04-08 23:09:08 +08:00
|
|
|
return ret;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
}
|
2014-11-22 02:45:48 +08:00
|
|
|
if (ret & (data->def->ctrl_masks[ST2_DERR] |
|
|
|
|
data->def->ctrl_masks[ST2_HOFL])) {
|
2013-03-25 00:58:00 +08:00
|
|
|
dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
|
2016-04-08 23:09:08 +08:00
|
|
|
return -EINVAL;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-08 23:09:08 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Retrieve raw flux value for one of the x, y, or z axis. */
|
|
|
|
static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
|
|
|
|
{
|
|
|
|
struct ak8975_data *data = iio_priv(indio_dev);
|
|
|
|
const struct i2c_client *client = data->client;
|
|
|
|
const struct ak_def *def = data->def;
|
2016-04-30 03:05:32 +08:00
|
|
|
u16 buff;
|
2016-04-08 23:09:08 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
|
|
|
|
ret = ak8975_start_read_axis(data, client);
|
|
|
|
if (ret)
|
|
|
|
goto exit;
|
|
|
|
|
2016-04-30 03:05:32 +08:00
|
|
|
ret = i2c_smbus_read_i2c_block_data_or_emulated(
|
|
|
|
client, def->data_regs[index],
|
|
|
|
sizeof(buff), (u8*)&buff);
|
2016-04-08 23:09:08 +08:00
|
|
|
if (ret < 0)
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
goto exit;
|
|
|
|
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
|
2016-04-30 03:05:32 +08:00
|
|
|
/* Swap bytes and convert to valid range. */
|
|
|
|
buff = le16_to_cpu(buff);
|
|
|
|
*val = clamp_t(s16, buff, -def->range, def->range);
|
2011-08-13 00:48:03 +08:00
|
|
|
return IIO_VAL_INT;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
|
|
|
exit:
|
|
|
|
mutex_unlock(&data->lock);
|
2016-04-08 23:09:08 +08:00
|
|
|
dev_err(&client->dev, "Error in reading axis\n");
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-08-13 00:48:03 +08:00
|
|
|
static int ak8975_read_raw(struct iio_dev *indio_dev,
|
|
|
|
struct iio_chan_spec const *chan,
|
|
|
|
int *val, int *val2,
|
|
|
|
long mask)
|
|
|
|
{
|
|
|
|
struct ak8975_data *data = iio_priv(indio_dev);
|
|
|
|
|
|
|
|
switch (mask) {
|
2012-04-16 00:41:23 +08:00
|
|
|
case IIO_CHAN_INFO_RAW:
|
2011-08-13 00:48:03 +08:00
|
|
|
return ak8975_read_axis(indio_dev, chan->address, val);
|
2011-10-27 00:41:36 +08:00
|
|
|
case IIO_CHAN_INFO_SCALE:
|
2014-04-02 16:15:00 +08:00
|
|
|
*val = 0;
|
|
|
|
*val2 = data->raw_to_gauss[chan->address];
|
|
|
|
return IIO_VAL_INT_PLUS_MICRO;
|
2011-08-13 00:48:03 +08:00
|
|
|
}
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2016-04-21 01:23:44 +08:00
|
|
|
static const struct iio_mount_matrix *
|
|
|
|
ak8975_get_mount_matrix(const struct iio_dev *indio_dev,
|
|
|
|
const struct iio_chan_spec *chan)
|
|
|
|
{
|
|
|
|
return &((struct ak8975_data *)iio_priv(indio_dev))->orientation;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct iio_chan_spec_ext_info ak8975_ext_info[] = {
|
|
|
|
IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, ak8975_get_mount_matrix),
|
|
|
|
{ },
|
|
|
|
};
|
|
|
|
|
2011-08-13 00:48:03 +08:00
|
|
|
#define AK8975_CHANNEL(axis, index) \
|
|
|
|
{ \
|
|
|
|
.type = IIO_MAGN, \
|
|
|
|
.modified = 1, \
|
|
|
|
.channel2 = IIO_MOD_##axis, \
|
2013-02-28 03:40:48 +08:00
|
|
|
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
|
|
|
|
BIT(IIO_CHAN_INFO_SCALE), \
|
2011-08-13 00:48:03 +08:00
|
|
|
.address = index, \
|
2016-04-08 23:09:08 +08:00
|
|
|
.scan_index = index, \
|
|
|
|
.scan_type = { \
|
|
|
|
.sign = 's', \
|
|
|
|
.realbits = 16, \
|
|
|
|
.storagebits = 16, \
|
|
|
|
.endianness = IIO_CPU \
|
2016-04-21 01:23:44 +08:00
|
|
|
}, \
|
|
|
|
.ext_info = ak8975_ext_info, \
|
2011-08-13 00:48:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct iio_chan_spec ak8975_channels[] = {
|
|
|
|
AK8975_CHANNEL(X, 0), AK8975_CHANNEL(Y, 1), AK8975_CHANNEL(Z, 2),
|
2016-04-08 23:09:08 +08:00
|
|
|
IIO_CHAN_SOFT_TIMESTAMP(3),
|
2011-08-13 00:48:03 +08:00
|
|
|
};
|
|
|
|
|
2016-04-08 23:09:08 +08:00
|
|
|
static const unsigned long ak8975_scan_masks[] = { 0x7, 0 };
|
|
|
|
|
2011-05-18 21:42:37 +08:00
|
|
|
static const struct iio_info ak8975_info = {
|
2011-08-13 00:48:03 +08:00
|
|
|
.read_raw = &ak8975_read_raw,
|
2011-05-18 21:42:37 +08:00
|
|
|
.driver_module = THIS_MODULE,
|
|
|
|
};
|
|
|
|
|
2014-03-20 00:56:00 +08:00
|
|
|
static const struct acpi_device_id ak_acpi_match[] = {
|
|
|
|
{"AK8975", AK8975},
|
|
|
|
{"AK8963", AK8963},
|
|
|
|
{"INVN6500", AK8963},
|
2014-11-22 02:45:49 +08:00
|
|
|
{"AK09911", AK09911},
|
|
|
|
{"AK09912", AK09912},
|
2014-03-20 00:56:00 +08:00
|
|
|
{ },
|
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
|
|
|
|
|
2014-08-09 22:18:00 +08:00
|
|
|
static const char *ak8975_match_acpi_device(struct device *dev,
|
|
|
|
enum asahi_compass_chipset *chipset)
|
2014-03-20 00:56:00 +08:00
|
|
|
{
|
|
|
|
const struct acpi_device_id *id;
|
|
|
|
|
|
|
|
id = acpi_match_device(dev->driver->acpi_match_table, dev);
|
|
|
|
if (!id)
|
|
|
|
return NULL;
|
|
|
|
*chipset = (int)id->driver_data;
|
|
|
|
|
2014-08-09 22:18:00 +08:00
|
|
|
return dev_name(dev);
|
2014-03-20 00:56:00 +08:00
|
|
|
}
|
|
|
|
|
2016-04-08 23:09:08 +08:00
|
|
|
static void ak8975_fill_buffer(struct iio_dev *indio_dev)
|
|
|
|
{
|
|
|
|
struct ak8975_data *data = iio_priv(indio_dev);
|
|
|
|
const struct i2c_client *client = data->client;
|
|
|
|
const struct ak_def *def = data->def;
|
|
|
|
int ret;
|
|
|
|
s16 buff[8]; /* 3 x 16 bits axis values + 1 aligned 64 bits timestamp */
|
|
|
|
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
|
|
|
|
ret = ak8975_start_read_axis(data, client);
|
|
|
|
if (ret)
|
|
|
|
goto unlock;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For each axis, read the flux value from the appropriate register
|
|
|
|
* (the register is specified in the iio device attributes).
|
|
|
|
*/
|
|
|
|
ret = i2c_smbus_read_i2c_block_data_or_emulated(client,
|
|
|
|
def->data_regs[0],
|
|
|
|
3 * sizeof(buff[0]),
|
|
|
|
(u8 *)buff);
|
|
|
|
if (ret < 0)
|
|
|
|
goto unlock;
|
|
|
|
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
|
|
|
|
/* Clamp to valid range. */
|
|
|
|
buff[0] = clamp_t(s16, le16_to_cpu(buff[0]), -def->range, def->range);
|
|
|
|
buff[1] = clamp_t(s16, le16_to_cpu(buff[1]), -def->range, def->range);
|
|
|
|
buff[2] = clamp_t(s16, le16_to_cpu(buff[2]), -def->range, def->range);
|
|
|
|
|
2016-03-10 02:05:49 +08:00
|
|
|
iio_push_to_buffers_with_timestamp(indio_dev, buff,
|
|
|
|
iio_get_time_ns(indio_dev));
|
2016-04-08 23:09:08 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
unlock:
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
dev_err(&client->dev, "Error in reading axes block\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static irqreturn_t ak8975_handle_trigger(int irq, void *p)
|
|
|
|
{
|
|
|
|
const struct iio_poll_func *pf = p;
|
|
|
|
struct iio_dev *indio_dev = pf->indio_dev;
|
|
|
|
|
|
|
|
ak8975_fill_buffer(indio_dev);
|
|
|
|
iio_trigger_notify_done(indio_dev->trig);
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
2012-11-20 02:21:57 +08:00
|
|
|
static int ak8975_probe(struct i2c_client *client,
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
const struct i2c_device_id *id)
|
|
|
|
{
|
|
|
|
struct ak8975_data *data;
|
2011-06-27 20:07:54 +08:00
|
|
|
struct iio_dev *indio_dev;
|
|
|
|
int eoc_gpio;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
int err;
|
2014-08-09 22:18:00 +08:00
|
|
|
const char *name = NULL;
|
2016-04-05 21:03:48 +08:00
|
|
|
enum asahi_compass_chipset chipset = AK_MAX_TYPE;
|
2016-04-21 01:23:44 +08:00
|
|
|
const struct ak8975_platform_data *pdata =
|
|
|
|
dev_get_platdata(&client->dev);
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
|
|
|
/* Grab and set up the supplied GPIO. */
|
2016-04-21 01:23:44 +08:00
|
|
|
if (pdata)
|
|
|
|
eoc_gpio = pdata->eoc_gpio;
|
2013-05-07 18:41:00 +08:00
|
|
|
else if (client->dev.of_node)
|
|
|
|
eoc_gpio = of_get_gpio(client->dev.of_node, 0);
|
|
|
|
else
|
|
|
|
eoc_gpio = -1;
|
|
|
|
|
|
|
|
if (eoc_gpio == -EPROBE_DEFER)
|
|
|
|
return -EPROBE_DEFER;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
2011-04-06 20:31:40 +08:00
|
|
|
/* We may not have a GPIO based IRQ to scan, that is fine, we will
|
|
|
|
poll if so */
|
2011-09-21 18:16:00 +08:00
|
|
|
if (gpio_is_valid(eoc_gpio)) {
|
2014-06-23 20:34:00 +08:00
|
|
|
err = devm_gpio_request_one(&client->dev, eoc_gpio,
|
|
|
|
GPIOF_IN, "ak_8975");
|
2011-04-06 20:31:40 +08:00
|
|
|
if (err < 0) {
|
|
|
|
dev_err(&client->dev,
|
|
|
|
"failed to request GPIO %d, error %d\n",
|
2011-06-27 20:07:54 +08:00
|
|
|
eoc_gpio, err);
|
2014-06-23 20:34:00 +08:00
|
|
|
return err;
|
2011-04-06 20:31:40 +08:00
|
|
|
}
|
2011-09-21 18:16:00 +08:00
|
|
|
}
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
2011-06-27 20:07:54 +08:00
|
|
|
/* Register with IIO */
|
2014-06-23 20:34:00 +08:00
|
|
|
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
|
|
|
|
if (indio_dev == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2011-06-27 20:07:54 +08:00
|
|
|
data = iio_priv(indio_dev);
|
2012-04-09 20:35:01 +08:00
|
|
|
i2c_set_clientdata(client, indio_dev);
|
2013-05-07 18:41:00 +08:00
|
|
|
|
|
|
|
data->client = client;
|
|
|
|
data->eoc_gpio = eoc_gpio;
|
|
|
|
data->eoc_irq = 0;
|
|
|
|
|
2016-04-21 01:23:44 +08:00
|
|
|
if (!pdata) {
|
|
|
|
err = of_iio_read_mount_matrix(&client->dev,
|
|
|
|
"mount-matrix",
|
|
|
|
&data->orientation);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
} else
|
|
|
|
data->orientation = pdata->orientation;
|
|
|
|
|
2014-03-20 00:56:00 +08:00
|
|
|
/* id will be NULL when enumerated via ACPI */
|
|
|
|
if (id) {
|
2014-11-22 02:45:48 +08:00
|
|
|
chipset = (enum asahi_compass_chipset)(id->driver_data);
|
2014-08-09 22:18:00 +08:00
|
|
|
name = id->name;
|
2016-03-03 18:44:03 +08:00
|
|
|
} else if (ACPI_HANDLE(&client->dev)) {
|
2014-11-22 02:45:48 +08:00
|
|
|
name = ak8975_match_acpi_device(&client->dev, &chipset);
|
2016-03-03 18:44:03 +08:00
|
|
|
if (!name)
|
|
|
|
return -ENODEV;
|
2016-04-15 03:36:41 +08:00
|
|
|
} else
|
2014-06-23 20:34:00 +08:00
|
|
|
return -ENOSYS;
|
|
|
|
|
2014-11-22 02:45:48 +08:00
|
|
|
if (chipset >= AK_MAX_TYPE) {
|
|
|
|
dev_err(&client->dev, "AKM device type unsupported: %d\n",
|
|
|
|
chipset);
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->def = &ak_def_array[chipset];
|
2016-03-18 00:43:26 +08:00
|
|
|
|
|
|
|
err = ak8975_power_on(client);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2014-11-22 02:45:49 +08:00
|
|
|
err = ak8975_who_i_am(client, data->def->type);
|
|
|
|
if (err < 0) {
|
|
|
|
dev_err(&client->dev, "Unexpected device\n");
|
2016-03-18 00:43:26 +08:00
|
|
|
goto power_off;
|
2014-11-22 02:45:49 +08:00
|
|
|
}
|
2014-03-20 00:56:00 +08:00
|
|
|
dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
|
2014-03-20 00:56:00 +08:00
|
|
|
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
/* Perform some basic start-of-day setup of the device. */
|
|
|
|
err = ak8975_setup(client);
|
|
|
|
if (err < 0) {
|
2014-11-22 02:45:47 +08:00
|
|
|
dev_err(&client->dev, "%s initialization fails\n", name);
|
2016-03-18 00:43:26 +08:00
|
|
|
goto power_off;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
}
|
|
|
|
|
2011-06-27 20:07:54 +08:00
|
|
|
mutex_init(&data->lock);
|
|
|
|
indio_dev->dev.parent = &client->dev;
|
2011-08-13 00:48:03 +08:00
|
|
|
indio_dev->channels = ak8975_channels;
|
|
|
|
indio_dev->num_channels = ARRAY_SIZE(ak8975_channels);
|
2011-06-27 20:07:54 +08:00
|
|
|
indio_dev->info = &ak8975_info;
|
2016-04-08 23:09:08 +08:00
|
|
|
indio_dev->available_scan_masks = ak8975_scan_masks;
|
2011-06-27 20:07:54 +08:00
|
|
|
indio_dev->modes = INDIO_DIRECT_MODE;
|
2014-03-20 00:56:00 +08:00
|
|
|
indio_dev->name = name;
|
2016-03-18 00:43:26 +08:00
|
|
|
|
2016-04-08 23:09:08 +08:00
|
|
|
err = iio_triggered_buffer_setup(indio_dev, NULL, ak8975_handle_trigger,
|
|
|
|
NULL);
|
|
|
|
if (err) {
|
|
|
|
dev_err(&client->dev, "triggered buffer setup failed\n");
|
2016-03-18 00:43:26 +08:00
|
|
|
goto power_off;
|
2016-04-08 23:09:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
err = iio_device_register(indio_dev);
|
|
|
|
if (err) {
|
|
|
|
dev_err(&client->dev, "device register failed\n");
|
|
|
|
goto cleanup_buffer;
|
|
|
|
}
|
2016-03-18 00:43:26 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2016-04-08 23:09:08 +08:00
|
|
|
cleanup_buffer:
|
|
|
|
iio_triggered_buffer_cleanup(indio_dev);
|
2016-03-18 00:43:26 +08:00
|
|
|
power_off:
|
|
|
|
ak8975_power_off(client);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ak8975_remove(struct i2c_client *client)
|
|
|
|
{
|
|
|
|
struct iio_dev *indio_dev = i2c_get_clientdata(client);
|
|
|
|
|
|
|
|
iio_device_unregister(indio_dev);
|
2016-04-08 23:09:08 +08:00
|
|
|
iio_triggered_buffer_cleanup(indio_dev);
|
2016-03-18 00:43:26 +08:00
|
|
|
ak8975_power_off(client);
|
|
|
|
|
|
|
|
return 0;
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const struct i2c_device_id ak8975_id[] = {
|
2014-03-20 00:56:00 +08:00
|
|
|
{"ak8975", AK8975},
|
|
|
|
{"ak8963", AK8963},
|
2015-01-10 07:30:38 +08:00
|
|
|
{"AK8963", AK8963},
|
2014-11-22 02:45:49 +08:00
|
|
|
{"ak09911", AK09911},
|
|
|
|
{"ak09912", AK09912},
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
MODULE_DEVICE_TABLE(i2c, ak8975_id);
|
|
|
|
|
2011-12-23 10:46:42 +08:00
|
|
|
static const struct of_device_id ak8975_of_match[] = {
|
|
|
|
{ .compatible = "asahi-kasei,ak8975", },
|
|
|
|
{ .compatible = "ak8975", },
|
2014-11-22 02:45:48 +08:00
|
|
|
{ .compatible = "asahi-kasei,ak8963", },
|
|
|
|
{ .compatible = "ak8963", },
|
2014-11-22 02:45:49 +08:00
|
|
|
{ .compatible = "asahi-kasei,ak09911", },
|
|
|
|
{ .compatible = "ak09911", },
|
|
|
|
{ .compatible = "asahi-kasei,ak09912", },
|
|
|
|
{ .compatible = "ak09912", },
|
2014-11-22 02:45:48 +08:00
|
|
|
{}
|
2011-12-23 10:46:42 +08:00
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(of, ak8975_of_match);
|
|
|
|
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
static struct i2c_driver ak8975_driver = {
|
|
|
|
.driver = {
|
|
|
|
.name = "ak8975",
|
2014-11-22 02:45:47 +08:00
|
|
|
.of_match_table = of_match_ptr(ak8975_of_match),
|
2014-03-20 00:56:00 +08:00
|
|
|
.acpi_match_table = ACPI_PTR(ak_acpi_match),
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
},
|
|
|
|
.probe = ak8975_probe,
|
2016-03-18 00:43:26 +08:00
|
|
|
.remove = ak8975_remove,
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
.id_table = ak8975_id,
|
|
|
|
};
|
2011-11-16 17:13:38 +08:00
|
|
|
module_i2c_driver(ak8975_driver);
|
staging: iio: ak8975: Add ak8975 magnetometer sensor
This is for the Asahi Kasei AK8975 3-axis magnetometer. It resides within
the magnetometer section of the IIO subsystem, and implements the raw
magn_x,y,z_raw attributes, as well as magn_x,y,z_scale attributes for
converting to Gauss.
Changed to use the magn_x,y,z_scale attributes, and made those attributes
give the scale factor to conert to Gauss. Also applied more fixes from
feedback.
Keeping mode as an unsigned long. I'm going to add proper power management
at some point anyway, which would deprecate this attribute.
Signed-off-by: Andrew Chew <achew@nvidia.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-09-09 13:02:17 +08:00
|
|
|
|
|
|
|
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
|
|
|
MODULE_DESCRIPTION("AK8975 magnetometer driver");
|
|
|
|
MODULE_LICENSE("GPL");
|