Commit 61e33120 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-v4.2b' of...

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

Jonathan writes:

Second set of new driver, functionality and cleanups for IIO in the 4.2 cycle.

Core functionality
* i and q modifiers from quadrature channels.
* IIO_CHAN_INFO_OVERSAMPLING_RATIO added.
* High pass filter attributes added to mirror the existing low pass filter
  ones.

Core cleanups
* Make IIO tools building more cross compiler friendly.
* Substantial rework of the function __iio_update_buffers to greatly simplify
  a hideously evolved function.

New drivers and support
* ACPI0008 ambient light sensor driver. This one has been around a long time to
  will be good to finally get it into mainline.
* Berlin SOC ADC support.
* BMC150 magnetometer.  The accelerometer in the same package has been supported
  for quite some time, so good to have this half as well.
* m62332 DAC driver
* MEMSIC MMC35420 magnetometer.
* ROHM BH1710 and similar ambient light sensors.
* Sensortek STK3310 light sensor.
* Sensortek STK8312 accelerometer.
* Sensortek STK8BA50 accelerometer.
* ti-adc128s052 gains support form the adc122s021 2 channel ADC.

Driver cleanups and functionality.
* Allow various drivers to compile with !GPIOLIB if COMPILE_TEST enabled.
* bmc150 - decouple trigger from buffer to allow other triggers to be used.
* bmg160 - decouple trigger from buffer to allow other triggers to be used.
  Fix a trivial unused field.
* Constify a load of platform_device_id structures.
* inv_mpu6050 - device tree bindings.
* hid-sensors - fix a memory leak during probe if certain errors occur.
* ltr501 - illuminance channel derived (in an non obvious fashion) from the
  intensity channels.
* ltr501 - fix a boundary check on the proximity threshold.
* mlx90614 - drop a pointless return.
* mma8452 - Debugfs register access and fix a bug that had no effect (by
  coincidence)
* ti_am335x_adc - add device tree bindings for sample-delay, open-delay and
  averaging.  The ideal settings for these tend to be board design specific.
