[PATCH 4/4] hwmon: vcnl3020: add hwmon driver for intrusion sensor

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Intrusion status detection via Interrupt Status Register.

Signed-off-by: Ivan Mikhaylov <i.mikhaylov@xxxxxxxxx>
---
 drivers/hwmon/Kconfig                  |  7 +++
 drivers/hwmon/Makefile                 |  1 +
 drivers/hwmon/vcnl3020-hwmon.c         | 57 ++++++++++++++++++++++
 drivers/iio/proximity/vcnl3020.c       | 67 ++++++++++++++++++++------
 include/linux/iio/proximity/vcnl3020.h | 26 ++++++++++
 5 files changed, 143 insertions(+), 15 deletions(-)
 create mode 100644 drivers/hwmon/vcnl3020-hwmon.c
 create mode 100644 include/linux/iio/proximity/vcnl3020.h

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 1ecf697d8d99..862205bbb3bf 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1916,6 +1916,13 @@ config SENSORS_TMP513
 	  This driver can also be built as a module. If so, the module
 	  will be called tmp513.
 
+config SENSORS_VCNL3020
+	tristate "VCNL3020"
+	depends on I2C && VCNL3020
+	help
+	  If you say yes here you get support for the intrusion
+	  sensor via VCNL3020 proximity sensor.
+
 config SENSORS_VEXPRESS
 	tristate "Versatile Express"
 	depends on VEXPRESS_CONFIG
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 09a86c5e1d29..1d96212587aa 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -186,6 +186,7 @@ obj-$(CONFIG_SENSORS_TMP108)	+= tmp108.o
 obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
 obj-$(CONFIG_SENSORS_TMP421)	+= tmp421.o
 obj-$(CONFIG_SENSORS_TMP513)	+= tmp513.o
+obj-$(CONFIG_SENSORS_VCNL3020)	+= vcnl3020-hwmon.o
 obj-$(CONFIG_SENSORS_VEXPRESS)	+= vexpress-hwmon.o
 obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
