Commit 7970b9e6 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-4.10b' of...

Merge tag 'iio-for-4.10b' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-testing

Jonathan writes:

Second round of new device support, cleanups and fixes for IIO in the 4.10 cycle

This includes two branch merges for elements that may also go via MFD.

New device support
* cros_ec
  - new driver to support these Chrome OS contiguous sensors which are behind
    the Chrome OS embedded controller.  Requires a few minor MFD and chrome
    platform changes.  One follow up fix deals with some dependency issues in
    Kconfig.
* mpu-3050
  - new driver and device tree bindings for this venerable device.
* st_accel
  - support for the lng2dm an

Driver features
* ad7192
  - Add DVdd regulator handling
* ad9832
  - Add DVDD regulator handling
* at91
  - Suspend and resume support
* si7020
  - Device tree bindings
* ti-am335x
  - DMA support - uses dma to accelerate short bursts of read back rather
  than full blown DMA buffer support.  Greatly improved performance.
  Includes an MFD addition to give access to the address needed for DMA.
* tsl2583
  - Device tree bindings

Cleanups and minor fixes
* ad7192
  - Fix regulator naming to match datasheet
  - Handle regulator errors correctly (so as to not break deferred probing)
  - Rename reg variable to reflect which regulator it is
* ad5933
  - Fix regulator naming to match datasheet
  - Handle regulator errors correctly (so as to not break deferred probing)
* ad7746
  - Fix a missing return value (fallout from previous patch set)
* ad7780
  - Fix regulator naming to match datasheet
  - Handle regulator errors correctly (so as to not break deferred probing)
* ad9832
  - Fix regulator naming to match datasheet
  - Handle regulator errors correctly (so as to not break deferred probing)
  - Rename reg regulator to reflect which one it is
* ad9834
  - Fix regulator naming to match datasheet
  - Handle regulator errors correctly (so as to not break deferred probing)
* hts221
  - Remove a duplicated include
* maxim thermocouple
  - Handle a wrong storage side in read function.  Prevent any problems that
  might be introduced by additions to this driver in future.
* tsl2583 - big set from Brian Masney to drive this towards a staging
  graduation.
  - Convert to iio_chan_spec and read_raw / write_raw (in a couple of steps)
  - Improved error handling in various functions
  - Drop redundant power_state custom sysfs attribute.
  - Use IIO_*_ATTR* macros for remaining attributes.
  - Return an error code to userspace on invalid parameters being writen to
    sysfs files.
  - Add locking to various attribute accesses to remove possible races.
  - Add defines for various magic numbers.
  - Use smbus_read_byte_data instead of a write_byte followed by read_byte.
  - Query only relevant registers in probe.
  - Tidy up ordering of code comments.
  - Remove a pointless power off sequence in taos_chip_on.
  - Don't bother shutting down the chip when updating the lux table.
  The table is held entirely in the driver and doesn't effect the chip at all.
  - Drop a redundant i2c call in taos_als_calibrate where the same register
  is read twice in a row.
parents c2b6028f c2b0d2cf
What: /sys/bus/iio/devices/iio:deviceX/calibrate
Date: July 2015
KernelVersion: 4.7
Contact: linux-iio@vger.kernel.org
Description:
Writing '1' will perform a FOC (Fast Online Calibration). The
corresponding calibration offsets can be read from *_calibbias
entries.
What: /sys/bus/iio/devices/iio:deviceX/location
Date: July 2015
KernelVersion: 4.7
Contact: linux-iio@vger.kernel.org
Description:
This attribute returns a string with the physical location where
the motion sensor is placed. For example, in a laptop a motion
sensor can be located on the base or on the lid. Current valid
values are 'base' and 'lid'.
......@@ -152,6 +152,7 @@ ricoh,rv5c387a I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
samsung,24ad0xd1 S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power)
sgx,vz89x SGX Sensortech VZ89X Sensors
sii,s35390a 2-wire CMOS real-time clock
silabs,si7020 Relative Humidity and Temperature Sensors
skyworks,sky81452 Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
st,24c256 i2c serial eeprom (24cxx)
st,m41t00 Serial real-time clock (RTC)
......
Invensense MPU-3050 Gyroscope device tree bindings
Required properties:
- compatible : should be "invensense,mpu3050"
- reg : the I2C address of the sensor
Optional properties:
- interrupt-parent : should be the phandle for the interrupt controller
- interrupts : interrupt mapping for the trigger interrupt from the
internal oscillator. The following IRQ modes are supported:
IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_LEVEL_HIGH and
IRQ_TYPE_LEVEL_LOW. The driver should detect and configure the hardware
for the desired interrupt type.
- vdd-supply : supply regulator for the main power voltage.
- vlogic-supply : supply regulator for the signal voltage.
- mount-matrix : see iio/mount-matrix.txt
Optional subnodes:
- The MPU-3050 will pass through and forward the I2C signals from the
incoming I2C bus, alternatively drive traffic to a slave device (usually
an accelerometer) on its own initiative. Therefore is supports a subnode
i2c gate node. For details see: i2c/i2c-gate.txt
Example:
mpu3050@68 {
compatible = "invensense,mpu3050";
reg = <0x68>;
interrupt-parent = <&foo>;
interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
vdd-supply = <&bar>;
vlogic-supply = <&baz>;
/* External I2C interface */
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
fnord@18 {
compatible = "fnord";
reg = <0x18>;
interrupt-parent = <&foo>;
interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
};
};
};
* TAOS TSL 2580/2581/2583 ALS sensor
Required properties:
- compatible: Should be one of
"amstaos,tsl2580"
"amstaos,tsl2581"
"amstaos,tsl2583"
- reg: the I2C address of the device
Optional properties:
- 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.
- vcc-supply: phandle to the regulator that provides power to the sensor.
Example:
tsl2581@29 {
compatible = "amstaos,tsl2581";
reg = <0x29>;
};
......@@ -42,6 +42,7 @@ Accelerometers:
- st,lsm303agr-accel
- st,lis2dh12-accel
- st,h3lis331dl-accel
- st,lng2dm-accel
Gyroscopes:
- st,l3g4200d-gyro
......
......@@ -6498,6 +6498,13 @@ S: Maintained
F: arch/x86/include/asm/pmc_core.h
F: drivers/platform/x86/intel_pmc_core*
INVENSENSE MPU-3050 GYROSCOPE DRIVER
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/gyro/mpu3050*
F: Documentation/devicetree/bindings/iio/gyroscope/inv,mpu3050.txt
IOC3 ETHERNET DRIVER
M: Ralf Baechle <ralf@linux-mips.org>
L: linux-mips@linux-mips.org
......
......@@ -127,7 +127,8 @@ config IIO_ST_ACCEL_3AXIS
help
Say yes here to build support for STMicroelectronics accelerometers:
LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL.
LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL,
LNG2DM
This driver can also be built as a module. If so, these modules
will be created:
......
......@@ -30,6 +30,7 @@
#define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel"
#define LIS2DH12_ACCEL_DEV_NAME "lis2dh12_accel"
#define LIS3L02DQ_ACCEL_DEV_NAME "lis3l02dq"
#define LNG2DM_ACCEL_DEV_NAME "lng2dm"
/**
* struct st_sensors_platform_data - default accel platform data
......
......@@ -231,6 +231,12 @@
#define ST_ACCEL_7_DRDY_IRQ_INT1_MASK 0x04
#define ST_ACCEL_7_MULTIREAD_BIT false
/* CUSTOM VALUES FOR SENSOR 8 */
#define ST_ACCEL_8_FS_AVL_2_GAIN IIO_G_TO_M_S_2(15600)
#define ST_ACCEL_8_FS_AVL_4_GAIN IIO_G_TO_M_S_2(31200)
#define ST_ACCEL_8_FS_AVL_8_GAIN IIO_G_TO_M_S_2(62500)
#define ST_ACCEL_8_FS_AVL_16_GAIN IIO_G_TO_M_S_2(187500)
static const struct iio_chan_spec st_accel_8bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
......@@ -726,6 +732,73 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.multi_read_bit = ST_ACCEL_7_MULTIREAD_BIT,
.bootime = 2,
},
{
.wai = ST_ACCEL_1_WAI_EXP,
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LNG2DM_ACCEL_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_accel_8bit_channels,
.odr = {
.addr = ST_ACCEL_1_ODR_ADDR,
.mask = ST_ACCEL_1_ODR_MASK,
.odr_avl = {
{ 1, ST_ACCEL_1_ODR_AVL_1HZ_VAL, },
{ 10, ST_ACCEL_1_ODR_AVL_10HZ_VAL, },
{ 25, ST_ACCEL_1_ODR_AVL_25HZ_VAL, },
{ 50, ST_ACCEL_1_ODR_AVL_50HZ_VAL, },
{ 100, ST_ACCEL_1_ODR_AVL_100HZ_VAL, },
{ 200, ST_ACCEL_1_ODR_AVL_200HZ_VAL, },
{ 400, ST_ACCEL_1_ODR_AVL_400HZ_VAL, },
{ 1600, ST_ACCEL_1_ODR_AVL_1600HZ_VAL, },
},
},
.pw = {
.addr = ST_ACCEL_1_ODR_ADDR,
.mask = ST_ACCEL_1_ODR_MASK,
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.enable_axis = {
.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
},
.fs = {
.addr = ST_ACCEL_1_FS_ADDR,
.mask = ST_ACCEL_1_FS_MASK,
.fs_avl = {
[0] = {
.num = ST_ACCEL_FS_AVL_2G,
.value = ST_ACCEL_1_FS_AVL_2_VAL,
.gain = ST_ACCEL_8_FS_AVL_2_GAIN,
},
[1] = {
.num = ST_ACCEL_FS_AVL_4G,
.value = ST_ACCEL_1_FS_AVL_4_VAL,
.gain = ST_ACCEL_8_FS_AVL_4_GAIN,
},
[2] = {
.num = ST_ACCEL_FS_AVL_8G,
.value = ST_ACCEL_1_FS_AVL_8_VAL,
.gain = ST_ACCEL_8_FS_AVL_8_GAIN,
},
[3] = {
.num = ST_ACCEL_FS_AVL_16G,
.value = ST_ACCEL_1_FS_AVL_16_VAL,
.gain = ST_ACCEL_8_FS_AVL_16_GAIN,
},
},
},
.drdy_irq = {
.addr = ST_ACCEL_1_DRDY_IRQ_ADDR,
.mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK,
.mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK,
.addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR,
.mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK,
.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
},
.multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
.bootime = 2,
},
};
static int st_accel_read_raw(struct iio_dev *indio_dev,
......
......@@ -84,6 +84,10 @@ static const struct of_device_id st_accel_of_match[] = {
.compatible = "st,lis3l02dq",
.data = LIS3L02DQ_ACCEL_DEV_NAME,
},
{
.compatible = "st,lng2dm-accel",
.data = LNG2DM_ACCEL_DEV_NAME,
},
{},
};
MODULE_DEVICE_TABLE(of, st_accel_of_match);
......@@ -135,6 +139,7 @@ static const struct i2c_device_id st_accel_id_table[] = {
{ LSM303AGR_ACCEL_DEV_NAME },
{ LIS2DH12_ACCEL_DEV_NAME },
{ LIS3L02DQ_ACCEL_DEV_NAME },
{ LNG2DM_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
......
......@@ -60,6 +60,7 @@ static const struct spi_device_id st_accel_id_table[] = {
{ LSM303AGR_ACCEL_DEV_NAME },
{ LIS2DH12_ACCEL_DEV_NAME },
{ LIS3L02DQ_ACCEL_DEV_NAME },
{ LNG2DM_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(spi, st_accel_id_table);
......
......@@ -30,6 +30,7 @@
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/pinctrl/consumer.h>
/* Registers */
#define AT91_ADC_CR 0x00 /* Control Register */
......@@ -1347,6 +1348,32 @@ static int at91_adc_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int at91_adc_suspend(struct device *dev)
{
struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev));
struct at91_adc_state *st = iio_priv(idev);
pinctrl_pm_select_sleep_state(dev);
clk_disable_unprepare(st->clk);
return 0;
}
static int at91_adc_resume(struct device *dev)
{
struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev));
struct at91_adc_state *st = iio_priv(idev);
clk_prepare_enable(st->clk);
pinctrl_pm_select_default_state(dev);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume);
static struct at91_adc_caps at91sam9260_caps = {
.calc_startup_ticks = calc_startup_ticks_9260,
.num_channels = 4,
......@@ -1441,6 +1468,7 @@ static struct platform_driver at91_adc_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(at91_adc_dt_ids),
.pm = &at91_adc_pm_ops,
},
};
......
......@@ -30,10 +30,28 @@
#include <linux/iio/buffer.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#define DMA_BUFFER_SIZE SZ_2K
struct tiadc_dma {
struct dma_slave_config conf;
struct dma_chan *chan;
dma_addr_t addr;
dma_cookie_t cookie;
u8 *buf;
int current_period;
int period_size;
u8 fifo_thresh;
};
struct tiadc_device {
struct ti_tscadc_dev *mfd_tscadc;
struct tiadc_dma dma;
struct mutex fifo1_lock; /* to protect fifo access */
int channels;
int total_ch_enabled;
u8 channel_line[8];
u8 channel_step[8];
int buffer_en_ch_steps;
......@@ -198,6 +216,67 @@ static irqreturn_t tiadc_worker_h(int irq, void *private)
return IRQ_HANDLED;
}
static void tiadc_dma_rx_complete(void *param)
{
struct iio_dev *indio_dev = param;
struct tiadc_device *adc_dev = iio_priv(indio_dev);
struct tiadc_dma *dma = &adc_dev->dma;
u8 *data;
int i;
data = dma->buf + dma->current_period * dma->period_size;
dma->current_period = 1 - dma->current_period; /* swap the buffer ID */
for (i = 0; i < dma->period_size; i += indio_dev->scan_bytes) {
iio_push_to_buffers(indio_dev, data);
data += indio_dev->scan_bytes;
}
}
static int tiadc_start_dma(struct iio_dev *indio_dev)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
struct tiadc_dma *dma = &adc_dev->dma;
struct dma_async_tx_descriptor *desc;
dma->current_period = 0; /* We start to fill period 0 */
/*
* Make the fifo thresh as the multiple of total number of
* channels enabled, so make sure that cyclic DMA period
* length is also a multiple of total number of channels
* enabled. This ensures that no invalid data is reported
* to the stack via iio_push_to_buffers().
*/
dma->fifo_thresh = rounddown(FIFO1_THRESHOLD + 1,
adc_dev->total_ch_enabled) - 1;
/* Make sure that period length is multiple of fifo thresh level */
dma->period_size = rounddown(DMA_BUFFER_SIZE / 2,
(dma->fifo_thresh + 1) * sizeof(u16));
dma->conf.src_maxburst = dma->fifo_thresh + 1;
dmaengine_slave_config(dma->chan, &dma->conf);
desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
dma->period_size * 2,
dma->period_size, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT);
if (!desc)
return -EBUSY;
desc->callback = tiadc_dma_rx_complete;
desc->callback_param = indio_dev;
dma->cookie = dmaengine_submit(desc);
dma_async_issue_pending(dma->chan);
tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
return 0;
}
static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
......@@ -218,20 +297,30 @@ static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
struct tiadc_dma *dma = &adc_dev->dma;
unsigned int irq_enable;
unsigned int enb = 0;
u8 bit;
tiadc_step_config(indio_dev);
for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels)
for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) {
enb |= (get_adc_step_bit(adc_dev, bit) << 1);
adc_dev->total_ch_enabled++;
}
adc_dev->buffer_en_ch_steps = enb;
if (dma->chan)
tiadc_start_dma(indio_dev);
am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES
| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
tiadc_writel(adc_dev, REG_IRQENABLE, IRQENB_FIFO1THRES
| IRQENB_FIFO1OVRRUN);
irq_enable = IRQENB_FIFO1OVRRUN;
if (!dma->chan)
irq_enable |= IRQENB_FIFO1THRES;
tiadc_writel(adc_dev, REG_IRQENABLE, irq_enable);
return 0;
}
......@@ -239,12 +328,18 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
struct tiadc_dma *dma = &adc_dev->dma;
int fifo1count, i, read;
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
adc_dev->buffer_en_ch_steps = 0;
adc_dev->total_ch_enabled = 0;
if (dma->chan) {
tiadc_writel(adc_dev, REG_DMAENABLE_CLEAR, 0x2);
dmaengine_terminate_async(dma->chan);
}
/* Flush FIFO of leftover data in the time it takes to disable adc */
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
......@@ -430,6 +525,41 @@ static const struct iio_info tiadc_info = {
.driver_module = THIS_MODULE,
};
static int tiadc_request_dma(struct platform_device *pdev,
struct tiadc_device *adc_dev)
{
struct tiadc_dma *dma = &adc_dev->dma;
dma_cap_mask_t mask;
/* Default slave configuration parameters */
dma->conf.direction = DMA_DEV_TO_MEM;
dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
dma_cap_zero(mask);
dma_cap_set(DMA_CYCLIC, mask);
/* Get a channel for RX */
dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
if (IS_ERR(dma->chan)) {
int ret = PTR_ERR(dma->chan);
dma->chan = NULL;
return ret;
}
/* RX buffer */
dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
&dma->addr, GFP_KERNEL);
if (!dma->buf)
goto err;
return 0;
err:
dma_release_channel(dma->chan);
return -ENOMEM;
}
static int tiadc_parse_dt(struct platform_device *pdev,
struct tiadc_device *adc_dev)
{
......@@ -512,8 +642,14 @@ static int tiadc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, indio_dev);
err = tiadc_request_dma(pdev, adc_dev);
if (err && err == -EPROBE_DEFER)
goto err_dma;
return 0;
err_dma:
iio_device_unregister(indio_dev);
err_buffer_unregister:
tiadc_iio_buffered_hardware_remove(indio_dev);
err_free_channels:
......@@ -525,8 +661,14 @@ static int tiadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct tiadc_device *adc_dev = iio_priv(indio_dev);
struct tiadc_dma *dma = &adc_dev->dma;
u32 step_en;
if (dma->chan) {
dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
dma->buf, dma->addr);
dma_release_channel(dma->chan);
}
iio_device_unregister(indio_dev);
tiadc_iio_buffered_hardware_remove(indio_dev);
tiadc_channels_remove(indio_dev);
......
......@@ -2,6 +2,7 @@
# IIO common modules
#
source "drivers/iio/common/cros_ec_sensors/Kconfig"
source "drivers/iio/common/hid-sensors/Kconfig"
source "drivers/iio/common/ms_sensors/Kconfig"
source "drivers/iio/common/ssp_sensors/Kconfig"
......
......@@ -7,6 +7,7 @@
#
# When adding new entries keep the list in alphabetical order
obj-y += cros_ec_sensors/
obj-y += hid-sensors/
obj-y += ms_sensors/
obj-y += ssp_sensors/
......
#
# Chrome OS Embedded Controller managed sensors library
#
config IIO_CROS_EC_SENSORS_CORE
tristate "ChromeOS EC Sensors Core"
depends on SYSFS && MFD_CROS_EC
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Base module for the ChromeOS EC Sensors module.
Contains core functions used by other IIO CrosEC sensor
drivers.
Define common attributes and sysfs interrupt handler.
config IIO_CROS_EC_SENSORS
tristate "ChromeOS EC Contiguous Sensors"
depends on IIO_CROS_EC_SENSORS_CORE
help
Module to handle 3d contiguous sensors like
Accelerometers, Gyroscope and Magnetometer that are
presented by the ChromeOS EC Sensor hub.
Creates an IIO device for each functions.
#
# Makefile for sensors seen through the ChromeOS EC sensor hub.
#
obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
/*
* cros_ec_sensors - Driver for Chrome OS Embedded Controller sensors.
*
* Copyright (C) 2016 Google, Inc
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*
* This driver uses the cros-ec interface to communicate with the Chrome OS
* EC about sensors data. Data access is presented through iio sysfs.
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/kernel.h>
#include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include "cros_ec_sensors_core.h"
#define CROS_EC_SENSORS_MAX_CHANNELS 4
/* State data for ec_sensors iio driver. */
struct cros_ec_sensors_state {
/* Shared by all sensors */
struct cros_ec_sensors_core_state core;
struct iio_chan_spec channels[CROS_EC_SENSORS_MAX_CHANNELS];
};
static int cros_ec_sensors_read(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct cros_ec_sensors_state *st = iio_priv(indio_dev);
s16 data = 0;
s64 val64;
int i;
int ret;
int idx = chan->scan_index;
mutex_lock(&st->core.cmd_lock);
switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = st->core.read_ec_sensors_data(indio_dev, 1 << idx, &data);
if (ret < 0)
break;
*val = data;
break;
case IIO_CHAN_INFO_CALIBBIAS:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
st->core.param.sensor_offset.flags = 0;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
if (ret < 0)
break;
/* Save values */
for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
st->core.calib[i] =
st->core.resp->sensor_offset.offset[i];
*val = st->core.calib[idx];
break;
case IIO_CHAN_INFO_SCALE:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
if (ret < 0)
break;
val64 = st->core.resp->sensor_range.ret;
switch (st->core.type) {
case MOTIONSENSE_TYPE_ACCEL:
/*
* EC returns data in g, iio exepects m/s^2.
* Do not use IIO_G_TO_M_S_2 to avoid precision loss.
*/
*val = div_s64(val64 * 980665, 10);
*val2 = 10000 << (CROS_EC_SENSOR_BITS - 1);
ret = IIO_VAL_FRACTIONAL;
break;
case MOTIONSENSE_TYPE_GYRO:
/*
* EC returns data in dps, iio expects rad/s.
* Do not use IIO_DEGREE_TO_RAD to avoid precision
* loss. Round to the nearest integer.
*/
*val = div_s64(val64 * 314159 + 9000000ULL, 1000);
*val2 = 18000 << (CROS_EC_SENSOR_BITS - 1);
ret = IIO_VAL_FRACTIONAL;
break;
case MOTIONSENSE_TYPE_MAG:
/*
* EC returns data in 16LSB / uT,
* iio expects Gauss
*/
*val = val64;
*val2 = 100 << (CROS_EC_SENSOR_BITS - 1);
ret = IIO_VAL_FRACTIONAL;
break;
default:
ret = -EINVAL;
}
break;
default:
ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,
mask);
break;
}
mutex_unlock(&st->core.cmd_lock);
return ret;
}
static int cros_ec_sensors_write(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct cros_ec_sensors_state *st = iio_priv(indio_dev);
int i;
int ret;
int idx = chan->scan_index;
mutex_lock(&st->core.cmd_lock);
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
st->core.calib[idx] = val;
/* Send to EC for each axis, even if not complete */
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
st->core.param.sensor_offset.flags =
MOTION_SENSE_SET_OFFSET;
for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
st->core.param.sensor_offset.offset[i] =
st->core.calib[i];
st->core.param.sensor_offset.temp =
EC_MOTION_SENSE_INVALID_CALIB_TEMP;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
break;
case IIO_CHAN_INFO_SCALE:
if (st->core.type == MOTIONSENSE_TYPE_MAG) {
ret = -EINVAL;
break;
}
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
st->core.param.sensor_range.data = val;
/* Always roundup, so caller gets at least what it asks for. */
st->core.param.sensor_range.roundup = 1;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
break;
default:
ret = cros_ec_sensors_core_write(
&st->core, chan, val, val2, mask);
break;
}
mutex_unlock(&st->core.cmd_lock);
return ret;
}
static const struct iio_info ec_sensors_info = {
.read_raw = &cros_ec_sensors_read,
.write_raw = &cros_ec_sensors_write,
.driver_module = THIS_MODULE,
};
static int cros_ec_sensors_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
struct cros_ec_device *ec_device;
struct iio_dev *indio_dev;
struct cros_ec_sensors_state *state;
struct iio_chan_spec *channel;
int ret, i;
if (!ec_dev || !ec_dev->ec_dev) {
dev_warn(&pdev->dev, "No CROS EC device found.\n");
return -EINVAL;
}
ec_device = ec_dev->ec_dev;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
if (!indio_dev)
return -ENOMEM;
ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
if (ret)
return ret;
indio_dev->info = &ec_sensors_info;
state = iio_priv(indio_dev);
for (channel = state->channels, i = CROS_EC_SENSOR_X;
i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) {
/* Common part */
channel->info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_CALIBBIAS);
channel->info_mask_shared_by_all =
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_FREQUENCY) |
BIT(IIO_CHAN_INFO_SAMP_FREQ);
channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
channel->scan_index = i;
channel->ext_info = cros_ec_sensors_ext_info;
channel->modified = 1;
channel->channel2 = IIO_MOD_X + i;
channel->scan_type.sign = 's';
/* Sensor specific */
switch (state->core.type) {
case MOTIONSENSE_TYPE_ACCEL:
channel->type = IIO_ACCEL;
break;
case MOTIONSENSE_TYPE_GYRO:
channel->type = IIO_ANGL_VEL;
break;
case MOTIONSENSE_TYPE_MAG:
channel->type = IIO_MAGN;
break;
default:
dev_err(&pdev->dev, "Unknown motion sensor\n");
return -EINVAL;
}
}
/* Timestamp */
channel->type = IIO_TIMESTAMP;
channel->channel = -1;
channel->scan_index = CROS_EC_SENSOR_MAX_AXIS;
channel->scan_type.sign = 's';
channel->scan_type.realbits = 64;
channel->scan_type.storagebits = 64;
indio_dev->channels = state->channels;
indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS;
/* There is only enough room for accel and gyro in the io space */
if ((state->core.ec->cmd_readmem != NULL) &&
(state->core.type != MOTIONSENSE_TYPE_MAG))
state->core.read_ec_sensors_data = cros_ec_sensors_read_lpc;
else
state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
cros_ec_sensors_capture, NULL);
if (ret)
return ret;
ret = iio_device_register(indio_dev);
if (ret)
goto error_uninit_buffer;
return 0;
error_uninit_buffer:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
static int cros_ec_sensors_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
return 0;
}
static const struct platform_device_id cros_ec_sensors_ids[] = {
{
.name = "cros-ec-accel",
},
{
.name = "cros-ec-gyro",
},
{
.name = "cros-ec-mag",
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
static struct platform_driver cros_ec_sensors_platform_driver = {
.driver = {
.name = "cros-ec-sensors",
},
.probe = cros_ec_sensors_probe,
.remove = cros_ec_sensors_remove,
.id_table = cros_ec_sensors_ids,
};
module_platform_driver(cros_ec_sensors_platform_driver);
MODULE_DESCRIPTION("ChromeOS EC 3-axis sensors driver");
MODULE_LICENSE("GPL v2");
This diff is collapsed.
/*
* ChromeOS EC sensor hub
*
* Copyright (C) 2016 Google, Inc
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* 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.
*/
#ifndef __CROS_EC_SENSORS_CORE_H
#define __CROS_EC_SENSORS_CORE_H
#include <linux/irqreturn.h>
enum {
CROS_EC_SENSOR_X,
CROS_EC_SENSOR_Y,
CROS_EC_SENSOR_Z,
CROS_EC_SENSOR_MAX_AXIS,
};
/* EC returns sensor values using signed 16 bit registers */
#define CROS_EC_SENSOR_BITS 16
/*
* 4 16 bit channels are allowed.
* Good enough for current sensors, they use up to 3 16 bit vectors.
*/
#define CROS_EC_SAMPLE_SIZE (sizeof(s64) * 2)
/* Minimum sampling period to use when device is suspending */
#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000 /* 1 second */
/**
* struct cros_ec_sensors_core_state - state data for EC sensors IIO driver
* @ec: cros EC device structure
* @cmd_lock: lock used to prevent simultaneous access to the
* commands.
* @msg: cros EC command structure
* @param: motion sensor parameters structure
* @resp: motion sensor response structure
* @type: type of motion sensor
* @loc: location where the motion sensor is placed
* @calib: calibration parameters. Note that trigger
* captured data will always provide the calibrated
* data
* @samples: static array to hold data from a single capture.
* For each channel we need 2 bytes, except for
* the timestamp. The timestamp is always last and
* is always 8-byte aligned.
* @read_ec_sensors_data: function used for accessing sensors values
* @cuur_sampl_freq: current sampling period
*/
struct cros_ec_sensors_core_state {
struct cros_ec_device *ec;
struct mutex cmd_lock;
struct cros_ec_command *msg;
struct ec_params_motion_sense param;
struct ec_response_motion_sense *resp;
enum motionsensor_type type;
enum motionsensor_location loc;
s16 calib[CROS_EC_SENSOR_MAX_AXIS];
u8 samples[CROS_EC_SAMPLE_SIZE];
int (*read_ec_sensors_data)(struct iio_dev *indio_dev,
unsigned long scan_mask, s16 *data);
int curr_sampl_freq;
};
/**
* cros_ec_sensors_read_lpc() - retrieve data from EC shared memory
* @indio_dev: pointer to IIO device
* @scan_mask: bitmap of the sensor indices to scan
* @data: location to store data
*
* This is the safe function for reading the EC data. It guarantees that the
* data sampled was not modified by the EC while being read.
*
* Return: 0 on success, -errno on failure.
*/
int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask,
s16 *data);
/**
* cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol
* @indio_dev: pointer to IIO device
* @scan_mask: bitmap of the sensor indices to scan
* @data: location to store data
*
* Return: 0 on success, -errno on failure.
*/
int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask,
s16 *data);
/**
* cros_ec_sensors_core_init() - basic initialization of the core structure
* @pdev: platform device created for the sensors
* @indio_dev: iio device structure of the device
* @physical_device: true if the device refers to a physical device
*
* Return: 0 on success, -errno on failure.
*/
int cros_ec_sensors_core_init(struct platform_device *pdev,
struct iio_dev *indio_dev, bool physical_device);
/**
* cros_ec_sensors_capture() - the trigger handler function
* @irq: the interrupt number.
* @p: a pointer to the poll function.
*
* On a trigger event occurring, if the pollfunc is attached then this
* handler is called as a threaded interrupt (and hence may sleep). It
* is responsible for grabbing data from the device and pushing it into
* the associated buffer.
*
* Return: IRQ_HANDLED
*/
irqreturn_t cros_ec_sensors_capture(int irq, void *p);
/**
* cros_ec_motion_send_host_cmd() - send motion sense host command
* @st: pointer to state information for device
* @opt_length: optional length to reduce the response size, useful on the data
* path. Otherwise, the maximal allowed response size is used
*
* When called, the sub-command is assumed to be set in param->cmd.
*
* Return: 0 on success, -errno on failure.
*/
int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st,
u16 opt_length);
/**
* cros_ec_sensors_core_read() - function to request a value from the sensor
* @st: pointer to state information for device
* @chan: channel specification structure table
* @val: will contain one element making up the returned value
* @val2: will contain another element making up the returned value
* @mask: specifies which values to be requested
*
* Return: the type of value returned by the device
*/
int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask);
/**
* cros_ec_sensors_core_write() - function to write a value to the sensor
* @st: pointer to state information for device
* @chan: channel specification structure table
* @val: first part of value to write
* @val2: second part of value to write
* @mask: specifies which values to write
*
* Return: the type of value returned by the device
*/
int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
struct iio_chan_spec const *chan,
int val, int val2, long mask);
/* List of extended channel specification for all sensors */
extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
#endif /* __CROS_EC_SENSORS_CORE_H */
......@@ -201,7 +201,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st,
int ret;
if (val1 < 0 || val2 < 0)
ret = -EINVAL;
return -EINVAL;
value = val1 * pow_10(6) + val2;
if (value) {
......@@ -250,6 +250,9 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st,
s32 value;
int ret;
if (val1 < 0 || val2 < 0)
return -EINVAL;
value = convert_to_vtf_format(st->sensitivity.size,
st->sensitivity.unit_expo,
val1, val2);
......
......@@ -84,6 +84,23 @@ config HID_SENSOR_GYRO_3D
Say yes here to build support for the HID SENSOR
Gyroscope 3D.
config MPU3050
tristate
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select REGMAP
config MPU3050_I2C
tristate "Invensense MPU3050 devices on I2C"
depends on !(INPUT_MPU3050=y || INPUT_MPU3050=m)
select MPU3050
select REGMAP_I2C
select I2C_MUX
help
This driver supports the Invensense MPU3050 gyroscope over I2C.
This driver can be built as a module. The module will be called
inv-mpu3050-i2c.
config IIO_ST_GYRO_3AXIS
tristate "STMicroelectronics gyroscopes 3-Axis Driver"
depends on (I2C || SPI_MASTER) && SYSFS
......
......@@ -14,6 +14,11 @@ obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o
obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
# Currently this is rolled into one module, split it if
# we ever create a separate SPI interface for MPU-3050
obj-$(CONFIG_MPU3050) += mpu3050.o
mpu3050-objs := mpu3050-core.o mpu3050-i2c.o
itg3200-y := itg3200_core.o
itg3200-$(CONFIG_IIO_BUFFER) += itg3200_buffer.o
obj-$(CONFIG_ITG3200) += itg3200.o
......
This diff is collapsed.
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
#include "mpu3050.h"
static const struct regmap_config mpu3050_i2c_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int mpu3050_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id)
{
struct mpu3050 *mpu3050 = i2c_mux_priv(mux);
/* Just power up the device, that is all that is needed */
pm_runtime_get_sync(mpu3050->dev);
return 0;
}
static int mpu3050_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id)
{
struct mpu3050 *mpu3050 = i2c_mux_priv(mux);
pm_runtime_mark_last_busy(mpu3050->dev);
pm_runtime_put_autosuspend(mpu3050->dev);
return 0;
}
static int mpu3050_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap *regmap;
const char *name;
struct mpu3050 *mpu3050;
int ret;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_I2C_BLOCK))
return -EOPNOTSUPP;
if (id)
name = id->name;
else
return -ENODEV;
regmap = devm_regmap_init_i2c(client, &mpu3050_i2c_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
(int)PTR_ERR(regmap));
return PTR_ERR(regmap);
}
ret = mpu3050_common_probe(&client->dev, regmap, client->irq, name);
if (ret)
return ret;
/* The main driver is up, now register the I2C mux */
mpu3050 = iio_priv(dev_get_drvdata(&client->dev));
mpu3050->i2cmux = i2c_mux_alloc(client->adapter, &client->dev,
1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
mpu3050_i2c_bypass_select,
mpu3050_i2c_bypass_deselect);
/* Just fail the mux, there is no point in killing the driver */
if (!mpu3050->i2cmux)
dev_err(&client->dev, "failed to allocate I2C mux\n");
else {
mpu3050->i2cmux->priv = mpu3050;
ret = i2c_mux_add_adapter(mpu3050->i2cmux, 0, 0, 0);
if (ret)
dev_err(&client->dev, "failed to add I2C mux\n");
}
return 0;
}
static int mpu3050_i2c_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
struct mpu3050 *mpu3050 = iio_priv(indio_dev);
if (mpu3050->i2cmux)
i2c_mux_del_adapters(mpu3050->i2cmux);
return mpu3050_common_remove(&client->dev);
}
/*
* device id table is used to identify what device can be
* supported by this driver
*/
static const struct i2c_device_id mpu3050_i2c_id[] = {
{ "mpu3050" },
{}
};
MODULE_DEVICE_TABLE(i2c, mpu3050_i2c_id);
static const struct of_device_id mpu3050_i2c_of_match[] = {
{ .compatible = "invensense,mpu3050", .data = "mpu3050" },
/* Deprecated vendor ID from the Input driver */
{ .compatible = "invn,mpu3050", .data = "mpu3050" },
{ },
};
MODULE_DEVICE_TABLE(of, mpu3050_i2c_of_match);
static struct i2c_driver mpu3050_i2c_driver = {
.probe = mpu3050_i2c_probe,
.remove = mpu3050_i2c_remove,
.id_table = mpu3050_i2c_id,
.driver = {
.of_match_table = mpu3050_i2c_of_match,
.name = "mpu3050-i2c",
.pm = &mpu3050_dev_pm_ops,
},
};
module_i2c_driver(mpu3050_i2c_driver);
MODULE_AUTHOR("Linus Walleij");
MODULE_DESCRIPTION("Invensense MPU3050 gyroscope driver");
MODULE_LICENSE("GPL");
#include <linux/iio/iio.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/i2c.h>
/**
* enum mpu3050_fullscale - indicates the full range of the sensor in deg/sec
*/
enum mpu3050_fullscale {
FS_250_DPS = 0,
FS_500_DPS,
FS_1000_DPS,
FS_2000_DPS,
};
/**
* enum mpu3050_lpf - indicates the low pass filter width
*/
enum mpu3050_lpf {
/* This implicity sets sample frequency to 8 kHz */
LPF_256_HZ_NOLPF = 0,
/* All others sets the sample frequency to 1 kHz */
LPF_188_HZ,
LPF_98_HZ,
LPF_42_HZ,
LPF_20_HZ,
LPF_10_HZ,
LPF_5_HZ,
LPF_2100_HZ_NOLPF,
};
enum mpu3050_axis {
AXIS_X = 0,
AXIS_Y,
AXIS_Z,
AXIS_MAX,
};
/**
* struct mpu3050 - instance state container for the device
* @dev: parent device for this instance
* @orientation: mounting matrix, flipped axis etc
* @map: regmap to reach the registers
* @lock: serialization lock to marshal all requests
* @irq: the IRQ used for this device
* @regs: the regulators to power this device
* @fullscale: the current fullscale setting for the device
* @lpf: digital low pass filter setting for the device
* @divisor: base frequency divider: divides 8 or 1 kHz
* @calibration: the three signed 16-bit calibration settings that
* get written into the offset registers for each axis to compensate
* for DC offsets
* @trig: trigger for the MPU-3050 interrupt, if present
* @hw_irq_trigger: hardware interrupt trigger is in use
* @irq_actl: interrupt is active low
* @irq_latch: latched IRQ, this means that it is a level IRQ
* @irq_opendrain: the interrupt line shall be configured open drain
* @pending_fifo_footer: tells us if there is a pending footer in the FIFO
* that we have to read out first when handling the FIFO
* @hw_timestamp: latest hardware timestamp from the trigger IRQ, when in
* use
* @i2cmux: an I2C mux reflecting the fact that this sensor is a hub with
* a pass-through I2C interface coming out of it: this device needs to be
* powered up in order to reach devices on the other side of this mux
*/
struct mpu3050 {
struct device *dev;
struct iio_mount_matrix orientation;
struct regmap *map;
struct mutex lock;
int irq;
struct regulator_bulk_data regs[2];
enum mpu3050_fullscale fullscale;
enum mpu3050_lpf lpf;
u8 divisor;
s16 calibration[3];
struct iio_trigger *trig;
bool hw_irq_trigger;
bool irq_actl;
bool irq_latch;
bool irq_opendrain;
bool pending_fifo_footer;
s64 hw_timestamp;
struct i2c_mux_core *i2cmux;
};
/* Probe called from different transports */
int mpu3050_common_probe(struct device *dev,
struct regmap *map,
int irq,
const char *name);
int mpu3050_common_remove(struct device *dev);
/* PM ops */
extern const struct dev_pm_ops mpu3050_dev_pm_ops;
......@@ -15,7 +15,6 @@
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/interrupt.h>
#include <linux/iio/events.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
......
......@@ -154,8 +154,17 @@ static const struct i2c_device_id si7020_id[] = {
};
MODULE_DEVICE_TABLE(i2c, si7020_id);
static const struct of_device_id si7020_dt_ids[] = {
{ .compatible = "silabs,si7020" },
{ }
};
MODULE_DEVICE_TABLE(of, si7020_dt_ids);
static struct i2c_driver si7020_driver = {
.driver.name = "si7020",
.driver = {
.name = "si7020",
.of_match_table = of_match_ptr(si7020_dt_ids),
},
.probe = si7020_probe,
.id_table = si7020_id,
};
......
......@@ -136,6 +136,8 @@ static int maxim_thermocouple_read(struct maxim_thermocouple_data *data,
ret = spi_read(data->spi, (void *)&buf32, storage_bytes);
*val = be32_to_cpu(buf32);
break;
default:
ret = -EINVAL;
}
if (ret)
......
......@@ -183,6 +183,7 @@ static int ti_tscadc_probe(struct platform_device *pdev)
tscadc->irq = err;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
tscadc->tscadc_phys_base = res->start;
tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(tscadc->tscadc_base))
return PTR_ERR(tscadc->tscadc_base);
......
......@@ -18,6 +18,7 @@
*/
#include <linux/fs.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
......@@ -87,6 +88,41 @@ static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
return ret;
}
static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
{
struct cros_ec_command *msg;
int ret;
if (ec->features[0] == -1U && ec->features[1] == -1U) {
/* features bitmap not read yet */
msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
if (!msg)
return -ENOMEM;
msg->version = 0;
msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
msg->insize = sizeof(ec->features);
msg->outsize = 0;
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
if (ret < 0 || msg->result != EC_RES_SUCCESS) {
dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
ret, msg->result);
memset(ec->features, 0, sizeof(ec->features));
}
memcpy(ec->features, msg->data, sizeof(ec->features));
dev_dbg(ec->dev, "EC features %08x %08x\n",
ec->features[0], ec->features[1]);
kfree(msg);
}
return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
}
/* Device file ops */
static int ec_device_open(struct inode *inode, struct file *filp)
{
......@@ -230,6 +266,123 @@ static void __remove(struct device *dev)
kfree(ec);
}
static void cros_ec_sensors_register(struct cros_ec_dev *ec)
{
/*
* Issue a command to get the number of sensor reported.
* Build an array of sensors driver and register them all.
*/
int ret, i, id, sensor_num;
struct mfd_cell *sensor_cells;
struct cros_ec_sensor_platform *sensor_platforms;
int sensor_type[MOTIONSENSE_TYPE_MAX];
struct ec_params_motion_sense *params;
struct ec_response_motion_sense *resp;
struct cros_ec_command *msg;
msg = kzalloc(sizeof(struct cros_ec_command) +
max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
if (msg == NULL)
return;
msg->version = 2;
msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
msg->outsize = sizeof(*params);
msg->insize = sizeof(*resp);
params = (struct ec_params_motion_sense *)msg->data;
params->cmd = MOTIONSENSE_CMD_DUMP;
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
if (ret < 0 || msg->result != EC_RES_SUCCESS) {
dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
ret, msg->result);
goto error;
}
resp = (struct ec_response_motion_sense *)msg->data;
sensor_num = resp->dump.sensor_count;
/* Allocate 2 extra sensors in case lid angle or FIFO are needed */
sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
GFP_KERNEL);
if (sensor_cells == NULL)
goto error;
sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
(sensor_num + 1), GFP_KERNEL);
if (sensor_platforms == NULL)
goto error_platforms;
memset(sensor_type, 0, sizeof(sensor_type));
id = 0;
for (i = 0; i < sensor_num; i++) {
params->cmd = MOTIONSENSE_CMD_INFO;
params->info.sensor_num = i;
ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
if (ret < 0 || msg->result != EC_RES_SUCCESS) {
dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
i, ret, msg->result);
continue;
}
switch (resp->info.type) {
case MOTIONSENSE_TYPE_ACCEL:
sensor_cells[id].name = "cros-ec-accel";
break;
case MOTIONSENSE_TYPE_GYRO:
sensor_cells[id].name = "cros-ec-gyro";
break;
case MOTIONSENSE_TYPE_MAG:
sensor_cells[id].name = "cros-ec-mag";
break;
case MOTIONSENSE_TYPE_PROX:
sensor_cells[id].name = "cros-ec-prox";
break;
case MOTIONSENSE_TYPE_LIGHT:
sensor_cells[id].name = "cros-ec-light";
break;
case MOTIONSENSE_TYPE_ACTIVITY:
sensor_cells[id].name = "cros-ec-activity";
break;
default:
dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
continue;
}
sensor_platforms[id].sensor_num = i;
sensor_cells[id].id = sensor_type[resp->info.type];
sensor_cells[id].platform_data = &sensor_platforms[id];
sensor_cells[id].pdata_size =
sizeof(struct cros_ec_sensor_platform);
sensor_type[resp->info.type]++;
id++;
}
if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
sensor_platforms[id].sensor_num = sensor_num;
sensor_cells[id].name = "cros-ec-angle";
sensor_cells[id].id = 0;
sensor_cells[id].platform_data = &sensor_platforms[id];
sensor_cells[id].pdata_size =
sizeof(struct cros_ec_sensor_platform);
id++;
}
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
sensor_cells[id].name = "cros-ec-ring";
id++;
}
ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
NULL, 0, NULL);
if (ret)
dev_err(ec->dev, "failed to add EC sensors\n");
kfree(sensor_platforms);
error_platforms:
kfree(sensor_cells);
error:
kfree(msg);
}
static int ec_device_probe(struct platform_device *pdev)
{
int retval = -ENOMEM;
......@@ -245,6 +398,8 @@ static int ec_device_probe(struct platform_device *pdev)
ec->ec_dev = dev_get_drvdata(dev->parent);
ec->dev = dev;
ec->cmd_offset = ec_platform->cmd_offset;
ec->features[0] = -1U; /* Not cached yet */
ec->features[1] = -1U; /* Not cached yet */
device_initialize(&ec->class_dev);
cdev_init(&ec->cdev, &fops);
......@@ -282,6 +437,10 @@ static int ec_device_probe(struct platform_device *pdev)
goto dev_reg_failed;
}
/* check whether this EC is a sensor hub. */
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
cros_ec_sensors_register(ec);
return 0;
dev_reg_failed:
......
......@@ -152,7 +152,8 @@
*/
struct ad7192_state {
struct regulator *reg;
struct regulator *avdd;
struct regulator *dvdd;
u16 int_vref_mv;
u32 mclk;
u32 f_order;
......@@ -633,15 +634,30 @@ static int ad7192_probe(struct spi_device *spi)
st = iio_priv(indio_dev);
st->reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
return ret;
st->avdd = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(st->avdd))
return PTR_ERR(st->avdd);
voltage_uv = regulator_get_voltage(st->reg);
ret = regulator_enable(st->avdd);
if (ret) {
dev_err(&spi->dev, "Failed to enable specified AVdd supply\n");
return ret;
}
st->dvdd = devm_regulator_get(&spi->dev, "dvdd");
if (IS_ERR(st->dvdd)) {
ret = PTR_ERR(st->dvdd);
goto error_disable_avdd;
}
ret = regulator_enable(st->dvdd);
if (ret) {
dev_err(&spi->dev, "Failed to enable specified DVdd supply\n");
goto error_disable_avdd;
}
voltage_uv = regulator_get_voltage(st->avdd);
if (pdata->vref_mv)
st->int_vref_mv = pdata->vref_mv;
else if (voltage_uv)
......@@ -675,7 +691,7 @@ static int ad7192_probe(struct spi_device *spi)
ret = ad_sd_setup_buffer_and_trigger(indio_dev);
if (ret)
goto error_disable_reg;
goto error_disable_dvdd;
ret = ad7192_setup(st, pdata);
if (ret)
......@@ -688,9 +704,10 @@ static int ad7192_probe(struct spi_device *spi)
error_remove_trigger:
ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
error_disable_dvdd:
regulator_disable(st->dvdd);
error_disable_avdd:
regulator_disable(st->avdd);
return ret;
}
......@@ -703,8 +720,8 @@ static int ad7192_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
regulator_disable(st->dvdd);
regulator_disable(st->avdd);
return 0;
}
......
......@@ -173,14 +173,16 @@ static int ad7780_probe(struct spi_device *spi)
ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info);
st->reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
return ret;
voltage_uv = regulator_get_voltage(st->reg);
st->reg = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
ret = regulator_enable(st->reg);
if (ret) {
dev_err(&spi->dev, "Failed to enable specified AVdd supply\n");
return ret;
}
voltage_uv = regulator_get_voltage(st->reg);
st->chip_info =
&ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
......@@ -222,8 +224,7 @@ static int ad7780_probe(struct spi_device *spi)
error_cleanup_buffer_and_trigger:
ad_sd_cleanup_buffer_and_trigger(indio_dev);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
regulator_disable(st->reg);
return ret;
}
......@@ -236,8 +237,7 @@ static int ad7780_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
ad_sd_cleanup_buffer_and_trigger(indio_dev);
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
regulator_disable(st->reg);
return 0;
}
......
......@@ -70,8 +70,10 @@
#define AD7746_EXCSETUP_EXCLVL(x) (((x) & 0x3) << 0)
/* Config Register Bit Designations (AD7746_REG_CFG) */
#define AD7746_CONF_VTFS(x) ((x) << 6)
#define AD7746_CONF_CAPFS(x) ((x) << 3)
#define AD7746_CONF_VTFS_SHIFT 6
#define AD7746_CONF_CAPFS_SHIFT 3
#define AD7746_CONF_VTFS_MASK GENMASK(7, 6)
#define AD7746_CONF_CAPFS_MASK GENMASK(5, 3)
#define AD7746_CONF_MODE_IDLE (0 << 0)
#define AD7746_CONF_MODE_CONT_CONV (1 << 0)
#define AD7746_CONF_MODE_SINGLE_CONV (2 << 0)
......@@ -217,15 +219,16 @@ static int ad7746_select_channel(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan)
{
struct ad7746_chip_info *chip = iio_priv(indio_dev);
int ret, delay;
int ret, delay, idx;
u8 vt_setup, cap_setup;
switch (chan->type) {
case IIO_CAPACITANCE:
cap_setup = (chan->address & 0xFF) | AD7746_CAPSETUP_CAPEN;
vt_setup = chip->vt_setup & ~AD7746_VTSETUP_VTEN;
delay = ad7746_cap_filter_rate_table[(chip->config >> 3) &
0x7][1];
idx = (chip->config & AD7746_CONF_CAPFS_MASK) >>
AD7746_CONF_CAPFS_SHIFT;
delay = ad7746_cap_filter_rate_table[idx][1];
if (chip->capdac_set != chan->channel) {
ret = i2c_smbus_write_byte_data(chip->client,
......@@ -246,8 +249,9 @@ static int ad7746_select_channel(struct iio_dev *indio_dev,
case IIO_TEMP:
vt_setup = (chan->address & 0xFF) | AD7746_VTSETUP_VTEN;
cap_setup = chip->cap_setup & ~AD7746_CAPSETUP_CAPEN;
delay = ad7746_cap_filter_rate_table[(chip->config >> 6) &
0x3][1];
idx = (chip->config & AD7746_CONF_VTFS_MASK) >>
AD7746_CONF_VTFS_SHIFT;
delay = ad7746_cap_filter_rate_table[idx][1];
break;
default:
return -EINVAL;
......@@ -369,8 +373,8 @@ static int ad7746_store_cap_filter_rate_setup(struct ad7746_chip_info *chip,
if (i >= ARRAY_SIZE(ad7746_cap_filter_rate_table))
i = ARRAY_SIZE(ad7746_cap_filter_rate_table) - 1;
chip->config &= ~AD7746_CONF_CAPFS(0x7);
chip->config |= AD7746_CONF_CAPFS(i);
chip->config &= ~AD7746_CONF_CAPFS_MASK;
chip->config |= i << AD7746_CONF_CAPFS_SHIFT;
return 0;
}
......@@ -387,8 +391,8 @@ static int ad7746_store_vt_filter_rate_setup(struct ad7746_chip_info *chip,
if (i >= ARRAY_SIZE(ad7746_vt_filter_rate_table))
i = ARRAY_SIZE(ad7746_vt_filter_rate_table) - 1;
chip->config &= ~AD7746_CONF_VTFS(0x3);
chip->config |= AD7746_CONF_VTFS(i);
chip->config &= ~AD7746_CONF_VTFS_MASK;
chip->config |= i << AD7746_CONF_VTFS_SHIFT;
return 0;
}
......@@ -527,7 +531,7 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
long mask)
{
struct ad7746_chip_info *chip = iio_priv(indio_dev);
int ret, delay;
int ret, delay, idx;
u8 regval, reg;
mutex_lock(&indio_dev->mlock);
......@@ -635,13 +639,16 @@ static int ad7746_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
switch (chan->type) {
case IIO_CAPACITANCE:
*val = ad7746_cap_filter_rate_table[
(chip->config >> 3) & 0x7][0];
idx = (chip->config & AD7746_CONF_CAPFS_MASK) >>
AD7746_CONF_CAPFS_SHIFT;
*val = ad7746_cap_filter_rate_table[idx][0];
ret = IIO_VAL_INT;
break;
case IIO_VOLTAGE:
*val = ad7746_vt_filter_rate_table[
(chip->config >> 6) & 0x3][0];
idx = (chip->config & AD7746_CONF_VTFS_MASK) >>
AD7746_CONF_VTFS_SHIFT;
*val = ad7746_vt_filter_rate_table[idx][0];
ret = IIO_VAL_INT;
break;
default:
ret = -EINVAL;
......
......@@ -204,7 +204,6 @@ static int ad9832_probe(struct spi_device *spi)
struct ad9832_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad9832_state *st;
struct regulator *reg;
int ret;
if (!pdata) {
......@@ -212,21 +211,35 @@ static int ad9832_probe(struct spi_device *spi)
return -ENODEV;
}
reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(reg)) {
ret = regulator_enable(reg);
if (ret)
return ret;
st->avdd = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(st->avdd))
return PTR_ERR(st->avdd);
ret = regulator_enable(st->avdd);
if (ret) {
dev_err(&spi->dev, "Failed to enable specified AVDD supply\n");
return ret;
}
st->dvdd = devm_regulator_get(&spi->dev, "dvdd");
if (IS_ERR(st->dvdd)) {
ret = PTR_ERR(st->dvdd);
goto error_disable_avdd;
}
ret = regulator_enable(st->dvdd);
if (ret) {
dev_err(&spi->dev, "Failed to enable specified DVDD supply\n");
goto error_disable_avdd;
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev) {
ret = -ENOMEM;
goto error_disable_reg;
goto error_disable_dvdd;
}
spi_set_drvdata(spi, indio_dev);
st = iio_priv(indio_dev);
st->reg = reg;
st->mclk = pdata->mclk;
st->spi = spi;
......@@ -277,42 +290,43 @@ static int ad9832_probe(struct spi_device *spi)
ret = spi_sync(st->spi, &st->msg);
if (ret) {
dev_err(&spi->dev, "device init failed\n");
goto error_disable_reg;
goto error_disable_dvdd;
}
ret = ad9832_write_frequency(st, AD9832_FREQ0HM, pdata->freq0);
if (ret)
goto error_disable_reg;
goto error_disable_dvdd;
ret = ad9832_write_frequency(st, AD9832_FREQ1HM, pdata->freq1);
if (ret)
goto error_disable_reg;
goto error_disable_dvdd;
ret = ad9832_write_phase(st, AD9832_PHASE0H, pdata->phase0);
if (ret)
goto error_disable_reg;
goto error_disable_dvdd;
ret = ad9832_write_phase(st, AD9832_PHASE1H, pdata->phase1);
if (ret)
goto error_disable_reg;
goto error_disable_dvdd;
ret = ad9832_write_phase(st, AD9832_PHASE2H, pdata->phase2);
if (ret)
goto error_disable_reg;
goto error_disable_dvdd;
ret = ad9832_write_phase(st, AD9832_PHASE3H, pdata->phase3);
if (ret)
goto error_disable_reg;
goto error_disable_dvdd;
ret = iio_device_register(indio_dev);
if (ret)
goto error_disable_reg;
goto error_disable_dvdd;
return 0;
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
error_disable_dvdd:
regulator_disable(st->dvdd);
error_disable_avdd:
regulator_disable(st->avdd);
return ret;
}
......@@ -323,8 +337,8 @@ static int ad9832_remove(struct spi_device *spi)
struct ad9832_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
regulator_disable(st->dvdd);
regulator_disable(st->avdd);
return 0;
}
......
......@@ -58,7 +58,8 @@
/**
* struct ad9832_state - driver instance specific data
* @spi: spi_device
* @reg: supply regulator
* @avdd: supply regulator for the analog section
* @dvdd: supply regulator for the digital section
* @mclk: external master clock
* @ctrl_fp: cached frequency/phase control word
* @ctrl_ss: cached sync/selsrc control word
......@@ -76,7 +77,8 @@
struct ad9832_state {
struct spi_device *spi;
struct regulator *reg;
struct regulator *avdd;
struct regulator *dvdd;
unsigned long mclk;
unsigned short ctrl_fp;
unsigned short ctrl_ss;
......
......@@ -329,11 +329,14 @@ static int ad9834_probe(struct spi_device *spi)
return -ENODEV;
}
reg = devm_regulator_get(&spi->dev, "vcc");
if (!IS_ERR(reg)) {
ret = regulator_enable(reg);
if (ret)
return ret;
reg = devm_regulator_get(&spi->dev, "avdd");
if (IS_ERR(reg))
return PTR_ERR(reg);
ret = regulator_enable(reg);
if (ret) {
dev_err(&spi->dev, "Failed to enable specified AVDD supply\n");
return ret;
}
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
......@@ -416,8 +419,7 @@ static int ad9834_probe(struct spi_device *spi)
return 0;
error_disable_reg:
if (!IS_ERR(reg))
regulator_disable(reg);
regulator_disable(reg);
return ret;
}
......@@ -428,8 +430,7 @@ static int ad9834_remove(struct spi_device *spi)
struct ad9834_state *st = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
regulator_disable(st->reg);
return 0;
}
......
......@@ -726,13 +726,16 @@ static int ad5933_probe(struct i2c_client *client,
if (!pdata)
pdata = &ad5933_default_pdata;
st->reg = devm_regulator_get(&client->dev, "vcc");
if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
return ret;
voltage_uv = regulator_get_voltage(st->reg);
st->reg = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR(st->reg))
return PTR_ERR(st->reg);
ret = regulator_enable(st->reg);
if (ret) {
dev_err(&client->dev, "Failed to enable specified VDD supply\n");
return ret;
}
voltage_uv = regulator_get_voltage(st->reg);
if (voltage_uv)
st->vref_mv = voltage_uv / 1000;
......@@ -775,8 +778,7 @@ static int ad5933_probe(struct i2c_client *client,
error_unreg_ring:
iio_kfifo_free(indio_dev->buffer);
error_disable_reg:
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
regulator_disable(st->reg);
return ret;
}
......@@ -788,8 +790,7 @@ static int ad5933_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
iio_kfifo_free(indio_dev->buffer);
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
regulator_disable(st->reg);
return 0;
}
......
This diff is collapsed.
......@@ -148,6 +148,15 @@ struct cros_ec_device {
int event_size;
};
/**
* struct cros_ec_sensor_platform - ChromeOS EC sensor platform information
*
* @sensor_num: Id of the sensor, as reported by the EC.
*/
struct cros_ec_sensor_platform {
u8 sensor_num;
};
/* struct cros_ec_platform - ChromeOS EC platform information
*
* @ec_name: name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
......@@ -175,6 +184,7 @@ struct cros_ec_dev {
struct cros_ec_device *ec_dev;
struct device *dev;
u16 cmd_offset;
u32 features[2];
};
/**
......
......@@ -713,6 +713,90 @@ struct ec_response_get_set_value {
/* More than one command can use these structs to get/set paramters. */
#define EC_CMD_GSV_PAUSE_IN_S5 0x0c
/*****************************************************************************/
/* List the features supported by the firmware */
#define EC_CMD_GET_FEATURES 0x0d
/* Supported features */
enum ec_feature_code {
/*
* This image contains a limited set of features. Another image
* in RW partition may support more features.
*/
EC_FEATURE_LIMITED = 0,
/*
* Commands for probing/reading/writing/erasing the flash in the
* EC are present.
*/
EC_FEATURE_FLASH = 1,
/*
* Can control the fan speed directly.
*/
EC_FEATURE_PWM_FAN = 2,
/*
* Can control the intensity of the keyboard backlight.
*/
EC_FEATURE_PWM_KEYB = 3,
/*
* Support Google lightbar, introduced on Pixel.
*/
EC_FEATURE_LIGHTBAR = 4,
/* Control of LEDs */
EC_FEATURE_LED = 5,
/* Exposes an interface to control gyro and sensors.
* The host goes through the EC to access these sensors.
* In addition, the EC may provide composite sensors, like lid angle.
*/
EC_FEATURE_MOTION_SENSE = 6,
/* The keyboard is controlled by the EC */
EC_FEATURE_KEYB = 7,
/* The AP can use part of the EC flash as persistent storage. */
EC_FEATURE_PSTORE = 8,
/* The EC monitors BIOS port 80h, and can return POST codes. */
EC_FEATURE_PORT80 = 9,
/*
* Thermal management: include TMP specific commands.
* Higher level than direct fan control.
*/
EC_FEATURE_THERMAL = 10,
/* Can switch the screen backlight on/off */
EC_FEATURE_BKLIGHT_SWITCH = 11,
/* Can switch the wifi module on/off */
EC_FEATURE_WIFI_SWITCH = 12,
/* Monitor host events, through for example SMI or SCI */
EC_FEATURE_HOST_EVENTS = 13,
/* The EC exposes GPIO commands to control/monitor connected devices. */
EC_FEATURE_GPIO = 14,
/* The EC can send i2c messages to downstream devices. */
EC_FEATURE_I2C = 15,
/* Command to control charger are included */
EC_FEATURE_CHARGER = 16,
/* Simple battery support. */
EC_FEATURE_BATTERY = 17,
/*
* Support Smart battery protocol
* (Common Smart Battery System Interface Specification)
*/
EC_FEATURE_SMART_BATTERY = 18,
/* EC can dectect when the host hangs. */
EC_FEATURE_HANG_DETECT = 19,
/* Report power information, for pit only */
EC_FEATURE_PMU = 20,
/* Another Cros EC device is present downstream of this one */
EC_FEATURE_SUB_MCU = 21,
/* Support USB Power delivery (PD) commands */
EC_FEATURE_USB_PD = 22,
/* Control USB multiplexer, for audio through USB port for instance. */
EC_FEATURE_USB_MUX = 23,
/* Motion Sensor code has an internal software FIFO */
EC_FEATURE_MOTION_SENSE_FIFO = 24,
};
#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32))
struct ec_response_get_features {
uint32_t flags[2];
} __packed;
/*****************************************************************************/
/* Flash commands */
......@@ -1315,6 +1399,24 @@ enum motionsense_command {
*/
MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5,
/*
* Returns a single sensor data.
*/
MOTIONSENSE_CMD_DATA = 6,
/*
* Perform low level calibration.. On sensors that support it, ask to
* do offset calibration.
*/
MOTIONSENSE_CMD_PERFORM_CALIB = 10,
/*
* Sensor Offset command is a setter/getter command for the offset used
* for calibration. The offsets can be calculated by the host, or via
* PERFORM_CALIB command.
*/
MOTIONSENSE_CMD_SENSOR_OFFSET = 11,
/* Number of motionsense sub-commands. */
MOTIONSENSE_NUM_CMDS
};
......@@ -1335,12 +1437,18 @@ enum motionsensor_id {
enum motionsensor_type {
MOTIONSENSE_TYPE_ACCEL = 0,
MOTIONSENSE_TYPE_GYRO = 1,
MOTIONSENSE_TYPE_MAG = 2,
MOTIONSENSE_TYPE_PROX = 3,
MOTIONSENSE_TYPE_LIGHT = 4,
MOTIONSENSE_TYPE_ACTIVITY = 5,
MOTIONSENSE_TYPE_MAX
};
/* List of motion sensor locations. */
enum motionsensor_location {
MOTIONSENSE_LOC_BASE = 0,
MOTIONSENSE_LOC_LID = 1,
MOTIONSENSE_LOC_MAX,
};
/* List of motion sensor chips. */
......@@ -1361,6 +1469,31 @@ enum motionsensor_chip {
*/
#define EC_MOTION_SENSE_NO_VALUE -1
#define EC_MOTION_SENSE_INVALID_CALIB_TEMP 0x8000
/* Set Calibration information */
#define MOTION_SENSE_SET_OFFSET 1
struct ec_response_motion_sensor_data {
/* Flags for each sensor. */
uint8_t flags;
/* Sensor number the data comes from */
uint8_t sensor_num;
/* Each sensor is up to 3-axis. */
union {
int16_t data[3];
struct {
uint16_t rsvd;
uint32_t timestamp;
} __packed;
struct {
uint8_t activity; /* motionsensor_activity */
uint8_t state;
int16_t add_info[2];
};
};
} __packed;
struct ec_params_motion_sense {
uint8_t cmd;
union {
......@@ -1378,9 +1511,37 @@ struct ec_params_motion_sense {
int16_t data;
} ec_rate, kb_wake_angle;
/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
struct {
uint8_t sensor_num;
/*
* bit 0: If set (MOTION_SENSE_SET_OFFSET), set
* the calibration information in the EC.
* If unset, just retrieve calibration information.
*/
uint16_t flags;
/*
* Temperature at calibration, in units of 0.01 C
* 0x8000: invalid / unknown.
* 0x0: 0C
* 0x7fff: +327.67C
*/
int16_t temp;
/*
* Offset for calibration.
* Unit:
* Accelerometer: 1/1024 g
* Gyro: 1/1024 deg/s
* Compass: 1/16 uT
*/
int16_t offset[3];
} __packed sensor_offset;
/* Used for MOTIONSENSE_CMD_INFO. */
struct {
/* Should be element of enum motionsensor_id. */
uint8_t sensor_num;
} info;
......@@ -1410,11 +1571,14 @@ struct ec_response_motion_sense {
/* Flags representing the motion sensor module. */
uint8_t module_flags;
/* Flags for each sensor in enum motionsensor_id. */
uint8_t sensor_flags[EC_MOTION_SENSOR_COUNT];
/* Number of sensors managed directly by the EC. */
uint8_t sensor_count;
/* Array of all sensor data. Each sensor is 3-axis. */
int16_t data[3*EC_MOTION_SENSOR_COUNT];
/*
* Sensor data is truncated if response_max is too small
* for holding all the data.
*/
struct ec_response_motion_sensor_data sensor[0];
} dump;
/* Used for MOTIONSENSE_CMD_INFO. */
......@@ -1429,6 +1593,9 @@ struct ec_response_motion_sense {
uint8_t chip;
} info;
/* Used for MOTIONSENSE_CMD_DATA */
struct ec_response_motion_sensor_data data;
/*
* Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR,
* MOTIONSENSE_CMD_SENSOR_RANGE, and
......@@ -1438,6 +1605,12 @@ struct ec_response_motion_sense {
/* Current value of the parameter queried. */
int32_t ret;
} ec_rate, sensor_odr, sensor_range, kb_wake_angle;
/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
struct {
int16_t temp;
int16_t offset[3];
} sensor_offset, perform_calib;
};
} __packed;
......
......@@ -23,6 +23,8 @@
#define REG_IRQENABLE 0x02C
#define REG_IRQCLR 0x030
#define REG_IRQWAKEUP 0x034
#define REG_DMAENABLE_SET 0x038
#define REG_DMAENABLE_CLEAR 0x03c
#define REG_CTRL 0x040
#define REG_ADCFSM 0x044
#define REG_CLKDIV 0x04C
......@@ -36,6 +38,7 @@
#define REG_FIFO0THR 0xE8
#define REG_FIFO1CNT 0xF0
#define REG_FIFO1THR 0xF4
#define REG_DMA1REQ 0xF8
#define REG_FIFO0 0x100
#define REG_FIFO1 0x200
......@@ -126,6 +129,10 @@
#define FIFOREAD_DATA_MASK (0xfff << 0)
#define FIFOREAD_CHNLID_MASK (0xf << 16)
/* DMA ENABLE/CLEAR Register */
#define DMA_FIFO0 BIT(0)
#define DMA_FIFO1 BIT(1)
/* Sequencer Status */
#define SEQ_STATUS BIT(5)
#define CHARGE_STEP 0x11
......@@ -155,6 +162,7 @@ struct ti_tscadc_dev {
struct device *dev;
struct regmap *regmap;
void __iomem *tscadc_base;
phys_addr_t tscadc_phys_base;
int irq;
int used_cells; /* 1-2 */
int tsc_wires;
......
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