parents 936a0cd5 884ca456
......@@ -71,6 +71,8 @@ Description:
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_raw
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_raw
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_raw
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_raw
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
Description:
......@@ -81,6 +83,11 @@ Description:
unique to allow association with event codes. Units after
application of scale and offset are millivolts.
Channels with 'i' and 'q' modifiers always exist in pairs and both
channels refer to the same signal. The 'i' channel contains the in-phase
component of the signal while the 'q' channel contains the quadrature
component.
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
......@@ -246,8 +253,16 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset
What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_q_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_i_offset
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_current_offset
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_i_offset
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_q_offset
What: /sys/bus/iio/devices/iio:deviceX/in_current_q_offset
What: /sys/bus/iio/devices/iio:deviceX/in_current_i_offset
What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset
......@@ -273,14 +288,22 @@ Description:
to the _raw output.
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_scale
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_scale
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_scale
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_scale
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_i_scale
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_q_scale
What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_scale
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_scale
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_scale
What: /sys/bus/iio/devices/iio:deviceX/in_current_scale
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_i_scale
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_q_scale
What: /sys/bus/iio/devices/iio:deviceX/in_current_i_scale
What: /sys/bus/iio/devices/iio:deviceX/in_current_q_scale
What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale
What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale
......@@ -328,6 +351,10 @@ Description:
What /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_voltage_i_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_voltage_q_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibscale
What /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibscale
......@@ -420,6 +447,16 @@ Description:
to the underlying data channel, then this parameter
gives the 3dB frequency of the filter in Hz.
What: /sys/.../in_accel_filter_high_pass_3db_frequency
What: /sys/.../in_anglvel_filter_high_pass_3db_frequency
What: /sys/.../in_magn_filter_high_pass_3db_frequency
KernelVersion: 4.2
Contact: linux-iio@vger.kernel.org
Description:
If a known or controllable high pass filter is applied
to the underlying data channel, then this parameter
gives the 3dB frequency of the filter in Hz.
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_raw
KernelVersion: 2.6.37
......@@ -880,6 +917,26 @@ Description:
met before an event is generated. If direction is not
specified then this period applies to both directions.
What: /sys/.../events/in_accel_thresh_rising_low_pass_filter_3db
What: /sys/.../events/in_anglvel_thresh_rising_low_pass_filter_3db
What: /sys/.../events/in_magn_thresh_rising_low_pass_filter_3db
KernelVersion: 4.2
Contact: linux-iio@vger.kernel.org
Description:
If a low pass filter can be applied to the event generation
this property gives its 3db frequency in Hz.
A value of zero disables the filter.
What: /sys/.../events/in_accel_thresh_rising_high_pass_filter_3db
What: /sys/.../events/in_anglvel_thresh_rising_high_pass_filter_3db
What: /sys/.../events/in_magn_thresh_rising_high_pass_filter_3db
KernelVersion: 4.2
Contact: linux-iio@vger.kernel.org
Description:
If a high pass filter can be applied to the event generation
this property gives its 3db frequency in Hz.
A value of zero disables the filter.
What: /sys/.../events/in_activity_still_thresh_rising_en
What: /sys/.../events/in_activity_still_thresh_falling_en
What: /sys/.../events/in_activity_walking_thresh_rising_en
......@@ -1016,6 +1073,10 @@ What: /sys/.../iio:deviceX/scan_elements/in_timestamp_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY-voltageZ_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_en
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_en
What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_en
What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_en
What: /sys/.../iio:deviceX/scan_elements/in_incli_x_en
What: /sys/.../iio:deviceX/scan_elements/in_incli_y_en
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_en
......@@ -1034,6 +1095,10 @@ What: /sys/.../iio:deviceX/scan_elements/in_incli_type
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_type
What: /sys/.../iio:deviceX/scan_elements/in_voltage_type
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_type
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_type
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_type
What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_type
What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_type
What: /sys/.../iio:deviceX/scan_elements/in_timestamp_type
What: /sys/.../iio:deviceX/scan_elements/in_pressureY_type
What: /sys/.../iio:deviceX/scan_elements/in_pressure_type
......@@ -1071,6 +1136,10 @@ Description:
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_index
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_index
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_index
What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_index
What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_index
What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_index
What: /sys/.../iio:deviceX/scan_elements/in_accel_x_index
What: /sys/.../iio:deviceX/scan_elements/in_accel_y_index
What: /sys/.../iio:deviceX/scan_elements/in_accel_z_index
......@@ -1230,6 +1299,8 @@ Description:
or without compensation from tilt sensors.
What: /sys/bus/iio/devices/iio:deviceX/in_currentX_raw
What: /sys/bus/iio/devices/iio:deviceX/in_currentX_i_raw
What: /sys/bus/iio/devices/iio:deviceX/in_currentX_q_raw
KernelVersion: 3.18
Contact: linux-iio@vger.kernel.org
Description:
......@@ -1238,6 +1309,11 @@ Description:
present, output should be considered as processed with the
unit in milliamps.
Channels with 'i' and 'q' modifiers always exist in pairs and both
channels refer to the same signal. The 'i' channel contains the in-phase
component of the signal while the 'q' channel contains the quadrature
component.
What: /sys/.../iio:deviceX/in_energy_en
What: /sys/.../iio:deviceX/in_distance_en
What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_en
......@@ -1375,3 +1451,15 @@ Description:
The emissivity ratio of the surface in the field of view of the
contactless temperature sensor. Emissivity varies from 0 to 1,
with 1 being the emissivity of a black body.
What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_oversampling_ratio
What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_oversampling_ratio
What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_oversampling_ratio
KernelVersion: 4.2
Contact: linux-iio@vger.kernel.org
Description:
Hardware applied number of measurements for acquiring one
data point. The HW will do <type>[_name]_oversampling_ratio
measurements and return the average value as output data. Each
value resulted from <type>[_name]_oversampling_ratio measurements
is considered as one sample for <type>[_name]_sampling_frequency.
* Berlin Analog to Digital Converter (ADC)
The Berlin ADC has 8 channels, with one connected to a temperature sensor.
It is part of the system controller register set. The ADC node should be a
sub-node of the system controller node.
Required properties:
- compatible: must be "marvell,berlin2-adc"
- interrupts: the interrupts for the ADC and the temperature sensor
- interrupt-names: should be "adc" and "tsen"
Example:
adc: adc {
compatible = "marvell,berlin2-adc";
interrupt-parent = <&sic>;
interrupts = <12>, <14>;
interrupt-names = "adc", "tsen";
};
* Texas Instruments' ADC128S052 ADC chip
* Texas Instruments' ADC128S052 and ADC122S021 ADC chip
Required properties:
- compatible: Should be "ti,adc128s052"
- compatible: Should be "ti,adc128s052" or "ti,adc122s021"
- reg: spi chip select number for the device
- vref-supply: The regulator supply for ADC reference voltage
......
InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device
http://www.invensense.com/mems/gyro/mpu6050.html
Required properties:
- compatible : should be "invensense,mpu6050"
- reg : the I2C address of the sensor
- interrupt-parent : should be the phandle for the interrupt controller
- interrupts : interrupt mapping for GPIO IRQ
Example:
mpu6050@68 {
compatible = "invensense,mpu6050";
reg = <0x68>;
interrupt-parent = <&gpio1>;
interrupts = <18 1>;
};
* Bosch BMC150 magnetometer sensor
http://ae-bst.resource.bosch.com/media/products/dokumente/bmc150/BST-BMC150-DS000-04.pdf
Required properties:
- compatible : should be "bosch,bmc150_magn"
- reg : the I2C address of the magnetometer
Optional properties:
- interrupt-parent : phandle to the parent interrupt controller
- interrupts : interrupt mapping for GPIO IRQ
Example:
bmc150_magn@12 {
compatible = "bosch,bmc150_magn";
reg = <0x12>;
interrupt-parent = <&gpio1>;
interrupts = <0 1>;
};
......@@ -42,6 +42,27 @@ Optional properties:
hardware knob for adjusting the amount of "settling
time".
- child "adc"
ti,chan-step-opendelay: List of open delays for each channel of
ADC in the order of ti,adc-channels. The
value corresponds to the number of ADC
clock cycles to wait after applying the
step configuration registers and before
sending the start of ADC conversion.
Maximum value is 0x3FFFF.
ti,chan-step-sampledelay: List of sample delays for each channel
of ADC in the order of ti,adc-channels.
The value corresponds to the number of
ADC clock cycles to sample (to hold
start of conversion high).
Maximum value is 0xFF.
ti,chan-step-avg: Number of averages to be performed for each
channel of ADC. If average is 16 then input
is sampled 16 times and averaged to get more
accurate value. This increases the time taken
by ADC to generate a sample. Valid range is 0
average to 16 averages. Maximum value is 16.
Example:
tscadc: tscadc@44e0d000 {
compatible = "ti,am3359-tscadc";
......@@ -55,5 +76,8 @@ Example:
adc {
ti,adc-channels = <4 5 6 7>;
ti,chan-step-opendelay = <0x098 0x3ffff 0x098 0x0>;
ti,chan-step-sampledelay = <0xff 0x0 0xf 0x0>;
ti,chan-step-avg = <16 2 4 8>;
};
}
......@@ -136,4 +136,25 @@ config MMA9553
To compile this driver as a module, choose M here: the module
will be called mma9553.
config STK8312
tristate "Sensortek STK8312 3-Axis Accelerometer Driver"
depends on I2C
help
Say yes here to get support for the Sensortek STK8312 3-axis
accelerometer.
Choosing M will build the driver as a module. If so, the module
will be called stk8312.
config STK8BA50
tristate "Sensortek STK8BA50 3-Axis Accelerometer Driver"
depends on I2C
help
Say yes here to get support for the Sensortek STK8BA50 3-axis
accelerometer.
Choosing M will build the driver as a module. If so, the module
will be called stk8ba50.
endmenu
......@@ -14,6 +14,9 @@ obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o
obj-$(CONFIG_MMA9551) += mma9551.o
obj-$(CONFIG_MMA9553) += mma9553.o
obj-$(CONFIG_STK8312) += stk8312.o
obj-$(CONFIG_STK8BA50) += stk8ba50.o
obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_accel_sensor.o
obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
......
......@@ -196,7 +196,7 @@ struct bmc150_accel_data {
u32 slope_thres;
u32 range;
int ev_enable_state;
int64_t timestamp, old_timestamp;
int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
const struct bmc150_accel_chip_info *chip_info;
};
......@@ -1183,7 +1183,6 @@ static const struct iio_info bmc150_accel_info = {
.write_event_value = bmc150_accel_write_event,
.write_event_config = bmc150_accel_write_event_config,
.read_event_config = bmc150_accel_read_event_config,
.validate_trigger = bmc150_accel_validate_trigger,
.driver_module = THIS_MODULE,
};
......@@ -1222,7 +1221,7 @@ static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p)
mutex_unlock(&data->mutex);
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
data->timestamp);
pf->timestamp);
err_read:
iio_trigger_notify_done(indio_dev->trig);
......@@ -1535,6 +1534,13 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data)
return ret;
}
static int bmc150_accel_buffer_preenable(struct iio_dev *indio_dev)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
return bmc150_accel_set_power_state(data, true);
}
static int bmc150_accel_buffer_postenable(struct iio_dev *indio_dev)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
......@@ -1591,9 +1597,18 @@ static int bmc150_accel_buffer_predisable(struct iio_dev *indio_dev)
return 0;
}
static int bmc150_accel_buffer_postdisable(struct iio_dev *indio_dev)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
return bmc150_accel_set_power_state(data, false);
}
static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = {
.preenable = bmc150_accel_buffer_preenable,
.postenable = bmc150_accel_buffer_postenable,
.predisable = bmc150_accel_buffer_predisable,
.postdisable = bmc150_accel_buffer_postdisable,
};
static int bmc150_accel_probe(struct i2c_client *client,
......@@ -1636,6 +1651,15 @@ static int bmc150_accel_probe(struct i2c_client *client,
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &bmc150_accel_info;
ret = iio_triggered_buffer_setup(indio_dev,
&iio_pollfunc_store_time,
bmc150_accel_trigger_handler,
&bmc150_accel_buffer_ops);
if (ret < 0) {
dev_err(&client->dev, "Failed: iio triggered buffer setup\n");
return ret;
}
if (client->irq < 0)
client->irq = bmc150_accel_gpio_probe(client, data);
......@@ -1648,7 +1672,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
BMC150_ACCEL_IRQ_NAME,
indio_dev);
if (ret)
return ret;
goto err_buffer_cleanup;
/*
* Set latched mode interrupt. While certain interrupts are
......@@ -1661,24 +1685,14 @@ static int bmc150_accel_probe(struct i2c_client *client,
BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
return ret;
goto err_buffer_cleanup;
}
bmc150_accel_interrupts_setup(indio_dev, data);
ret = bmc150_accel_triggers_setup(indio_dev, data);
if (ret)
return ret;
ret = iio_triggered_buffer_setup(indio_dev,
&iio_pollfunc_store_time,
bmc150_accel_trigger_handler,
&bmc150_accel_buffer_ops);
if (ret < 0) {
dev_err(&client->dev,
"Failed: iio triggered buffer setup\n");
goto err_trigger_unregister;
}
goto err_buffer_cleanup;
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
i2c_check_functionality(client->adapter,
......@@ -1692,7 +1706,7 @@ static int bmc150_accel_probe(struct i2c_client *client,
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "Unable to register iio device\n");
goto err_buffer_cleanup;
goto err_trigger_unregister;
}
ret = pm_runtime_set_active(&client->dev);
......@@ -1708,11 +1722,10 @@ static int bmc150_accel_probe(struct i2c_client *client,
err_iio_unregister:
iio_device_unregister(indio_dev);
err_buffer_cleanup:
if (indio_dev->pollfunc)
iio_triggered_buffer_cleanup(indio_dev);
err_trigger_unregister:
bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1);
err_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
......@@ -1730,6 +1743,8 @@ static int bmc150_accel_remove(struct i2c_client *client)
bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1);
iio_triggered_buffer_cleanup(indio_dev);
mutex_lock(&data->mutex);
bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_DEEP_SUSPEND, 0);
mutex_unlock(&data->mutex);
......
......@@ -299,7 +299,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct accel_3d_state *accel_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct accel_3d_state));
......@@ -320,21 +319,21 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
return ret;
}
channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels),
GFP_KERNEL);
if (!channels) {
indio_dev->channels = kmemdup(accel_3d_channels,
sizeof(accel_3d_channels), GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
}
ret = accel_3d_parse_report(pdev, hsdev, channels,
HID_USAGE_SENSOR_ACCEL_3D, accel_state);
ret = accel_3d_parse_report(pdev, hsdev,
(struct iio_chan_spec *)indio_dev->channels,
HID_USAGE_SENSOR_ACCEL_3D, accel_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
goto error_free_dev_mem;
}
indio_dev->channels = channels;
indio_dev->num_channels = ARRAY_SIZE(accel_3d_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &accel_3d_info;
......@@ -400,7 +399,7 @@ static int hid_accel_3d_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id hid_accel_3d_ids[] = {
static const struct platform_device_id hid_accel_3d_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200073",
......
......@@ -32,6 +32,9 @@
#define MMA8452_OFF_Z 0x31
#define MMA8452_CTRL_REG1 0x2a
#define MMA8452_CTRL_REG2 0x2b
#define MMA8452_CTRL_REG2_RST BIT(6)
#define MMA8452_MAX_REG 0x31
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
......@@ -291,6 +294,28 @@ static irqreturn_t mma8452_trigger_handler(int irq, void *p)
return IRQ_HANDLED;
}
static int mma8452_reg_access_dbg(struct iio_dev *indio_dev,
unsigned reg, unsigned writeval,
unsigned *readval)
{
int ret;
struct mma8452_data *data = iio_priv(indio_dev);
if (reg > MMA8452_MAX_REG)
return -EINVAL;
if (!readval)
return mma8452_change_config(data, reg, writeval);
ret = i2c_smbus_read_byte_data(data->client, reg);
if (ret < 0)
return ret;
*readval = ret;
return 0;
}
#define MMA8452_CHANNEL(axis, idx) { \
.type = IIO_ACCEL, \
.modified = 1, \
......@@ -330,11 +355,36 @@ static const struct iio_info mma8452_info = {
.attrs = &mma8452_group,
.read_raw = &mma8452_read_raw,
.write_raw = &mma8452_write_raw,
.debugfs_reg_access = &mma8452_reg_access_dbg,
.driver_module = THIS_MODULE,
};
static const unsigned long mma8452_scan_masks[] = {0x7, 0};
static int mma8452_reset(struct i2c_client *client)
{
int i;
int ret;
ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG2,
MMA8452_CTRL_REG2_RST);
if (ret < 0)
return ret;
for (i = 0; i < 10; i++) {
usleep_range(100, 200);
ret = i2c_smbus_read_byte_data(client, MMA8452_CTRL_REG2);
if (ret == -EIO)
continue; /* I2C comm reset */
if (ret < 0)
return ret;
if (!(ret & MMA8452_CTRL_REG2_RST))
return 0;
}
return -ETIMEDOUT;
}
static int mma8452_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
......@@ -365,10 +415,7 @@ static int mma8452_probe(struct i2c_client *client,
indio_dev->num_channels = ARRAY_SIZE(mma8452_channels);
indio_dev->available_scan_masks = mma8452_scan_masks;
data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
(MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
data->ctrl_reg1);
ret = mma8452_reset(client);
if (ret < 0)
return ret;
......@@ -378,6 +425,13 @@ static int mma8452_probe(struct i2c_client *client,
if (ret < 0)
return ret;
data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
(MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
data->ctrl_reg1);
if (ret < 0)
return ret;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
mma8452_trigger_handler, NULL);
if (ret < 0)
......
/**
* Sensortek STK8312 3-Axis Accelerometer
*
* Copyright (c) 2015, Intel Corporation.
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* IIO driver for STK8312; 7-bit I2C address: 0x3D.
*/
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define STK8312_REG_XOUT 0x00
#define STK8312_REG_YOUT 0x01
#define STK8312_REG_ZOUT 0x02
#define STK8312_REG_MODE 0x07
#define STK8312_REG_STH 0x13
#define STK8312_REG_RESET 0x20
#define STK8312_REG_AFECTRL 0x24
#define STK8312_REG_OTPADDR 0x3D
#define STK8312_REG_OTPDATA 0x3E
#define STK8312_REG_OTPCTRL 0x3F
#define STK8312_MODE_ACTIVE 1
#define STK8312_MODE_STANDBY 0
#define STK8312_MODE_MASK 0x01
#define STK8312_RNG_MASK 0xC0
#define STK8312_RNG_SHIFT 6
#define STK8312_READ_RETRIES 16
#define STK8312_DRIVER_NAME "stk8312"
/*
* The accelerometer has two measurement ranges:
*
* -6g - +6g (8-bit, signed)
* -16g - +16g (8-bit, signed)
*
* scale1 = (6 + 6) * 9.81 / (2^8 - 1) = 0.4616
* scale2 = (16 + 16) * 9.81 / (2^8 - 1) = 1.2311
*/
#define STK8312_SCALE_AVAIL "0.4616 1.2311"
static const int stk8312_scale_table[][2] = {
{0, 461600}, {1, 231100}
};
#define STK8312_ACCEL_CHANNEL(reg, axis) { \
.type = IIO_ACCEL, \
.address = reg, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec stk8312_channels[] = {
STK8312_ACCEL_CHANNEL(STK8312_REG_XOUT, X),
STK8312_ACCEL_CHANNEL(STK8312_REG_YOUT, Y),
STK8312_ACCEL_CHANNEL(STK8312_REG_ZOUT, Z),
};
struct stk8312_data {
struct i2c_client *client;
struct mutex lock;
int range;
u8 mode;
};
static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL);
static struct attribute *stk8312_attributes[] = {
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
NULL,
};
static const struct attribute_group stk8312_attribute_group = {
.attrs = stk8312_attributes
};
static int stk8312_otp_init(struct stk8312_data *data)
{
int ret;
int count = 10;
struct i2c_client *client = data->client;
ret = i2c_smbus_write_byte_data(client, STK8312_REG_OTPADDR, 0x70);
if (ret < 0)
goto exit_err;
ret = i2c_smbus_write_byte_data(client, STK8312_REG_OTPCTRL, 0x02);
if (ret < 0)
goto exit_err;
do {
usleep_range(1000, 5000);
ret = i2c_smbus_read_byte_data(client, STK8312_REG_OTPCTRL);
if (ret < 0)
goto exit_err;
count--;
} while (!(ret & 0x80) && count > 0);
if (count == 0)
goto exit_err;
ret = i2c_smbus_read_byte_data(client, STK8312_REG_OTPDATA);
if (ret < 0)
goto exit_err;
ret = i2c_smbus_write_byte_data(data->client,
STK8312_REG_AFECTRL, ret);
if (ret < 0)
goto exit_err;
msleep(150);
return ret;
exit_err:
dev_err(&client->dev, "failed to initialize sensor\n");
return ret;
}
static int stk8312_set_mode(struct stk8312_data *data, u8 mode)
{
int ret;
u8 masked_reg;
struct i2c_client *client = data->client;
if (mode > 1)
return -EINVAL;
else if (mode == data->mode)
return 0;
ret = i2c_smbus_read_byte_data(client, STK8312_REG_MODE);
if (ret < 0) {
dev_err(&client->dev, "failed to change sensor mode\n");
return ret;
}
masked_reg = ret & (~STK8312_MODE_MASK);
masked_reg |= mode;
ret = i2c_smbus_write_byte_data(client,
STK8312_REG_MODE, masked_reg);
if (ret < 0) {
dev_err(&client->dev, "failed to change sensor mode\n");
return ret;
}
data->mode = mode;
if (mode == STK8312_MODE_ACTIVE) {
/* Need to run OTP sequence before entering active mode */
usleep_range(1000, 5000);
ret = stk8312_otp_init(data);
}
return ret;
}
static int stk8312_set_range(struct stk8312_data *data, u8 range)
{
int ret;
u8 masked_reg;
u8 mode;
struct i2c_client *client = data->client;
if (range != 1 && range != 2)
return -EINVAL;
else if (range == data->range)
return 0;
mode = data->mode;
/* We need to go in standby mode to modify registers */
ret = stk8312_set_mode(data, STK8312_MODE_STANDBY);
if (ret < 0)
return ret;
ret = i2c_smbus_read_byte_data(client, STK8312_REG_STH);
if (ret < 0) {
dev_err(&client->dev, "failed to change sensor range\n");
return ret;
}
masked_reg = ret & (~STK8312_RNG_MASK);
masked_reg |= range << STK8312_RNG_SHIFT;
ret = i2c_smbus_write_byte_data(client, STK8312_REG_STH, masked_reg);
if (ret < 0)
dev_err(&client->dev, "failed to change sensor range\n");
else
data->range = range;
return stk8312_set_mode(data, mode);
}
static int stk8312_read_accel(struct stk8312_data *data, u8 address)
{
int ret;
struct i2c_client *client = data->client;
if (address > 2)
return -EINVAL;
ret = i2c_smbus_read_byte_data(client, address);
if (ret < 0) {
dev_err(&client->dev, "register read failed\n");
return ret;
}
return sign_extend32(ret, 7);
}
static int stk8312_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct stk8312_data *data = iio_priv(indio_dev);
if (chan->type != IIO_ACCEL)
return -EINVAL;
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&data->lock);
*val = stk8312_read_accel(data, chan->address);
mutex_unlock(&data->lock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = stk8312_scale_table[data->range - 1][0];
*val2 = stk8312_scale_table[data->range - 1][1];
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static int stk8312_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
int i;
int index = -1;
int ret;
struct stk8312_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
for (i = 0; i < ARRAY_SIZE(stk8312_scale_table); i++)
if (val == stk8312_scale_table[i][0] &&
val2 == stk8312_scale_table[i][1]) {
index = i + 1;
break;
}
if (index < 0)
return -EINVAL;
mutex_lock(&data->lock);
ret = stk8312_set_range(data, index);
mutex_unlock(&data->lock);
return ret;
}
return -EINVAL;
}
static const struct iio_info stk8312_info = {
.driver_module = THIS_MODULE,
.read_raw = stk8312_read_raw,
.write_raw = stk8312_write_raw,
.attrs = &stk8312_attribute_group,
};
static int stk8312_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct iio_dev *indio_dev;
struct stk8312_data *data;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev) {
dev_err(&client->dev, "iio allocation failed!\n");
return -ENOMEM;
}
data = iio_priv(indio_dev);
data->client = client;
i2c_set_clientdata(client, indio_dev);
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
indio_dev->info = &stk8312_info;
indio_dev->name = STK8312_DRIVER_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = stk8312_channels;
indio_dev->num_channels = ARRAY_SIZE(stk8312_channels);
/* A software reset is recommended at power-on */
ret = i2c_smbus_write_byte_data(data->client, STK8312_REG_RESET, 0x00);
if (ret < 0) {
dev_err(&client->dev, "failed to reset sensor\n");
return ret;
}
ret = stk8312_set_range(data, 1);
if (ret < 0)
return ret;
ret = stk8312_set_mode(data, STK8312_MODE_ACTIVE);
if (ret < 0)
return ret;
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "device_register failed\n");
stk8312_set_mode(data, STK8312_MODE_STANDBY);
}
return ret;
}
static int stk8312_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
return stk8312_set_mode(iio_priv(indio_dev), STK8312_MODE_STANDBY);
}
#ifdef CONFIG_PM_SLEEP
static int stk8312_suspend(struct device *dev)
{
struct stk8312_data *data;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
return stk8312_set_mode(data, STK8312_MODE_STANDBY);
}
static int stk8312_resume(struct device *dev)
{
struct stk8312_data *data;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
return stk8312_set_mode(data, STK8312_MODE_ACTIVE);
}
static SIMPLE_DEV_PM_OPS(stk8312_pm_ops, stk8312_suspend, stk8312_resume);
#define STK8312_PM_OPS (&stk8312_pm_ops)
#else
#define STK8312_PM_OPS NULL
#endif
static const struct i2c_device_id stk8312_i2c_id[] = {
{"STK8312", 0},
{}
};
static const struct acpi_device_id stk8312_acpi_id[] = {
{"STK8312", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, stk8312_acpi_id);
static struct i2c_driver stk8312_driver = {
.driver = {
.name = "stk8312",
.pm = STK8312_PM_OPS,
.acpi_match_table = ACPI_PTR(stk8312_acpi_id),
},
.probe = stk8312_probe,
.remove = stk8312_remove,
.id_table = stk8312_i2c_id,
};
module_i2c_driver(stk8312_driver);
MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
MODULE_DESCRIPTION("STK8312 3-Axis Accelerometer driver");
MODULE_LICENSE("GPL v2");
/**
* Sensortek STK8BA50 3-Axis Accelerometer
*
* Copyright (c) 2015, Intel Corporation.
*
* This file is subject to the terms and conditions of version 2 of
* the GNU General Public License. See the file COPYING in the main
* directory of this archive for more details.
*
* STK8BA50 7-bit I2C address: 0x18.
*/
#include <linux/acpi.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#define STK8BA50_REG_XOUT 0x02
#define STK8BA50_REG_YOUT 0x04
#define STK8BA50_REG_ZOUT 0x06
#define STK8BA50_REG_RANGE 0x0F
#define STK8BA50_REG_POWMODE 0x11
#define STK8BA50_REG_SWRST 0x14
#define STK8BA50_MODE_NORMAL 0
#define STK8BA50_MODE_SUSPEND 1
#define STK8BA50_MODE_POWERBIT BIT(7)
#define STK8BA50_DATA_SHIFT 6
#define STK8BA50_RESET_CMD 0xB6
#define STK8BA50_DRIVER_NAME "stk8ba50"
#define STK8BA50_SCALE_AVAIL "0.0384 0.0767 0.1534 0.3069"
/*
* The accelerometer has four measurement ranges:
* +/-2g; +/-4g; +/-8g; +/-16g
*
* Acceleration values are 10-bit, 2's complement.
* Scales are calculated as following:
*
* scale1 = (2 + 2) * 9.81 / (2^10 - 1) = 0.0384
* scale2 = (4 + 4) * 9.81 / (2^10 - 1) = 0.0767
* etc.
*
* Scales are stored in this format:
* { <register value>, <scale value> }
*
* Locally, the range is stored as a table index.
*/
static const int stk8ba50_scale_table[][2] = {
{3, 38400}, {5, 76700}, {8, 153400}, {12, 306900}
};
struct stk8ba50_data {
struct i2c_client *client;
struct mutex lock;
int range;
};
#define STK8BA50_ACCEL_CHANNEL(reg, axis) { \
.type = IIO_ACCEL, \
.address = reg, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
}
static const struct iio_chan_spec stk8ba50_channels[] = {
STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_XOUT, X),
STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_YOUT, Y),
STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_ZOUT, Z),
};
static IIO_CONST_ATTR(in_accel_scale_available, STK8BA50_SCALE_AVAIL);
static struct attribute *stk8ba50_attributes[] = {
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
NULL,
};
static const struct attribute_group stk8ba50_attribute_group = {
.attrs = stk8ba50_attributes
};
static int stk8ba50_read_accel(struct stk8ba50_data *data, u8 reg)
{
int ret;
struct i2c_client *client = data->client;
ret = i2c_smbus_read_word_data(client, reg);
if (ret < 0) {
dev_err(&client->dev, "register read failed\n");
return ret;
}
return sign_extend32(ret >> STK8BA50_DATA_SHIFT, 9);
}
static int stk8ba50_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct stk8ba50_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&data->lock);
*val = stk8ba50_read_accel(data, chan->address);
mutex_unlock(&data->lock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = stk8ba50_scale_table[data->range][1];
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
static int stk8ba50_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
int ret;
int i;
int index = -1;
struct stk8ba50_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
if (val != 0)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(stk8ba50_scale_table); i++)
if (val2 == stk8ba50_scale_table[i][1]) {
index = i;
break;
}
if (index < 0)
return -EINVAL;
ret = i2c_smbus_write_byte_data(data->client,
STK8BA50_REG_RANGE,
stk8ba50_scale_table[index][0]);
if (ret < 0)
dev_err(&data->client->dev,
"failed to set measurement range\n");
else
data->range = index;
return ret;
}
return -EINVAL;
}
static const struct iio_info stk8ba50_info = {
.driver_module = THIS_MODULE,
.read_raw = stk8ba50_read_raw,
.write_raw = stk8ba50_write_raw,
.attrs = &stk8ba50_attribute_group,
};
static int stk8ba50_set_power(struct stk8ba50_data *data, bool mode)
{
int ret;
u8 masked_reg;
struct i2c_client *client = data->client;
ret = i2c_smbus_read_byte_data(client, STK8BA50_REG_POWMODE);
if (ret < 0)
goto exit_err;
if (mode)
masked_reg = ret | STK8BA50_MODE_POWERBIT;
else
masked_reg = ret & (~STK8BA50_MODE_POWERBIT);
ret = i2c_smbus_write_byte_data(client, STK8BA50_REG_POWMODE,
masked_reg);
if (ret < 0)
goto exit_err;
return ret;
exit_err:
dev_err(&client->dev, "failed to change sensor mode\n");
return ret;
}
static int stk8ba50_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret;
struct iio_dev *indio_dev;
struct stk8ba50_data *data;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev) {
dev_err(&client->dev, "iio allocation failed!\n");
return -ENOMEM;
}
data = iio_priv(indio_dev);
data->client = client;
i2c_set_clientdata(client, indio_dev);
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
indio_dev->info = &stk8ba50_info;
indio_dev->name = STK8BA50_DRIVER_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = stk8ba50_channels;
indio_dev->num_channels = ARRAY_SIZE(stk8ba50_channels);
/* Reset all registers on startup */
ret = i2c_smbus_write_byte_data(client,
STK8BA50_REG_SWRST, STK8BA50_RESET_CMD);
if (ret < 0) {
dev_err(&client->dev, "failed to reset sensor\n");
return ret;
}
/* The default range is +/-2g */
data->range = 0;
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "device_register failed\n");
stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
}
return ret;
}
static int stk8ba50_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
return stk8ba50_set_power(iio_priv(indio_dev), STK8BA50_MODE_SUSPEND);
}
#ifdef CONFIG_PM_SLEEP
static int stk8ba50_suspend(struct device *dev)
{
struct stk8ba50_data *data;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
return stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
}
static int stk8ba50_resume(struct device *dev)
{
struct stk8ba50_data *data;
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
return stk8ba50_set_power(data, STK8BA50_MODE_NORMAL);
}
static SIMPLE_DEV_PM_OPS(stk8ba50_pm_ops, stk8ba50_suspend, stk8ba50_resume);
#define STK8BA50_PM_OPS (&stk8ba50_pm_ops)
#else
#define STK8BA50_PM_OPS NULL
#endif
static const struct i2c_device_id stk8ba50_i2c_id[] = {
{"stk8ba50", 0},
{}
};
static const struct acpi_device_id stk8ba50_acpi_id[] = {
{"STK8BA50", 0},
{}
};
MODULE_DEVICE_TABLE(acpi, stk8ba50_acpi_id);
static struct i2c_driver stk8ba50_driver = {
.driver = {
.name = "stk8ba50",
.pm = STK8BA50_PM_OPS,
.acpi_match_table = ACPI_PTR(stk8ba50_acpi_id),
},
.probe = stk8ba50_probe,
.remove = stk8ba50_remove,
.id_table = stk8ba50_i2c_id,
};
module_i2c_driver(stk8ba50_driver);
MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
MODULE_DESCRIPTION("STK8BA50 3-Axis Accelerometer driver");
MODULE_LICENSE("GPL v2");
......@@ -135,6 +135,13 @@ config AXP288_ADC
device. Depending on platform configuration, this general purpose ADC can
be used for sampling sensors such as thermal resistors.
config BERLIN2_ADC
tristate "Marvell Berlin2 ADC driver"
depends on ARCH_BERLIN
help
Marvell Berlin2 ADC driver. This ADC has 8 channels, with one used for
temperature measurement.
config DA9150_GPADC
tristate "Dialog DA9150 GPADC driver support"
depends on MFD_DA9150
......@@ -285,11 +292,11 @@ config TI_ADC081C
called ti-adc081c.
config TI_ADC128S052
tristate "Texas Instruments ADC128S052"
tristate "Texas Instruments ADC128S052/ADC122S021"
depends on SPI
help
If you say yes here you get support for Texas Instruments ADC128S052
chip.
and ADC122S021 chips.
This driver can also be built as a module. If so, the module will be
called ti-adc128s052.
......
......@@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
obj-$(CONFIG_AD799X) += ad799x.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_AXP288_ADC) += axp288_adc.o
obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o
obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
......
......@@ -238,7 +238,7 @@ static int axp288_adc_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id axp288_adc_id_table[] = {
static const struct platform_device_id axp288_adc_id_table[] = {
{ .name = "axp288_adc" },
{},
};
......
This diff is collapsed.
/*
* Copyright (C) 2014 Angelo Compagnucci <angelo.compagnucci@gmail.com>
*
* Driver for Texas Instruments' ADC128S052 ADC chip.
* Datasheet can be found here:
* Driver for Texas Instruments' ADC128S052 and ADC122S021 ADC chip.
* Datasheets can be found here:
* http://www.ti.com/lit/ds/symlink/adc128s052.pdf
* http://www.ti.com/lit/ds/symlink/adc122s021.pdf
*
* 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
......@@ -16,6 +17,11 @@
#include <linux/iio/iio.h>
#include <linux/regulator/consumer.h>
struct adc128_configuration {
const struct iio_chan_spec *channels;
u8 num_channels;
};
struct adc128 {
struct spi_device *spi;
......@@ -92,7 +98,7 @@ static int adc128_read_raw(struct iio_dev *indio_dev,
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
}
static const struct iio_chan_spec adc128_channels[] = {
static const struct iio_chan_spec adc128s052_channels[] = {
ADC128_VOLTAGE_CHANNEL(0),
ADC128_VOLTAGE_CHANNEL(1),
ADC128_VOLTAGE_CHANNEL(2),
......@@ -103,6 +109,16 @@ static const struct iio_chan_spec adc128_channels[] = {
ADC128_VOLTAGE_CHANNEL(7),
};
static const struct iio_chan_spec adc122s021_channels[] = {
ADC128_VOLTAGE_CHANNEL(0),
ADC128_VOLTAGE_CHANNEL(1),
};
static const struct adc128_configuration adc128_config[] = {
{ adc128s052_channels, ARRAY_SIZE(adc128s052_channels) },
{ adc122s021_channels, ARRAY_SIZE(adc122s021_channels) },
};
static const struct iio_info adc128_info = {
.read_raw = adc128_read_raw,
.driver_module = THIS_MODULE,
......@@ -112,6 +128,7 @@ static int adc128_probe(struct spi_device *spi)
{
struct iio_dev *indio_dev;
struct adc128 *adc;
int config = spi_get_device_id(spi)->driver_data;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
......@@ -128,8 +145,8 @@ static int adc128_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &adc128_info;
indio_dev->channels = adc128_channels;
indio_dev->num_channels = ARRAY_SIZE(adc128_channels);
indio_dev->channels = adc128_config[config].channels;
indio_dev->num_channels = adc128_config[config].num_channels;
adc->reg = devm_regulator_get(&spi->dev, "vref");
if (IS_ERR(adc->reg))
......@@ -158,7 +175,8 @@ static int adc128_remove(struct spi_device *spi)
}
static const struct spi_device_id adc128_id[] = {
{ "adc128s052", 0},
{ "adc128s052", 0}, /* index into adc128_config */
{ "adc122s021", 1},
{ }
};
MODULE_DEVICE_TABLE(spi, adc128_id);
......
......@@ -37,6 +37,7 @@ struct tiadc_device {
u8 channel_step[8];
int buffer_en_ch_steps;
u16 data[8];
u32 open_delay[8], sample_delay[8], step_avg[8];
};
static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg)
......@@ -85,6 +86,7 @@ static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
static void tiadc_step_config(struct iio_dev *indio_dev)
{
struct tiadc_device *adc_dev = iio_priv(indio_dev);
struct device *dev = adc_dev->mfd_tscadc->dev;
unsigned int stepconfig;
int i, steps = 0;
......@@ -98,20 +100,47 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
* needs to be given to ADC to digitalize data.
*/
if (iio_buffer_enabled(indio_dev))
stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1
| STEPCONFIG_MODE_SWCNT;
else
stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1;
for (i = 0; i < adc_dev->channels; i++) {
int chan;
chan = adc_dev->channel_line[i];
if (adc_dev->step_avg[i] > STEPCONFIG_AVG_16) {
dev_warn(dev, "chan %d step_avg truncating to %d\n",
chan, STEPCONFIG_AVG_16);
adc_dev->step_avg[i] = STEPCONFIG_AVG_16;
}
if (adc_dev->step_avg[i])
stepconfig =
STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) |
STEPCONFIG_FIFO1;
else
stepconfig = STEPCONFIG_FIFO1;
if (iio_buffer_enabled(indio_dev))
stepconfig |= STEPCONFIG_MODE_SWCNT;
tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
stepconfig | STEPCONFIG_INP(chan));
if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) {
dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n",
chan);
adc_dev->open_delay[i] = STEPDELAY_OPEN_MASK;
}
if (adc_dev->sample_delay[i] > 0xFF) {
dev_warn(dev, "chan %d sample delay truncating to 0xFF\n",
chan);
adc_dev->sample_delay[i] = 0xFF;
}
tiadc_writel(adc_dev, REG_STEPDELAY(steps),
STEPCONFIG_OPENDLY);
STEPDELAY_OPEN(adc_dev->open_delay[i]) |
STEPDELAY_SAMPLE(adc_dev->sample_delay[i]));
adc_dev->channel_step[i] = steps;
steps++;
}
......@@ -406,9 +435,22 @@ static int tiadc_parse_dt(struct platform_device *pdev,
of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
adc_dev->channel_line[channels] = val;
/* Set Default values for optional DT parameters */
adc_dev->open_delay[channels] = STEPCONFIG_OPENDLY;
adc_dev->sample_delay[channels] = STEPCONFIG_SAMPLEDLY;
adc_dev->step_avg[channels] = 16;
channels++;
}
of_property_read_u32_array(node, "ti,chan-step-avg",
adc_dev->step_avg, channels);
of_property_read_u32_array(node, "ti,chan-step-opendelay",
adc_dev->open_delay, channels);
of_property_read_u32_array(node, "ti,chan-step-sampledelay",
adc_dev->sample_delay, channels);
adc_dev->channels = channels;
return 0;
}
......
......@@ -142,6 +142,16 @@ config AD7303
To compile this driver as module choose M here: the module will be called
ad7303.
config M62332
tristate "Mitsubishi M62332 DAC driver"
depends on I2C
help
If you say yes here you get support for the Mitsubishi M62332
(I2C 8-Bit DACs with rail-to-rail outputs).
This driver can also be built as a module. If so, the module
will be called m62332.
config MAX517
tristate "Maxim MAX517/518/519/520/521 DAC driver"
depends on I2C
......
......@@ -16,6 +16,7 @@ obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o
obj-$(CONFIG_AD7303) += ad7303.o
obj-$(CONFIG_M62332) += m62332.o
obj-$(CONFIG_MAX517) += max517.o
obj-$(CONFIG_MAX5821) += max5821.o
obj-$(CONFIG_MCP4725) += mcp4725.o
......
/*
* m62332.c - Support for Mitsubishi m62332 DAC
*
* Copyright (c) 2014 Dmitry Eremin-Solenikov
*
* Based on max517 driver:
* Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de>
*
* 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/slab.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
#include <linux/iio/driver.h>
#include <linux/regulator/consumer.h>
#define M62332_CHANNELS 2
struct m62332_data {
struct i2c_client *client;
u16 vref_mv;
struct regulator *vcc;
struct mutex mutex;
u8 raw[M62332_CHANNELS];
#ifdef CONFIG_PM_SLEEP
u8 save[M62332_CHANNELS];
#endif
};
static int m62332_set_value(struct iio_dev *indio_dev,
u8 val, int channel)
{
struct m62332_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
u8 outbuf[2];
int res;
if (val == data->raw[channel])
return 0;
outbuf[0] = channel;
outbuf[1] = val;
mutex_lock(&data->mutex);
if (val) {
res = regulator_enable(data->vcc);
if (res)
goto out;
}
res = i2c_master_send(client, outbuf, 2);
if (res >= 0 && res != 2)
res = -EIO;
if (res < 0)
goto out;
data->raw[channel] = val;
if (!val)
regulator_disable(data->vcc);
mutex_unlock(&data->mutex);
return 0;
out:
mutex_unlock(&data->mutex);
return res;
}
static int m62332_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long m)
{
struct m62332_data *data = iio_priv(indio_dev);
switch (m) {
case IIO_CHAN_INFO_SCALE:
/* Corresponds to Vref / 2^(bits) */
*val = data->vref_mv;
*val2 = 8;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_CHAN_INFO_RAW:
*val = data->raw[chan->channel];
return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET:
*val = 1;
return IIO_VAL_INT;
default:
break;
}
return -EINVAL;
}
static int m62332_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val, int val2, long mask)
{
int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
if (val < 0 || val > 255)
return -EINVAL;
ret = m62332_set_value(indio_dev, val, chan->channel);
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
#ifdef CONFIG_PM_SLEEP
static int m62332_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct m62332_data *data = iio_priv(indio_dev);
int ret;
data->save[0] = data->raw[0];
data->save[1] = data->raw[1];
ret = m62332_set_value(indio_dev, 0, 0);
if (ret < 0)
return ret;
return m62332_set_value(indio_dev, 0, 1);
}
static int m62332_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct m62332_data *data = iio_priv(indio_dev);
int ret;
ret = m62332_set_value(indio_dev, data->save[0], 0);
if (ret < 0)
return ret;
return m62332_set_value(indio_dev, data->save[1], 1);
}
static SIMPLE_DEV_PM_OPS(m62332_pm_ops, m62332_suspend, m62332_resume);
#define M62332_PM_OPS (&m62332_pm_ops)
#else
#define M62332_PM_OPS NULL
#endif
static const struct iio_info m62332_info = {
.read_raw = m62332_read_raw,
.write_raw = m62332_write_raw,
.driver_module = THIS_MODULE,
};
#define M62332_CHANNEL(chan) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (chan), \
.datasheet_name = "CH" #chan, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_OFFSET), \
}
static const struct iio_chan_spec m62332_channels[M62332_CHANNELS] = {
M62332_CHANNEL(0),
M62332_CHANNEL(1)
};
static int m62332_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct m62332_data *data;
struct iio_dev *indio_dev;
int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
mutex_init(&data->mutex);
data->vcc = devm_regulator_get(&client->dev, "VCC");
if (IS_ERR(data->vcc))
return PTR_ERR(data->vcc);
/* establish that the iio_dev is a child of the i2c device */
indio_dev->dev.parent = &client->dev;
indio_dev->num_channels = M62332_CHANNELS;
indio_dev->channels = m62332_channels;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &m62332_info;
ret = regulator_get_voltage(data->vcc);
if (ret < 0)
return ret;
data->vref_mv = ret / 1000; /* mV */
ret = iio_map_array_register(indio_dev, client->dev.platform_data);
if (ret < 0)
return ret;
ret = iio_device_register(indio_dev);
if (ret < 0)
goto err;
return 0;
err:
iio_map_array_unregister(indio_dev);
return ret;
}
static int m62332_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
iio_device_unregister(indio_dev);
iio_map_array_unregister(indio_dev);
return 0;
}
static const struct i2c_device_id m62332_id[] = {
{ "m62332", },
{ }
};
MODULE_DEVICE_TABLE(i2c, m62332_id);
static struct i2c_driver m62332_driver = {
.driver = {
.name = "m62332",
.pm = M62332_PM_OPS,
},
.probe = m62332_probe,
.remove = m62332_remove,
.id_table = m62332_id,
};
module_i2c_driver(m62332_driver);
MODULE_AUTHOR("Dmitry Eremin-Solenikov");
MODULE_DESCRIPTION("M62332 8-bit DAC");
MODULE_LICENSE("GPL v2");
......@@ -108,7 +108,6 @@ struct bmg160_data {
int slope_thres;
bool dready_trigger_on;
bool motion_trigger_on;
int64_t timestamp;
};
enum bmg160_axis {
......@@ -738,17 +737,6 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev,
return 0;
}
static int bmg160_validate_trigger(struct iio_dev *indio_dev,
struct iio_trigger *trig)
{
struct bmg160_data *data = iio_priv(indio_dev);
if (data->dready_trig != trig && data->motion_trig != trig)
return -EINVAL;
return 0;
}
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 400 1000 2000");
static IIO_CONST_ATTR(in_anglvel_scale_available,
......@@ -810,7 +798,6 @@ static const struct iio_info bmg160_info = {
.write_event_value = bmg160_write_event,
.write_event_config = bmg160_write_event_config,
.read_event_config = bmg160_read_event_config,
.validate_trigger = bmg160_validate_trigger,
.driver_module = THIS_MODULE,
};
......@@ -835,7 +822,7 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p)
mutex_unlock(&data->mutex);
iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
data->timestamp);
pf->timestamp);
err:
iio_trigger_notify_done(indio_dev->trig);
......@@ -938,21 +925,21 @@ static irqreturn_t bmg160_event_handler(int irq, void *private)
IIO_MOD_X,
IIO_EV_TYPE_ROC,
dir),
data->timestamp);
iio_get_time_ns());
if (ret & BMG160_ANY_MOTION_BIT_Y)
iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
0,
IIO_MOD_Y,
IIO_EV_TYPE_ROC,
dir),
data->timestamp);
iio_get_time_ns());
if (ret & BMG160_ANY_MOTION_BIT_Z)
iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL,
0,
IIO_MOD_Z,
IIO_EV_TYPE_ROC,
dir),
data->timestamp);
iio_get_time_ns());
ack_intr_status:
if (!data->dready_trigger_on) {
......@@ -973,8 +960,6 @@ static irqreturn_t bmg160_data_rdy_trig_poll(int irq, void *private)
struct iio_dev *indio_dev = private;
struct bmg160_data *data = iio_priv(indio_dev);
data->timestamp = iio_get_time_ns();
if (data->dready_trigger_on)
iio_trigger_poll(data->dready_trig);
else if (data->motion_trigger_on)
......@@ -987,6 +972,27 @@ static irqreturn_t bmg160_data_rdy_trig_poll(int irq, void *private)
}
static int bmg160_buffer_preenable(struct iio_dev *indio_dev)
{
struct bmg160_data *data = iio_priv(indio_dev);
return bmg160_set_power_state(data, true);
}
static int bmg160_buffer_postdisable(struct iio_dev *indio_dev)
{
struct bmg160_data *data = iio_priv(indio_dev);
return bmg160_set_power_state(data, false);
}
static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
.preenable = bmg160_buffer_preenable,
.postenable = iio_triggered_buffer_postenable,
.predisable = iio_triggered_buffer_predisable,
.postdisable = bmg160_buffer_postdisable,
};
static int bmg160_gpio_probe(struct i2c_client *client,
struct bmg160_data *data)
......@@ -1103,16 +1109,16 @@ static int bmg160_probe(struct i2c_client *client,
data->motion_trig = NULL;
goto err_trigger_unregister;
}
}
ret = iio_triggered_buffer_setup(indio_dev,
NULL,
bmg160_trigger_handler,
NULL);
if (ret < 0) {
dev_err(&client->dev,
"iio triggered buffer setup failed\n");
goto err_trigger_unregister;
}
ret = iio_triggered_buffer_setup(indio_dev,
iio_pollfunc_store_time,
bmg160_trigger_handler,
&bmg160_buffer_setup_ops);
if (ret < 0) {
dev_err(&client->dev,
"iio triggered buffer setup failed\n");
goto err_trigger_unregister;
}
ret = iio_device_register(indio_dev);
......@@ -1135,8 +1141,7 @@ static int bmg160_probe(struct i2c_client *client,
err_iio_unregister:
iio_device_unregister(indio_dev);
err_buffer_cleanup:
if (data->dready_trig)
iio_triggered_buffer_cleanup(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
err_trigger_unregister:
if (data->dready_trig)
iio_trigger_unregister(data->dready_trig);
......@@ -1156,9 +1161,9 @@ static int bmg160_remove(struct i2c_client *client)
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
if (data->dready_trig) {
iio_triggered_buffer_cleanup(indio_dev);
iio_trigger_unregister(data->dready_trig);
iio_trigger_unregister(data->motion_trig);
}
......
......@@ -298,7 +298,6 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct gyro_3d_state *gyro_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state));
if (!indio_dev)
......@@ -317,21 +316,21 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
return ret;
}
channels = kmemdup(gyro_3d_channels, sizeof(gyro_3d_channels),
GFP_KERNEL);
if (!channels) {
indio_dev->channels = kmemdup(gyro_3d_channels,
sizeof(gyro_3d_channels), GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
}
ret = gyro_3d_parse_report(pdev, hsdev, channels,
HID_USAGE_SENSOR_GYRO_3D, gyro_state);
ret = gyro_3d_parse_report(pdev, hsdev,
(struct iio_chan_spec *)indio_dev->channels,
HID_USAGE_SENSOR_GYRO_3D, gyro_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
goto error_free_dev_mem;
}
indio_dev->channels = channels;
indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &gyro_3d_info;
......@@ -397,7 +396,7 @@ static int hid_gyro_3d_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id hid_gyro_3d_ids[] = {
static const struct platform_device_id hid_gyro_3d_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200076",
......
......@@ -5,7 +5,7 @@ menu "Humidity sensors"
config DHT11
tristate "DHT11 (and compatible sensors) driver"
depends on GPIOLIB
depends on GPIOLIB || COMPILE_TEST
help
This driver supports reading data via a single interrupt
generating GPIO line. Currently tested are DHT11 and DHT22.
......
This diff is collapsed.
......@@ -101,6 +101,8 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_WALKING] = "walking",
[IIO_MOD_STILL] = "still",
[IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
[IIO_MOD_I] = "i",
[IIO_MOD_Q] = "q",
};
/* relies on pairs of these shared then separate */
......@@ -117,6 +119,8 @@ static const char * const iio_chan_info_postfix[] = {
[IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw",
[IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY]
= "filter_low_pass_3db_frequency",
[IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY]
= "filter_high_pass_3db_frequency",
[IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency",
[IIO_CHAN_INFO_FREQUENCY] = "frequency",
[IIO_CHAN_INFO_PHASE] = "phase",
......@@ -129,6 +133,7 @@ static const char * const iio_chan_info_postfix[] = {
[IIO_CHAN_INFO_DEBOUNCE_COUNT] = "debounce_count",
[IIO_CHAN_INFO_DEBOUNCE_TIME] = "debounce_time",
[IIO_CHAN_INFO_CALIBEMISSIVITY] = "calibemissivity",
[IIO_CHAN_INFO_OVERSAMPLING_RATIO] = "oversampling_ratio",
};
/**
......
......@@ -211,6 +211,8 @@ static const char * const iio_ev_info_text[] = {
[IIO_EV_INFO_VALUE] = "value",
[IIO_EV_INFO_HYSTERESIS] = "hysteresis",
[IIO_EV_INFO_PERIOD] = "period",
[IIO_EV_INFO_HIGH_PASS_FILTER_3DB] = "high_pass_filter_3db",
[IIO_EV_INFO_LOW_PASS_FILTER_3DB] = "low_pass_filter_3db",
};
static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr)
......
......@@ -5,6 +5,19 @@
menu "Light sensors"
config ACPI_ALS
tristate "ACPI Ambient Light Sensor"
depends on ACPI
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select IIO_KFIFO_BUF
help
Say Y here if you want to build a driver for the ACPI0008
Ambient Light Sensor.
To compile this driver as a module, choose M here: the module will
be called acpi-als.
config ADJD_S311
tristate "ADJD-S311-CR999 digital color sensor"
select IIO_BUFFER
......@@ -37,6 +50,16 @@ config APDS9300
To compile this driver as a module, choose M here: the
module will be called apds9300.
config BH1750
tristate "ROHM BH1750 ambient light sensor"
depends on I2C
help
Say Y here to build support for the ROHM BH1710, BH1715, BH1721,
BH1750, BH1751 ambient light sensors.
To compile this driver as a module, choose M here: the module will
be called bh1750.
config CM32181
depends on I2C
tristate "CM32181 driver"
......@@ -175,6 +198,17 @@ config LTR501
This driver can also be built as a module. If so, the module
will be called ltr501.
config STK3310
tristate "STK3310 ALS and proximity sensor"
depends on I2C
help
Say yes here to get support for the Sensortek STK3310 ambient light
and proximity sensor. The STK3311 model is also supported by this
driver.
Choosing M will build the driver as a module. If so, the module
will be called stk3310.
config TCS3414
tristate "TAOS TCS3414 digital color sensor"
depends on I2C
......
......@@ -3,9 +3,11 @@
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_ACPI_ALS) += acpi-als.o
obj-$(CONFIG_ADJD_S311) += adjd_s311.o
obj-$(CONFIG_AL3320A) += al3320a.o
obj-$(CONFIG_APDS9300) += apds9300.o
obj-$(CONFIG_BH1750) += bh1750.o
obj-$(CONFIG_CM32181) += cm32181.o
obj-$(CONFIG_CM3232) += cm3232.o
obj-$(CONFIG_CM3323) += cm3323.o
......@@ -18,6 +20,7 @@ obj-$(CONFIG_JSA1212) += jsa1212.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_LTR501) += ltr501.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
obj-$(CONFIG_STK3310) += stk3310.o
obj-$(CONFIG_TCS3414) += tcs3414.o
obj-$(CONFIG_TCS3472) += tcs3472.o
obj-$(CONFIG_TSL4531) += tsl4531.o
......
/*
* ACPI Ambient Light Sensor Driver
*
* Based on ALS driver:
* Copyright (C) 2009 Zhang Rui <rui.zhang@intel.com>
*
* Rework for IIO subsystem:
* Copyright (C) 2012-2013 Martin Liska <marxin.liska@gmail.com>
*
* Final cleanup and debugging:
* Copyright (C) 2013-2014 Marek Vasut <marex@denx.de>
* Copyright (C) 2015 Gabriele Mazzotta <gabriele.mzt@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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/acpi.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/kfifo_buf.h>
#define ACPI_ALS_CLASS "als"
#define ACPI_ALS_DEVICE_NAME "acpi-als"
#define ACPI_ALS_NOTIFY_ILLUMINANCE 0x80
ACPI_MODULE_NAME("acpi-als");
/*
* So far, there's only one channel in here, but the specification for
* ACPI0008 says there can be more to what the block can report. Like
* chromaticity and such. We are ready for incoming additions!
*/
static const struct iio_chan_spec acpi_als_channels[] = {
{
.type = IIO_LIGHT,
.scan_type = {
.sign = 's',
.realbits = 32,
.storagebits = 32,
},
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
},
};
/*
* The event buffer contains timestamp and all the data from
* the ACPI0008 block. There are multiple, but so far we only
* support _ALI (illuminance). Once someone adds new channels
* to acpi_als_channels[], the evt_buffer below will grow
* automatically.
*/
#define EVT_NR_SOURCES ARRAY_SIZE(acpi_als_channels)
#define EVT_BUFFER_SIZE \
(sizeof(s64) + (EVT_NR_SOURCES * sizeof(s32)))
struct acpi_als {
struct acpi_device *device;
struct mutex lock;
s32 evt_buffer[EVT_BUFFER_SIZE];
};
/*
* All types of properties the ACPI0008 block can report. The ALI, ALC, ALT
* and ALP can all be handled by als_read_value() below, while the ALR is
* special.
*
* The _ALR property returns tables that can be used to fine-tune the values
* reported by the other props based on the particular hardware type and it's
* location (it contains tables for "rainy", "bright inhouse lighting" etc.).
*
* So far, we support only ALI (illuminance).
*/
#define ACPI_ALS_ILLUMINANCE "_ALI"
#define ACPI_ALS_CHROMATICITY "_ALC"
#define ACPI_ALS_COLOR_TEMP "_ALT"
#define ACPI_ALS_POLLING "_ALP"
#define ACPI_ALS_TABLES "_ALR"
static int als_read_value(struct acpi_als *als, char *prop, s32 *val)
{
unsigned long long temp_val;
acpi_status status;
status = acpi_evaluate_integer(als->device->handle, prop, NULL,
&temp_val);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Error reading ALS %s", prop));
return -EIO;
}
*val = temp_val;
return 0;
}
static void acpi_als_notify(struct acpi_device *device, u32 event)
{
struct iio_dev *indio_dev = acpi_driver_data(device);
struct acpi_als *als = iio_priv(indio_dev);
s32 *buffer = als->evt_buffer;
s64 time_ns = iio_get_time_ns();
s32 val;
int ret;
mutex_lock(&als->lock);
memset(buffer, 0, EVT_BUFFER_SIZE);
switch (event) {
case ACPI_ALS_NOTIFY_ILLUMINANCE:
ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &val);
if (ret < 0)
goto out;
*buffer++ = val;
break;
default:
/* Unhandled event */
dev_dbg(&device->dev, "Unhandled ACPI ALS event (%08x)!\n",
event);
goto out;
}
iio_push_to_buffers_with_timestamp(indio_dev, als->evt_buffer, time_ns);
out:
mutex_unlock(&als->lock);
}
static int acpi_als_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
{
struct acpi_als *als = iio_priv(indio_dev);
s32 temp_val;
int ret;
if (mask != IIO_CHAN_INFO_RAW)
return -EINVAL;
/* we support only illumination (_ALI) so far. */
if (chan->type != IIO_LIGHT)
return -EINVAL;
ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val);
if (ret < 0)
return ret;
*val = temp_val;
return IIO_VAL_INT;
}
static const struct iio_info acpi_als_info = {
.driver_module = THIS_MODULE,
.read_raw = acpi_als_read_raw,
};
static int acpi_als_add(struct acpi_device *device)
{
struct acpi_als *als;
struct iio_dev *indio_dev;
struct iio_buffer *buffer;
indio_dev = devm_iio_device_alloc(&device->dev, sizeof(*als));
if (!indio_dev)
return -ENOMEM;
als = iio_priv(indio_dev);
device->driver_data = indio_dev;
als->device = device;
mutex_init(&als->lock);
indio_dev->name = ACPI_ALS_DEVICE_NAME;
indio_dev->dev.parent = &device->dev;
indio_dev->info = &acpi_als_info;
indio_dev->modes = INDIO_BUFFER_SOFTWARE;
indio_dev->channels = acpi_als_channels;
indio_dev->num_channels = ARRAY_SIZE(acpi_als_channels);
buffer = devm_iio_kfifo_allocate(&device->dev);
if (!buffer)
return -ENOMEM;
iio_device_attach_buffer(indio_dev, buffer);
return devm_iio_device_register(&device->dev, indio_dev);
}
static const struct acpi_device_id acpi_als_device_ids[] = {
{"ACPI0008", 0},
{},
};
MODULE_DEVICE_TABLE(acpi, acpi_als_device_ids);
static struct acpi_driver acpi_als_driver = {
.name = "acpi_als",
.class = ACPI_ALS_CLASS,
.ids = acpi_als_device_ids,
.ops = {
.add = acpi_als_add,
.notify = acpi_als_notify,
},
};
module_acpi_driver(acpi_als_driver);
MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
MODULE_AUTHOR("Martin Liska <marxin.liska@gmail.com>");
MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
MODULE_DESCRIPTION("ACPI Ambient Light Sensor Driver");
MODULE_LICENSE("GPL");
/*
* ROHM BH1710/BH1715/BH1721/BH1750/BH1751 ambient light sensor driver
*
* Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
*
* 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.
*
* Data sheets:
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1710fvc-e.pdf
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1715fvc-e.pdf
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1721fvc-e.pdf
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1750fvi-e.pdf
* http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1751fvi-e.pdf
*
* 7-bit I2C slave addresses:
* 0x23 (ADDR pin low)
* 0x5C (ADDR pin high)
*
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/module.h>
#define BH1750_POWER_DOWN 0x00
#define BH1750_ONE_TIME_H_RES_MODE 0x20 /* auto-mode for BH1721 */
#define BH1750_CHANGE_INT_TIME_H_BIT 0x40
#define BH1750_CHANGE_INT_TIME_L_BIT 0x60
enum {
BH1710,
BH1721,
BH1750,
};
struct bh1750_chip_info;
struct bh1750_data {
struct i2c_client *client;
struct mutex lock;
const struct bh1750_chip_info *chip_info;
u16 mtreg;
};
struct bh1750_chip_info {
u16 mtreg_min;
u16 mtreg_max;
u16 mtreg_default;
int mtreg_to_usec;
int mtreg_to_scale;
/*
* For BH1710/BH1721 all possible integration time values won't fit
* into one page so displaying is limited to every second one.
* Note, that user can still write proper values which were not
* listed.
*/
int inc;
u16 int_time_low_mask;
u16 int_time_high_mask;
}
static const bh1750_chip_info_tbl[] = {
[BH1710] = { 140, 1022, 300, 400, 250000000, 2, 0x001F, 0x03E0 },
[BH1721] = { 140, 1020, 300, 400, 250000000, 2, 0x0010, 0x03E0 },
[BH1750] = { 31, 254, 69, 1740, 57500000, 1, 0x001F, 0x00E0 },
};
static int bh1750_change_int_time(struct bh1750_data *data, int usec)
{
int ret;
u16 val;
u8 regval;
const struct bh1750_chip_info *chip_info = data->chip_info;
if ((usec % chip_info->mtreg_to_usec) != 0)
return -EINVAL;
val = usec / chip_info->mtreg_to_usec;
if (val < chip_info->mtreg_min || val > chip_info->mtreg_max)
return -EINVAL;
ret = i2c_smbus_write_byte(data->client, BH1750_POWER_DOWN);
if (ret < 0)
return ret;
regval = (val & chip_info->int_time_high_mask) >> 5;
ret = i2c_smbus_write_byte(data->client,
BH1750_CHANGE_INT_TIME_H_BIT | regval);
if (ret < 0)
return ret;
regval = val & chip_info->int_time_low_mask;
ret = i2c_smbus_write_byte(data->client,
BH1750_CHANGE_INT_TIME_L_BIT | regval);
if (ret < 0)
return ret;
data->mtreg = val;
return 0;
}
static int bh1750_read(struct bh1750_data *data, int *val)
{
int ret;
__be16 result;
const struct bh1750_chip_info *chip_info = data->chip_info;
unsigned long delay = chip_info->mtreg_to_usec * data->mtreg;
/*
* BH1721 will enter continuous mode on receiving this command.
* Note, that this eliminates need for bh1750_resume().
*/
ret = i2c_smbus_write_byte(data->client, BH1750_ONE_TIME_H_RES_MODE);
if (ret < 0)
return ret;
usleep_range(delay + 15000, delay + 40000);
ret = i2c_master_recv(data->client, (char *)&result, 2);
if (ret < 0)
return ret;
*val = be16_to_cpu(result);
return 0;
}
static int bh1750_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
int ret, tmp;
struct bh1750_data *data = iio_priv(indio_dev);
const struct bh1750_chip_info *chip_info = data->chip_info;
switch (mask) {
case IIO_CHAN_INFO_RAW:
switch (chan->type) {
case IIO_LIGHT:
mutex_lock(&data->lock);
ret = bh1750_read(data, val);
mutex_unlock(&data->lock);
if (ret < 0)
return ret;
return IIO_VAL_INT;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_SCALE:
tmp = chip_info->mtreg_to_scale / data->mtreg;
*val = tmp / 1000000;
*val2 = tmp % 1000000;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_INT_TIME:
*val = 0;
*val2 = chip_info->mtreg_to_usec * data->mtreg;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
}
}
static int bh1750_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
int ret;
struct bh1750_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_INT_TIME:
if (val != 0)
return -EINVAL;
mutex_lock(&data->lock);
ret = bh1750_change_int_time(data, val2);
mutex_unlock(&data->lock);
return ret;
default:
return -EINVAL;
}
}
static ssize_t bh1750_show_int_time_available(struct device *dev,
struct device_attribute *attr, char *buf)
{
int i;
size_t len = 0;
struct bh1750_data *data = iio_priv(dev_to_iio_dev(dev));
const struct bh1750_chip_info *chip_info = data->chip_info;
for (i = chip_info->mtreg_min; i <= chip_info->mtreg_max; i += chip_info->inc)
len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06d ",
chip_info->mtreg_to_usec * i);
buf[len - 1] = '\n';
return len;
}
static IIO_DEV_ATTR_INT_TIME_AVAIL(bh1750_show_int_time_available);
static struct attribute *bh1750_attributes[] = {
&iio_dev_attr_integration_time_available.dev_attr.attr,
NULL,
};
static struct attribute_group bh1750_attribute_group = {
.attrs = bh1750_attributes,
};
static const struct iio_info bh1750_info = {
.driver_module = THIS_MODULE,
.attrs = &bh1750_attribute_group,
.read_raw = bh1750_read_raw,
.write_raw = bh1750_write_raw,
};
static const struct iio_chan_spec bh1750_channels[] = {
{
.type = IIO_LIGHT,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_INT_TIME)
}
};
static int bh1750_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret, usec;
struct bh1750_data *data;
struct iio_dev *indio_dev;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
I2C_FUNC_SMBUS_WRITE_BYTE))
return -ENODEV;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
return -ENOMEM;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
data->chip_info = &bh1750_chip_info_tbl[id->driver_data];
usec = data->chip_info->mtreg_to_usec * data->chip_info->mtreg_default;
ret = bh1750_change_int_time(data, usec);
if (ret < 0)
return ret;
mutex_init(&data->lock);
indio_dev->dev.parent = &client->dev;
indio_dev->info = &bh1750_info;
indio_dev->name = id->name;
indio_dev->channels = bh1750_channels;
indio_dev->num_channels = ARRAY_SIZE(bh1750_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
return iio_device_register(indio_dev);
}
static int bh1750_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct bh1750_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
mutex_lock(&data->lock);
i2c_smbus_write_byte(client, BH1750_POWER_DOWN);
mutex_unlock(&data->lock);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int bh1750_suspend(struct device *dev)
{
int ret;
struct bh1750_data *data =
iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
/*
* This is mainly for BH1721 which doesn't enter power down
* mode automatically.
*/
mutex_lock(&data->lock);
ret = i2c_smbus_write_byte(data->client, BH1750_POWER_DOWN);
mutex_unlock(&data->lock);
return ret;
}
static SIMPLE_DEV_PM_OPS(bh1750_pm_ops, bh1750_suspend, NULL);
#define BH1750_PM_OPS (&bh1750_pm_ops)
#else
#define BH1750_PM_OPS NULL
#endif
static const struct i2c_device_id bh1750_id[] = {
{ "bh1710", BH1710 },
{ "bh1715", BH1750 },
{ "bh1721", BH1721 },
{ "bh1750", BH1750 },
{ "bh1751", BH1750 },
{ }
};
MODULE_DEVICE_TABLE(i2c, bh1750_id);
static struct i2c_driver bh1750_driver = {
.driver = {
.name = "bh1750",
.owner = THIS_MODULE,
.pm = BH1750_PM_OPS,
},
.probe = bh1750_probe,
.remove = bh1750_remove,
.id_table = bh1750_id,
};
module_i2c_driver(bh1750_driver);
MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
MODULE_DESCRIPTION("ROHM BH1710/BH1715/BH1721/BH1750/BH1751 als driver");
MODULE_LICENSE("GPL v2");
......@@ -263,7 +263,6 @@ static int hid_als_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct als_state *als_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state));
if (!indio_dev)
......@@ -281,20 +280,21 @@ static int hid_als_probe(struct platform_device *pdev)
return ret;
}
channels = kmemdup(als_channels, sizeof(als_channels), GFP_KERNEL);
if (!channels) {
indio_dev->channels = kmemdup(als_channels,
sizeof(als_channels), GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
}
ret = als_parse_report(pdev, hsdev, channels,
HID_USAGE_SENSOR_ALS, als_state);
ret = als_parse_report(pdev, hsdev,
(struct iio_chan_spec *)indio_dev->channels,
HID_USAGE_SENSOR_ALS, als_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
goto error_free_dev_mem;
}
indio_dev->channels = channels;
indio_dev->num_channels =
ARRAY_SIZE(als_channels);
indio_dev->dev.parent = &pdev->dev;
......@@ -361,7 +361,7 @@ static int hid_als_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id hid_als_ids[] = {
static const struct platform_device_id hid_als_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200041",
......
......@@ -350,7 +350,7 @@ static int hid_prox_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id hid_prox_ids[] = {
static const struct platform_device_id hid_prox_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200011",
......
......@@ -66,6 +66,9 @@
#define LTR501_REGMAP_NAME "ltr501_regmap"
#define LTR501_LUX_CONV(vis_coeff, vis_data, ir_coeff, ir_data) \
((vis_coeff * vis_data) - (ir_coeff * ir_data))
static const int int_time_mapping[] = {100000, 50000, 200000, 400000};
static const struct reg_field reg_field_it =
......@@ -298,6 +301,29 @@ static int ltr501_ps_read_samp_period(struct ltr501_data *data, int *val)
return IIO_VAL_INT;
}
/* IR and visible spectrum coeff's are given in data sheet */
static unsigned long ltr501_calculate_lux(u16 vis_data, u16 ir_data)
{
unsigned long ratio, lux;
if (vis_data == 0)
return 0;
/* multiply numerator by 100 to avoid handling ratio < 1 */
ratio = DIV_ROUND_UP(ir_data * 100, ir_data + vis_data);
if (ratio < 45)
lux = LTR501_LUX_CONV(1774, vis_data, -1105, ir_data);
else if (ratio >= 45 && ratio < 64)
lux = LTR501_LUX_CONV(3772, vis_data, 1336, ir_data);
else if (ratio >= 64 && ratio < 85)
lux = LTR501_LUX_CONV(1690, vis_data, 169, ir_data);
else
lux = 0;
return lux / 1000;
}
static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask)
{
int tries = 100;
......@@ -548,7 +574,14 @@ static const struct iio_event_spec ltr501_pxs_event_spec[] = {
.num_event_specs = _evsize,\
}
#define LTR501_LIGHT_CHANNEL() { \
.type = IIO_LIGHT, \
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
.scan_index = -1, \
}
static const struct iio_chan_spec ltr501_channels[] = {
LTR501_LIGHT_CHANNEL(),
LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0,
ltr501_als_event_spec,
ARRAY_SIZE(ltr501_als_event_spec)),
......@@ -576,6 +609,7 @@ static const struct iio_chan_spec ltr501_channels[] = {
};
static const struct iio_chan_spec ltr301_channels[] = {
LTR501_LIGHT_CHANNEL(),
LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0,
ltr501_als_event_spec,
ARRAY_SIZE(ltr501_als_event_spec)),
......@@ -596,6 +630,23 @@ static int ltr501_read_raw(struct iio_dev *indio_dev,
int ret, i;
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
switch (chan->type) {
case IIO_LIGHT:
mutex_lock(&data->lock_als);
ret = ltr501_read_als(data, buf);
mutex_unlock(&data->lock_als);
if (ret < 0)
return ret;
*val = ltr501_calculate_lux(le16_to_cpu(buf[1]),
le16_to_cpu(buf[0]));
return IIO_VAL_INT;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_RAW:
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
......@@ -865,9 +916,9 @@ static int ltr501_write_thresh(struct iio_dev *indio_dev,
return -EINVAL;
}
case IIO_PROXIMITY:
switch (dir) {
if (val > LTR501_PS_THRESH_MASK)
return -EINVAL;
switch (dir) {
case IIO_EV_DIR_RISING:
mutex_lock(&data->lock_ps);
ret = regmap_bulk_write(data->regmap,
......
This diff is collapsed.
......@@ -8,7 +8,7 @@ menu "Magnetometer sensors"
config AK8975
tristate "Asahi Kasei AK 3-Axis Magnetometer"
depends on I2C
depends on GPIOLIB
depends on GPIOLIB || COMPILE_TEST
help
Say yes here to build support for Asahi Kasei AK8975, AK8963,
AK09911 or AK09912 3-Axis Magnetometer.
......@@ -19,7 +19,7 @@ config AK8975
config AK09911
tristate "Asahi Kasei AK09911 3-axis Compass"
depends on I2C
depends on GPIOLIB
depends on GPIOLIB || COMPILE_TEST
select AK8975
help
Deprecated: AK09911 is now supported by AK8975 driver.
......@@ -47,6 +47,17 @@ config HID_SENSOR_MAGNETOMETER_3D
Say yes here to build support for the HID SENSOR
Magnetometer 3D.
config MMC35240
tristate "MEMSIC MMC35240 3-axis magnetic sensor"
select REGMAP_I2C
depends on I2C
help
Say yes here to build support for the MEMSIC MMC35240 3-axis
magnetic sensor.
To compile this driver as a module, choose M here: the module
will be called mmc35240.
config IIO_ST_MAGN_3AXIS
tristate "STMicroelectronics magnetometers 3-Axis Driver"
depends on (I2C || SPI_MASTER) && SYSFS
......@@ -76,4 +87,18 @@ config IIO_ST_MAGN_SPI_3AXIS
depends on IIO_ST_MAGN_3AXIS
depends on IIO_ST_SENSORS_SPI
config BMC150_MAGN
tristate "Bosch BMC150 Magnetometer Driver"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for the BMC150 magnetometer.
Currently this only supports the device via an i2c interface.
This is a combo module with both accelerometer and magnetometer.
This driver is only implementing magnetometer part, which has
its own address and register map.
endmenu
......@@ -6,6 +6,7 @@
obj-$(CONFIG_AK8975) += ak8975.o
obj-$(CONFIG_MAG3110) += mag3110.o
obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
obj-$(CONFIG_MMC35240) += mmc35240.o
obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o
st_magn-y := st_magn_core.o
......@@ -13,3 +14,5 @@ st_magn-$(CONFIG_IIO_BUFFER) += st_magn_buffer.o
obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o
obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o
obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o
This diff is collapsed.
......@@ -510,7 +510,7 @@ static int hid_magn_3d_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id hid_magn_3d_ids[] = {
static const struct platform_device_id hid_magn_3d_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200083",
......
This diff is collapsed.
......@@ -315,7 +315,6 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct incl_3d_state *incl_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct incl_3d_state));
......@@ -336,21 +335,22 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
return ret;
}
channels = kmemdup(incl_3d_channels, sizeof(incl_3d_channels),
GFP_KERNEL);
if (!channels) {
indio_dev->channels = kmemdup(incl_3d_channels,
sizeof(incl_3d_channels), GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
}
ret = incl_3d_parse_report(pdev, hsdev, channels,
HID_USAGE_SENSOR_INCLINOMETER_3D, incl_state);
ret = incl_3d_parse_report(pdev, hsdev,
(struct iio_chan_spec *)indio_dev->channels,
HID_USAGE_SENSOR_INCLINOMETER_3D,
incl_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
goto error_free_dev_mem;
}
indio_dev->channels = channels;
indio_dev->num_channels = ARRAY_SIZE(incl_3d_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &incl_3d_info;
......@@ -417,7 +417,7 @@ static int hid_incl_3d_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id hid_incl_3d_ids[] = {
static const struct platform_device_id hid_incl_3d_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200086",
......
......@@ -222,7 +222,6 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct dev_rot_state *rot_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct dev_rot_state));
......@@ -243,21 +242,23 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
return ret;
}
channels = devm_kmemdup(&pdev->dev, dev_rot_channels,
sizeof(dev_rot_channels), GFP_KERNEL);
if (!channels) {
indio_dev->channels = devm_kmemdup(&pdev->dev, dev_rot_channels,
sizeof(dev_rot_channels),
GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
}
ret = dev_rot_parse_report(pdev, hsdev, channels,
HID_USAGE_SENSOR_DEVICE_ORIENTATION, rot_state);
ret = dev_rot_parse_report(pdev, hsdev,
(struct iio_chan_spec *)indio_dev->channels,
HID_USAGE_SENSOR_DEVICE_ORIENTATION,
rot_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
return ret;
}
indio_dev->channels = channels;
indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &dev_rot_info;
......@@ -321,7 +322,7 @@ static int hid_dev_rot_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id hid_dev_rot_ids[] = {
static const struct platform_device_id hid_dev_rot_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-20008a",
......
......@@ -260,7 +260,6 @@ static int hid_press_probe(struct platform_device *pdev)
struct iio_dev *indio_dev;
struct press_state *press_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct press_state));
......@@ -280,20 +279,21 @@ static int hid_press_probe(struct platform_device *pdev)
return ret;
}
channels = kmemdup(press_channels, sizeof(press_channels), GFP_KERNEL);
if (!channels) {
indio_dev->channels = kmemdup(press_channels, sizeof(press_channels),
GFP_KERNEL);
if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
}
ret = press_parse_report(pdev, hsdev, channels,
HID_USAGE_SENSOR_PRESSURE, press_state);
ret = press_parse_report(pdev, hsdev,
(struct iio_chan_spec *)indio_dev->channels,
HID_USAGE_SENSOR_PRESSURE, press_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
goto error_free_dev_mem;
}
indio_dev->channels = channels;
indio_dev->num_channels =
ARRAY_SIZE(press_channels);
indio_dev->dev.parent = &pdev->dev;
......@@ -360,7 +360,7 @@ static int hid_press_remove(struct platform_device *pdev)
return 0;
}
static struct platform_device_id hid_press_ids[] = {
static const struct platform_device_id hid_press_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-200031",
......
......@@ -254,9 +254,7 @@ static int mlx90614_write_raw(struct iio_dev *indio_dev,
mutex_unlock(&data->lock);
mlx90614_power_put(data);
if (ret < 0)
return ret;
return 0;
return ret;
default:
return -EINVAL;
}
......
......@@ -79,7 +79,7 @@ config LIS3L02DQ
depends on SPI
select IIO_TRIGGER if IIO_BUFFER
depends on !IIO_BUFFER || IIO_KFIFO_BUF
depends on GPIOLIB
depends on GPIOLIB || COMPILE_TEST
help
Say Y here to build SPI support for the ST microelectronics
accelerometer. The driver supplies direct access via sysfs files
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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