diff --git a/drivers/hwmon/vcnl3020-hwmon.c b/drivers/hwmon/vcnl3020-hwmon.c
new file mode 100644
index 000000000000..199bea25723b
--- /dev/null
+++ b/drivers/hwmon/vcnl3020-hwmon.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * vcnl3020-hwmon.c - intrusion sensor.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/iio/proximity/vcnl3020.h>
+
+static ssize_t vcnl3020_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct vcnl3020_data *vcnl3020_data = dev_get_drvdata(dev);
+
+	bool data = vcnl3020_is_thr_triggered(vcnl3020_data);
+
+	return sprintf(buf, "%u\n", data);
+}
+
+static SENSOR_DEVICE_ATTR_2_RO(intrusion0_alarm, vcnl3020, 0, 0);
+
+static struct attribute *vcnl3020_attrs[] = {
+	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(vcnl3020);
+
+static int32_t vcnl3020_hwmon_probe(struct platform_device *pdev)
+{
+	struct vcnl3020_data *vcnl3020_data = platform_get_drvdata(pdev);
+	struct device *hwmon_dev;
+
+	hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev,
+							   VCNL3020_DRV,
+							   vcnl3020_data,
+							   vcnl3020_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static struct platform_driver vcnl3020_hwmon_driver = {
+	.probe = vcnl3020_hwmon_probe,
+	.driver = {
+		.name = VCNL3020_DRV_HWMON,
+	},
+};
+
+module_platform_driver(vcnl3020_hwmon_driver);
+
+MODULE_AUTHOR("Ivan Mikhaylov <i.mikhaylov@xxxxxxxxx>");
+MODULE_DESCRIPTION("Intrusion sensor for VCNL3020");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
index bff59c7af966..67baa14cc900 100644
--- a/drivers/iio/proximity/vcnl3020.c
+++ b/drivers/iio/proximity/vcnl3020.c
@@ -11,9 +11,11 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/regmap.h>
+#include <linux/platform_device.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/proximity/vcnl3020.h>
 
 #define VCNL3020_PROD_ID	0x21
 
@@ -66,18 +68,6 @@ static const int vcnl3020_prox_sampling_frequency[][2] = {
 	{250, 0},
 };
 
-/**
- * struct vcnl3020_data - vcnl3020 specific data.
- * @regmap:	device register map.
- * @dev:	vcnl3020 device.
- * @rev:	revision id.
- */
-struct vcnl3020_data {
-	struct regmap *regmap;
-	struct device *dev;
-	u8 rev;
-};
-
 /**
  * struct vcnl3020_property - vcnl3020 property.
  * @name:	property name.
@@ -330,6 +320,23 @@ static int vcnl3020_write_event(struct iio_dev *indio_dev,
 	return rc;
 }
 
+#ifdef CONFIG_SENSORS_VCNL3020
+
+bool vcnl3020_is_thr_triggered(struct vcnl3020_data *data)
+{
+	int rc;
+	unsigned int isr;
+
+	rc = regmap_read(data->regmap, VCNL_ISR, &isr);
+	if (rc)
+		return false;
+
+	return !!((isr & VCNL_INT_TH_LOW) || (isr & VCNL_INT_TH_HI));
+}
+EXPORT_SYMBOL_GPL(vcnl3020_is_thr_triggered);
+
+#endif
+
 static int vcnl3020_config_threshold(struct iio_dev *indio_dev, bool state)
 {
 	struct vcnl3020_data *data = iio_priv(indio_dev);
@@ -536,6 +543,7 @@ static int vcnl3020_probe(struct i2c_client *client)
 	struct vcnl3020_data *data;
 	struct iio_dev *indio_dev;
 	struct regmap *regmap;
+	struct platform_device *pdev;
 	int rc;
 
 	regmap = devm_regmap_init_i2c(client, &vcnl3020_regmap_config);
@@ -560,10 +568,39 @@ static int vcnl3020_probe(struct i2c_client *client)
 	indio_dev->info = &vcnl3020_info;
 	indio_dev->channels = vcnl3020_channels;
 	indio_dev->num_channels = ARRAY_SIZE(vcnl3020_channels);
-	indio_dev->name = "vcnl3020";
+	indio_dev->name = VCNL3020_DRV;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	return devm_iio_device_register(&client->dev, indio_dev);
+	rc = devm_iio_device_register(&client->dev, indio_dev);
+	if (rc != 0)
+		goto err_out;
+
+#ifdef CONFIG_SENSORS_VCNL3020
+
+	pdev = platform_device_alloc(VCNL3020_DRV_HWMON, -1);
+	if (!pdev) {
+		dev_err(&client->dev, "Failed to allocate %s\n",
+			VCNL3020_DRV_HWMON);
+		rc = -ENOMEM;
+		goto err_out;
+	}
+
+	pdev->dev.parent = &indio_dev->dev;
+	platform_set_drvdata(pdev, data);
+	rc = platform_device_add(pdev);
+	if (rc != 0) {
+		dev_err(&client->dev, "Failed to register %s: %d\n",
+			VCNL3020_DRV_HWMON, rc);
+		platform_device_put(pdev);
+		pdev = NULL;
+		goto err_out;
+	}
+
+#endif
+
+err_out:
+
+	return rc;
 }
 
 static const struct of_device_id vcnl3020_of_match[] = {
@@ -576,7 +613,7 @@ MODULE_DEVICE_TABLE(of, vcnl3020_of_match);
 
 static struct i2c_driver vcnl3020_driver = {
 	.driver = {
-		.name   = "vcnl3020",
+		.name   = VCNL3020_DRV,
 		.of_match_table = vcnl3020_of_match,
 	},
 	.probe_new  = vcnl3020_probe,
diff --git a/include/linux/iio/proximity/vcnl3020.h b/include/linux/iio/proximity/vcnl3020.h
new file mode 100644
index 000000000000..d99783298e6e
--- /dev/null
+++ b/include/linux/iio/proximity/vcnl3020.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This file describe API for VCNL3020 proximity sensor.
+ */
+
+#ifndef VCNL3020_PROXIMITY_H
+#define VCNL3020_PROXIMITY_H
+
+#define VCNL3020_DRV_HWMON	"vcnl3020-hwmon"
+#define VCNL3020_DRV		"vcnl3020"
+
+/**
+ * struct vcnl3020_data - vcnl3020 specific data.
+ * @regmap:	device register map.
+ * @dev:	vcnl3020 device.
+ * @rev:	revision id.
+ */
+struct vcnl3020_data {
+	struct regmap *regmap;
+	struct device *dev;
+	u8 rev;
+};
+
+bool vcnl3020_is_thr_triggered(struct vcnl3020_data *data);
+
+#endif
-- 
2.26.3




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux