天天看點

RV1126 lsm6dsl中斷未接硬體iio驅動修改方法一方法二

目錄

方法一

裝置樹

 代碼修改

方法二

裝置樹

代碼修改

lsm6dsl硬體上沒接中斷管腳,iio驅動修改方法。

方法一

裝置樹

硬體上并未接中斷管腳,裝置樹配置一沒有被使用的GPIO管腳作為中斷管腳。

&i2c2 {
    status = "okay";
    clock-frequency = <400000>;

    lsm6dsl: [email protected] {
        status = "okay";
        compatible = "st,lsm6dsl";
        reg = <0x6b>;
        interrupt-parent = <&gpio0>;
        interrupts = <30 IRQ_TYPE_EDGE_RISING>;
    };
};
           

否則st_lsm6dsx_fifo_setup不會被調用。不會出現/sys/bus/iio/devices/iio\:device1/buffer目錄。

844     if (hw->irq > 0) {
845         err = st_lsm6dsx_fifo_setup(hw);
846         if (err < 0)
847             return err;
848     }
           

 代碼修改

由于沒有連接配接中斷管腳,增加核心線程來采集資料。

--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -161,6 +161,7 @@ struct st_lsm6dsx_hw {
        struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX];

        const struct st_lsm6dsx_settings *settings;
+       struct task_struct *task;
 };

 extern const struct dev_pm_ops st_lsm6dsx_pm_ops;
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -32,6 +32,7 @@
 #include <linux/iio/buffer.h>
 #include <linux/regmap.h>
 #include <linux/bitfield.h>
+#include <linux/kthread.h>

 #include <linux/platform_data/st_sensors_pdata.h>

@@ -414,6 +415,23 @@ int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
        return err;
 }

+static int kthread_read_fifo(void *arg)
+{
+       struct st_lsm6dsx_hw *hw = (struct st_lsm6dsx_hw *)arg;
+       int count;
+
+       while (!kthread_should_stop()) {
+               mutex_lock(&hw->fifo_lock);
+               count = st_lsm6dsx_read_fifo(hw);
+               mutex_unlock(&hw->fifo_lock);
+               if (count <= 0) {
+                       schedule_timeout_interruptible(msecs_to_jiffies(10));
+               }
+       }
+
+       return 0;
+}
+
 static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
 {
        struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
@@ -457,6 +475,14 @@ static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
                        goto out;

                err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
+               if (!hw->task) {
+                       hw->task = kthread_run(kthread_read_fifo, hw, "lsm6dsxd");
+               }
+       } else {
+               if (hw->task) {
+                       kthread_stop(hw->task);
+                       hw->task = NULL;
+               }
        }

 out:
           

方法二

裝置樹

裝置樹不配置中斷管腳。

&i2c2 {
    status = "okay";
    clock-frequency = <400000>;

    lsm6dsl: [email protected] {
        status = "okay";
        compatible = "st,lsm6dsl";
        reg = <0x6b>;
    };
};
           

代碼修改

--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -161,6 +161,7 @@ struct st_lsm6dsx_hw {
        struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX];

        const struct st_lsm6dsx_settings *settings;
+       struct task_struct *task;
 };

 extern const struct dev_pm_ops st_lsm6dsx_pm_ops;
@@ -170,6 +171,7 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
 int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor);
 int st_lsm6dsx_sensor_disable(struct st_lsm6dsx_sensor *sensor);
 int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw);
+int st_lsm6dsx_fifo_setup_noirq(struct st_lsm6dsx_hw *hw);
 int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor,
                                u16 watermark);
 int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw);
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -32,6 +32,7 @@
 #include <linux/iio/buffer.h>
 #include <linux/regmap.h>
 #include <linux/bitfield.h>
+#include <linux/kthread.h>

 #include <linux/platform_data/st_sensors_pdata.h>

@@ -414,6 +415,23 @@ int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
        return err;
 }

+static int kthread_read_fifo(void *arg)
+{
+       struct st_lsm6dsx_hw *hw = (struct st_lsm6dsx_hw *)arg;
+       int count;
+
+       while (!kthread_should_stop()) {
+               mutex_lock(&hw->fifo_lock);
+               count = st_lsm6dsx_read_fifo(hw);
+               mutex_unlock(&hw->fifo_lock);
+               if (count <= 0) {
+                       schedule_timeout_interruptible(msecs_to_jiffies(10));
+               }
+       }
+
+       return 0;
+}
+
 static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
 {
        struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
@@ -457,6 +475,14 @@ static int st_lsm6dsx_update_fifo(struct iio_dev *iio_dev, bool enable)
                        goto out;

                err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
+               if ((hw->irq <= 0) && (!hw->task)) {
+                       hw->task = kthread_run(kthread_read_fifo, hw, "lsm6dsxd");
+               }
+       } else {
+               if (hw->task) {
+                       kthread_stop(hw->task);
+                       hw->task = NULL;
+               }
        }

 out:
@@ -567,3 +593,21 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)

        return 0;
 }
+
+int st_lsm6dsx_fifo_setup_noirq(struct st_lsm6dsx_hw *hw)
+{
+       struct iio_buffer *buffer;
+       int i;
+
+       for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
+               buffer = devm_iio_kfifo_allocate(hw->dev);
+               if (!buffer)
+                       return -ENOMEM;
+
+               iio_device_attach_buffer(hw->iio_devs[i], buffer);
+               hw->iio_devs[i]->modes |= INDIO_BUFFER_SOFTWARE;
+               hw->iio_devs[i]->setup_ops = &st_lsm6dsx_buffer_ops;
+       }
+
+       return 0;
+}
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -845,6 +845,10 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
                err = st_lsm6dsx_fifo_setup(hw);
                if (err < 0)
                        return err;
+       } else {
+               err = st_lsm6dsx_fifo_setup_noirq(hw);
+               if (err < 0)
+                       return err;
        }

        for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {