Commit d5cef008 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-3.16a' of...

Merge tag 'iio-for-3.16a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next

Jonathan writes:

First round of IIO new driver, functionality and cleanups for the 3.16 cycle.

New device support
* AS3935 Lightning Sensor
* MCP3426/7/8 support added to the existing MCP3422 ADC driver
* AK8963 support in the AK8975 driver
* MPU6500 support in the MPU6050 driver (the functionality that is different
  is mostly not supported yet in either part).

Staging Graduations
* AD799x ADC

New functionality
* ACPI enumeration for the ak8975 driver

Cleanup / tweaks
* Use snprintf as a matter of good practice in a few additional places.
* Document *_mean_raw attributes.  These have been there a while, but were
  undocumented.
* Add an in kernel interface to get the mean values.
* Bug in the length of the event info mask that by coincidence wasn't yet
  actually causing any problems.
* itg3000 drop an unreachable return statement.
* spear_adc cleanups (heading for a staging graduation but a few more
  issues showed up in the review of these patches).
* Exynos ADC dependencies changed so it is only built when Exynos is present
  or COMPILE_TEST and OF are set.
* tsl2583 cleanups.
* Some cut and paste typos in the comments of various drivers still in staging.
* Couple of minor improvements to the ST sensor drivers.
parents 58612c60 ea7e586b
...@@ -210,6 +210,14 @@ Contact: linux-iio@vger.kernel.org ...@@ -210,6 +210,14 @@ Contact: linux-iio@vger.kernel.org
Description: Description:
Scaled humidity measurement in milli percent. Scaled humidity measurement in milli percent.
What: /sys/bus/iio/devices/iio:deviceX/in_X_mean_raw
KernelVersion: 3.5
Contact: linux-iio@vger.kernel.org
Description:
Averaged raw measurement from channel X. The number of values
used for averaging is device specific. The converting rules for
normal raw values also applies to the averaged raw values.
What: /sys/bus/iio/devices/iio:deviceX/in_accel_offset What: /sys/bus/iio/devices/iio:deviceX/in_accel_offset
What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_offset What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_offset
What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset
......
What /sys/bus/iio/devices/iio:deviceX/in_proximity_raw
Date: March 2014
KernelVersion: 3.15
Contact: Matt Ranostay <mranostay@gmail.com>
Description:
Get the current distance in meters of storm (1km steps)
1000-40000 = distance in meters
What /sys/bus/iio/devices/iio:deviceX/sensor_sensitivity
Date: March 2014
KernelVersion: 3.15
Contact: Matt Ranostay <mranostay@gmail.com>
Description:
Show or set the gain boost of the amp, from 0-31 range.
18 = indoors (default)
14 = outdoors
Austrian Microsystems AS3935 Franklin lightning sensor device driver
Required properties:
- compatible: must be "ams,as3935"
- reg: SPI chip select number for the device
- spi-cpha: SPI Mode 1. Refer to spi/spi-bus.txt for generic SPI
slave node bindings.
- interrupt-parent : should be the phandle for the interrupt controller
- interrupts : the sole interrupt generated by the device
Refer to interrupt-controller/interrupts.txt for generic
interrupt client node bindings.
Optional properties:
- ams,tuning-capacitor-pf: Calibration tuning capacitor stepping
value 0 - 120pF. This will require using the calibration data from
the manufacturer.
Example:
as3935@0 {
compatible = "ams,as3935";
reg = <0>;
spi-cpha;
interrupt-parent = <&gpio1>;
interrupts = <16 1>;
ams,tuning-capacitor-pf = <80>;
};
...@@ -13,6 +13,7 @@ allwinner Allwinner Technology Co., Ltd. ...@@ -13,6 +13,7 @@ allwinner Allwinner Technology Co., Ltd.
altr Altera Corp. altr Altera Corp.
amcc Applied Micro Circuits Corporation (APM, formally AMCC) amcc Applied Micro Circuits Corporation (APM, formally AMCC)
amd Advanced Micro Devices (AMD), Inc. amd Advanced Micro Devices (AMD), Inc.
ams AMS AG
amstaos AMS-Taos Inc. amstaos AMS-Taos Inc.
apm Applied Micro Circuits Corporation (APM) apm Applied Micro Circuits Corporation (APM)
arm ARM Ltd. arm ARM Ltd.
......
...@@ -74,6 +74,7 @@ if IIO_TRIGGER ...@@ -74,6 +74,7 @@ if IIO_TRIGGER
source "drivers/iio/trigger/Kconfig" source "drivers/iio/trigger/Kconfig"
endif #IIO_TRIGGER endif #IIO_TRIGGER
source "drivers/iio/pressure/Kconfig" source "drivers/iio/pressure/Kconfig"
source "drivers/iio/proximity/Kconfig"
source "drivers/iio/temperature/Kconfig" source "drivers/iio/temperature/Kconfig"
endif # IIO endif # IIO
...@@ -24,5 +24,6 @@ obj-y += light/ ...@@ -24,5 +24,6 @@ obj-y += light/
obj-y += magnetometer/ obj-y += magnetometer/
obj-y += orientation/ obj-y += orientation/
obj-y += pressure/ obj-y += pressure/
obj-y += proximity/
obj-y += temperature/ obj-y += temperature/
obj-y += trigger/ obj-y += trigger/
...@@ -459,6 +459,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev, ...@@ -459,6 +459,8 @@ int st_accel_common_probe(struct iio_dev *indio_dev,
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &accel_info; indio_dev->info = &accel_info;
st_sensors_power_enable(indio_dev);
err = st_sensors_check_device_support(indio_dev, err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_accel_sensors), st_accel_sensors); ARRAY_SIZE(st_accel_sensors), st_accel_sensors);
if (err < 0) if (err < 0)
...@@ -496,6 +498,9 @@ int st_accel_common_probe(struct iio_dev *indio_dev, ...@@ -496,6 +498,9 @@ int st_accel_common_probe(struct iio_dev *indio_dev,
if (err) if (err)
goto st_accel_device_register_error; goto st_accel_device_register_error;
dev_info(&indio_dev->dev, "registered accelerometer %s\n",
indio_dev->name);
return 0; return 0;
st_accel_device_register_error: st_accel_device_register_error:
...@@ -512,6 +517,8 @@ void st_accel_common_remove(struct iio_dev *indio_dev) ...@@ -512,6 +517,8 @@ void st_accel_common_remove(struct iio_dev *indio_dev)
{ {
struct st_sensor_data *adata = iio_priv(indio_dev); struct st_sensor_data *adata = iio_priv(indio_dev);
st_sensors_power_disable(indio_dev);
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
if (adata->get_irq_data_ready(indio_dev) > 0) if (adata->get_irq_data_ready(indio_dev) > 0)
st_sensors_deallocate_trigger(indio_dev); st_sensors_deallocate_trigger(indio_dev);
......
...@@ -96,6 +96,17 @@ config AD7923 ...@@ -96,6 +96,17 @@ config AD7923
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ad7923. module will be called ad7923.
config AD799X
tristate "Analog Devices AD799x ADC driver"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Analog Devices:
ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, ad7998
i2c analog to digital converters (ADC). Provides direct access
via sysfs.
config AT91_ADC config AT91_ADC
tristate "Atmel AT91 ADC" tristate "Atmel AT91 ADC"
depends on ARCH_AT91 depends on ARCH_AT91
...@@ -107,7 +118,7 @@ config AT91_ADC ...@@ -107,7 +118,7 @@ config AT91_ADC
config EXYNOS_ADC config EXYNOS_ADC
bool "Exynos ADC driver support" bool "Exynos ADC driver support"
depends on OF depends on ARCH_EXYNOS || (OF && COMPILE_TEST)
help help
Core support for the ADC block found in the Samsung EXYNOS series Core support for the ADC block found in the Samsung EXYNOS series
of SoCs for drivers such as the touchscreen and hwmon to use to share of SoCs for drivers such as the touchscreen and hwmon to use to share
...@@ -146,11 +157,12 @@ config MCP320X ...@@ -146,11 +157,12 @@ config MCP320X
called mcp320x. called mcp320x.
config MCP3422 config MCP3422
tristate "Microchip Technology MCP3422/3/4 driver" tristate "Microchip Technology MCP3422/3/4/6/7/8 driver"
depends on I2C depends on I2C
help help
Say yes here to build support for Microchip Technology's MCP3422, Say yes here to build support for Microchip Technology's
MCP3423 or MCP3424 analog to digital converters. MCP3422, MCP3423, MCP3424, MCP3426, MCP3427 or MCP3428
analog to digital converters.
This driver can also be built as a module. If so, the module will be This driver can also be built as a module. If so, the module will be
called mcp3422. called mcp3422.
......
...@@ -11,6 +11,7 @@ obj-$(CONFIG_AD7476) += ad7476.o ...@@ -11,6 +11,7 @@ obj-$(CONFIG_AD7476) += ad7476.o
obj-$(CONFIG_AD7791) += ad7791.o obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o obj-$(CONFIG_AD7793) += ad7793.o
obj-$(CONFIG_AD7887) += ad7887.o obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
......
...@@ -37,8 +37,144 @@ ...@@ -37,8 +37,144 @@
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/iio/events.h> #include <linux/iio/events.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include "ad799x.h" #define AD799X_CHANNEL_SHIFT 4
#define AD799X_STORAGEBITS 16
/*
* AD7991, AD7995 and AD7999 defines
*/
#define AD7991_REF_SEL 0x08
#define AD7991_FLTR 0x04
#define AD7991_BIT_TRIAL_DELAY 0x02
#define AD7991_SAMPLE_DELAY 0x01
/*
* AD7992, AD7993, AD7994, AD7997 and AD7998 defines
*/
#define AD7998_FLTR 0x08
#define AD7998_ALERT_EN 0x04
#define AD7998_BUSY_ALERT 0x02
#define AD7998_BUSY_ALERT_POL 0x01
#define AD7998_CONV_RES_REG 0x0
#define AD7998_ALERT_STAT_REG 0x1
#define AD7998_CONF_REG 0x2
#define AD7998_CYCLE_TMR_REG 0x3
#define AD7998_DATALOW_REG(x) ((x) * 3 + 0x4)
#define AD7998_DATAHIGH_REG(x) ((x) * 3 + 0x5)
#define AD7998_HYST_REG(x) ((x) * 3 + 0x6)
#define AD7998_CYC_MASK 0x7
#define AD7998_CYC_DIS 0x0
#define AD7998_CYC_TCONF_32 0x1
#define AD7998_CYC_TCONF_64 0x2
#define AD7998_CYC_TCONF_128 0x3
#define AD7998_CYC_TCONF_256 0x4
#define AD7998_CYC_TCONF_512 0x5
#define AD7998_CYC_TCONF_1024 0x6
#define AD7998_CYC_TCONF_2048 0x7
#define AD7998_ALERT_STAT_CLEAR 0xFF
/*
* AD7997 and AD7997 defines
*/
#define AD7997_8_READ_SINGLE 0x80
#define AD7997_8_READ_SEQUENCE 0x70
/* TODO: move this into a common header */
#define RES_MASK(bits) ((1 << (bits)) - 1)
enum {
ad7991,
ad7995,
ad7999,
ad7992,
ad7993,
ad7994,
ad7997,
ad7998
};
/**
* struct ad799x_chip_info - chip specific information
* @channel: channel specification
* @num_channels: number of channels
* @monitor_mode: whether the chip supports monitor interrupts
* @default_config: device default configuration
* @event_attrs: pointer to the monitor event attribute group
*/
struct ad799x_chip_info {
struct iio_chan_spec channel[9];
int num_channels;
u16 default_config;
const struct iio_info *info;
};
struct ad799x_state {
struct i2c_client *client;
const struct ad799x_chip_info *chip_info;
struct regulator *reg;
struct regulator *vref;
unsigned id;
u16 config;
u8 *rx_buf;
unsigned int transfer_size;
};
/**
* ad799x_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring.
**/
static irqreturn_t ad799x_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad799x_state *st = iio_priv(indio_dev);
int b_sent;
u8 cmd;
switch (st->id) {
case ad7991:
case ad7995:
case ad7999:
cmd = st->config |
(*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT);
break;
case ad7992:
case ad7993:
case ad7994:
cmd = (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT) |
AD7998_CONV_RES_REG;
break;
case ad7997:
case ad7998:
cmd = AD7997_8_READ_SEQUENCE | AD7998_CONV_RES_REG;
break;
default:
cmd = 0;
}
b_sent = i2c_smbus_read_i2c_block_data(st->client,
cmd, st->transfer_size, st->rx_buf);
if (b_sent < 0)
goto out;
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
iio_get_time_ns());
out:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
/* /*
* ad799x register access by I2C * ad799x register access by I2C
...@@ -578,7 +714,8 @@ static int ad799x_probe(struct i2c_client *client, ...@@ -578,7 +714,8 @@ static int ad799x_probe(struct i2c_client *client,
indio_dev->channels = st->chip_info->channel; indio_dev->channels = st->chip_info->channel;
indio_dev->num_channels = st->chip_info->num_channels; indio_dev->num_channels = st->chip_info->num_channels;
ret = ad799x_register_ring_funcs_and_init(indio_dev); ret = iio_triggered_buffer_setup(indio_dev, NULL,
&ad799x_trigger_handler, NULL);
if (ret) if (ret)
goto error_disable_reg; goto error_disable_reg;
...@@ -601,7 +738,7 @@ static int ad799x_probe(struct i2c_client *client, ...@@ -601,7 +738,7 @@ static int ad799x_probe(struct i2c_client *client,
return 0; return 0;
error_cleanup_ring: error_cleanup_ring:
ad799x_ring_cleanup(indio_dev); iio_triggered_buffer_cleanup(indio_dev);
error_disable_reg: error_disable_reg:
if (!IS_ERR(st->vref)) if (!IS_ERR(st->vref))
regulator_disable(st->vref); regulator_disable(st->vref);
...@@ -618,7 +755,7 @@ static int ad799x_remove(struct i2c_client *client) ...@@ -618,7 +755,7 @@ static int ad799x_remove(struct i2c_client *client)
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
ad799x_ring_cleanup(indio_dev); iio_triggered_buffer_cleanup(indio_dev);
if (!IS_ERR(st->vref)) if (!IS_ERR(st->vref))
regulator_disable(st->vref); regulator_disable(st->vref);
if (!IS_ERR(st->reg)) if (!IS_ERR(st->reg))
......
/* /*
* mcp3422.c - driver for the Microchip mcp3422/3/4 chip family * mcp3422.c - driver for the Microchip mcp3422/3/4/6/7/8 chip family
* *
* Copyright (C) 2013, Angelo Compagnucci * Copyright (C) 2013, Angelo Compagnucci
* Author: Angelo Compagnucci <angelo.compagnucci@gmail.com> * Author: Angelo Compagnucci <angelo.compagnucci@gmail.com>
* *
* Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf
* http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf
* *
* This driver exports the value of analog input voltage to sysfs, the * This driver exports the value of analog input voltage to sysfs, the
* voltage unit is nV. * voltage unit is nV.
...@@ -96,6 +97,7 @@ static const int mcp3422_sign_extend[4] = { ...@@ -96,6 +97,7 @@ static const int mcp3422_sign_extend[4] = {
/* Client data (each client gets its own) */ /* Client data (each client gets its own) */
struct mcp3422 { struct mcp3422 {
struct i2c_client *i2c; struct i2c_client *i2c;
u8 id;
u8 config; u8 config;
u8 pga[4]; u8 pga[4];
struct mutex lock; struct mutex lock;
...@@ -238,6 +240,8 @@ static int mcp3422_write_raw(struct iio_dev *iio, ...@@ -238,6 +240,8 @@ static int mcp3422_write_raw(struct iio_dev *iio,
temp = MCP3422_SRATE_15; temp = MCP3422_SRATE_15;
break; break;
case 3: case 3:
if (adc->id > 4)
return -EINVAL;
temp = MCP3422_SRATE_3; temp = MCP3422_SRATE_3;
break; break;
default: default:
...@@ -271,6 +275,17 @@ static int mcp3422_write_raw_get_fmt(struct iio_dev *indio_dev, ...@@ -271,6 +275,17 @@ static int mcp3422_write_raw_get_fmt(struct iio_dev *indio_dev,
} }
} }
static ssize_t mcp3422_show_samp_freqs(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct mcp3422 *adc = iio_priv(dev_to_iio_dev(dev));
if (adc->id > 4)
return sprintf(buf, "240 60 15\n");
return sprintf(buf, "240 60 15 3\n");
}
static ssize_t mcp3422_show_scales(struct device *dev, static ssize_t mcp3422_show_scales(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -284,12 +299,13 @@ static ssize_t mcp3422_show_scales(struct device *dev, ...@@ -284,12 +299,13 @@ static ssize_t mcp3422_show_scales(struct device *dev,
mcp3422_scales[sample_rate][3]); mcp3422_scales[sample_rate][3]);
} }
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("240 60 15 3"); static IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO,
mcp3422_show_samp_freqs, NULL, 0);
static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO, static IIO_DEVICE_ATTR(in_voltage_scale_available, S_IRUGO,
mcp3422_show_scales, NULL, 0); mcp3422_show_scales, NULL, 0);
static struct attribute *mcp3422_attributes[] = { static struct attribute *mcp3422_attributes[] = {
&iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
&iio_dev_attr_in_voltage_scale_available.dev_attr.attr, &iio_dev_attr_in_voltage_scale_available.dev_attr.attr,
NULL, NULL,
}; };
...@@ -335,6 +351,7 @@ static int mcp3422_probe(struct i2c_client *client, ...@@ -335,6 +351,7 @@ static int mcp3422_probe(struct i2c_client *client,
adc = iio_priv(indio_dev); adc = iio_priv(indio_dev);
adc->i2c = client; adc->i2c = client;
adc->id = (u8)(id->driver_data);
mutex_init(&adc->lock); mutex_init(&adc->lock);
...@@ -343,13 +360,16 @@ static int mcp3422_probe(struct i2c_client *client, ...@@ -343,13 +360,16 @@ static int mcp3422_probe(struct i2c_client *client,
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &mcp3422_info; indio_dev->info = &mcp3422_info;
switch ((unsigned int)(id->driver_data)) { switch (adc->id) {
case 2: case 2:
case 3: case 3:
case 6:
case 7:
indio_dev->channels = mcp3422_channels; indio_dev->channels = mcp3422_channels;
indio_dev->num_channels = ARRAY_SIZE(mcp3422_channels); indio_dev->num_channels = ARRAY_SIZE(mcp3422_channels);
break; break;
case 4: case 4:
case 8:
indio_dev->channels = mcp3424_channels; indio_dev->channels = mcp3424_channels;
indio_dev->num_channels = ARRAY_SIZE(mcp3424_channels); indio_dev->num_channels = ARRAY_SIZE(mcp3424_channels);
break; break;
...@@ -375,6 +395,9 @@ static const struct i2c_device_id mcp3422_id[] = { ...@@ -375,6 +395,9 @@ static const struct i2c_device_id mcp3422_id[] = {
{ "mcp3422", 2 }, { "mcp3422", 2 },
{ "mcp3423", 3 }, { "mcp3423", 3 },
{ "mcp3424", 4 }, { "mcp3424", 4 },
{ "mcp3426", 6 },
{ "mcp3427", 7 },
{ "mcp3428", 8 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, mcp3422_id); MODULE_DEVICE_TABLE(i2c, mcp3422_id);
...@@ -399,5 +422,5 @@ static struct i2c_driver mcp3422_driver = { ...@@ -399,5 +422,5 @@ static struct i2c_driver mcp3422_driver = {
module_i2c_driver(mcp3422_driver); module_i2c_driver(mcp3422_driver);
MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>"); MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>");
MODULE_DESCRIPTION("Microchip mcp3422/3/4 driver"); MODULE_DESCRIPTION("Microchip mcp3422/3/4/6/7/8 driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors.h>
...@@ -198,6 +199,42 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable) ...@@ -198,6 +199,42 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
} }
EXPORT_SYMBOL(st_sensors_set_axis_enable); EXPORT_SYMBOL(st_sensors_set_axis_enable);
void st_sensors_power_enable(struct iio_dev *indio_dev)
{
struct st_sensor_data *pdata = iio_priv(indio_dev);
int err;
/* Regulators not mandatory, but if requested we should enable them. */
pdata->vdd = devm_regulator_get_optional(indio_dev->dev.parent, "vdd");
if (!IS_ERR(pdata->vdd)) {
err = regulator_enable(pdata->vdd);
if (err != 0)
dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd supply\n");
}
pdata->vdd_io = devm_regulator_get_optional(indio_dev->dev.parent, "vddio");
if (!IS_ERR(pdata->vdd_io)) {
err = regulator_enable(pdata->vdd_io);
if (err != 0)
dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd_IO supply\n");
}
}
EXPORT_SYMBOL(st_sensors_power_enable);
void st_sensors_power_disable(struct iio_dev *indio_dev)
{
struct st_sensor_data *pdata = iio_priv(indio_dev);
if (!IS_ERR(pdata->vdd))
regulator_disable(pdata->vdd);
if (!IS_ERR(pdata->vdd_io))
regulator_disable(pdata->vdd_io);
}
EXPORT_SYMBOL(st_sensors_power_disable);
static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
struct st_sensors_platform_data *pdata) struct st_sensors_platform_data *pdata)
{ {
......
...@@ -110,8 +110,6 @@ static int itg3200_read_raw(struct iio_dev *indio_dev, ...@@ -110,8 +110,6 @@ static int itg3200_read_raw(struct iio_dev *indio_dev,
default: default:
return -EINVAL; return -EINVAL;
} }
return ret;
} }
static ssize_t itg3200_read_frequency(struct device *dev, static ssize_t itg3200_read_frequency(struct device *dev,
......
...@@ -311,6 +311,8 @@ int st_gyro_common_probe(struct iio_dev *indio_dev, ...@@ -311,6 +311,8 @@ int st_gyro_common_probe(struct iio_dev *indio_dev,
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &gyro_info; indio_dev->info = &gyro_info;
st_sensors_power_enable(indio_dev);
err = st_sensors_check_device_support(indio_dev, err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_gyro_sensors), st_gyro_sensors); ARRAY_SIZE(st_gyro_sensors), st_gyro_sensors);
if (err < 0) if (err < 0)
...@@ -344,6 +346,9 @@ int st_gyro_common_probe(struct iio_dev *indio_dev, ...@@ -344,6 +346,9 @@ int st_gyro_common_probe(struct iio_dev *indio_dev,
if (err) if (err)
goto st_gyro_device_register_error; goto st_gyro_device_register_error;
dev_info(&indio_dev->dev, "registered gyroscope %s\n",
indio_dev->name);
return 0; return 0;
st_gyro_device_register_error: st_gyro_device_register_error:
...@@ -360,6 +365,8 @@ void st_gyro_common_remove(struct iio_dev *indio_dev) ...@@ -360,6 +365,8 @@ void st_gyro_common_remove(struct iio_dev *indio_dev)
{ {
struct st_sensor_data *gdata = iio_priv(indio_dev); struct st_sensor_data *gdata = iio_priv(indio_dev);
st_sensors_power_disable(indio_dev);
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
if (gdata->get_irq_data_ready(indio_dev) > 0) if (gdata->get_irq_data_ready(indio_dev) > 0)
st_sensors_deallocate_trigger(indio_dev); st_sensors_deallocate_trigger(indio_dev);
......
...@@ -9,6 +9,8 @@ config INV_MPU6050_IIO ...@@ -9,6 +9,8 @@ config INV_MPU6050_IIO
select IIO_TRIGGERED_BUFFER select IIO_TRIGGERED_BUFFER
help help
This driver supports the Invensense MPU6050 devices. This driver supports the Invensense MPU6050 devices.
This driver can also support MPU6500 in MPU6050 compatibility mode
and also in MPU6500 mode with some limitations.
It is a gyroscope/accelerometer combo device. It is a gyroscope/accelerometer combo device.
This driver can be built as a module. The module will be called This driver can be built as a module. The module will be called
inv-mpu6050. inv-mpu6050.
...@@ -764,6 +764,7 @@ static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume); ...@@ -764,6 +764,7 @@ static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume);
*/ */
static const struct i2c_device_id inv_mpu_id[] = { static const struct i2c_device_id inv_mpu_id[] = {
{"mpu6050", INV_MPU6050}, {"mpu6050", INV_MPU6050},
{"mpu6500", INV_MPU6500},
{} {}
}; };
......
...@@ -59,6 +59,7 @@ struct inv_mpu6050_reg_map { ...@@ -59,6 +59,7 @@ struct inv_mpu6050_reg_map {
/*device enum */ /*device enum */
enum inv_devices { enum inv_devices {
INV_MPU6050, INV_MPU6050,
INV_MPU6500,
INV_NUM_PARTS INV_NUM_PARTS
}; };
......
...@@ -340,7 +340,7 @@ ssize_t iio_enum_read(struct iio_dev *indio_dev, ...@@ -340,7 +340,7 @@ ssize_t iio_enum_read(struct iio_dev *indio_dev,
else if (i >= e->num_items) else if (i >= e->num_items)
return -EINVAL; return -EINVAL;
return sprintf(buf, "%s\n", e->items[i]); return snprintf(buf, PAGE_SIZE, "%s\n", e->items[i]);
} }
EXPORT_SYMBOL_GPL(iio_enum_read); EXPORT_SYMBOL_GPL(iio_enum_read);
...@@ -716,6 +716,8 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev, ...@@ -716,6 +716,8 @@ static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
int i, ret, attrcount = 0; int i, ret, attrcount = 0;
for_each_set_bit(i, infomask, sizeof(infomask)*8) { for_each_set_bit(i, infomask, sizeof(infomask)*8) {
if (i >= ARRAY_SIZE(iio_chan_info_postfix))
return -EINVAL;
ret = __iio_add_chan_devattr(iio_chan_info_postfix[i], ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
chan, chan,
&iio_read_channel_info, &iio_read_channel_info,
...@@ -820,7 +822,7 @@ static ssize_t iio_show_dev_name(struct device *dev, ...@@ -820,7 +822,7 @@ static ssize_t iio_show_dev_name(struct device *dev,
char *buf) char *buf)
{ {
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
return sprintf(buf, "%s\n", indio_dev->name); return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->name);
} }
static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
......
...@@ -321,7 +321,9 @@ static int iio_device_add_event(struct iio_dev *indio_dev, ...@@ -321,7 +321,9 @@ static int iio_device_add_event(struct iio_dev *indio_dev,
char *postfix; char *postfix;
int ret; int ret;
for_each_set_bit(i, mask, sizeof(*mask)) { for_each_set_bit(i, mask, sizeof(*mask)*8) {
if (i >= ARRAY_SIZE(iio_ev_info_text))
return -EINVAL;
postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_ev_type_text[type], iio_ev_dir_text[dir], iio_ev_type_text[type], iio_ev_dir_text[dir],
iio_ev_info_text[i]); iio_ev_info_text[i]);
......
...@@ -443,6 +443,24 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val) ...@@ -443,6 +443,24 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val)
} }
EXPORT_SYMBOL_GPL(iio_read_channel_raw); EXPORT_SYMBOL_GPL(iio_read_channel_raw);
int iio_read_channel_average_raw(struct iio_channel *chan, int *val)
{
int ret;
mutex_lock(&chan->indio_dev->info_exist_lock);
if (chan->indio_dev->info == NULL) {
ret = -ENODEV;
goto err_unlock;
}
ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_AVERAGE_RAW);
err_unlock:
mutex_unlock(&chan->indio_dev->info_exist_lock);
return ret;
}
EXPORT_SYMBOL_GPL(iio_read_channel_average_raw);
static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan, static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
int raw, int *processed, unsigned int scale) int raw, int *processed, unsigned int scale)
{ {
......
...@@ -11,7 +11,8 @@ config AK8975 ...@@ -11,7 +11,8 @@ config AK8975
depends on GPIOLIB depends on GPIOLIB
help help
Say yes here to build support for Asahi Kasei AK8975 3-Axis Say yes here to build support for Asahi Kasei AK8975 3-Axis
Magnetometer. Magnetometer. This driver can also support AK8963, if i2c
device name is identified as ak8963.
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called ak8975. will be called ak8975.
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
...@@ -85,7 +86,14 @@ ...@@ -85,7 +86,14 @@
#define AK8975_MAX_CONVERSION_TIMEOUT 500 #define AK8975_MAX_CONVERSION_TIMEOUT 500
#define AK8975_CONVERSION_DONE_POLL_TIME 10 #define AK8975_CONVERSION_DONE_POLL_TIME 10
#define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000) #define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000)
#define RAW_TO_GAUSS(asa) ((((asa) + 128) * 3000) / 256) #define RAW_TO_GAUSS_8975(asa) ((((asa) + 128) * 3000) / 256)
#define RAW_TO_GAUSS_8963(asa) ((((asa) + 128) * 6000) / 256)
/* Compatible Asahi Kasei Compass parts */
enum asahi_compass_chipset {
AK8975,
AK8963,
};
/* /*
* Per-instance context data for the device. * Per-instance context data for the device.
...@@ -101,6 +109,7 @@ struct ak8975_data { ...@@ -101,6 +109,7 @@ struct ak8975_data {
int eoc_irq; int eoc_irq;
wait_queue_head_t data_ready_queue; wait_queue_head_t data_ready_queue;
unsigned long flags; unsigned long flags;
enum asahi_compass_chipset chipset;
}; };
static const int ak8975_index_to_reg[] = { static const int ak8975_index_to_reg[] = {
...@@ -272,9 +281,21 @@ static int ak8975_setup(struct i2c_client *client) ...@@ -272,9 +281,21 @@ static int ak8975_setup(struct i2c_client *client)
* Since ASA doesn't change, we cache the resultant scale factor into the * Since ASA doesn't change, we cache the resultant scale factor into the
* device context in ak8975_setup(). * device context in ak8975_setup().
*/ */
data->raw_to_gauss[0] = RAW_TO_GAUSS(data->asa[0]); if (data->chipset == AK8963) {
data->raw_to_gauss[1] = RAW_TO_GAUSS(data->asa[1]); /*
data->raw_to_gauss[2] = RAW_TO_GAUSS(data->asa[2]); * H range is +-8190 and magnetometer range is +-4912.
* So HuT using the above explanation for 8975,
* 4912/8190 = ~ 6/10.
* So the Hadj should use 6/10 instead of 3/10.
*/
data->raw_to_gauss[0] = RAW_TO_GAUSS_8963(data->asa[0]);
data->raw_to_gauss[1] = RAW_TO_GAUSS_8963(data->asa[1]);
data->raw_to_gauss[2] = RAW_TO_GAUSS_8963(data->asa[2]);
} else {
data->raw_to_gauss[0] = RAW_TO_GAUSS_8975(data->asa[0]);
data->raw_to_gauss[1] = RAW_TO_GAUSS_8975(data->asa[1]);
data->raw_to_gauss[2] = RAW_TO_GAUSS_8975(data->asa[2]);
}
return 0; return 0;
} }
...@@ -455,6 +476,27 @@ static const struct iio_info ak8975_info = { ...@@ -455,6 +476,27 @@ static const struct iio_info ak8975_info = {
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
static const struct acpi_device_id ak_acpi_match[] = {
{"AK8975", AK8975},
{"AK8963", AK8963},
{"INVN6500", AK8963},
{ },
};
MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
static char *ak8975_match_acpi_device(struct device *dev,
enum asahi_compass_chipset *chipset)
{
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;
return (char *)dev_name(dev);
}
static int ak8975_probe(struct i2c_client *client, static int ak8975_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -462,6 +504,7 @@ static int ak8975_probe(struct i2c_client *client, ...@@ -462,6 +504,7 @@ static int ak8975_probe(struct i2c_client *client,
struct iio_dev *indio_dev; struct iio_dev *indio_dev;
int eoc_gpio; int eoc_gpio;
int err; int err;
char *name = NULL;
/* Grab and set up the supplied GPIO. */ /* Grab and set up the supplied GPIO. */
if (client->dev.platform_data) if (client->dev.platform_data)
...@@ -499,6 +542,19 @@ static int ak8975_probe(struct i2c_client *client, ...@@ -499,6 +542,19 @@ static int ak8975_probe(struct i2c_client *client,
data->eoc_gpio = eoc_gpio; data->eoc_gpio = eoc_gpio;
data->eoc_irq = 0; data->eoc_irq = 0;
/* id will be NULL when enumerated via ACPI */
if (id) {
data->chipset =
(enum asahi_compass_chipset)(id->driver_data);
name = (char *) id->name;
} else if (ACPI_HANDLE(&client->dev))
name = ak8975_match_acpi_device(&client->dev, &data->chipset);
else {
err = -ENOSYS;
goto exit_free_iio;
}
dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
/* Perform some basic start-of-day setup of the device. */ /* Perform some basic start-of-day setup of the device. */
err = ak8975_setup(client); err = ak8975_setup(client);
if (err < 0) { if (err < 0) {
...@@ -515,7 +571,7 @@ static int ak8975_probe(struct i2c_client *client, ...@@ -515,7 +571,7 @@ static int ak8975_probe(struct i2c_client *client,
indio_dev->info = &ak8975_info; indio_dev->info = &ak8975_info;
indio_dev->name = id->name; indio_dev->name = id->name;
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->name = name;
err = iio_device_register(indio_dev); err = iio_device_register(indio_dev);
if (err < 0) if (err < 0)
goto exit_free_iio; goto exit_free_iio;
...@@ -552,7 +608,8 @@ static int ak8975_remove(struct i2c_client *client) ...@@ -552,7 +608,8 @@ static int ak8975_remove(struct i2c_client *client)
} }
static const struct i2c_device_id ak8975_id[] = { static const struct i2c_device_id ak8975_id[] = {
{"ak8975", 0}, {"ak8975", AK8975},
{"ak8963", AK8963},
{} {}
}; };
...@@ -569,6 +626,7 @@ static struct i2c_driver ak8975_driver = { ...@@ -569,6 +626,7 @@ static struct i2c_driver ak8975_driver = {
.driver = { .driver = {
.name = "ak8975", .name = "ak8975",
.of_match_table = ak8975_of_match, .of_match_table = ak8975_of_match,
.acpi_match_table = ACPI_PTR(ak_acpi_match),
}, },
.probe = ak8975_probe, .probe = ak8975_probe,
.remove = ak8975_remove, .remove = ak8975_remove,
......
...@@ -355,6 +355,8 @@ int st_magn_common_probe(struct iio_dev *indio_dev, ...@@ -355,6 +355,8 @@ int st_magn_common_probe(struct iio_dev *indio_dev,
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &magn_info; indio_dev->info = &magn_info;
st_sensors_power_enable(indio_dev);
err = st_sensors_check_device_support(indio_dev, err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_magn_sensors), st_magn_sensors); ARRAY_SIZE(st_magn_sensors), st_magn_sensors);
if (err < 0) if (err < 0)
...@@ -387,6 +389,9 @@ int st_magn_common_probe(struct iio_dev *indio_dev, ...@@ -387,6 +389,9 @@ int st_magn_common_probe(struct iio_dev *indio_dev,
if (err) if (err)
goto st_magn_device_register_error; goto st_magn_device_register_error;
dev_info(&indio_dev->dev, "registered magnetometer %s\n",
indio_dev->name);
return 0; return 0;
st_magn_device_register_error: st_magn_device_register_error:
...@@ -403,6 +408,8 @@ void st_magn_common_remove(struct iio_dev *indio_dev) ...@@ -403,6 +408,8 @@ void st_magn_common_remove(struct iio_dev *indio_dev)
{ {
struct st_sensor_data *mdata = iio_priv(indio_dev); struct st_sensor_data *mdata = iio_priv(indio_dev);
st_sensors_power_disable(indio_dev);
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
if (mdata->get_irq_data_ready(indio_dev) > 0) if (mdata->get_irq_data_ready(indio_dev) > 0)
st_sensors_deallocate_trigger(indio_dev); st_sensors_deallocate_trigger(indio_dev);
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h> #include <linux/iio/trigger.h>
#include <linux/iio/buffer.h> #include <linux/iio/buffer.h>
#include <linux/regulator/consumer.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <linux/iio/common/st_sensors.h> #include <linux/iio/common/st_sensors.h>
...@@ -387,40 +386,6 @@ static const struct iio_trigger_ops st_press_trigger_ops = { ...@@ -387,40 +386,6 @@ static const struct iio_trigger_ops st_press_trigger_ops = {
#define ST_PRESS_TRIGGER_OPS NULL #define ST_PRESS_TRIGGER_OPS NULL
#endif #endif
static void st_press_power_enable(struct iio_dev *indio_dev)
{
struct st_sensor_data *pdata = iio_priv(indio_dev);
int err;
/* Regulators not mandatory, but if requested we should enable them. */
pdata->vdd = devm_regulator_get_optional(&indio_dev->dev, "vdd");
if (!IS_ERR(pdata->vdd)) {
err = regulator_enable(pdata->vdd);
if (err != 0)
dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd supply\n");
}
pdata->vdd_io = devm_regulator_get_optional(&indio_dev->dev, "vddio");
if (!IS_ERR(pdata->vdd_io)) {
err = regulator_enable(pdata->vdd_io);
if (err != 0)
dev_warn(&indio_dev->dev,
"Failed to enable specified Vdd_IO supply\n");
}
}
static void st_press_power_disable(struct iio_dev *indio_dev)
{
struct st_sensor_data *pdata = iio_priv(indio_dev);
if (!IS_ERR(pdata->vdd))
regulator_disable(pdata->vdd);
if (!IS_ERR(pdata->vdd_io))
regulator_disable(pdata->vdd_io);
}
int st_press_common_probe(struct iio_dev *indio_dev, int st_press_common_probe(struct iio_dev *indio_dev,
struct st_sensors_platform_data *plat_data) struct st_sensors_platform_data *plat_data)
{ {
...@@ -431,7 +396,7 @@ int st_press_common_probe(struct iio_dev *indio_dev, ...@@ -431,7 +396,7 @@ int st_press_common_probe(struct iio_dev *indio_dev,
indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &press_info; indio_dev->info = &press_info;
st_press_power_enable(indio_dev); st_sensors_power_enable(indio_dev);
err = st_sensors_check_device_support(indio_dev, err = st_sensors_check_device_support(indio_dev,
ARRAY_SIZE(st_press_sensors), ARRAY_SIZE(st_press_sensors),
...@@ -474,6 +439,9 @@ int st_press_common_probe(struct iio_dev *indio_dev, ...@@ -474,6 +439,9 @@ int st_press_common_probe(struct iio_dev *indio_dev,
if (err) if (err)
goto st_press_device_register_error; goto st_press_device_register_error;
dev_info(&indio_dev->dev, "registered pressure sensor %s\n",
indio_dev->name);
return err; return err;
st_press_device_register_error: st_press_device_register_error:
...@@ -490,7 +458,7 @@ void st_press_common_remove(struct iio_dev *indio_dev) ...@@ -490,7 +458,7 @@ void st_press_common_remove(struct iio_dev *indio_dev)
{ {
struct st_sensor_data *pdata = iio_priv(indio_dev); struct st_sensor_data *pdata = iio_priv(indio_dev);
st_press_power_disable(indio_dev); st_sensors_power_disable(indio_dev);
iio_device_unregister(indio_dev); iio_device_unregister(indio_dev);
if (pdata->get_irq_data_ready(indio_dev) > 0) if (pdata->get_irq_data_ready(indio_dev) > 0)
......
#
# Proximity sensors
#
menu "Lightning sensors"
config AS3935
tristate "AS3935 Franklin lightning sensor"
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
depends on SPI
help
Say Y here to build SPI interface support for the Austrian
Microsystems AS3935 lightning detection sensor.
To compile this driver as a module, choose M here: the
module will be called as3935
endmenu
#
# Makefile for IIO proximity sensors
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AS3935) += as3935.o
/*
* as3935.c - Support for AS3935 Franklin lightning sensor
*
* Copyright (C) 2014 Matt Ranostay <mranostay@gmail.com>
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/of_gpio.h>
#define AS3935_AFE_GAIN 0x00
#define AS3935_AFE_MASK 0x3F
#define AS3935_AFE_GAIN_MAX 0x1F
#define AS3935_AFE_PWR_BIT BIT(0)
#define AS3935_INT 0x03
#define AS3935_INT_MASK 0x07
#define AS3935_EVENT_INT BIT(3)
#define AS3935_NOISE_INT BIT(1)
#define AS3935_DATA 0x07
#define AS3935_DATA_MASK 0x3F
#define AS3935_TUNE_CAP 0x08
#define AS3935_CALIBRATE 0x3D
#define AS3935_WRITE_DATA BIT(15)
#define AS3935_READ_DATA BIT(14)
#define AS3935_ADDRESS(x) ((x) << 8)
#define MAX_PF_CAP 120
#define TUNE_CAP_DIV 8
struct as3935_state {
struct spi_device *spi;
struct iio_trigger *trig;
struct mutex lock;
struct delayed_work work;
u32 tune_cap;
u8 buf[2] ____cacheline_aligned;
};
static const struct iio_chan_spec as3935_channels[] = {
{
.type = IIO_PROXIMITY,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_PROCESSED),
.scan_index = 0,
.scan_type = {
.sign = 'u',
.realbits = 6,
.storagebits = 8,
},
},
IIO_CHAN_SOFT_TIMESTAMP(1),
};
static int as3935_read(struct as3935_state *st, unsigned int reg, int *val)
{
u8 cmd;
int ret;
cmd = (AS3935_READ_DATA | AS3935_ADDRESS(reg)) >> 8;
ret = spi_w8r8(st->spi, cmd);
if (ret < 0)
return ret;
*val = ret;
return 0;
};
static int as3935_write(struct as3935_state *st,
unsigned int reg,
unsigned int val)
{
u8 *buf = st->buf;
buf[0] = (AS3935_WRITE_DATA | AS3935_ADDRESS(reg)) >> 8;
buf[1] = val;
return spi_write(st->spi, buf, 2);
};
static ssize_t as3935_sensor_sensitivity_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct as3935_state *st = iio_priv(dev_to_iio_dev(dev));
int val, ret;
ret = as3935_read(st, AS3935_AFE_GAIN, &val);
if (ret)
return ret;
val = (val & AS3935_AFE_MASK) >> 1;
return sprintf(buf, "%d\n", val);
};
static ssize_t as3935_sensor_sensitivity_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
struct as3935_state *st = iio_priv(dev_to_iio_dev(dev));
unsigned long val;
int ret;
ret = kstrtoul((const char *) buf, 10, &val);
if (ret)
return -EINVAL;
if (val > AS3935_AFE_GAIN_MAX)
return -EINVAL;
as3935_write(st, AS3935_AFE_GAIN, val << 1);
return len;
};
static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR,
as3935_sensor_sensitivity_show, as3935_sensor_sensitivity_store, 0);
static struct attribute *as3935_attributes[] = {
&iio_dev_attr_sensor_sensitivity.dev_attr.attr,
NULL,
};
static struct attribute_group as3935_attribute_group = {
.attrs = as3935_attributes,
};
static int as3935_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long m)
{
struct as3935_state *st = iio_priv(indio_dev);
int ret;
switch (m) {
case IIO_CHAN_INFO_PROCESSED:
case IIO_CHAN_INFO_RAW:
*val2 = 0;
ret = as3935_read(st, AS3935_DATA, val);
if (ret)
return ret;
if (m == IIO_CHAN_INFO_RAW)
return IIO_VAL_INT;
/* storm out of range */
if (*val == AS3935_DATA_MASK)
return -EINVAL;
*val *= 1000;
break;
default:
return -EINVAL;
}
return IIO_VAL_INT;
}
static const struct iio_info as3935_info = {
.driver_module = THIS_MODULE,
.attrs = &as3935_attribute_group,
.read_raw = &as3935_read_raw,
};
static irqreturn_t as3935_trigger_handler(int irq, void *private)
{
struct iio_poll_func *pf = private;
struct iio_dev *indio_dev = pf->indio_dev;
struct as3935_state *st = iio_priv(indio_dev);
int val, ret;
ret = as3935_read(st, AS3935_DATA, &val);
if (ret)
goto err_read;
val &= AS3935_DATA_MASK;
val *= 1000;
iio_push_to_buffers_with_timestamp(indio_dev, &val, pf->timestamp);
err_read:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
};
static const struct iio_trigger_ops iio_interrupt_trigger_ops = {
.owner = THIS_MODULE,
};
static void as3935_event_work(struct work_struct *work)
{
struct as3935_state *st;
int val;
st = container_of(work, struct as3935_state, work.work);
as3935_read(st, AS3935_INT, &val);
val &= AS3935_INT_MASK;
switch (val) {
case AS3935_EVENT_INT:
iio_trigger_poll(st->trig, iio_get_time_ns());
break;
case AS3935_NOISE_INT:
dev_warn(&st->spi->dev, "noise level is too high");
break;
}
};
static irqreturn_t as3935_interrupt_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct as3935_state *st = iio_priv(indio_dev);
/*
* Delay work for >2 milliseconds after an interrupt to allow
* estimated distance to recalculated.
*/
schedule_delayed_work(&st->work, msecs_to_jiffies(3));
return IRQ_HANDLED;
}
static void calibrate_as3935(struct as3935_state *st)
{
mutex_lock(&st->lock);
/* mask disturber interrupt bit */
as3935_write(st, AS3935_INT, BIT(5));
as3935_write(st, AS3935_CALIBRATE, 0x96);
as3935_write(st, AS3935_TUNE_CAP,
BIT(5) | (st->tune_cap / TUNE_CAP_DIV));
mdelay(2);
as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV));
mutex_unlock(&st->lock);
}
#ifdef CONFIG_PM_SLEEP
static int as3935_suspend(struct spi_device *spi, pm_message_t msg)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct as3935_state *st = iio_priv(indio_dev);
int val, ret;
mutex_lock(&st->lock);
ret = as3935_read(st, AS3935_AFE_GAIN, &val);
if (ret)
goto err_suspend;
val |= AS3935_AFE_PWR_BIT;
ret = as3935_write(st, AS3935_AFE_GAIN, val);
err_suspend:
mutex_unlock(&st->lock);
return ret;
}
static int as3935_resume(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct as3935_state *st = iio_priv(indio_dev);
int val, ret;
mutex_lock(&st->lock);
ret = as3935_read(st, AS3935_AFE_GAIN, &val);
if (ret)
goto err_resume;
val &= ~AS3935_AFE_PWR_BIT;
ret = as3935_write(st, AS3935_AFE_GAIN, val);
err_resume:
mutex_unlock(&st->lock);
return ret;
}
#else
#define as3935_suspend NULL
#define as3935_resume NULL
#endif
static int as3935_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct iio_trigger *trig;
struct as3935_state *st;
struct device_node *np = spi->dev.of_node;
int ret;
/* Be sure lightning event interrupt is specified */
if (!spi->irq) {
dev_err(&spi->dev, "unable to get event interrupt\n");
return -EINVAL;
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
st->spi = spi;
st->tune_cap = 0;
spi_set_drvdata(spi, indio_dev);
mutex_init(&st->lock);
INIT_DELAYED_WORK(&st->work, as3935_event_work);
ret = of_property_read_u32(np,
"ams,tuning-capacitor-pf", &st->tune_cap);
if (ret) {
st->tune_cap = 0;
dev_warn(&spi->dev,
"no tuning-capacitor-pf set, defaulting to %d",
st->tune_cap);
}
if (st->tune_cap > MAX_PF_CAP) {
dev_err(&spi->dev,
"wrong tuning-capacitor-pf setting of %d\n",
st->tune_cap);
return -EINVAL;
}
indio_dev->dev.parent = &spi->dev;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->channels = as3935_channels;
indio_dev->num_channels = ARRAY_SIZE(as3935_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &as3935_info;
trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
indio_dev->name, indio_dev->id);
if (!trig)
return -ENOMEM;
st->trig = trig;
trig->dev.parent = indio_dev->dev.parent;
iio_trigger_set_drvdata(trig, indio_dev);
trig->ops = &iio_interrupt_trigger_ops;
ret = iio_trigger_register(trig);
if (ret) {
dev_err(&spi->dev, "failed to register trigger\n");
return ret;
}
ret = iio_triggered_buffer_setup(indio_dev, NULL,
&as3935_trigger_handler, NULL);
if (ret) {
dev_err(&spi->dev, "cannot setup iio trigger\n");
goto unregister_trigger;
}
calibrate_as3935(st);
ret = devm_request_irq(&spi->dev, spi->irq,
&as3935_interrupt_handler,
IRQF_TRIGGER_RISING,
dev_name(&spi->dev),
indio_dev);
if (ret) {
dev_err(&spi->dev, "unable to request irq\n");
goto unregister_buffer;
}
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&spi->dev, "unable to register device\n");
goto unregister_buffer;
}
return 0;
unregister_buffer:
iio_triggered_buffer_cleanup(indio_dev);
unregister_trigger:
iio_trigger_unregister(st->trig);
return ret;
};
static int as3935_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
struct as3935_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
iio_trigger_unregister(st->trig);
return 0;
};
static const struct spi_device_id as3935_id[] = {
{"as3935", 0},
{},
};
MODULE_DEVICE_TABLE(spi, as3935_id);
static struct spi_driver as3935_driver = {
.driver = {
.name = "as3935",
.owner = THIS_MODULE,
},
.probe = as3935_probe,
.remove = as3935_remove,
.id_table = as3935_id,
.suspend = as3935_suspend,
.resume = as3935_resume,
};
module_spi_driver(as3935_driver);
MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
MODULE_DESCRIPTION("AS3935 lightning sensor");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:as3935");
...@@ -37,26 +37,6 @@ config AD7606_IFACE_SPI ...@@ -37,26 +37,6 @@ config AD7606_IFACE_SPI
Say yes here to include parallel interface support on the AD7606 Say yes here to include parallel interface support on the AD7606
ADC driver. ADC driver.
config AD799X
tristate "Analog Devices AD799x ADC driver"
depends on I2C
select IIO_TRIGGER if IIO_BUFFER
select AD799X_RING_BUFFER
help
Say yes here to build support for Analog Devices:
ad7991, ad7995, ad7999, ad7992, ad7993, ad7994, ad7997, ad7998
i2c analog to digital converters (ADC). Provides direct access
via sysfs.
config AD799X_RING_BUFFER
bool "Analog Devices AD799x: use ring buffer"
depends on AD799X
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to include ring buffer support in the AD799X
ADC driver.
config AD7780 config AD7780
tristate "Analog Devices AD7780 and similar ADCs driver" tristate "Analog Devices AD7780 and similar ADCs driver"
depends on SPI depends on SPI
......
...@@ -8,10 +8,6 @@ ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o ...@@ -8,10 +8,6 @@ ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
obj-$(CONFIG_AD7606) += ad7606.o obj-$(CONFIG_AD7606) += ad7606.o
ad799x-y := ad799x_core.o
ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AD7291) += ad7291.o obj-$(CONFIG_AD7291) += ad7291.o
obj-$(CONFIG_AD7780) += ad7780.o obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7816) += ad7816.o obj-$(CONFIG_AD7816) += ad7816.o
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
*/ */
/** /**
* struct ad7606_platform_data - platform/board specifc information * struct ad7606_platform_data - platform/board specific information
* @default_os: default oversampling value {0, 2, 4, 8, 16, 32, 64} * @default_os: default oversampling value {0, 2, 4, 8, 16, 32, 64}
* @default_range: default range +/-{5000, 10000} mVolt * @default_range: default range +/-{5000, 10000} mVolt
* @gpio_convst: number of gpio connected to the CONVST pin * @gpio_convst: number of gpio connected to the CONVST pin
...@@ -41,7 +41,7 @@ struct ad7606_platform_data { ...@@ -41,7 +41,7 @@ struct ad7606_platform_data {
}; };
/** /**
* struct ad7606_chip_info - chip specifc information * struct ad7606_chip_info - chip specific information
* @name: identification string for chip * @name: identification string for chip
* @int_vref_mv: the internal reference voltage * @int_vref_mv: the internal reference voltage
* @channels: channel specification * @channels: channel specification
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
/* /*
* struct ad7816_chip_info - chip specifc information * struct ad7816_chip_info - chip specific information
*/ */
struct ad7816_chip_info { struct ad7816_chip_info {
......
/*
* Copyright (C) 2010-2011 Michael Hennerich, Analog Devices Inc.
* Copyright (C) 2008-2010 Jonathan Cameron
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* ad799x.h
*/
#ifndef _AD799X_H_
#define _AD799X_H_
#define AD799X_CHANNEL_SHIFT 4
#define AD799X_STORAGEBITS 16
/*
* AD7991, AD7995 and AD7999 defines
*/
#define AD7991_REF_SEL 0x08
#define AD7991_FLTR 0x04
#define AD7991_BIT_TRIAL_DELAY 0x02
#define AD7991_SAMPLE_DELAY 0x01
/*
* AD7992, AD7993, AD7994, AD7997 and AD7998 defines
*/
#define AD7998_FLTR 0x08
#define AD7998_ALERT_EN 0x04
#define AD7998_BUSY_ALERT 0x02
#define AD7998_BUSY_ALERT_POL 0x01
#define AD7998_CONV_RES_REG 0x0
#define AD7998_ALERT_STAT_REG 0x1
#define AD7998_CONF_REG 0x2
#define AD7998_CYCLE_TMR_REG 0x3
#define AD7998_DATALOW_REG(x) ((x) * 3 + 0x4)
#define AD7998_DATAHIGH_REG(x) ((x) * 3 + 0x5)
#define AD7998_HYST_REG(x) ((x) * 3 + 0x6)
#define AD7998_CYC_MASK 0x7
#define AD7998_CYC_DIS 0x0
#define AD7998_CYC_TCONF_32 0x1
#define AD7998_CYC_TCONF_64 0x2
#define AD7998_CYC_TCONF_128 0x3
#define AD7998_CYC_TCONF_256 0x4
#define AD7998_CYC_TCONF_512 0x5
#define AD7998_CYC_TCONF_1024 0x6
#define AD7998_CYC_TCONF_2048 0x7
#define AD7998_ALERT_STAT_CLEAR 0xFF
/*
* AD7997 and AD7997 defines
*/
#define AD7997_8_READ_SINGLE 0x80
#define AD7997_8_READ_SEQUENCE 0x70
/* TODO: move this into a common header */
#define RES_MASK(bits) ((1 << (bits)) - 1)
enum {
ad7991,
ad7995,
ad7999,
ad7992,
ad7993,
ad7994,
ad7997,
ad7998
};
struct ad799x_state;
/**
* struct ad799x_chip_info - chip specifc information
* @channel: channel specification
* @num_channels: number of channels
* @monitor_mode: whether the chip supports monitor interrupts
* @default_config: device default configuration
* @event_attrs: pointer to the monitor event attribute group
*/
struct ad799x_chip_info {
struct iio_chan_spec channel[9];
int num_channels;
u16 default_config;
const struct iio_info *info;
};
struct ad799x_state {
struct i2c_client *client;
const struct ad799x_chip_info *chip_info;
struct regulator *reg;
struct regulator *vref;
unsigned id;
u16 config;
u8 *rx_buf;
unsigned int transfer_size;
};
#ifdef CONFIG_AD799X_RING_BUFFER
int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void ad799x_ring_cleanup(struct iio_dev *indio_dev);
#else /* CONFIG_AD799X_RING_BUFFER */
static inline int
ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
return 0;
}
static inline void ad799x_ring_cleanup(struct iio_dev *indio_dev)
{
}
#endif /* CONFIG_AD799X_RING_BUFFER */
#endif /* _AD799X_H_ */
/*
* Copyright (C) 2010-2012 Michael Hennerich, Analog Devices Inc.
* Copyright (C) 2008-2010 Jonathan Cameron
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* ad799x_ring.c
*/
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/i2c.h>
#include <linux/bitops.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include "ad799x.h"
/**
* ad799x_trigger_handler() bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring.
**/
static irqreturn_t ad799x_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct ad799x_state *st = iio_priv(indio_dev);
int b_sent;
u8 cmd;
switch (st->id) {
case ad7991:
case ad7995:
case ad7999:
cmd = st->config |
(*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT);
break;
case ad7992:
case ad7993:
case ad7994:
cmd = (*indio_dev->active_scan_mask << AD799X_CHANNEL_SHIFT) |
AD7998_CONV_RES_REG;
break;
case ad7997:
case ad7998:
cmd = AD7997_8_READ_SEQUENCE | AD7998_CONV_RES_REG;
break;
default:
cmd = 0;
}
b_sent = i2c_smbus_read_i2c_block_data(st->client,
cmd, st->transfer_size, st->rx_buf);
if (b_sent < 0)
goto out;
iio_push_to_buffers_with_timestamp(indio_dev, st->rx_buf,
iio_get_time_ns());
out:
iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
{
return iio_triggered_buffer_setup(indio_dev, NULL,
&ad799x_trigger_handler, NULL);
}
void ad799x_ring_cleanup(struct iio_dev *indio_dev)
{
iio_triggered_buffer_cleanup(indio_dev);
}
...@@ -22,39 +22,36 @@ ...@@ -22,39 +22,36 @@
#include <linux/iio/iio.h> #include <linux/iio/iio.h>
#include <linux/iio/sysfs.h> #include <linux/iio/sysfs.h>
/* /* SPEAR registers definitions */
* SPEAR registers definitions #define SPEAR600_ADC_SCAN_RATE_LO(x) ((x) & 0xFFFF)
*/ #define SPEAR600_ADC_SCAN_RATE_HI(x) (((x) >> 0x10) & 0xFFFF)
#define SPEAR_ADC_CLK_LOW(x) (((x) & 0xf) << 0)
#define SCAN_RATE_LO(x) ((x) & 0xFFFF) #define SPEAR_ADC_CLK_HIGH(x) (((x) & 0xf) << 4)
#define SCAN_RATE_HI(x) (((x) >> 0x10) & 0xFFFF)
#define CLK_LOW(x) (((x) & 0xf) << 0)
#define CLK_HIGH(x) (((x) & 0xf) << 4)
/* Bit definitions for SPEAR_ADC_STATUS */ /* Bit definitions for SPEAR_ADC_STATUS */
#define START_CONVERSION (1 << 0) #define SPEAR_ADC_STATUS_START_CONVERSION (1 << 0)
#define CHANNEL_NUM(x) ((x) << 1) #define SPEAR_ADC_STATUS_CHANNEL_NUM(x) ((x) << 1)
#define ADC_ENABLE (1 << 4) #define SPEAR_ADC_STATUS_ADC_ENABLE (1 << 4)
#define AVG_SAMPLE(x) ((x) << 5) #define SPEAR_ADC_STATUS_AVG_SAMPLE(x) ((x) << 5)
#define VREF_INTERNAL (1 << 9) #define SPEAR_ADC_STATUS_VREF_INTERNAL (1 << 9)
#define DATA_MASK 0x03ff #define SPEAR_ADC_DATA_MASK 0x03ff
#define DATA_BITS 10 #define SPEAR_ADC_DATA_BITS 10
#define MOD_NAME "spear-adc" #define SPEAR_ADC_MOD_NAME "spear-adc"
#define ADC_CHANNEL_NUM 8 #define SPEAR_ADC_CHANNEL_NUM 8
#define CLK_MIN 2500000 #define SPEAR_ADC_CLK_MIN 2500000
#define CLK_MAX 20000000 #define SPEAR_ADC_CLK_MAX 20000000
struct adc_regs_spear3xx { struct adc_regs_spear3xx {
u32 status; u32 status;
u32 average; u32 average;
u32 scan_rate; u32 scan_rate;
u32 clk; /* Not avail for 1340 & 1310 */ u32 clk; /* Not avail for 1340 & 1310 */
u32 ch_ctrl[ADC_CHANNEL_NUM]; u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
u32 ch_data[ADC_CHANNEL_NUM]; u32 ch_data[SPEAR_ADC_CHANNEL_NUM];
}; };
struct chan_data { struct chan_data {
...@@ -66,14 +63,14 @@ struct adc_regs_spear6xx { ...@@ -66,14 +63,14 @@ struct adc_regs_spear6xx {
u32 status; u32 status;
u32 pad[2]; u32 pad[2];
u32 clk; u32 clk;
u32 ch_ctrl[ADC_CHANNEL_NUM]; u32 ch_ctrl[SPEAR_ADC_CHANNEL_NUM];
struct chan_data ch_data[ADC_CHANNEL_NUM]; struct chan_data ch_data[SPEAR_ADC_CHANNEL_NUM];
u32 scan_rate_lo; u32 scan_rate_lo;
u32 scan_rate_hi; u32 scan_rate_hi;
struct chan_data average; struct chan_data average;
}; };
struct spear_adc_info { struct spear_adc_state {
struct device_node *np; struct device_node *np;
struct adc_regs_spear3xx __iomem *adc_base_spear3xx; struct adc_regs_spear3xx __iomem *adc_base_spear3xx;
struct adc_regs_spear6xx __iomem *adc_base_spear6xx; struct adc_regs_spear6xx __iomem *adc_base_spear6xx;
...@@ -91,100 +88,129 @@ struct spear_adc_info { ...@@ -91,100 +88,129 @@ struct spear_adc_info {
* static inline functions, because of different register offsets * static inline functions, because of different register offsets
* on different SoC variants (SPEAr300 vs SPEAr600 etc). * on different SoC variants (SPEAr300 vs SPEAr600 etc).
*/ */
static void spear_adc_set_status(struct spear_adc_info *info, u32 val) static void spear_adc_set_status(struct spear_adc_state *st, u32 val)
{ {
__raw_writel(val, &info->adc_base_spear6xx->status); __raw_writel(val, &st->adc_base_spear6xx->status);
} }
static void spear_adc_set_clk(struct spear_adc_info *info, u32 val) static void spear_adc_set_clk(struct spear_adc_state *st, u32 val)
{ {
u32 clk_high, clk_low, count; u32 clk_high, clk_low, count;
u32 apb_clk = clk_get_rate(info->clk); u32 apb_clk = clk_get_rate(st->clk);
count = (apb_clk + val - 1) / val; count = (apb_clk + val - 1) / val;
clk_low = count / 2; clk_low = count / 2;
clk_high = count - clk_low; clk_high = count - clk_low;
info->current_clk = apb_clk / count; st->current_clk = apb_clk / count;
__raw_writel(CLK_LOW(clk_low) | CLK_HIGH(clk_high), __raw_writel(SPEAR_ADC_CLK_LOW(clk_low) | SPEAR_ADC_CLK_HIGH(clk_high),
&info->adc_base_spear6xx->clk); &st->adc_base_spear6xx->clk);
} }
static void spear_adc_set_ctrl(struct spear_adc_info *info, int n, static void spear_adc_set_ctrl(struct spear_adc_state *st, int n,
u32 val) u32 val)
{ {
__raw_writel(val, &info->adc_base_spear6xx->ch_ctrl[n]); __raw_writel(val, &st->adc_base_spear6xx->ch_ctrl[n]);
} }
static u32 spear_adc_get_average(struct spear_adc_info *info) static u32 spear_adc_get_average(struct spear_adc_state *st)
{ {
if (of_device_is_compatible(info->np, "st,spear600-adc")) { if (of_device_is_compatible(st->np, "st,spear600-adc")) {
return __raw_readl(&info->adc_base_spear6xx->average.msb) & return __raw_readl(&st->adc_base_spear6xx->average.msb) &
DATA_MASK; SPEAR_ADC_DATA_MASK;
} else { } else {
return __raw_readl(&info->adc_base_spear3xx->average) & return __raw_readl(&st->adc_base_spear3xx->average) &
DATA_MASK; SPEAR_ADC_DATA_MASK;
} }
} }
static void spear_adc_set_scanrate(struct spear_adc_info *info, u32 rate) static void spear_adc_set_scanrate(struct spear_adc_state *st, u32 rate)
{ {
if (of_device_is_compatible(info->np, "st,spear600-adc")) { if (of_device_is_compatible(st->np, "st,spear600-adc")) {
__raw_writel(SCAN_RATE_LO(rate), __raw_writel(SPEAR600_ADC_SCAN_RATE_LO(rate),
&info->adc_base_spear6xx->scan_rate_lo); &st->adc_base_spear6xx->scan_rate_lo);
__raw_writel(SCAN_RATE_HI(rate), __raw_writel(SPEAR600_ADC_SCAN_RATE_HI(rate),
&info->adc_base_spear6xx->scan_rate_hi); &st->adc_base_spear6xx->scan_rate_hi);
} else { } else {
__raw_writel(rate, &info->adc_base_spear3xx->scan_rate); __raw_writel(rate, &st->adc_base_spear3xx->scan_rate);
} }
} }
static int spear_read_raw(struct iio_dev *indio_dev, static int spear_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, struct iio_chan_spec const *chan,
int *val, int *val,
int *val2, int *val2,
long mask) long mask)
{ {
struct spear_adc_info *info = iio_priv(indio_dev); struct spear_adc_state *st = iio_priv(indio_dev);
u32 status; u32 status;
switch (mask) { switch (mask) {
case IIO_CHAN_INFO_RAW: case IIO_CHAN_INFO_RAW:
mutex_lock(&indio_dev->mlock); mutex_lock(&indio_dev->mlock);
status = CHANNEL_NUM(chan->channel) | status = SPEAR_ADC_STATUS_CHANNEL_NUM(chan->channel) |
AVG_SAMPLE(info->avg_samples) | SPEAR_ADC_STATUS_AVG_SAMPLE(st->avg_samples) |
START_CONVERSION | ADC_ENABLE; SPEAR_ADC_STATUS_START_CONVERSION |
if (info->vref_external == 0) SPEAR_ADC_STATUS_ADC_ENABLE;
status |= VREF_INTERNAL; if (st->vref_external == 0)
status |= SPEAR_ADC_STATUS_VREF_INTERNAL;
spear_adc_set_status(info, status); spear_adc_set_status(st, status);
wait_for_completion(&info->completion); /* set by ISR */ wait_for_completion(&st->completion); /* set by ISR */
*val = info->value; *val = st->value;
mutex_unlock(&indio_dev->mlock); mutex_unlock(&indio_dev->mlock);
return IIO_VAL_INT; return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE: case IIO_CHAN_INFO_SCALE:
*val = info->vref_external; *val = st->vref_external;
*val2 = DATA_BITS; *val2 = SPEAR_ADC_DATA_BITS;
return IIO_VAL_FRACTIONAL_LOG2; return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_SAMP_FREQ:
*val = st->current_clk;
return IIO_VAL_INT;
} }
return -EINVAL; return -EINVAL;
} }
static int spear_adc_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long mask)
{
struct spear_adc_state *st = iio_priv(indio_dev);
int ret = 0;
if (mask != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
mutex_lock(&indio_dev->mlock);
if ((val < SPEAR_ADC_CLK_MIN) ||
(val > SPEAR_ADC_CLK_MAX) ||
(val2 != 0)) {
ret = -EINVAL;
goto out;
}
spear_adc_set_clk(st, val);
out:
mutex_unlock(&indio_dev->mlock);
return ret;
}
#define SPEAR_ADC_CHAN(idx) { \ #define SPEAR_ADC_CHAN(idx) { \
.type = IIO_VOLTAGE, \ .type = IIO_VOLTAGE, \
.indexed = 1, \ .indexed = 1, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
.channel = idx, \ .channel = idx, \
.scan_type = { \
.sign = 'u', \
.storagebits = 16, \
}, \
} }
static const struct iio_chan_spec spear_adc_iio_channels[] = { static const struct iio_chan_spec spear_adc_iio_channels[] = {
...@@ -200,92 +226,34 @@ static const struct iio_chan_spec spear_adc_iio_channels[] = { ...@@ -200,92 +226,34 @@ static const struct iio_chan_spec spear_adc_iio_channels[] = {
static irqreturn_t spear_adc_isr(int irq, void *dev_id) static irqreturn_t spear_adc_isr(int irq, void *dev_id)
{ {
struct spear_adc_info *info = (struct spear_adc_info *)dev_id; struct spear_adc_state *st = (struct spear_adc_state *)dev_id;
/* Read value to clear IRQ */ /* Read value to clear IRQ */
info->value = spear_adc_get_average(info); st->value = spear_adc_get_average(st);
complete(&info->completion); complete(&st->completion);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int spear_adc_configure(struct spear_adc_info *info) static int spear_adc_configure(struct spear_adc_state *st)
{ {
int i; int i;
/* Reset ADC core */ /* Reset ADC core */
spear_adc_set_status(info, 0); spear_adc_set_status(st, 0);
__raw_writel(0, &info->adc_base_spear6xx->clk); __raw_writel(0, &st->adc_base_spear6xx->clk);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
spear_adc_set_ctrl(info, i, 0); spear_adc_set_ctrl(st, i, 0);
spear_adc_set_scanrate(info, 0); spear_adc_set_scanrate(st, 0);
spear_adc_set_clk(info, info->sampling_freq); spear_adc_set_clk(st, st->sampling_freq);
return 0; return 0;
} }
static ssize_t spear_adc_read_frequency(struct device *dev, static const struct iio_info spear_adc_info = {
struct device_attribute *attr, .read_raw = &spear_adc_read_raw,
char *buf) .write_raw = &spear_adc_write_raw,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct spear_adc_info *info = iio_priv(indio_dev);
return sprintf(buf, "%d\n", info->current_clk);
}
static ssize_t spear_adc_write_frequency(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t len)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct spear_adc_info *info = iio_priv(indio_dev);
u32 clk_high, clk_low, count;
u32 apb_clk = clk_get_rate(info->clk);
unsigned long lval;
int ret;
ret = kstrtoul(buf, 10, &lval);
if (ret)
return ret;
mutex_lock(&indio_dev->mlock);
if ((lval < CLK_MIN) || (lval > CLK_MAX)) {
ret = -EINVAL;
goto out;
}
count = (apb_clk + lval - 1) / lval;
clk_low = count / 2;
clk_high = count - clk_low;
info->current_clk = apb_clk / count;
spear_adc_set_clk(info, lval);
out:
mutex_unlock(&indio_dev->mlock);
return ret ? ret : len;
}
static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
spear_adc_read_frequency,
spear_adc_write_frequency);
static struct attribute *spear_attributes[] = {
&iio_dev_attr_sampling_frequency.dev_attr.attr,
NULL
};
static const struct attribute_group spear_attribute_group = {
.attrs = spear_attributes,
};
static const struct iio_info spear_adc_iio_info = {
.read_raw = &spear_read_raw,
.attrs = &spear_attribute_group,
.driver_module = THIS_MODULE, .driver_module = THIS_MODULE,
}; };
...@@ -293,40 +261,40 @@ static int spear_adc_probe(struct platform_device *pdev) ...@@ -293,40 +261,40 @@ static int spear_adc_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct spear_adc_info *info; struct spear_adc_state *st;
struct iio_dev *iodev = NULL; struct iio_dev *indio_dev = NULL;
int ret = -ENODEV; int ret = -ENODEV;
int irq; int irq;
iodev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_info)); indio_dev = devm_iio_device_alloc(dev, sizeof(struct spear_adc_state));
if (!iodev) { if (!indio_dev) {
dev_err(dev, "failed allocating iio device\n"); dev_err(dev, "failed allocating iio device\n");
return -ENOMEM; return -ENOMEM;
} }
info = iio_priv(iodev); st = iio_priv(indio_dev);
info->np = np; st->np = np;
/* /*
* SPEAr600 has a different register layout than other SPEAr SoC's * SPEAr600 has a different register layout than other SPEAr SoC's
* (e.g. SPEAr3xx). Let's provide two register base addresses * (e.g. SPEAr3xx). Let's provide two register base addresses
* to support multi-arch kernels. * to support multi-arch kernels.
*/ */
info->adc_base_spear6xx = of_iomap(np, 0); st->adc_base_spear6xx = of_iomap(np, 0);
if (!info->adc_base_spear6xx) { if (!st->adc_base_spear6xx) {
dev_err(dev, "failed mapping memory\n"); dev_err(dev, "failed mapping memory\n");
return -ENOMEM; return -ENOMEM;
} }
info->adc_base_spear3xx = st->adc_base_spear3xx =
(struct adc_regs_spear3xx __iomem *)info->adc_base_spear6xx; (struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx;
info->clk = clk_get(dev, NULL); st->clk = clk_get(dev, NULL);
if (IS_ERR(info->clk)) { if (IS_ERR(st->clk)) {
dev_err(dev, "failed getting clock\n"); dev_err(dev, "failed getting clock\n");
goto errout1; goto errout1;
} }
ret = clk_prepare_enable(info->clk); ret = clk_prepare_enable(st->clk);
if (ret) { if (ret) {
dev_err(dev, "failed enabling clock\n"); dev_err(dev, "failed enabling clock\n");
goto errout2; goto errout2;
...@@ -339,14 +307,15 @@ static int spear_adc_probe(struct platform_device *pdev) ...@@ -339,14 +307,15 @@ static int spear_adc_probe(struct platform_device *pdev)
goto errout3; goto errout3;
} }
ret = devm_request_irq(dev, irq, spear_adc_isr, 0, MOD_NAME, info); ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME,
st);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed requesting interrupt\n"); dev_err(dev, "failed requesting interrupt\n");
goto errout3; goto errout3;
} }
if (of_property_read_u32(np, "sampling-frequency", if (of_property_read_u32(np, "sampling-frequency",
&info->sampling_freq)) { &st->sampling_freq)) {
dev_err(dev, "sampling-frequency missing in DT\n"); dev_err(dev, "sampling-frequency missing in DT\n");
ret = -EINVAL; ret = -EINVAL;
goto errout3; goto errout3;
...@@ -356,28 +325,28 @@ static int spear_adc_probe(struct platform_device *pdev) ...@@ -356,28 +325,28 @@ static int spear_adc_probe(struct platform_device *pdev)
* Optional avg_samples defaults to 0, resulting in single data * Optional avg_samples defaults to 0, resulting in single data
* conversion * conversion
*/ */
of_property_read_u32(np, "average-samples", &info->avg_samples); of_property_read_u32(np, "average-samples", &st->avg_samples);
/* /*
* Optional vref_external defaults to 0, resulting in internal vref * Optional vref_external defaults to 0, resulting in internal vref
* selection * selection
*/ */
of_property_read_u32(np, "vref-external", &info->vref_external); of_property_read_u32(np, "vref-external", &st->vref_external);
spear_adc_configure(info); spear_adc_configure(st);
platform_set_drvdata(pdev, iodev); platform_set_drvdata(pdev, indio_dev);
init_completion(&info->completion); init_completion(&st->completion);
iodev->name = MOD_NAME; indio_dev->name = SPEAR_ADC_MOD_NAME;
iodev->dev.parent = dev; indio_dev->dev.parent = dev;
iodev->info = &spear_adc_iio_info; indio_dev->info = &spear_adc_info;
iodev->modes = INDIO_DIRECT_MODE; indio_dev->modes = INDIO_DIRECT_MODE;
iodev->channels = spear_adc_iio_channels; indio_dev->channels = spear_adc_iio_channels;
iodev->num_channels = ARRAY_SIZE(spear_adc_iio_channels); indio_dev->num_channels = ARRAY_SIZE(spear_adc_iio_channels);
ret = iio_device_register(iodev); ret = iio_device_register(indio_dev);
if (ret) if (ret)
goto errout3; goto errout3;
...@@ -386,23 +355,23 @@ static int spear_adc_probe(struct platform_device *pdev) ...@@ -386,23 +355,23 @@ static int spear_adc_probe(struct platform_device *pdev)
return 0; return 0;
errout3: errout3:
clk_disable_unprepare(info->clk); clk_disable_unprepare(st->clk);
errout2: errout2:
clk_put(info->clk); clk_put(st->clk);
errout1: errout1:
iounmap(info->adc_base_spear6xx); iounmap(st->adc_base_spear6xx);
return ret; return ret;
} }
static int spear_adc_remove(struct platform_device *pdev) static int spear_adc_remove(struct platform_device *pdev)
{ {
struct iio_dev *iodev = platform_get_drvdata(pdev); struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct spear_adc_info *info = iio_priv(iodev); struct spear_adc_state *st = iio_priv(indio_dev);
iio_device_unregister(iodev); iio_device_unregister(indio_dev);
clk_disable_unprepare(info->clk); clk_disable_unprepare(st->clk);
clk_put(info->clk); clk_put(st->clk);
iounmap(info->adc_base_spear6xx); iounmap(st->adc_base_spear6xx);
return 0; return 0;
} }
...@@ -419,7 +388,7 @@ static struct platform_driver spear_adc_driver = { ...@@ -419,7 +388,7 @@ static struct platform_driver spear_adc_driver = {
.probe = spear_adc_probe, .probe = spear_adc_probe,
.remove = spear_adc_remove, .remove = spear_adc_remove,
.driver = { .driver = {
.name = MOD_NAME, .name = SPEAR_ADC_MOD_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(spear_adc_dt_ids), .of_match_table = of_match_ptr(spear_adc_dt_ids),
}, },
......
...@@ -172,7 +172,7 @@ ...@@ -172,7 +172,7 @@
#define ID_ADT75XX 0x10 #define ID_ADT75XX 0x10
/* /*
* struct adt7316_chip_info - chip specifc information * struct adt7316_chip_info - chip specific information
*/ */
struct adt7316_chip_info { struct adt7316_chip_info {
...@@ -208,7 +208,7 @@ struct adt7316_chip_info { ...@@ -208,7 +208,7 @@ struct adt7316_chip_info {
(ADT7316_TEMP_INT_MASK) (ADT7316_TEMP_INT_MASK)
/* /*
* struct adt7316_chip_info - chip specifc information * struct adt7316_chip_info - chip specific information
*/ */
struct adt7316_limit_regs { struct adt7316_limit_regs {
......
...@@ -78,7 +78,7 @@ enum { ...@@ -78,7 +78,7 @@ enum {
}; };
/* /*
* struct ad7152_chip_info - chip specifc information * struct ad7152_chip_info - chip specific information
*/ */
struct ad7152_chip_info { struct ad7152_chip_info {
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
#define AD7746_CAPDAC_DACP(x) ((x) & 0x7F) #define AD7746_CAPDAC_DACP(x) ((x) & 0x7F)
/* /*
* struct ad7746_chip_info - chip specifc information * struct ad7746_chip_info - chip specific information
*/ */
struct ad7746_chip_info { struct ad7746_chip_info {
......
...@@ -269,6 +269,10 @@ int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable); ...@@ -269,6 +269,10 @@ int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable);
int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable); int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable);
void st_sensors_power_enable(struct iio_dev *indio_dev);
void st_sensors_power_disable(struct iio_dev *indio_dev);
int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr); int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr);
int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable); int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable);
......
...@@ -122,6 +122,19 @@ struct iio_channel ...@@ -122,6 +122,19 @@ struct iio_channel
int iio_read_channel_raw(struct iio_channel *chan, int iio_read_channel_raw(struct iio_channel *chan,
int *val); int *val);
/**
* iio_read_channel_average_raw() - read from a given channel
* @chan: The channel being queried.
* @val: Value read back.
*
* Note raw reads from iio channels are in adc counts and hence
* scale will need to be applied if standard units required.
*
* In opposit to the normal iio_read_channel_raw this function
* returns the average of multiple reads.
*/
int iio_read_channel_average_raw(struct iio_channel *chan, int *val);
/** /**
* iio_read_channel_processed() - read processed value from a given channel * iio_read_channel_processed() - read processed value from a given channel
* @chan: The channel being queried. * @chan: The channel being queried.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment