summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2023-05-18 11:24:02 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2023-05-18 11:24:02 +1000
commit7856761916cf8cb3d5e92b0344f78bc6f9bedd22 (patch)
tree38fdf681d60bf27275d73f68059969e4ca649ef0
parenta678e7e10940743ffd5b6c5c63a124d53e3eade5 (diff)
parenta508fbfed333aea05e4ac42d98803a031cda8ce8 (diff)
downloadlinux-next-7856761916cf8cb3d5e92b0344f78bc6f9bedd22.tar.gz
Merge branch 'togreg' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
-rw-r--r--Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml1
-rw-r--r--Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml28
-rw-r--r--Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml68
-rw-r--r--Documentation/devicetree/bindings/iio/st,st-sensors.yaml1
-rw-r--r--drivers/iio/accel/bma400_core.c3
-rw-r--r--drivers/iio/accel/kionix-kx022a-i2c.c1
-rw-r--r--drivers/iio/accel/kionix-kx022a-spi.c1
-rw-r--r--drivers/iio/accel/st_accel_core.c1
-rw-r--r--drivers/iio/adc/palmas_gpadc.c1
-rw-r--r--drivers/iio/adc/stm32-adc.c2
-rw-r--r--drivers/iio/imu/st_lsm9ds0/Kconfig3
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c12
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c5
-rw-r--r--drivers/iio/industrialio-buffer.c98
-rw-r--r--drivers/iio/light/Kconfig11
-rw-r--r--drivers/iio/light/Makefile1
-rw-r--r--drivers/iio/light/al3320a.c8
-rw-r--r--drivers/iio/light/opt4001.c467
-rw-r--r--drivers/iio/light/rohm-bu27034.c1
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c1
-rw-r--r--include/linux/iio/common/st_sensors.h1
-rw-r--r--include/linux/platform_data/st_sensors_pdata.h2
22 files changed, 650 insertions, 67 deletions
diff --git a/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml b/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml
index 7f79a06e76f5..6168b44ea72c 100644
--- a/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/mediatek,mt2701-auxadc.yaml
@@ -26,6 +26,7 @@ properties:
- mediatek,mt2712-auxadc
- mediatek,mt6765-auxadc
- mediatek,mt7622-auxadc
+ - mediatek,mt7986-auxadc
- mediatek,mt8173-auxadc
- items:
- enum:
diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
index bd6e0d6f6e0c..ad7d6fc49de5 100644
--- a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
@@ -54,7 +54,7 @@ required:
- '#io-channel-cells'
patternProperties:
- "^.*@[0-9a-f]+$":
+ "^channel@[0-9a-f]+$":
type: object
additionalProperties: false
description: |
@@ -101,7 +101,7 @@ patternProperties:
oneOf:
- items:
- const: 1
- - enum: [ 1, 3, 4, 6, 20, 8, 10 ]
+ - enum: [ 1, 3, 4, 6, 20, 8, 10, 16 ]
- items:
- const: 10
- const: 81
@@ -148,7 +148,7 @@ allOf:
then:
patternProperties:
- "^.*@[0-9a-f]+$":
+ "^channel@[0-9a-f]+$":
properties:
qcom,decimation:
enum: [ 512, 1024, 2048, 4096 ]
@@ -171,7 +171,7 @@ allOf:
then:
patternProperties:
- "^.*@[0-9a-f]+$":
+ "^channel@[0-9a-f]+$":
properties:
qcom,decimation:
enum: [ 256, 512, 1024 ]
@@ -194,7 +194,7 @@ allOf:
then:
patternProperties:
- "^.*@[0-9a-f]+$":
+ "^channel@[0-9a-f]+$":
properties:
qcom,decimation:
enum: [ 250, 420, 840 ]
@@ -217,7 +217,7 @@ allOf:
then:
patternProperties:
- "^.*@[0-9a-f]+$":
+ "^channel@[0-9a-f]+$":
properties:
qcom,decimation:
enum: [ 85, 340, 1360 ]
@@ -249,7 +249,7 @@ examples:
#io-channel-cells = <1>;
/* Channel node */
- adc-chan@39 {
+ channel@39 {
reg = <0x39>;
qcom,decimation = <512>;
qcom,ratiometric;
@@ -258,19 +258,19 @@ examples:
qcom,pre-scaling = <1 3>;
};
- adc-chan@9 {
+ channel@9 {
reg = <0x9>;
};
- adc-chan@a {
+ channel@a {
reg = <0xa>;
};
- adc-chan@e {
+ channel@e {
reg = <0xe>;
};
- adc-chan@f {
+ channel@f {
reg = <0xf>;
};
};
@@ -292,16 +292,18 @@ examples:
#io-channel-cells = <1>;
/* Other properties are omitted */
- xo-therm@44 {
+ channel@44 {
reg = <PMK8350_ADC7_AMUX_THM1_100K_PU>;
qcom,ratiometric;
qcom,hw-settle-time = <200>;
+ label = "xo_therm";
};
- conn-therm@47 {
+ channel@47 {
reg = <PM8350_ADC7_AMUX_THM4_100K_PU(1)>;
qcom,ratiometric;
qcom,hw-settle-time = <200>;
+ label = "conn_therm";
};
};
};
diff --git a/Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml b/Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml
new file mode 100644
index 000000000000..12b0c7ed5d72
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/light/ti,opt4001.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/light/ti,opt4001.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments OPT4001 Ambient Light Sensor
+
+maintainers:
+ - Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>
+
+description:
+ Ambient light sensor with an i2c interface.
+ Last part of compatible is for the packaging used.
+ Picostar is a 4 pinned SMT and sot-5x3 is a 8 pinned SOT.
+ https://www.ti.com/lit/gpn/opt4001
+
+properties:
+ compatible:
+ enum:
+ - ti,opt4001-picostar
+ - ti,opt4001-sot-5x3
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ vdd-supply:
+ description: Regulator that provides power to the sensor
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: ti,opt4001-sot-5x3
+ then:
+ properties:
+ interrupts:
+ maxItems: 1
+ else:
+ properties:
+ interrupts: false
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ light-sensor@44 {
+ compatible = "ti,opt4001-sot-5x3";
+ reg = <0x44>;
+ vdd-supply = <&vdd_reg>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/st,st-sensors.yaml b/Documentation/devicetree/bindings/iio/st,st-sensors.yaml
index 1ff3afca9149..e450821a741d 100644
--- a/Documentation/devicetree/bindings/iio/st,st-sensors.yaml
+++ b/Documentation/devicetree/bindings/iio/st,st-sensors.yaml
@@ -84,6 +84,7 @@ properties:
- st,lps35hw
- description: IMUs
enum:
+ - st,lsm303d-imu
- st,lsm9ds0-imu
- description: Deprecated bindings
enum:
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index a68b845f5b4f..e90e2f01550a 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -868,8 +868,7 @@ static int bma400_init(struct bma400_data *data)
ARRAY_SIZE(regulator_names),
regulator_names);
if (ret)
- return dev_err_probe(data->dev, ret, "Failed to get regulators: %d\n",
- ret);
+ return dev_err_probe(data->dev, ret, "Failed to get regulators\n");
/* Try to read chip_id register. It must return 0x90. */
ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val);
diff --git a/drivers/iio/accel/kionix-kx022a-i2c.c b/drivers/iio/accel/kionix-kx022a-i2c.c
index e6fd02d931b6..ee982206e5dd 100644
--- a/drivers/iio/accel/kionix-kx022a-i2c.c
+++ b/drivers/iio/accel/kionix-kx022a-i2c.c
@@ -40,6 +40,7 @@ static struct i2c_driver kx022a_i2c_driver = {
.driver = {
.name = "kx022a-i2c",
.of_match_table = kx022a_of_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe_new = kx022a_i2c_probe,
};
diff --git a/drivers/iio/accel/kionix-kx022a-spi.c b/drivers/iio/accel/kionix-kx022a-spi.c
index 9cd047f7b346..f45a46899a5f 100644
--- a/drivers/iio/accel/kionix-kx022a-spi.c
+++ b/drivers/iio/accel/kionix-kx022a-spi.c
@@ -46,6 +46,7 @@ static struct spi_driver kx022a_spi_driver = {
.driver = {
.name = "kx022a-spi",
.of_match_table = kx022a_of_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe = kx022a_spi_probe,
.id_table = kx022a_id,
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 282e539157f8..d2104e14e255 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -1007,6 +1007,7 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM9DS0_IMU_DEV_NAME,
+ [1] = LSM303D_IMU_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_accel_16bit_channels,
.odr = {
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 7dfc9c927a23..27b2632c1037 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -14,7 +14,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/delay.h>
-#include <linux/i2c.h>
#include <linux/pm.h>
#include <linux/mfd/palmas.h>
#include <linux/completion.h>
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index bd7e2408bf28..f7613efb870d 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -1993,6 +1993,8 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm
const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
int num_channels = 0, ret;
+ dev_dbg(&indio_dev->dev, "using legacy channel config\n");
+
ret = device_property_count_u32(dev, "st,adc-channels");
if (ret > adc_info->max_channels) {
dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
diff --git a/drivers/iio/imu/st_lsm9ds0/Kconfig b/drivers/iio/imu/st_lsm9ds0/Kconfig
index d29558edee60..7aef714b6ecb 100644
--- a/drivers/iio/imu/st_lsm9ds0/Kconfig
+++ b/drivers/iio/imu/st_lsm9ds0/Kconfig
@@ -10,7 +10,8 @@ config IIO_ST_LSM9DS0
help
Say yes here to build support for STMicroelectronics LSM9DS0 IMU
- sensor. Supported devices: accelerometer/magnetometer of lsm9ds0.
+ sensor. Supported devices: accelerometer/magnetometer of lsm9ds0
+ and lsm303d.
To compile this driver as a module, choose M here: the module
will be called st_lsm9ds0.
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
index a90138d8b06a..a0b9b2df11ce 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
@@ -19,6 +19,10 @@
static const struct of_device_id st_lsm9ds0_of_match[] = {
{
+ .compatible = "st,lsm303d-imu",
+ .data = LSM303D_IMU_DEV_NAME,
+ },
+ {
.compatible = "st,lsm9ds0-imu",
.data = LSM9DS0_IMU_DEV_NAME,
},
@@ -27,11 +31,18 @@ static const struct of_device_id st_lsm9ds0_of_match[] = {
MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match);
static const struct i2c_device_id st_lsm9ds0_id_table[] = {
+ { LSM303D_IMU_DEV_NAME },
{ LSM9DS0_IMU_DEV_NAME },
{}
};
MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table);
+static const struct acpi_device_id st_lsm9ds0_acpi_match[] = {
+ {"ACCL0001", (kernel_ulong_t)LSM303D_IMU_DEV_NAME},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, st_lsm9ds0_acpi_match);
+
static const struct regmap_config st_lsm9ds0_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
@@ -68,6 +79,7 @@ static struct i2c_driver st_lsm9ds0_driver = {
.driver = {
.name = "st-lsm9ds0-i2c",
.of_match_table = st_lsm9ds0_of_match,
+ .acpi_match_table = st_lsm9ds0_acpi_match,
},
.probe_new = st_lsm9ds0_i2c_probe,
.id_table = st_lsm9ds0_id_table,
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
index b743bf3546a7..8cc041d56cf7 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
@@ -19,6 +19,10 @@
static const struct of_device_id st_lsm9ds0_of_match[] = {
{
+ .compatible = "st,lsm303d-imu",
+ .data = LSM303D_IMU_DEV_NAME,
+ },
+ {
.compatible = "st,lsm9ds0-imu",
.data = LSM9DS0_IMU_DEV_NAME,
},
@@ -27,6 +31,7 @@ static const struct of_device_id st_lsm9ds0_of_match[] = {
MODULE_DEVICE_TABLE(of, st_lsm9ds0_of_match);
static const struct spi_device_id st_lsm9ds0_id_table[] = {
+ { LSM303D_IMU_DEV_NAME },
{ LSM9DS0_IMU_DEV_NAME },
{}
};
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index a7a080bed180..176d31d9f9d8 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -194,7 +194,7 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
written = 0;
add_wait_queue(&rb->pollq, &wait);
do {
- if (indio_dev->info == NULL)
+ if (!indio_dev->info)
return -ENODEV;
if (!iio_buffer_space_available(rb)) {
@@ -210,7 +210,7 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf,
}
wait_woken(&wait, TASK_INTERRUPTIBLE,
- MAX_SCHEDULE_TIMEOUT);
+ MAX_SCHEDULE_TIMEOUT);
continue;
}
@@ -242,7 +242,7 @@ static __poll_t iio_buffer_poll(struct file *filp,
struct iio_buffer *rb = ib->buffer;
struct iio_dev *indio_dev = ib->indio_dev;
- if (!indio_dev->info || rb == NULL)
+ if (!indio_dev->info || !rb)
return 0;
poll_wait(filp, &rb->pollq, wait);
@@ -407,9 +407,9 @@ static ssize_t iio_scan_el_show(struct device *dev,
/* Note NULL used as error indicator as it doesn't make sense. */
static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
- unsigned int masklength,
- const unsigned long *mask,
- bool strict)
+ unsigned int masklength,
+ const unsigned long *mask,
+ bool strict)
{
if (bitmap_empty(mask, masklength))
return NULL;
@@ -427,7 +427,7 @@ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
}
static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
- const unsigned long *mask)
+ const unsigned long *mask)
{
if (!indio_dev->setup_ops->validate_scan_mask)
return true;
@@ -446,7 +446,7 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev,
* individual buffers request is plausible.
*/
static int iio_scan_mask_set(struct iio_dev *indio_dev,
- struct iio_buffer *buffer, int bit)
+ struct iio_buffer *buffer, int bit)
{
const unsigned long *mask;
unsigned long *trialmask;
@@ -539,7 +539,6 @@ error_ret:
mutex_unlock(&iio_dev_opaque->mlock);
return ret < 0 ? ret : len;
-
}
static ssize_t iio_scan_el_ts_show(struct device *dev,
@@ -706,7 +705,7 @@ static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
}
static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
- const unsigned long *mask, bool timestamp)
+ const unsigned long *mask, bool timestamp)
{
unsigned int bytes = 0;
int length, i, largest = 0;
@@ -732,7 +731,7 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
}
static void iio_buffer_activate(struct iio_dev *indio_dev,
- struct iio_buffer *buffer)
+ struct iio_buffer *buffer)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
@@ -753,12 +752,12 @@ static void iio_buffer_deactivate_all(struct iio_dev *indio_dev)
struct iio_buffer *buffer, *_buffer;
list_for_each_entry_safe(buffer, _buffer,
- &iio_dev_opaque->buffer_list, buffer_list)
+ &iio_dev_opaque->buffer_list, buffer_list)
iio_buffer_deactivate(buffer);
}
static int iio_buffer_enable(struct iio_buffer *buffer,
- struct iio_dev *indio_dev)
+ struct iio_dev *indio_dev)
{
if (!buffer->access->enable)
return 0;
@@ -766,7 +765,7 @@ static int iio_buffer_enable(struct iio_buffer *buffer,
}
static int iio_buffer_disable(struct iio_buffer *buffer,
- struct iio_dev *indio_dev)
+ struct iio_dev *indio_dev)
{
if (!buffer->access->disable)
return 0;
@@ -774,7 +773,7 @@ static int iio_buffer_disable(struct iio_buffer *buffer,
}
static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
- struct iio_buffer *buffer)
+ struct iio_buffer *buffer)
{
unsigned int bytes;
@@ -782,13 +781,13 @@ static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
return;
bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
- buffer->scan_timestamp);
+ buffer->scan_timestamp);
buffer->access->set_bytes_per_datum(buffer, bytes);
}
static int iio_buffer_request_update(struct iio_dev *indio_dev,
- struct iio_buffer *buffer)
+ struct iio_buffer *buffer)
{
int ret;
@@ -797,7 +796,7 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev,
ret = buffer->access->request_update(buffer);
if (ret) {
dev_dbg(&indio_dev->dev,
- "Buffer not started: buffer parameter update failed (%d)\n",
+ "Buffer not started: buffer parameter update failed (%d)\n",
ret);
return ret;
}
@@ -807,7 +806,7 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev,
}
static void iio_free_scan_mask(struct iio_dev *indio_dev,
- const unsigned long *mask)
+ const unsigned long *mask)
{
/* If the mask is dynamically allocated free it, otherwise do nothing */
if (!indio_dev->available_scan_masks)
@@ -823,8 +822,9 @@ struct iio_device_config {
};
static int iio_verify_update(struct iio_dev *indio_dev,
- struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer,
- struct iio_device_config *config)
+ struct iio_buffer *insert_buffer,
+ struct iio_buffer *remove_buffer,
+ struct iio_device_config *config)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
unsigned long *compound_mask;
@@ -864,7 +864,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
if (insert_buffer) {
modes &= insert_buffer->access->modes;
config->watermark = min(config->watermark,
- insert_buffer->watermark);
+ insert_buffer->watermark);
}
/* Definitely possible for devices to support both of these. */
@@ -890,7 +890,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
/* What scan mask do we actually have? */
compound_mask = bitmap_zalloc(indio_dev->masklength, GFP_KERNEL);
- if (compound_mask == NULL)
+ if (!compound_mask)
return -ENOMEM;
scan_timestamp = false;
@@ -911,18 +911,18 @@ static int iio_verify_update(struct iio_dev *indio_dev,
if (indio_dev->available_scan_masks) {
scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks,
- indio_dev->masklength,
- compound_mask,
- strict_scanmask);
+ indio_dev->masklength,
+ compound_mask,
+ strict_scanmask);
bitmap_free(compound_mask);
- if (scan_mask == NULL)
+ if (!scan_mask)
return -EINVAL;
} else {
scan_mask = compound_mask;
}
config->scan_bytes = iio_compute_scan_bytes(indio_dev,
- scan_mask, scan_timestamp);
+ scan_mask, scan_timestamp);
config->scan_mask = scan_mask;
config->scan_timestamp = scan_timestamp;
@@ -954,16 +954,16 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer)
}
static int iio_buffer_add_demux(struct iio_buffer *buffer,
- struct iio_demux_table **p, unsigned int in_loc, unsigned int out_loc,
- unsigned int length)
+ struct iio_demux_table **p, unsigned int in_loc,
+ unsigned int out_loc,
+ unsigned int length)
{
-
if (*p && (*p)->from + (*p)->length == in_loc &&
- (*p)->to + (*p)->length == out_loc) {
+ (*p)->to + (*p)->length == out_loc) {
(*p)->length += length;
} else {
*p = kmalloc(sizeof(**p), GFP_KERNEL);
- if (*p == NULL)
+ if (!(*p))
return -ENOMEM;
(*p)->from = in_loc;
(*p)->to = out_loc;
@@ -1027,7 +1027,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev,
out_loc += length;
}
buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
- if (buffer->demux_bounce == NULL) {
+ if (!buffer->demux_bounce) {
ret = -ENOMEM;
goto error_clear_mux_table;
}
@@ -1060,7 +1060,7 @@ error_clear_mux_table:
}
static int iio_enable_buffers(struct iio_dev *indio_dev,
- struct iio_device_config *config)
+ struct iio_device_config *config)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
struct iio_buffer *buffer, *tmp = NULL;
@@ -1078,7 +1078,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
ret = indio_dev->setup_ops->preenable(indio_dev);
if (ret) {
dev_dbg(&indio_dev->dev,
- "Buffer not started: buffer preenable failed (%d)\n", ret);
+ "Buffer not started: buffer preenable failed (%d)\n", ret);
goto err_undo_config;
}
}
@@ -1118,7 +1118,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
ret = indio_dev->setup_ops->postenable(indio_dev);
if (ret) {
dev_dbg(&indio_dev->dev,
- "Buffer not started: postenable failed (%d)\n", ret);
+ "Buffer not started: postenable failed (%d)\n", ret);
goto err_detach_pollfunc;
}
}
@@ -1194,15 +1194,15 @@ static int iio_disable_buffers(struct iio_dev *indio_dev)
}
static int __iio_update_buffers(struct iio_dev *indio_dev,
- struct iio_buffer *insert_buffer,
- struct iio_buffer *remove_buffer)
+ struct iio_buffer *insert_buffer,
+ struct iio_buffer *remove_buffer)
{
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
struct iio_device_config new_config;
int ret;
ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer,
- &new_config);
+ &new_config);
if (ret)
return ret;
@@ -1258,7 +1258,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
return 0;
if (insert_buffer &&
- (insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT))
+ insert_buffer->direction == IIO_BUFFER_DIRECTION_OUT)
return -EINVAL;
mutex_lock(&iio_dev_opaque->info_exist_lock);
@@ -1275,7 +1275,7 @@ int iio_update_buffers(struct iio_dev *indio_dev,
goto out_unlock;
}
- if (indio_dev->info == NULL) {
+ if (!indio_dev->info) {
ret = -ENODEV;
goto out_unlock;
}
@@ -1615,7 +1615,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
buffer_attrcount = 0;
if (buffer->attrs) {
- while (buffer->attrs[buffer_attrcount] != NULL)
+ while (buffer->attrs[buffer_attrcount])
buffer_attrcount++;
}
buffer_attrcount += ARRAY_SIZE(iio_buffer_attrs);
@@ -1643,7 +1643,7 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
}
ret = iio_buffer_add_channel_sysfs(indio_dev, buffer,
- &channels[i]);
+ &channels[i]);
if (ret < 0)
goto error_cleanup_dynamic;
scan_el_attrcount += ret;
@@ -1651,10 +1651,10 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer,
iio_dev_opaque->scan_index_timestamp =
channels[i].scan_index;
}
- if (indio_dev->masklength && buffer->scan_mask == NULL) {
+ if (indio_dev->masklength && !buffer->scan_mask) {
buffer->scan_mask = bitmap_zalloc(indio_dev->masklength,
GFP_KERNEL);
- if (buffer->scan_mask == NULL) {
+ if (!buffer->scan_mask) {
ret = -ENOMEM;
goto error_cleanup_dynamic;
}
@@ -1771,7 +1771,7 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
goto error_unwind_sysfs_and_mask;
}
- sz = sizeof(*(iio_dev_opaque->buffer_ioctl_handler));
+ sz = sizeof(*iio_dev_opaque->buffer_ioctl_handler);
iio_dev_opaque->buffer_ioctl_handler = kzalloc(sz, GFP_KERNEL);
if (!iio_dev_opaque->buffer_ioctl_handler) {
ret = -ENOMEM;
@@ -1820,14 +1820,14 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev)
* a time.
*/
bool iio_validate_scan_mask_onehot(struct iio_dev *indio_dev,
- const unsigned long *mask)
+ const unsigned long *mask)
{
return bitmap_weight(mask, indio_dev->masklength) == 1;
}
EXPORT_SYMBOL_GPL(iio_validate_scan_mask_onehot);
static const void *iio_demux(struct iio_buffer *buffer,
- const void *datain)
+ const void *datain)
{
struct iio_demux_table *t;
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 6fa31fcd71a1..811fa9599abc 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -413,6 +413,17 @@ config OPT3001
If built as a dynamically linked module, it will be called
opt3001.
+config OPT4001
+ tristate "Texas Instruments OPT4001 Light Sensor"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say Y or M here, you get support for Texas Instruments
+ OPT4001 Ambient Light Sensor.
+
+ If built as a dynamically linked module, it will be called
+ opt4001.
+
config PA12203001
tristate "TXC PA12203001 light and proximity sensor"
depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 985f6feaccd4..810ed6ffd9c4 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_MAX44000) += max44000.o
obj-$(CONFIG_MAX44009) += max44009.o
obj-$(CONFIG_NOA1305) += noa1305.o
obj-$(CONFIG_OPT3001) += opt3001.o
+obj-$(CONFIG_OPT4001) += opt4001.o
obj-$(CONFIG_PA12203001) += pa12203001.o
obj-$(CONFIG_ROHM_BU27034) += rohm-bu27034.o
obj-$(CONFIG_RPR0521) += rpr0521.o
diff --git a/drivers/iio/light/al3320a.c b/drivers/iio/light/al3320a.c
index 9ff28bbf34bb..36214d790f71 100644
--- a/drivers/iio/light/al3320a.c
+++ b/drivers/iio/light/al3320a.c
@@ -16,6 +16,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/mod_devicetable.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -247,11 +248,18 @@ static const struct of_device_id al3320a_of_match[] = {
};
MODULE_DEVICE_TABLE(of, al3320a_of_match);
+static const struct acpi_device_id al3320a_acpi_match[] = {
+ {"CALS0001"},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, al3320a_acpi_match);
+
static struct i2c_driver al3320a_driver = {
.driver = {
.name = AL3320A_DRV_NAME,
.of_match_table = al3320a_of_match,
.pm = pm_sleep_ptr(&al3320a_pm_ops),
+ .acpi_match_table = al3320a_acpi_match,
},
.probe_new = al3320a_probe,
.id_table = al3320a_id,
diff --git a/drivers/iio/light/opt4001.c b/drivers/iio/light/opt4001.c
new file mode 100644
index 000000000000..feb57cb99aa4
--- /dev/null
+++ b/drivers/iio/light/opt4001.c
@@ -0,0 +1,467 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Axis Communications AB
+ *
+ * Datasheet: https://www.ti.com/lit/gpn/opt4001
+ *
+ * Device driver for the Texas Instruments OPT4001.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+/* OPT4001 register set */
+#define OPT4001_LIGHT1_MSB 0x00
+#define OPT4001_LIGHT1_LSB 0x01
+#define OPT4001_CTRL 0x0A
+#define OPT4001_DEVICE_ID 0x11
+
+/* OPT4001 register mask */
+#define OPT4001_EXPONENT_MASK GENMASK(15, 12)
+#define OPT4001_MSB_MASK GENMASK(11, 0)
+#define OPT4001_LSB_MASK GENMASK(15, 8)
+#define OPT4001_COUNTER_MASK GENMASK(7, 4)
+#define OPT4001_CRC_MASK GENMASK(3, 0)
+
+/* OPT4001 device id mask */
+#define OPT4001_DEVICE_ID_MASK GENMASK(11, 0)
+
+/* OPT4001 control registers mask */
+#define OPT4001_CTRL_QWAKE_MASK GENMASK(15, 15)
+#define OPT4001_CTRL_RANGE_MASK GENMASK(13, 10)
+#define OPT4001_CTRL_CONV_TIME_MASK GENMASK(9, 6)
+#define OPT4001_CTRL_OPER_MODE_MASK GENMASK(5, 4)
+#define OPT4001_CTRL_LATCH_MASK GENMASK(3, 3)
+#define OPT4001_CTRL_INT_POL_MASK GENMASK(2, 2)
+#define OPT4001_CTRL_FAULT_COUNT GENMASK(0, 1)
+
+/* OPT4001 constants */
+#define OPT4001_DEVICE_ID_VAL 0x121
+
+/* OPT4001 operating modes */
+#define OPT4001_CTRL_OPER_MODE_OFF 0x0
+#define OPT4001_CTRL_OPER_MODE_FORCED 0x1
+#define OPT4001_CTRL_OPER_MODE_ONE_SHOT 0x2
+#define OPT4001_CTRL_OPER_MODE_CONTINUOUS 0x3
+
+/* OPT4001 conversion control register definitions */
+#define OPT4001_CTRL_CONVERSION_0_6MS 0x0
+#define OPT4001_CTRL_CONVERSION_1MS 0x1
+#define OPT4001_CTRL_CONVERSION_1_8MS 0x2
+#define OPT4001_CTRL_CONVERSION_3_4MS 0x3
+#define OPT4001_CTRL_CONVERSION_6_5MS 0x4
+#define OPT4001_CTRL_CONVERSION_12_7MS 0x5
+#define OPT4001_CTRL_CONVERSION_25MS 0x6
+#define OPT4001_CTRL_CONVERSION_50MS 0x7
+#define OPT4001_CTRL_CONVERSION_100MS 0x8
+#define OPT4001_CTRL_CONVERSION_200MS 0x9
+#define OPT4001_CTRL_CONVERSION_400MS 0xa
+#define OPT4001_CTRL_CONVERSION_800MS 0xb
+
+/* OPT4001 scale light level range definitions */
+#define OPT4001_CTRL_LIGHT_SCALE_AUTO 12
+
+/* OPT4001 default values */
+#define OPT4001_DEFAULT_CONVERSION_TIME OPT4001_CTRL_CONVERSION_800MS
+
+/*
+ * The different packaging of OPT4001 has different constants used when calculating
+ * lux values.
+ */
+struct opt4001_chip_info {
+ int mul;
+ int div;
+ const char *name;
+};
+
+struct opt4001_chip {
+ struct regmap *regmap;
+ struct i2c_client *client;
+ u8 int_time;
+ const struct opt4001_chip_info *chip_info;
+};
+
+static const struct opt4001_chip_info opt4001_sot_5x3_info = {
+ .mul = 4375,
+ .div = 10000000,
+ .name = "opt4001-sot-5x3"
+};
+
+static const struct opt4001_chip_info opt4001_picostar_info = {
+ .mul = 3125,
+ .div = 10000000,
+ .name = "opt4001-picostar"
+};
+
+static const int opt4001_int_time_available[][2] = {
+ { 0, 600 },
+ { 0, 1000 },
+ { 0, 1800 },
+ { 0, 3400 },
+ { 0, 6500 },
+ { 0, 12700 },
+ { 0, 25000 },
+ { 0, 50000 },
+ { 0, 100000 },
+ { 0, 200000 },
+ { 0, 400000 },
+ { 0, 800000 },
+};
+
+/*
+ * Conversion time is integration time + time to set register
+ * this is used as integration time.
+ */
+static const int opt4001_int_time_reg[][2] = {
+ { 600, OPT4001_CTRL_CONVERSION_0_6MS },
+ { 1000, OPT4001_CTRL_CONVERSION_1MS },
+ { 1800, OPT4001_CTRL_CONVERSION_1_8MS },
+ { 3400, OPT4001_CTRL_CONVERSION_3_4MS },
+ { 6500, OPT4001_CTRL_CONVERSION_6_5MS },
+ { 12700, OPT4001_CTRL_CONVERSION_12_7MS },
+ { 25000, OPT4001_CTRL_CONVERSION_25MS },
+ { 50000, OPT4001_CTRL_CONVERSION_50MS },
+ { 100000, OPT4001_CTRL_CONVERSION_100MS },
+ { 200000, OPT4001_CTRL_CONVERSION_200MS },
+ { 400000, OPT4001_CTRL_CONVERSION_400MS },
+ { 800000, OPT4001_CTRL_CONVERSION_800MS },
+};
+
+static int opt4001_als_time_to_index(const u32 als_integration_time)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(opt4001_int_time_available); i++) {
+ if (als_integration_time == opt4001_int_time_available[i][1])
+ return i;
+ }
+
+ return -EINVAL;
+}
+
+static u8 opt4001_calculate_crc(u8 exp, u32 mantissa, u8 count)
+{
+ u8 crc;
+
+ crc = (hweight32(mantissa) + hweight32(exp) + hweight32(count)) % 2;
+ crc |= ((hweight32(mantissa & 0xAAAAA) + hweight32(exp & 0xA)
+ + hweight32(count & 0xA)) % 2) << 1;
+ crc |= ((hweight32(mantissa & 0x88888) + hweight32(exp & 0x8)
+ + hweight32(count & 0x8)) % 2) << 2;
+ crc |= (hweight32(mantissa & 0x80808) % 2) << 3;
+
+ return crc;
+}
+
+static int opt4001_read_lux_value(struct iio_dev *indio_dev,
+ int *val, int *val2)
+{
+ struct opt4001_chip *chip = iio_priv(indio_dev);
+ struct device *dev = &chip->client->dev;
+ unsigned int light1;
+ unsigned int light2;
+ u16 msb;
+ u16 lsb;
+ u8 exp;
+ u8 count;
+ u8 crc;
+ u8 calc_crc;
+ u64 lux_raw;
+ int ret;
+
+ ret = regmap_read(chip->regmap, OPT4001_LIGHT1_MSB, &light1);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read data bytes");
+ return ret;
+ }
+
+ ret = regmap_read(chip->regmap, OPT4001_LIGHT1_LSB, &light2);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read data bytes");
+ return ret;
+ }
+
+ count = FIELD_GET(OPT4001_COUNTER_MASK, light2);
+ exp = FIELD_GET(OPT4001_EXPONENT_MASK, light1);
+ crc = FIELD_GET(OPT4001_CRC_MASK, light2);
+ msb = FIELD_GET(OPT4001_MSB_MASK, light1);
+ lsb = FIELD_GET(OPT4001_LSB_MASK, light2);
+ lux_raw = (msb << 8) + lsb;
+ calc_crc = opt4001_calculate_crc(exp, lux_raw, count);
+ if (calc_crc != crc)
+ return -EIO;
+
+ lux_raw = lux_raw << exp;
+ lux_raw = lux_raw * chip->chip_info->mul;
+ *val = div_u64_rem(lux_raw, chip->chip_info->div, val2);
+ *val2 = *val2 * 100;
+
+ return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int opt4001_set_conf(struct opt4001_chip *chip)
+{
+ struct device *dev = &chip->client->dev;
+ u16 reg;
+ int ret;
+
+ reg = FIELD_PREP(OPT4001_CTRL_RANGE_MASK, OPT4001_CTRL_LIGHT_SCALE_AUTO);
+ reg |= FIELD_PREP(OPT4001_CTRL_CONV_TIME_MASK, chip->int_time);
+ reg |= FIELD_PREP(OPT4001_CTRL_OPER_MODE_MASK, OPT4001_CTRL_OPER_MODE_CONTINUOUS);
+
+ ret = regmap_write(chip->regmap, OPT4001_CTRL, reg);
+ if (ret)
+ dev_err(dev, "Failed to set configuration\n");
+
+ return ret;
+}
+
+static int opt4001_power_down(struct opt4001_chip *chip)
+{
+ struct device *dev = &chip->client->dev;
+ int ret;
+ unsigned int reg;
+
+ ret = regmap_read(chip->regmap, OPT4001_DEVICE_ID, &reg);
+ if (ret) {
+ dev_err(dev, "Failed to read configuration\n");
+ return ret;
+ }
+
+ /* MODE_OFF is 0x0 so just set bits to 0 */
+ reg &= ~OPT4001_CTRL_OPER_MODE_MASK;
+
+ ret = regmap_write(chip->regmap, OPT4001_CTRL, reg);
+ if (ret)
+ dev_err(dev, "Failed to set configuration to power down\n");
+
+ return ret;
+}
+
+static void opt4001_chip_off_action(void *data)
+{
+ struct opt4001_chip *chip = data;
+
+ opt4001_power_down(chip);
+}
+
+static const struct iio_chan_spec opt4001_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME)
+ },
+};
+
+static int opt4001_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct opt4001_chip *chip = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ return opt4001_read_lux_value(indio_dev, val, val2);
+ case IIO_CHAN_INFO_INT_TIME:
+ *val = 0;
+ *val2 = opt4001_int_time_reg[chip->int_time][0];
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int opt4001_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct opt4001_chip *chip = iio_priv(indio_dev);
+ int int_time;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ int_time = opt4001_als_time_to_index(val2);
+ if (int_time < 0)
+ return int_time;
+ chip->int_time = int_time;
+ return opt4001_set_conf(chip);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int opt4001_read_available(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *length = ARRAY_SIZE(opt4001_int_time_available) * 2;
+ *vals = (const int *)opt4001_int_time_available;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info opt4001_info_no_irq = {
+ .read_raw = opt4001_read_raw,
+ .write_raw = opt4001_write_raw,
+ .read_avail = opt4001_read_available,
+};
+
+static int opt4001_load_defaults(struct opt4001_chip *chip)
+{
+ chip->int_time = OPT4001_DEFAULT_CONVERSION_TIME;
+
+ return opt4001_set_conf(chip);
+}
+
+static bool opt4001_readable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case OPT4001_LIGHT1_MSB:
+ case OPT4001_LIGHT1_LSB:
+ case OPT4001_CTRL:
+ case OPT4001_DEVICE_ID:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool opt4001_writable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case OPT4001_CTRL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool opt4001_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case OPT4001_LIGHT1_MSB:
+ case OPT4001_LIGHT1_LSB:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config opt4001_regmap_config = {
+ .name = "opt4001",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = OPT4001_DEVICE_ID,
+ .readable_reg = opt4001_readable_reg,
+ .writeable_reg = opt4001_writable_reg,
+ .volatile_reg = opt4001_volatile_reg,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+};
+
+static int opt4001_probe(struct i2c_client *client)
+{
+ struct opt4001_chip *chip;
+ struct iio_dev *indio_dev;
+ int ret;
+ uint dev_id;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ chip = iio_priv(indio_dev);
+
+ ret = devm_regulator_get_enable(&client->dev, "vdd");
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "Failed to enable vdd supply\n");
+
+ chip->regmap = devm_regmap_init_i2c(client, &opt4001_regmap_config);
+ if (IS_ERR(chip->regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(chip->regmap),
+ "regmap initialization failed\n");
+ chip->client = client;
+
+ indio_dev->info = &opt4001_info_no_irq;
+
+ ret = regmap_reinit_cache(chip->regmap, &opt4001_regmap_config);
+ if (ret)
+ return dev_err_probe(&client->dev, ret,
+ "failed to reinit regmap cache\n");
+
+ ret = regmap_read(chip->regmap, OPT4001_DEVICE_ID, &dev_id);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to read the device ID register\n");
+
+ dev_id = FIELD_GET(OPT4001_DEVICE_ID_MASK, dev_id);
+ if (dev_id != OPT4001_DEVICE_ID_VAL)
+ dev_warn(&client->dev, "Device ID: %#04x unknown\n", dev_id);
+
+ chip->chip_info = device_get_match_data(&client->dev);
+
+ indio_dev->channels = opt4001_channels;
+ indio_dev->num_channels = ARRAY_SIZE(opt4001_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = chip->chip_info->name;
+
+ ret = opt4001_load_defaults(chip);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to set sensor defaults\n");
+
+ ret = devm_add_action_or_reset(&client->dev,
+ opt4001_chip_off_action,
+ chip);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "Failed to setup power off action\n");
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+/*
+ * The compatible string determines which constants to use depending on
+ * opt4001 packaging
+ */
+static const struct i2c_device_id opt4001_id[] = {
+ { "opt4001-sot-5x3", (kernel_ulong_t)&opt4001_sot_5x3_info },
+ { "opt4001-picostar", (kernel_ulong_t)&opt4001_picostar_info },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, opt4001_id);
+
+static const struct of_device_id opt4001_of_match[] = {
+ { .compatible = "ti,opt4001-sot-5x3", .data = &opt4001_sot_5x3_info},
+ { .compatible = "ti,opt4001-picostar", .data = &opt4001_picostar_info},
+ {}
+};
+MODULE_DEVICE_TABLE(of, opt4001_of_match);
+
+static struct i2c_driver opt4001_driver = {
+ .driver = {
+ .name = "opt4001",
+ .of_match_table = opt4001_of_match,
+ },
+ .probe_new = opt4001_probe,
+ .id_table = opt4001_id,
+};
+module_i2c_driver(opt4001_driver);
+
+MODULE_AUTHOR("Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>");
+MODULE_DESCRIPTION("Texas Instruments opt4001 ambient light sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/rohm-bu27034.c b/drivers/iio/light/rohm-bu27034.c
index f85194fda6b0..183cf550af13 100644
--- a/drivers/iio/light/rohm-bu27034.c
+++ b/drivers/iio/light/rohm-bu27034.c
@@ -1500,6 +1500,7 @@ static struct i2c_driver bu27034_i2c_driver = {
.driver = {
.name = "bu27034-als",
.of_match_table = bu27034_of_match,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
.probe_new = bu27034_probe,
};
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index 8faa7409d9e1..6cc0dfd31821 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -427,6 +427,7 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM9DS0_IMU_DEV_NAME,
+ [1] = LSM303D_IMU_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_magn_4_16bit_channels,
.odr = {
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index f5f3ee57bc70..607c3a89a647 100644
--- a/include/linux/iio/common/st_sensors.h
+++ b/include/linux/iio/common/st_sensors.h
@@ -22,6 +22,7 @@
#include <linux/platform_data/st_sensors_pdata.h>
#define LSM9DS0_IMU_DEV_NAME "lsm9ds0"
+#define LSM303D_IMU_DEV_NAME "lsm303d"
/*
* Buffer size max case: 2bytes per channel, 3 channels in total +
diff --git a/include/linux/platform_data/st_sensors_pdata.h b/include/linux/platform_data/st_sensors_pdata.h
index 897051e51b78..a657830232ae 100644
--- a/include/linux/platform_data/st_sensors_pdata.h
+++ b/include/linux/platform_data/st_sensors_pdata.h
@@ -15,7 +15,7 @@
* @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
* Available only for accelerometer, magnetometer and pressure sensors.
* Accelerometer DRDY on LSM330 available only on pin 1 (see datasheet).
- * Magnetometer DRDY is supported only on LSM9DS0.
+ * Magnetometer DRDY is supported only on LSM9DS0 and LSM303D.
* @open_drain: set the interrupt line to be open drain if possible.
* @spi_3wire: enable spi-3wire mode.
* @pullups: enable/disable i2c controller pullup resistors.