[Feature][T8TSK-26][TCAM_T800_SW_0253]Add imu/smi230 sensor
Change-Id: Ic071e46b8a31273235cbd4117d06295db7e188c3
diff --git a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb_gsw.dts b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb_gsw.dts
index b313cff..1e8f584 100755
--- a/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb_gsw.dts
+++ b/src/kernel/linux/v4.19/arch/arm64/boot/dts/mediatek/auto2735evb_gsw.dts
@@ -247,20 +247,40 @@
// status = "okay";
//};
+ //dongyu@2022.12.13 Modify the dts of imu/smi230 start
+ /*
kxtj3@0e {
compatible = "mediatek,kxtj3_gsensor";
reg = <0x68>;
direction = <2>;
status = "okay";
};
- /*
- mtk-iicd@74 {
+ */
+ //dongyu@2022.12.13 Modify the dts of imu/smi230 end
+
+ /*
+ mtk-iicd@74 {
compatible = "mediatek,mtk-iicd";
reg = <0x74>;
status = "okay";
};
*/
-
+
+ //dongyu@2022.12.13 Add imu/smi230 sensor start
+ smi230acc@18 {
+ compatible = "SMI230ACC";
+ reg = <0x18>;
+ smi-pwr-gpios = <&pio 200 GPIO_ACTIVE_HIGH>;
+ gpio_irq = <&pio 29 GPIO_ACTIVE_LOW>;
+ status = "okay";
+ };
+ smi230gyro@68 {
+ compatible = "SMI230GYRO";
+ reg = <0x68>;
+ gpio_irq = <&pio 177 GPIO_ACTIVE_LOW>;
+ status = "okay";
+ };
+ //dongyu@2022.12.13 Add imu/smi230 sensor end
};
&i2c2 {
diff --git a/src/kernel/linux/v4.19/arch/arm64/configs/auto2735evb_gsw_defconfig b/src/kernel/linux/v4.19/arch/arm64/configs/auto2735evb_gsw_defconfig
index b862b32..351e1c0 100644
--- a/src/kernel/linux/v4.19/arch/arm64/configs/auto2735evb_gsw_defconfig
+++ b/src/kernel/linux/v4.19/arch/arm64/configs/auto2735evb_gsw_defconfig
@@ -816,3 +816,17 @@
CONFIG_PHY_DRIVER_GSW=y
CONFIG_AHEAD_PHY_RESUME=y
#xf.li@2022.12.13 modify for phy-merge end
+
+#dongyu@2022.12.13 Add imu/smi230 sensor start
+CONFIG_IIO_BUFFER=y
+CONFIG_IIO_BUFFER_HW_CONSUMER=y
+CONFIG_IIO_KFIFO_BUF=y
+CONFIG_IIO_TRIGGER=y
+CONFIG_IIO_SW_DEVICE=y
+CONFIG_IIO_SW_TRIGGER=y
+CONFIG_ROCKCHIP_SARADC=y
+CONFIG_IIO_SMI230_ACC=y
+CONFIG_IIO_SMI230_ACC_I2C=y
+CONFIG_SMI230_GYRO=y
+CONFIG_SMI230_GYRO_I2C=y
+#dongyu@2022.12.13 Add imu/smi230 sensor end
diff --git a/src/kernel/linux/v4.19/drivers/iio/accel/Kconfig b/src/kernel/linux/v4.19/drivers/iio/accel/Kconfig
index 829dc96..aa8f733 100644
--- a/src/kernel/linux/v4.19/drivers/iio/accel/Kconfig
+++ b/src/kernel/linux/v4.19/drivers/iio/accel/Kconfig
@@ -408,4 +408,38 @@
Choosing M will build the driver as a module. If so, the module
will be called stk8ba50.
+config IIO_SMI230_ACC
+ tristate "Bosch Sensor SMI230 Accelerometer"
+ depends on (I2C || SPI_MASTER)
+ select IIO_BUFFER
+ select IIO_TRIGGER
+ help
+ Build driver for Bosch SMI230 tri-axis accelerometer sensor.
+
+choice
+ prompt "Select communication interface"
+ depends on IIO_SMI230_ACC
+ help
+ Note: SPI and I2C are not supported at the same time, that is to say:
+ Choose either SPI or I2C to build the driver.
+
+ config IIO_SMI230_ACC_SPI
+ bool "Enable SPI connection"
+ depends on SPI_MASTER
+
+ config IIO_SMI230_ACC_I2C
+ bool "Enable I2C connection"
+ depends on I2C
+endchoice
+
+if IIO_SMI230_ACC
+
+config IIO_SMI230_ACC_MAX_BUFFER_LEN
+ int "configue read buffer size"
+ default "1024"
+ help
+ Considering using FIFO, 1024 bytes are big enough for most cases. Do not change this value if not sure.
+
+endif
+
endmenu
diff --git a/src/kernel/linux/v4.19/drivers/iio/accel/Makefile b/src/kernel/linux/v4.19/drivers/iio/accel/Makefile
index 636d4d1..1d55902 100644
--- a/src/kernel/linux/v4.19/drivers/iio/accel/Makefile
+++ b/src/kernel/linux/v4.19/drivers/iio/accel/Makefile
@@ -56,3 +56,14 @@
obj-$(CONFIG_IIO_ST_ACCEL_I2C_3AXIS) += st_accel_i2c.o
obj-$(CONFIG_IIO_ST_ACCEL_SPI_3AXIS) += st_accel_spi.o
+
+#dongyu@2022.12.13 Add imu/smi230 sensor start
+obj-$(CONFIG_IIO_SMI230_ACC) += smi230_acc.o
+smi230_acc-objs := smi230_acc_core.o
+
+ifeq ($(CONFIG_IIO_SMI230_ACC_I2C),y)
+ smi230_acc-objs += smi230_acc_i2c.o
+else
+ smi230_acc-objs += smi230_acc_spi.o
+endif
+#dongyu@2022.12.13 Add imu/smi230 sensor end
diff --git a/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc.h b/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc.h
new file mode 100644
index 0000000..915e40d
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc.h
@@ -0,0 +1,589 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/**
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
+ *
+ * This file is free software licensed under the terms of version 2
+ * of the GNU General Public License, available from the file LICENSE-GPL
+ * in the main directory of this source tree.
+ *
+ * BSD LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
+ *
+ * BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#ifndef _SMI230_ACC_H
+#define _SMI230_ACC_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/kernel.h>
+#else
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#endif
+
+#include <linux/device.h>
+
+#define DRIVER_VERSION "1.0.0"
+#define MODULE_NAME "SMI230ACC"
+#define SENSOR_ACC_NAME "SMI230ACC"
+
+#if !defined(UINT8_C) && !defined(INT8_C)
+#define INT8_C(x) S8_C(x)
+#define UINT8_C(x) U8_C(x)
+#endif
+
+#if !defined(UINT16_C) && !defined(INT16_C)
+#define INT16_C(x) S16_C(x)
+#define UINT16_C(x) U16_C(x)
+#endif
+
+#if !defined(INT32_C) && !defined(UINT32_C)
+#define INT32_C(x) S32_C(x)
+#define UINT32_C(x) U32_C(x)
+#endif
+
+#if !defined(INT64_C) && !defined(UINT64_C)
+#define INT64_C(x) S64_C(x)
+#define UINT64_C(x) U64_C(x)
+#endif
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *) 0)
+#endif
+#endif
+
+#ifndef TRUE
+#define TRUE UINT8_C(1)
+#endif
+
+#ifndef FALSE
+#define FALSE UINT8_C(0)
+#endif
+
+#define SMI230_ACCEL_CHIP_ID_REG UINT8_C(0x00)
+#define SMI230_ACCEL_ERR_REG UINT8_C(0x02)
+#define SMI230_ACCEL_STATUS_REG UINT8_C(0x03)
+#define SMI230_ACCEL_X_LSB_REG UINT8_C(0x12)
+#define SMI230_ACCEL_X_MSB_REG UINT8_C(0x13)
+#define SMI230_ACCEL_Y_LSB_REG UINT8_C(0x14)
+#define SMI230_ACCEL_Y_MSB_REG UINT8_C(0x15)
+#define SMI230_ACCEL_Z_LSB_REG UINT8_C(0x16)
+#define SMI230_ACCEL_Z_MSB_REG UINT8_C(0x17)
+#define SMI230_ACCEL_SENSORTIME_0_REG UINT8_C(0x18)
+#define SMI230_ACCEL_SENSORTIME_1_REG UINT8_C(0x19)
+#define SMI230_ACCEL_SENSORTIME_2_REG UINT8_C(0x1A)
+#define SMI230_ACCEL_INT_STAT_0_REG UINT8_C(0x1C)
+#define SMI230_ACCEL_INT_STAT_1_REG UINT8_C(0x1D)
+#define SMI230_ACCEL_GP_0_REG UINT8_C(0x1E)
+#define SMI230_TEMP_MSB_REG UINT8_C(0x22)
+#define SMI230_TEMP_LSB_REG UINT8_C(0x23)
+#define SMI230_ACCEL_GP_4_REG UINT8_C(0x27)
+#define SMI230_REG_ORIENT_HIGHG_OUT UINT8_C(0x29)
+#define SMI230_ACCEL_INTERNAL_STAT_REG UINT8_C(0x2A)
+#define SMI230_ACCEL_CONF_REG UINT8_C(0x40)
+#define SMI230_ACCEL_RANGE_REG UINT8_C(0x41)
+#define SMI230_ACCEL_INT1_IO_CONF_REG UINT8_C(0x53)
+#define SMI230_ACCEL_INT2_IO_CONF_REG UINT8_C(0x54)
+#define SMI230_ACCEL_INT_LATCH_CONF_REG UINT8_C(0x55)
+#define SMI230_ACCEL_INT1_MAP_REG UINT8_C(0x56)
+#define SMI230_ACCEL_INT2_MAP_REG UINT8_C(0x57)
+#define SMI230_ACCEL_INT1_INT2_MAP_DATA_REG UINT8_C(0x58)
+#define SMI230_ACCEL_INIT_CTRL_REG UINT8_C(0x59)
+#define SMI230_ACCEL_SELF_TEST_REG UINT8_C(0x6D)
+#define SMI230_ACCEL_PWR_CONF_REG UINT8_C(0x7C)
+#define SMI230_ACCEL_PWR_CTRL_REG UINT8_C(0x7D)
+#define SMI230_ACCEL_SOFTRESET_REG UINT8_C(0x7E)
+#define SMI230_ACCEL_CHIP_ID UINT8_C(0x1F)
+#define SMI230_ACCEL_I2C_ADDR_PRIMARY UINT8_C(0x18)
+#define SMI230_ACCEL_I2C_ADDR_SECONDARY UINT8_C(0x19)
+#define SMI230_ACCEL_RESERVED_5B_REG UINT8_C(0x5B)
+#define SMI230_ACCEL_RESERVED_5C_REG UINT8_C(0x5C)
+#define SMI230_ACCEL_FEATURE_CFG_REG UINT8_C(0x5E)
+#define SMI230_ACCEL_DATA_READY_INT UINT8_C(0x80)
+
+#define SMI230_ACCEL_BW_OSR4 UINT8_C(0x00)
+#define SMI230_ACCEL_BW_OSR2 UINT8_C(0x01)
+#define SMI230_ACCEL_BW_NORMAL UINT8_C(0x02)
+
+#define SMI230_ACCEL_RANGE_2G UINT8_C(0x00)
+#define SMI230_ACCEL_RANGE_4G UINT8_C(0x01)
+#define SMI230_ACCEL_RANGE_8G UINT8_C(0x02)
+#define SMI230_ACCEL_RANGE_16G UINT8_C(0x03)
+
+#define SMI230_ACCEL_ODR_12_5_HZ UINT8_C(0x05)
+#define SMI230_ACCEL_ODR_25_HZ UINT8_C(0x06)
+#define SMI230_ACCEL_ODR_50_HZ UINT8_C(0x07)
+#define SMI230_ACCEL_ODR_100_HZ UINT8_C(0x08)
+#define SMI230_ACCEL_ODR_200_HZ UINT8_C(0x09)
+#define SMI230_ACCEL_ODR_400_HZ UINT8_C(0x0A)
+#define SMI230_ACCEL_ODR_800_HZ UINT8_C(0x0B)
+#define SMI230_ACCEL_ODR_1600_HZ UINT8_C(0x0C)
+
+#define SMI230_ACCEL_SWITCH_OFF_SELF_TEST UINT8_C(0x00)
+#define SMI230_ACCEL_POSITIVE_SELF_TEST UINT8_C(0x0D)
+#define SMI230_ACCEL_NEGATIVE_SELF_TEST UINT8_C(0x09)
+
+#define SMI230_ACCEL_PM_ACTIVE UINT8_C(0x00)
+#define SMI230_ACCEL_PM_SUSPEND UINT8_C(0x03)
+
+#define SMI230_ACCEL_POWER_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_POWER_ENABLE UINT8_C(0x04)
+
+#define SMI230_ACCEL_INTA_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_INTA_ENABLE UINT8_C(0x01)
+#define SMI230_ACCEL_INTB_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_INTB_ENABLE UINT8_C(0x02)
+
+#define SMI230_ACCEL_DATA_SYNC_INT_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_DATA_SYNC_INT_ENABLE UINT8_C(0x01)
+#define SMI230_ACCEL_ANY_MOT_INT_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_ANY_MOT_INT_ENABLE UINT8_C(0x02)
+#define SMI230_ACCEL_HIGH_G_INT_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_HIGH_G_INT_ENABLE UINT8_C(0x04)
+#define SMI230_ACCEL_LOW_G_INT_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_LOW_G_INT_ENABLE UINT8_C(0x08)
+#define SMI230_ACCEL_ORIENT_INT_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_ORIENT_INT_ENABLE UINT8_C(0x10)
+#define SMI230_ACCEL_NO_MOT_INT_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_NO_MOT_INT_ENABLE UINT8_C(0x20)
+#define SMI230_ACCEL_ERR_INT_DISABLE UINT8_C(0x00)
+#define SMI230_ACCEL_ERR_INT_ENABLE UINT8_C(0x80)
+
+#define SMI230_ACCEL_SOFTRESET_DELAY_MS UINT8_C(1)
+
+#define SMI230_FATAL_ERR_MASK UINT8_C(0x01)
+#define SMI230_ERR_CODE_MASK UINT8_C(0x1C)
+
+#define SMI230_CMD_ERR_POS UINT8_C(1)
+#define SMI230_ERR_CODE_POS UINT8_C(2)
+
+#define SMI230_ACCEL_STATUS_MASK UINT8_C(0x80)
+#define SMI230_ACCEL_STATUS_POS UINT8_C(7)
+
+#define SMI230_ACCEL_ODR_MASK UINT8_C(0x0F)
+#define SMI230_ACCEL_BW_MASK UINT8_C(0x70)
+#define SMI230_ACCEL_RANGE_MASK UINT8_C(0x03)
+
+#define SMI230_ACCEL_BW_POS UINT8_C(4)
+
+#define SMI230_ACCEL_INT_EDGE_MASK UINT8_C(0x01)
+#define SMI230_ACCEL_INT_LVL_MASK UINT8_C(0x02)
+#define SMI230_ACCEL_INT_OD_MASK UINT8_C(0x04)
+#define SMI230_ACCEL_INT_IO_MASK UINT8_C(0x08)
+#define SMI230_ACCEL_INT_IN_MASK UINT8_C(0x10)
+
+#define SMI230_ACCEL_INT_EDGE_POS UINT8_C(0)
+#define SMI230_ACCEL_INT_LVL_POS UINT8_C(1)
+#define SMI230_ACCEL_INT_OD_POS UINT8_C(2)
+#define SMI230_ACCEL_INT_IO_POS UINT8_C(3)
+#define SMI230_ACCEL_INT_IN_POS UINT8_C(4)
+
+#define SMI230_ACCEL_MAP_INTA_MASK UINT8_C(0x01)
+#define SMI230_ACCEL_MAP_INTA_POS UINT8_C(0x00)
+
+#define SMI230_ACCEL_INT1_DRDY_MASK UINT8_C(0x04)
+#define SMI230_ACCEL_INT2_DRDY_MASK UINT8_C(0x40)
+#define SMI230_ACCEL_INT1_DRDY_POS UINT8_C(2)
+#define SMI230_ACCEL_INT2_DRDY_POS UINT8_C(6)
+
+#define SMI230_ASIC_INITIALIZED UINT8_C(0x01)
+
+#define SMI230_SPI_RD_MASK UINT8_C(0x80)
+#define SMI230_SPI_WR_MASK UINT8_C(0x7F)
+
+#define SMI230_OK INT8_C(0)
+#define SMI230_E_NULL_PTR INT8_C(-1)
+#define SMI230_E_COM_FAIL INT8_C(-2)
+#define SMI230_E_DEV_NOT_FOUND INT8_C(-3)
+#define SMI230_E_OUT_OF_RANGE INT8_C(-4)
+#define SMI230_E_INVALID_INPUT INT8_C(-5)
+#define SMI230_E_CONFIG_STREAM_ERROR INT8_C(-6)
+#define SMI230_E_RD_WR_LENGTH_INVALID INT8_C(-7)
+#define SMI230_E_INVALID_CONFIG INT8_C(-8)
+#define SMI230_E_FEATURE_NOT_SUPPORTED INT8_C(-9)
+
+#define SMI230_W_SELF_TEST_FAIL INT8_C(1)
+
+#define SMI230_SOFT_RESET_CMD UINT8_C(0xB6)
+#define SMI230_FIFO_RESET_CMD UINT8_C(0xB0)
+
+#define SMI230_DISABLE UINT8_C(0)
+#define SMI230_ENABLE UINT8_C(1)
+
+#define SMI230_SENSOR_DATA_SYNC_TIME_MS UINT8_C(1)
+#define SMI230_DELAY_BETWEEN_WRITES_MS UINT8_C(1)
+#define SMI230_SELF_TEST_DELAY_MS UINT8_C(3)
+#define SMI230_POWER_CONFIG_DELAY UINT8_C(5)
+#define SMI230_SENSOR_SETTLE_TIME_MS UINT8_C(30)
+#define SMI230_SELF_TEST_DATA_READ_MS UINT8_C(50)
+#define SMI230_ASIC_INIT_TIME_MS UINT8_C(150)
+
+#define SMI230_CONFIG_STREAM_SIZE UINT16_C(6144)
+
+#define SMI230_SENSOR_TIME_MSB_BYTE UINT8_C(2)
+#define SMI230_SENSOR_TIME_XLSB_BYTE UINT8_C(1)
+#define SMI230_SENSOR_TIME_LSB_BYTE UINT8_C(0)
+
+#define SMI230_INT_ACTIVE_LOW UINT8_C(0)
+#define SMI230_INT_ACTIVE_HIGH UINT8_C(1)
+#define SMI230_INT_MODE_PUSH_PULL UINT8_C(0)
+#define SMI230_INT_MODE_OPEN_DRAIN UINT8_C(1)
+
+#define SMI230_16_BIT_RESOLUTION UINT8_C(16)
+
+#ifndef SMI230_ABS
+#define SMI230_ABS(a) ((a) > 0 ? (a) : -(a))
+#endif
+
+#define SMI230_SET_LOW_BYTE UINT16_C(0x00FF)
+#define SMI230_SET_HIGH_BYTE UINT16_C(0xFF00)
+#define SMI230_SET_LOW_NIBBLE UINT8_C(0x0F)
+
+#define SMI230_ACCEL_ANYMOTION_ADR UINT8_C(0x00)
+#define SMI230_ACCEL_DATA_SYNC_ADR UINT8_C(0x02)
+#define SMI230_HIGH_G_START_ADR UINT8_C(0x03)
+#define SMI230_LOW_G_START_ADR UINT8_C(0x06)
+#define SMI230_ORIENT_START_ADR UINT8_C(0x09)
+#define SMI230_NO_MOTION_START_ADR UINT8_C(0x0B)
+
+#define SMI230_ACCEL_ANYMOTION_LEN UINT8_C(0x02)
+#define SMI230_ACCEL_ANYMOTION_THRESHOLD_MASK UINT16_C(0x07FF)
+#define SMI230_ACCEL_ANYMOTION_THRESHOLD_SHIFT UINT8_C(0x00)
+#define SMI230_ACCEL_ANYMOTION_NOMOTION_SEL_MASK UINT16_C(0x0800)
+#define SMI230_ACCEL_ANYMOTION_NOMOTION_SEL_SHIFT UINT8_C(0x0B)
+#define SMI230_ACCEL_ANYMOTION_DURATION_MASK UINT16_C(0x1FFF)
+#define SMI230_ACCEL_ANYMOTION_DURATION_SHIFT UINT8_C(0x00)
+#define SMI230_ACCEL_ANYMOTION_X_EN_MASK UINT16_C(0x2000)
+#define SMI230_ACCEL_ANYMOTION_X_EN_SHIFT UINT8_C(0x0D)
+#define SMI230_ACCEL_ANYMOTION_Y_EN_MASK UINT16_C(0x4000)
+#define SMI230_ACCEL_ANYMOTION_Y_EN_SHIFT UINT8_C(0x0E)
+#define SMI230_ACCEL_ANYMOTION_Z_EN_MASK UINT16_C(0x8000)
+#define SMI230_ACCEL_ANYMOTION_Z_EN_SHIFT UINT8_C(0x0F)
+
+#define SMI230_HIGH_G_THRES_MASK UINT16_C(0x7FFF)
+#define SMI230_HIGH_G_HYST_MASK UINT16_C(0x0FFF)
+#define SMI230_HIGH_G_X_SEL_MASK UINT16_C(0x1000)
+#define SMI230_HIGH_G_Y_SEL_MASK UINT16_C(0x2000)
+#define SMI230_HIGH_G_Z_SEL_MASK UINT16_C(0x4000)
+#define SMI230_HIGH_G_ENABLE_MASK UINT16_C(0x8000)
+#define SMI230_HIGH_G_DUR_MASK UINT16_C(0x0FFF)
+#define SMI230_HIGH_G_OUT_CONF_MASK UINT16_C(0xF000)
+
+#define SMI230_HIGH_G_THRES_POS UINT8_C(0x00)
+#define SMI230_HIGH_G_HYST_POS UINT8_C(0x00)
+#define SMI230_HIGH_G_OUT_CONF_POS UINT8_C(0x0C)
+#define SMI230_HIGH_G_X_SEL_POS UINT8_C(0x0C)
+#define SMI230_HIGH_G_Y_SEL_POS UINT8_C(0x0D)
+#define SMI230_HIGH_G_Z_SEL_POS UINT8_C(0x0E)
+#define SMI230_HIGH_G_ENABLE_POS UINT8_C(0x0F)
+#define SMI230_HIGH_G_DUR_POS UINT8_C(0x00)
+#define SMI230_HIGH_G_AXIS_X_POS UINT8_C(0x03)
+#define SMI230_HIGH_G_AXIS_Y_POS UINT8_C(0x04)
+#define SMI230_HIGH_G_AXIS_Z_POS UINT8_C(0x05)
+#define SMI230_HIGH_G_AXIS_DIRECTION_POS UINT8_C(0x06)
+
+#define SMI230_HIGH_G_AXIS_X_MASK UINT8_C(0x08)
+#define SMI230_HIGH_G_AXIS_Y_MASK UINT8_C(0x10)
+#define SMI230_HIGH_G_AXIS_Z_MASK UINT8_C(0x20)
+#define SMI230_HIGH_G_AXIS_DIRECTION_MASK UINT8_C(0x80)
+
+#define SMI230_LOW_G_THRES_MASK UINT16_C(0x7FFF)
+#define SMI230_LOW_G_HYST_MASK UINT16_C(0x0FFF)
+#define SMI230_LOW_G_DUR_MASK UINT16_C(0x0FFF)
+#define SMI230_LOW_G_ENABLE_MASK UINT16_C(0x1000)
+
+#define SMI230_LOW_G_THRES_POS UINT16_C(0x00)
+#define SMI230_LOW_G_HYST_POS UINT16_C(0x00)
+#define SMI230_LOW_G_DUR_POS UINT16_C(0x00)
+#define SMI230_LOW_G_ENABLE_POS UINT16_C(0x0C)
+
+#define SMI230_ORIENT_ENABLE_MASK UINT16_C(0x0001)
+#define SMI230_ORIENT_UP_DOWN_MASK UINT16_C(0x0002)
+#define SMI230_ORIENT_SYMM_MODE_MASK UINT16_C(0x000C)
+#define SMI230_ORIENT_BLOCK_MODE_MASK UINT16_C(0x0030)
+#define SMI230_ORIENT_THETA_MASK UINT16_C(0x0FC0)
+#define SMI230_ORIENT_HYST_MASK UINT16_C(0x07FF)
+#define SMI230_ORIENT_PORTRAIT_LANDSCAPE_MASK UINT8_C(0x03)
+#define SMI230_ORIENT_FACEUP_DOWN_MASK UINT8_C(0x04)
+
+#define SMI230_ORIENT_ENABLE_POS UINT8_C(0x00)
+#define SMI230_ORIENT_UP_DOWN_POS UINT8_C(0x01)
+#define SMI230_ORIENT_SYMM_MODE_POS UINT8_C(0x02)
+#define SMI230_ORIENT_BLOCK_MODE_POS UINT8_C(0x04)
+#define SMI230_ORIENT_THETA_POS UINT8_C(0x06)
+#define SMI230_ORIENT_HYST_POS UINT8_C(0x00)
+#define SMI230_ORIENT_PORTRAIT_LANDSCAPE_POS UINT8_C(0x00)
+#define SMI230_ORIENT_FACEUP_DOWN_POS UINT8_C(0x02)
+
+#define SMI230_ORIENT_PORTRAIT_UPRIGHT UINT8_C(0x00)
+#define SMI230_ORIENT_LANDSCAPE_LEFT UINT8_C(0x01)
+#define SMI230_ORIENT_PORTRAIT_UPSIDE_DOWN UINT8_C(0x02)
+#define SMI230_ORIENT_LANDSCAPE_RIGHT UINT8_C(0x03)
+#define SMI230_ORIENT_FACE_UP UINT8_C(0x00)
+#define SMI230_ORIENT_FACE_DOWN UINT8_C(0x01)
+
+#define SMI230_NO_MOTION_THRESHOLD_MASK UINT16_C(0x07FF)
+#define SMI230_NO_MOTION_SEL_MASK UINT16_C(0x0800)
+#define SMI230_NO_MOTION_DURATION_MASK UINT16_C(0x1FFF)
+#define SMI230_NO_MOTION_X_EN_MASK UINT16_C(0x2000)
+#define SMI230_NO_MOTION_Y_EN_MASK UINT16_C(0x4000)
+#define SMI230_NO_MOTION_Z_EN_MASK UINT16_C(0x8000)
+
+#define SMI230_NO_MOTION_THRESHOLD_POS UINT8_C(0)
+#define SMI230_NO_MOTION_SEL_POS UINT8_C(11)
+#define SMI230_NO_MOTION_DURATION_POS UINT8_C(0)
+#define SMI230_NO_MOTION_X_EN_POS UINT8_C(13)
+#define SMI230_NO_MOTION_Y_EN_POS UINT8_C(14)
+#define SMI230_NO_MOTION_Z_EN_POS UINT8_C(15)
+
+#define SMI230_ACCEL_DATA_SYNC_LEN 1
+#define SMI230_ACCEL_DATA_SYNC_MODE_MASK 0x0003
+#define SMI230_ACCEL_DATA_SYNC_MODE_SHIFT 0
+
+#define SMI230_ACCEL_DATA_SYNC_MODE_OFF 0x00
+#define SMI230_ACCEL_DATA_SYNC_MODE_400HZ 0x01
+#define SMI230_ACCEL_DATA_SYNC_MODE_1000HZ 0x02
+#define SMI230_ACCEL_DATA_SYNC_MODE_2000HZ 0x03
+
+#define SMI230_SET_BITS(reg_var, bitname, val) \
+ ((reg_var & ~(bitname##_MASK)) | \
+ ((val << bitname##_POS) & bitname##_MASK))
+
+#define SMI230_GET_BITS(reg_var, bitname) \
+ ((reg_var & (bitname##_MASK)) >> \
+ (bitname##_POS))
+
+#define SMI230_SET_BITS_POS_0(reg_var, bitname, val) \
+ ((reg_var & ~(bitname##_MASK)) | \
+ (val & bitname##_MASK))
+
+#define SMI230_GET_BITS_POS_0(reg_var, bitname) (reg_var & (bitname##_MASK))
+#define SMI230_SET_BIT_VAL_0(reg_var, bitname) (reg_var & ~(bitname##_MASK))
+
+#define SMI230_GET_DIFF(x, y) ((x) - (y))
+
+#define SMI230_GET_LSB(var) (uint8_t)(var & SMI230_SET_LOW_BYTE)
+#define SMI230_GET_MSB(var) (uint8_t)((var & SMI230_SET_HIGH_BYTE) >> 8)
+
+enum smi230_intf {
+ SMI230_I2C_INTF,
+ SMI230_SPI_INTF
+};
+
+typedef int8_t(*smi230_com_fptr_t) (uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t *data, uint16_t len);
+
+typedef void (*smi230_delay_fptr_t)(uint32_t period);
+
+struct smi230_sensor_data {
+ int16_t x;
+ int16_t y;
+ int16_t z;
+};
+
+struct smi230_sensor_data_f {
+ float x;
+ float y;
+ float z;
+};
+
+struct smi230_cfg {
+ uint8_t power;
+ uint8_t range;
+ uint8_t bw;
+ uint8_t odr;
+};
+
+struct smi230_err_reg {
+ uint8_t fatal_err;
+ uint8_t err_code;
+};
+
+struct smi230_anymotion_cfg {
+ /* 11 bit threshold of anymotion detection
+ * (threshold = X mg * 2,048 (5.11 format))
+ */
+ uint16_t threshold;
+ uint16_t enable;
+
+ /* 13 bit set the duration for any- and nomotion
+ * (time = duration * 20ms (@50Hz))
+ */
+ uint16_t duration;
+ uint16_t x_en;
+ uint16_t y_en;
+ uint16_t z_en;
+};
+
+struct smi230_data_sync_cfg {
+ /*! Mode (0 = off, 1 = 400Hz, 2 = 1kHz, 3 = 2kHz) */
+ uint8_t mode;
+};
+
+struct smi230_high_g_cfg {
+ uint16_t threshold;
+ uint16_t hysteresis;
+ uint16_t select_x;
+ uint16_t select_y;
+ uint16_t select_z;
+ uint16_t enable;
+ uint16_t duration;
+};
+
+struct smi230_low_g_cfg {
+ uint16_t threshold;
+ uint16_t hysteresis;
+ uint16_t duration;
+ uint16_t enable;
+
+};
+
+struct smi230_high_g_out {
+ uint8_t x;
+ uint8_t y;
+ uint8_t z;
+ uint8_t direction;
+};
+
+struct smi230_orient_cfg {
+ uint16_t ud_en;
+ uint16_t mode;
+ uint16_t blocking;
+ uint16_t theta;
+ uint16_t hysteresis;
+ uint16_t enable;
+};
+
+struct smi230_orient_out {
+ uint8_t portrait_landscape;
+ uint8_t faceup_down;
+};
+
+struct smi230_no_motion_cfg {
+ uint16_t duration;
+ uint16_t threshold;
+ uint16_t select_x;
+ uint16_t select_y;
+ uint16_t select_z;
+ uint16_t enable;
+
+};
+
+enum smi230_accel_int_channel {
+ SMI230_INT_CHANNEL_1,
+ SMI230_INT_CHANNEL_2
+};
+
+enum smi230_accel_int_types {
+ SMI230_ACCEL_DATA_RDY_INT,
+ SMI230_ACCEL_SYNC_DATA_RDY_INT,
+ SMI230_ACCEL_SYNC_INPUT,
+ SMI230_ACCEL_FIFO_WM_INT,
+ SMI230_ACCEL_FIFO_FULL_INT,
+ //SMI230_ACCEL_INT_FIFO_FULL,
+ SMI230_ACCEL_ANYMOTION_INT,
+ SMI230_ACCEL_HIGH_G_INT,
+ SMI230_ACCEL_LOW_G_INT,
+ SMI230_ACCEL_ORIENT_INT,
+ SMI230_ACCEL_NO_MOTION_INT,
+ SMI230_ACCEL_ERROR_INT
+};
+
+struct smi230_int_pin_cfg {
+
+ /*! interrupt pin level configuration
+ * Assignable macros :
+ * - SMI230_INT_ACTIVE_LOW
+ * - SMI230_INT_ACTIVE_HIGH
+ */
+ uint8_t lvl:1;
+
+ /*! interrupt pin mode configuration
+ * Assignable macros :
+ * - SMI230_INT_MODE_PUSH_PULL
+ * - SMI230_INT_MODE_OPEN_DRAIN
+ */
+ uint8_t output_mode:1;
+
+ /*! Enable interrupt pin
+ * Assignable Macros :
+ * - SMI230_ENABLE
+ * - SMI230_DISABLE
+ */
+ uint8_t enable_int_pin:1;
+};
+
+struct smi230_accel_int_channel_cfg {
+ enum smi230_accel_int_channel int_channel;
+ enum smi230_accel_int_types int_type;
+ struct smi230_int_pin_cfg int_pin_cfg;
+};
+
+struct smi230_int_cfg {
+ struct smi230_accel_int_channel_cfg accel_int_config_1;
+ struct smi230_accel_int_channel_cfg accel_int_config_2;
+};
+
+struct smi230_dev {
+ uint8_t accel_chip_id;
+ uint8_t gyro_chip_id;
+ uint8_t accel_id;
+ uint8_t gyro_id;
+ enum smi230_intf intf;
+ uint8_t dummy_byte;
+ struct smi230_cfg accel_cfg;
+ struct smi230_cfg gyro_cfg;
+ const uint8_t *config_file_ptr;
+ uint8_t read_write_len;
+ smi230_com_fptr_t read;
+ smi230_com_fptr_t write;
+ smi230_delay_fptr_t delay_ms;
+};
+
+void smi230_delay(uint32_t msec);
+
+int smi230_acc_probe(struct device *dev, struct smi230_dev *p_smi230_dev);
+
+int8_t smi230_acc_init(struct smi230_dev *dev);
+
+#endif /* _SMI230_ACC_H */
diff --git a/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc_core.c b/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc_core.c
new file mode 100644
index 0000000..fe4e0e9
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc_core.c
@@ -0,0 +1,1227 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/**
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * This file is free software licensed under the terms of version 2
+ * of the GNU General Public License, available from the file LICENSE-GPL
+ * in the main directory of this source tree.
+ *
+ * BSD LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/of_gpio.h>
+#include <linux/ioport.h>
+
+#include "smi230_acc.h"
+
+#define SMI230_CHANNEL(_type, _axis, _index) { \
+ .type = _type, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+}
+
+static uint8_t temp_buff[CONFIG_IIO_SMI230_ACC_MAX_BUFFER_LEN + 1];
+
+static const struct iio_chan_spec smi230_channels[] = {
+ SMI230_CHANNEL(IIO_ACCEL, X, 0),
+ SMI230_CHANNEL(IIO_ACCEL, Y, 1),
+ SMI230_CHANNEL(IIO_ACCEL, Z, 2),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static struct smi230_int_cfg int_config;
+
+int8_t null_ptr_check(const struct smi230_dev *dev)
+{
+ int8_t rslt;
+
+ if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL)
+ || (dev->delay_ms == NULL))
+ rslt = SMI230_E_NULL_PTR;
+ else
+ rslt = SMI230_OK;
+
+ return rslt;
+}
+
+static int8_t get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint16_t index;
+ uint16_t temp_len = len + dev->dummy_byte;
+
+ if (WARN(temp_len > CONFIG_IIO_SMI230_ACC_MAX_BUFFER_LEN,
+ "SMI230 buffer overflow\n"))
+ return SMI230_E_COM_FAIL;
+
+ if (dev->intf == SMI230_SPI_INTF)
+ reg_addr = reg_addr | SMI230_SPI_RD_MASK;
+
+ rslt = dev->read(dev->accel_id, reg_addr, temp_buff, temp_len);
+
+ if (rslt == SMI230_OK) {
+ for (index = 0; index < len; index++)
+ reg_data[index] = temp_buff[index + dev->dummy_byte];
+ } else {
+ rslt = SMI230_E_COM_FAIL;
+ }
+
+ return rslt;
+}
+
+static int8_t set_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+
+ if (dev->intf == SMI230_SPI_INTF) {
+ reg_addr = (reg_addr & SMI230_SPI_WR_MASK);
+ }
+
+ rslt = dev->write(dev->accel_id, reg_addr, reg_data, len);
+
+ if (rslt != SMI230_OK)
+ rslt = SMI230_E_COM_FAIL;
+
+ return rslt;
+}
+
+static int8_t set_int_pin_config(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t reg_addr = 0;
+ uint8_t data;
+ uint8_t is_channel_invalid = FALSE;
+
+ switch (int_config->int_channel) {
+ case SMI230_INT_CHANNEL_1:
+ reg_addr = SMI230_ACCEL_INT1_IO_CONF_REG;
+ break;
+
+ case SMI230_INT_CHANNEL_2:
+ reg_addr = SMI230_ACCEL_INT2_IO_CONF_REG;
+ break;
+
+ default:
+ is_channel_invalid = TRUE;
+ break;
+ }
+
+ if (!is_channel_invalid) {
+ rslt = get_regs(reg_addr, &data, 1, dev);
+
+ if (rslt == SMI230_OK) {
+ data = SMI230_SET_BITS(data, SMI230_ACCEL_INT_LVL,
+ int_config->int_pin_cfg.lvl);
+
+ data = SMI230_SET_BITS(data, SMI230_ACCEL_INT_OD,
+ int_config->int_pin_cfg.output_mode);
+
+ if (int_config->int_type == SMI230_ACCEL_SYNC_INPUT) {
+ data = SMI230_SET_BITS_POS_0(data, SMI230_ACCEL_INT_EDGE,
+ SMI230_ENABLE);
+
+ data = SMI230_SET_BITS(data, SMI230_ACCEL_INT_IN,
+ int_config->int_pin_cfg.enable_int_pin);
+
+ data = SMI230_SET_BIT_VAL_0(data, SMI230_ACCEL_INT_IO);
+ } else {
+ data = SMI230_SET_BITS(data, SMI230_ACCEL_INT_IO,
+ int_config->int_pin_cfg.enable_int_pin);
+
+ data = SMI230_SET_BIT_VAL_0(data, SMI230_ACCEL_INT_IN);
+ }
+
+ rslt = set_regs(reg_addr, &data, 1, dev);
+ }
+ } else {
+ rslt = SMI230_E_INVALID_INPUT;
+ }
+
+ return rslt;
+}
+
+static int8_t set_accel_data_ready_int(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data = 0, conf;
+
+ rslt = get_regs(SMI230_ACCEL_INT1_INT2_MAP_DATA_REG, &data, 1, dev);
+
+ if (rslt == SMI230_OK) {
+ conf = int_config->int_pin_cfg.enable_int_pin;
+
+ switch (int_config->int_channel) {
+ case SMI230_INT_CHANNEL_1:
+ data = SMI230_SET_BITS(data, SMI230_ACCEL_INT1_DRDY, conf);
+ break;
+
+ case SMI230_INT_CHANNEL_2:
+ data = SMI230_SET_BITS(data, SMI230_ACCEL_INT2_DRDY, conf);
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK) {
+ rslt = set_int_pin_config(int_config, dev);
+ if (rslt == SMI230_OK)
+ rslt = set_regs(SMI230_ACCEL_INT1_INT2_MAP_DATA_REG,
+ &data, 1, dev);
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t set_accel_sync_data_ready_int(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data, reg_addr = 0;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK) {
+
+ data = SMI230_ACCEL_INTA_DISABLE;
+
+ switch (int_config->int_channel) {
+ case SMI230_INT_CHANNEL_1:
+ reg_addr = SMI230_ACCEL_INT1_MAP_REG;
+ break;
+
+ case SMI230_INT_CHANNEL_2:
+ reg_addr = SMI230_ACCEL_INT2_MAP_REG;
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK) {
+ if (int_config->int_pin_cfg.enable_int_pin == SMI230_ENABLE)
+ data = SMI230_ACCEL_INTA_ENABLE;
+
+ rslt = set_regs(reg_addr, &data, 1, dev);
+ if (rslt == SMI230_OK)
+ rslt = set_int_pin_config(int_config, dev);
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t set_accel_sync_input(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK)
+ rslt = set_int_pin_config(int_config, dev);
+
+ return rslt;
+}
+
+static int8_t set_accel_anymotion_int(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data, reg_addr = 0;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK) {
+ data = SMI230_ACCEL_INTB_DISABLE;
+
+ switch (int_config->int_channel) {
+ case SMI230_INT_CHANNEL_1:
+ reg_addr = SMI230_ACCEL_INT1_MAP_REG;
+ break;
+
+ case SMI230_INT_CHANNEL_2:
+ reg_addr = SMI230_ACCEL_INT2_MAP_REG;
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK) {
+ if (int_config->int_pin_cfg.enable_int_pin == SMI230_ENABLE)
+ data = SMI230_ACCEL_INTB_ENABLE;
+
+ rslt = set_regs(reg_addr, &data, 1, dev);
+ if (rslt == SMI230_OK)
+ rslt = set_int_pin_config(int_config, dev);
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t set_accel_high_g_int(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data, reg_addr = 0;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK) {
+ data = SMI230_ACCEL_HIGH_G_INT_DISABLE;
+
+ switch (int_config->int_channel) {
+ case SMI230_INT_CHANNEL_1:
+ reg_addr = SMI230_ACCEL_INT1_MAP_REG;
+ break;
+
+ case SMI230_INT_CHANNEL_2:
+ reg_addr = SMI230_ACCEL_INT2_MAP_REG;
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK) {
+ rslt = get_regs(reg_addr, &data, 1, dev);
+
+ if (int_config->int_pin_cfg.enable_int_pin == SMI230_ENABLE)
+ data |= SMI230_ACCEL_HIGH_G_INT_ENABLE;
+ else
+ data &= ~SMI230_ACCEL_HIGH_G_INT_ENABLE;
+
+ if (rslt == SMI230_OK)
+ rslt = set_regs(reg_addr, &data, 1, dev);
+
+ if (rslt == SMI230_OK)
+ rslt = set_int_pin_config(int_config, dev);
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t set_accel_low_g_int(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data, reg_addr = 0;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK) {
+ data = SMI230_ACCEL_LOW_G_INT_DISABLE;
+
+ switch (int_config->int_channel) {
+ case SMI230_INT_CHANNEL_1:
+ reg_addr = SMI230_ACCEL_INT1_MAP_REG;
+ break;
+
+ case SMI230_INT_CHANNEL_2:
+ reg_addr = SMI230_ACCEL_INT2_MAP_REG;
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK) {
+ rslt = get_regs(reg_addr, &data, 1, dev);
+
+ if (int_config->int_pin_cfg.enable_int_pin == SMI230_ENABLE)
+ data |= SMI230_ACCEL_LOW_G_INT_ENABLE;
+ else
+ data &= ~SMI230_ACCEL_LOW_G_INT_DISABLE;
+
+ if (rslt == SMI230_OK)
+ rslt = set_regs(reg_addr, &data, 1, dev);
+
+ if (rslt == SMI230_OK)
+ rslt = set_int_pin_config(int_config, dev);
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t set_accel_orient_int(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data, reg_addr = 0;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK) {
+ data = SMI230_ACCEL_ORIENT_INT_DISABLE;
+
+ switch (int_config->int_channel) {
+ case SMI230_INT_CHANNEL_1:
+ reg_addr = SMI230_ACCEL_INT1_MAP_REG;
+ break;
+
+ case SMI230_INT_CHANNEL_2:
+ reg_addr = SMI230_ACCEL_INT2_MAP_REG;
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK) {
+ rslt = get_regs(reg_addr, &data, 1, dev);
+
+ if (int_config->int_pin_cfg.enable_int_pin == SMI230_ENABLE)
+ data |= SMI230_ACCEL_ORIENT_INT_ENABLE;
+ else
+ data &= ~SMI230_ACCEL_ORIENT_INT_ENABLE;
+
+ if (rslt == SMI230_OK)
+ rslt = set_regs(reg_addr, &data, 1, dev);
+
+ if (rslt == SMI230_OK)
+ rslt = set_int_pin_config(int_config, dev);
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t set_accel_no_motion_int(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data, reg_addr = 0;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK) {
+ data = SMI230_ACCEL_NO_MOT_INT_DISABLE;
+
+ switch (int_config->int_channel) {
+ case SMI230_INT_CHANNEL_1:
+ reg_addr = SMI230_ACCEL_INT1_MAP_REG;
+ break;
+
+ case SMI230_INT_CHANNEL_2:
+ reg_addr = SMI230_ACCEL_INT2_MAP_REG;
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK) {
+ rslt = get_regs(reg_addr, &data, 1, dev);
+
+ if (int_config->int_pin_cfg.enable_int_pin == SMI230_ENABLE)
+ data |= SMI230_ACCEL_NO_MOT_INT_ENABLE;
+ else
+ data &= ~SMI230_ACCEL_NO_MOT_INT_ENABLE;
+
+ if (rslt == SMI230_OK)
+ rslt = set_regs(reg_addr, &data, 1, dev);
+
+ if (rslt == SMI230_OK)
+ rslt = set_int_pin_config(int_config, dev);
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t set_accel_err_int(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data, reg_addr = 0;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK) {
+ data = SMI230_ACCEL_ERR_INT_DISABLE;
+
+ switch (int_config->int_channel) {
+ case SMI230_INT_CHANNEL_1:
+ reg_addr = SMI230_ACCEL_INT1_MAP_REG;
+ break;
+
+ case SMI230_INT_CHANNEL_2:
+ reg_addr = SMI230_ACCEL_INT2_MAP_REG;
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK) {
+ rslt = get_regs(reg_addr, &data, 1, dev);
+
+ if (int_config->int_pin_cfg.enable_int_pin == SMI230_ENABLE)
+ data |= SMI230_ACCEL_ERR_INT_ENABLE;
+ else
+ data &= ~SMI230_ACCEL_ERR_INT_ENABLE;
+
+ if (rslt == SMI230_OK)
+ rslt = set_regs(reg_addr, &data, 1, dev);
+
+ if (rslt == SMI230_OK)
+ rslt = set_int_pin_config(int_config, dev);
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t smi230_acc_soft_reset(const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data;
+
+ rslt = null_ptr_check(dev);
+
+ if (rslt == SMI230_OK) {
+ data = SMI230_SOFT_RESET_CMD;
+ rslt = set_regs(SMI230_ACCEL_SOFTRESET_REG, &data, 1, dev);
+
+ if (rslt == SMI230_OK) {
+ dev->delay_ms(SMI230_ACCEL_SOFTRESET_DELAY_MS);
+
+ /* After soft reset SPI mode in the initialization phase, need to
+ * perform a dummy SPI read operation.
+ * The soft-reset performs a fundamental reset to the device,
+ * which is largely equivalent to a power cycle.
+ */
+ if (dev->intf == SMI230_SPI_INTF) {
+ /* Dummy SPI read operation of Chip-ID */
+ rslt = get_regs(SMI230_ACCEL_CHIP_ID_REG, &data, 1, dev);
+ }
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t smi230_acc_get_meas_conf(struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2];
+
+ rslt = null_ptr_check(dev);
+
+ if (rslt == SMI230_OK) {
+ rslt = get_regs(SMI230_ACCEL_CONF_REG, data, 2, dev);
+
+ if (rslt == SMI230_OK) {
+ dev->accel_cfg.odr = data[0] & SMI230_ACCEL_ODR_MASK;
+ dev->accel_cfg.bw = (data[0] & SMI230_ACCEL_BW_MASK) >> 4;
+ dev->accel_cfg.range = data[1] & SMI230_ACCEL_RANGE_MASK;
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t smi230_acc_set_meas_conf(const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2] = { 0 };
+ uint8_t bw, range, odr;
+ uint8_t is_odr_invalid = FALSE;
+ uint8_t is_bw_invalid = FALSE;
+ uint8_t is_range_invalid = FALSE;
+
+ rslt = null_ptr_check(dev);
+
+ if (rslt == SMI230_OK) {
+ odr = dev->accel_cfg.odr;
+ bw = dev->accel_cfg.bw;
+ range = dev->accel_cfg.range;
+
+ if ((odr < SMI230_ACCEL_ODR_12_5_HZ)
+ || (odr > SMI230_ACCEL_ODR_1600_HZ)) {
+ is_odr_invalid = TRUE;
+ }
+
+ if (bw > SMI230_ACCEL_BW_NORMAL)
+ is_bw_invalid = TRUE;
+
+ if (range > SMI230_ACCEL_RANGE_16G)
+ is_range_invalid = TRUE;
+
+ /* If ODR, BW and Range are valid, write it to accel config registers */
+ if ((!is_odr_invalid) && (!is_bw_invalid) && (!is_range_invalid)) {
+ rslt = get_regs(SMI230_ACCEL_CONF_REG, data, 2, dev);
+ if (rslt == SMI230_OK) {
+ /* Update data with new odr and bw values */
+ data[0] = SMI230_SET_BITS_POS_0(data[0], SMI230_ACCEL_ODR, odr);
+ data[0] = SMI230_SET_BITS(data[0], SMI230_ACCEL_BW, bw);
+
+ /* Update data with current range values */
+ data[1] = SMI230_SET_BITS_POS_0(data[1], SMI230_ACCEL_RANGE,
+ range);
+
+ /* write to range register */
+ rslt = set_regs(SMI230_ACCEL_CONF_REG, data, 2, dev);
+ }
+ } else {
+ rslt = SMI230_E_INVALID_CONFIG;
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t smi230_acc_set_power_mode(const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2];
+
+ rslt = null_ptr_check(dev);
+
+ if (rslt == SMI230_OK) {
+ if (dev->accel_cfg.power == SMI230_ACCEL_PM_ACTIVE) {
+ data[0] = SMI230_ACCEL_PM_ACTIVE;
+ data[1] = SMI230_ACCEL_POWER_ENABLE;
+ } else if (dev->accel_cfg.power == SMI230_ACCEL_PM_SUSPEND) {
+ data[0] = SMI230_ACCEL_PM_SUSPEND;
+ data[1] = SMI230_ACCEL_POWER_DISABLE;
+ } else {
+ rslt = SMI230_E_INVALID_INPUT;
+ }
+
+ if (rslt == SMI230_OK) {
+ rslt = set_regs(SMI230_ACCEL_PWR_CONF_REG, &data[0], 1, dev);
+
+ if (rslt == SMI230_OK) {
+ dev->delay_ms(SMI230_POWER_CONFIG_DELAY);
+ rslt = set_regs(SMI230_ACCEL_PWR_CTRL_REG, &data[1], 1, dev);
+ if (rslt == SMI230_OK)
+ dev->delay_ms(SMI230_POWER_CONFIG_DELAY);
+ }
+
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t smi230_acc_get_data(struct smi230_sensor_data *accel,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[6];
+ uint8_t lsb, msb;
+ uint16_t msblsb;
+
+ rslt = null_ptr_check(dev);
+
+ if ((rslt == SMI230_OK) && (accel != NULL)) {
+ rslt = get_regs(SMI230_ACCEL_X_LSB_REG, data, 6, dev);
+
+ if (rslt == SMI230_OK) {
+ lsb = data[0];
+ msb = data[1];
+ msblsb = (msb << 8) | lsb;
+ accel->x = ((int16_t) msblsb); /* Data in X axis */
+
+ lsb = data[2];
+ msb = data[3];
+ msblsb = (msb << 8) | lsb;
+ accel->y = ((int16_t) msblsb); /* Data in Y axis */
+
+ lsb = data[4];
+ msb = data[5];
+ msblsb = (msb << 8) | lsb;
+ accel->z = ((int16_t) msblsb); /* Data in Z axis */
+ }
+
+ } else {
+ rslt = SMI230_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+static int8_t smi230_acc_set_int_config(
+ const struct smi230_accel_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+
+ rslt = null_ptr_check(dev);
+
+ if ((rslt == SMI230_OK) && (int_config != NULL)) {
+ switch (int_config->int_type) {
+ case SMI230_ACCEL_DATA_RDY_INT:
+ rslt = set_accel_data_ready_int(int_config, dev);
+ break;
+ case SMI230_ACCEL_SYNC_DATA_RDY_INT:
+ rslt = set_accel_sync_data_ready_int(int_config, dev);
+ break;
+ case SMI230_ACCEL_SYNC_INPUT:
+ rslt = set_accel_sync_input(int_config, dev);
+ break;
+ case SMI230_ACCEL_ANYMOTION_INT:
+ rslt = set_accel_anymotion_int(int_config, dev);
+ break;
+ case SMI230_ACCEL_HIGH_G_INT:
+ rslt = set_accel_high_g_int(int_config, dev);
+ break;
+ case SMI230_ACCEL_LOW_G_INT:
+ rslt = set_accel_low_g_int(int_config, dev);
+ break;
+ case SMI230_ACCEL_ORIENT_INT:
+ rslt = set_accel_orient_int(int_config, dev);
+ break;
+ case SMI230_ACCEL_NO_MOTION_INT:
+ rslt = set_accel_no_motion_int(int_config, dev);
+ break;
+ case SMI230_ACCEL_ERROR_INT:
+ rslt = set_accel_err_int(int_config, dev);
+ break;
+ default:
+ rslt = SMI230_E_INVALID_CONFIG;
+ break;
+ }
+ } else {
+ rslt = SMI230_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+void smi230_delay(uint32_t msec)
+{
+ unsigned long mseond = msec;
+ unsigned long min = mseond * (1000);
+ if (msec <= 20)
+ usleep_range(min, (min + 1000));
+ else
+ msleep(msec);
+}
+
+int8_t smi230_acc_init(struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t chip_id = 0;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK) {
+ if (dev->intf == SMI230_SPI_INTF) {
+ /* Set dummy byte in case of SPI interface */
+ dev->dummy_byte = SMI230_ENABLE;
+
+ /* Dummy read of Chip-ID in SPI mode */
+ rslt = get_regs(SMI230_ACCEL_CHIP_ID_REG, &chip_id, 1, dev);
+ } else {
+ /* Make dummy byte 0 in case of I2C interface */
+ dev->dummy_byte = SMI230_DISABLE;
+ }
+
+ if (rslt == SMI230_OK) {
+ rslt = get_regs(SMI230_ACCEL_CHIP_ID_REG, &chip_id, 1, dev);
+
+ if (rslt == SMI230_OK) {
+ if (chip_id == SMI230_ACCEL_CHIP_ID) {
+ dev->accel_chip_id = chip_id;
+ } else
+ rslt = SMI230_E_DEV_NOT_FOUND;
+ }
+ }
+ }
+
+ return rslt;
+}
+
+static int smi230_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret;
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+ struct smi230_sensor_data data = { 0 };
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = smi230_acc_get_data(&data, p_smi230_dev);
+ if (ret != SMI230_OK)
+ return 0;
+ switch (chan->channel2) {
+ case IIO_MOD_X:
+ *val = data.x;
+ break;
+ case IIO_MOD_Y:
+ *val = data.y;
+ break;
+ case IIO_MOD_Z:
+ *val = data.z;
+ break;
+ }
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = smi230_acc_get_meas_conf(p_smi230_dev);
+ if (ret)
+ return ret;
+
+ switch (p_smi230_dev->accel_cfg.odr) {
+ case SMI230_ACCEL_ODR_12_5_HZ:
+ *val = 12;
+ *val2 = 5000000;
+ break;
+ case SMI230_ACCEL_ODR_25_HZ:
+ *val = 25;
+ *val2 = 0;
+ break;
+ case SMI230_ACCEL_ODR_50_HZ:
+ *val = 50;
+ *val2 = 0;
+ break;
+ case SMI230_ACCEL_ODR_100_HZ:
+ *val = 100;
+ *val2 = 0;
+ break;
+ case SMI230_ACCEL_ODR_200_HZ:
+ *val = 200;
+ *val2 = 0;
+ break;
+ case SMI230_ACCEL_ODR_400_HZ:
+ *val = 400;
+ *val2 = 0;
+ break;
+ case SMI230_ACCEL_ODR_800_HZ:
+ *val = 800;
+ *val2 = 0;
+ break;
+ case SMI230_ACCEL_ODR_1600_HZ:
+ *val = 1600;
+ *val2 = 0;
+ break;
+ }
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int smi230_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ int ret;
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch (val) {
+ case 12:
+ p_smi230_dev->accel_cfg.odr = SMI230_ACCEL_ODR_12_5_HZ;
+ break;
+ case 25:
+ p_smi230_dev->accel_cfg.odr = SMI230_ACCEL_ODR_25_HZ;
+ break;
+ case 50:
+ p_smi230_dev->accel_cfg.odr = SMI230_ACCEL_ODR_50_HZ;
+ break;
+ case 100:
+ p_smi230_dev->accel_cfg.odr = SMI230_ACCEL_ODR_100_HZ;
+ break;
+ case 200:
+ p_smi230_dev->accel_cfg.odr = SMI230_ACCEL_ODR_200_HZ;
+ break;
+ case 400:
+ p_smi230_dev->accel_cfg.odr = SMI230_ACCEL_ODR_400_HZ;
+ break;
+ case 800:
+ p_smi230_dev->accel_cfg.odr = SMI230_ACCEL_ODR_800_HZ;
+ break;
+ case 1600:
+ p_smi230_dev->accel_cfg.odr = SMI230_ACCEL_ODR_1600_HZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = smi230_acc_set_meas_conf(p_smi230_dev);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+
+}
+
+static
+IIO_CONST_ATTR(in_accel_sampling_frequency_available,
+ "12.5 25 50 100 200 400 800 1600");
+
+/* 8192 LSB/g */
+static IIO_CONST_ATTR(in_accel_scale_available, "0.0001221");
+
+//dongyu@2022.11.03 Add smi230_set_accel_power_mode start
+static int8_t smi230_acc_get_power_mode(struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK) {
+ rslt = get_regs(SMI230_ACCEL_PWR_CONF_REG, &data, 1, dev);
+ if (rslt == SMI230_OK)
+ dev->accel_cfg.power = data;
+ }
+
+ return rslt;
+}
+
+static ssize_t smi230_get_accel_power_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+
+ ret = smi230_acc_get_power_mode(p_smi230_dev);
+ if (ret) {
+ dev_err(dev, "Failed to read power config.");
+ return ret;
+ }
+
+ switch (p_smi230_dev->accel_cfg.power) {
+ case SMI230_ACCEL_PM_ACTIVE:
+ return sprintf(buf, "normal\n");
+ case SMI230_ACCEL_PM_SUSPEND:
+ return sprintf(buf, "suspend\n");
+ default:
+ return sprintf(buf, "error\n");
+ }
+}
+
+static ssize_t smi230_set_accel_power_mode(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+
+ if (strncmp(buf, "normal", 6) == 0) {
+ p_smi230_dev->accel_cfg.power = SMI230_ACCEL_PM_ACTIVE;
+ } else if (strncmp(buf, "suspend", 7) == 0) {
+ p_smi230_dev->accel_cfg.power = SMI230_ACCEL_PM_SUSPEND;
+ } else {
+ dev_err(dev, "Invalid argument for power mode.");
+ return -EINVAL;
+ }
+
+ ret = smi230_acc_set_power_mode(p_smi230_dev);
+ if (ret)
+ dev_err(dev, "Failed to set power mode.");
+
+ return count;
+}
+
+static IIO_DEVICE_ATTR(in_accel_power_mode, S_IRUGO|S_IWUSR|S_IWGRP,
+ smi230_get_accel_power_mode, smi230_set_accel_power_mode, 0);
+
+static struct attribute *smi230_attrs[] = {
+ &iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
+ &iio_const_attr_in_accel_scale_available.dev_attr.attr,
+ &iio_dev_attr_in_accel_power_mode.dev_attr.attr,
+ NULL,
+};
+//dongyu@2022.11.03 Add smi230_set_accel_power_mode end
+
+static const struct attribute_group smi230_attrs_group = {
+ .attrs = smi230_attrs,
+};
+
+static const struct iio_info smi230_info = {
+ .read_raw = smi230_read_raw,
+ .write_raw = smi230_write_raw,
+ .attrs = &smi230_attrs_group,
+};
+
+static int smi230_init(struct smi230_dev *dev)
+{
+ int err = 0;
+
+ /* Reset the accelerometer and wait for 1 ms
+ * delay taken care inside the function
+ */
+ err |= smi230_acc_soft_reset(dev);
+
+ /*set accel power mode */
+ dev->accel_cfg.power = SMI230_ACCEL_PM_ACTIVE;
+ err |= smi230_acc_set_power_mode(dev);
+
+ /*disable acc int1 */
+ int_config.accel_int_config_1.int_pin_cfg.enable_int_pin =
+ SMI230_DISABLE;
+
+ /*configure int2 as accel FIFO interrupt pin */
+ int_config.accel_int_config_2.int_pin_cfg.enable_int_pin =
+ SMI230_ENABLE;
+
+ dev->accel_cfg.odr = SMI230_ACCEL_ODR_100_HZ;
+ dev->accel_cfg.bw = SMI230_ACCEL_BW_NORMAL;
+ dev->accel_cfg.range = SMI230_ACCEL_RANGE_4G;
+
+ err |= smi230_acc_set_meas_conf(dev);
+ smi230_delay(100);
+
+ int_config.accel_int_config_2.int_channel = SMI230_INT_CHANNEL_1;
+ int_config.accel_int_config_2.int_type = SMI230_ACCEL_DATA_RDY_INT;
+ int_config.accel_int_config_2.int_pin_cfg.output_mode =
+ SMI230_INT_MODE_PUSH_PULL;
+ int_config.accel_int_config_2.int_pin_cfg.lvl = SMI230_INT_ACTIVE_HIGH;
+
+ err |= smi230_acc_set_int_config(&int_config.accel_int_config_2, dev);
+
+ smi230_delay(100);
+
+ return err;
+}
+
+static int smi230_read_channel(struct smi230_sensor_data *sdata, int i,
+ s16 *sample)
+{
+ switch (i) {
+ case 0:
+ *sample = sdata->x;
+ break;
+ case 1:
+ *sample = sdata->y;
+ break;
+ case 2:
+ *sample = sdata->z;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static irqreturn_t smi230_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+
+ s16 buf[8];
+ s16 sample;
+ int ret, i, j = 0;
+
+ struct smi230_sensor_data sensor_data = { 0 };
+
+ ret = smi230_acc_get_data(&sensor_data, p_smi230_dev);
+ if (ret) {
+ pr_err("Reading sensor data failed");
+ goto done;
+ }
+
+ for_each_set_bit(i, indio_dev->active_scan_mask, indio_dev->masklength) {
+ ret = smi230_read_channel(&sensor_data, i, &sample);
+ if (ret) {
+ pr_err("Read channel %d failed", i);
+ goto done;
+ }
+ buf[j++] = sample;
+ }
+
+ ret = iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp);
+ if (ret)
+ pr_err("Push to buffer failed");
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int smi230_get_irq(struct device *dev, int *irq)
+{
+ int gpio_pin, ret;
+
+ gpio_pin = of_get_named_gpio_flags(dev->of_node, "gpio_irq", 0, NULL);
+
+ ret = gpio_request_one(gpio_pin, GPIOF_IN, "smi230_acc_interrupt");
+ if (ret) {
+ pr_err("Request GPIO pin %d failed", gpio_pin);
+ return ret;
+ }
+
+ ret = gpio_direction_input(gpio_pin);
+ if (ret)
+ return ret;
+
+ *irq = gpio_to_irq(gpio_pin);
+
+ return ret;
+}
+
+static int smi230_new_data_trigger_set_state(
+ struct iio_trigger *trig, bool enable)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+ u8 en;
+
+ dev_dbg(indio_dev->dev.parent, "trigger set state %d", enable);
+ if (enable)
+ en = SMI230_ENABLE;
+ else
+ en = SMI230_DISABLE;
+
+ int_config.accel_int_config_2.int_pin_cfg.enable_int_pin = en;
+ return smi230_acc_set_int_config(
+ &int_config.accel_int_config_2, p_smi230_dev);
+}
+
+static const struct iio_trigger_ops smi230_trigger_ops = {
+ .set_trigger_state = &smi230_new_data_trigger_set_state,
+};
+
+int smi230_acc_probe(struct device *dev, struct smi230_dev *p_smi230_dev)
+{
+ int ret = 0;
+ int irq;
+ struct iio_dev *indio_dev;
+
+ ret = smi230_init(p_smi230_dev);
+ if (ret == SMI230_OK) {
+ dev_dbg(dev, "Bosch Sensor %s hardware initialized", SENSOR_ACC_NAME);
+ } else {
+ dev_dbg(dev, "Bosch Sensor %s initialization failed %d",
+ SENSOR_ACC_NAME, ret);
+ return ret;
+ }
+
+ indio_dev = devm_iio_device_alloc(dev, 0);
+ if (!indio_dev)
+ return -ENOMEM;
+
+ iio_device_set_drvdata(indio_dev, p_smi230_dev);
+ dev_set_drvdata(dev, indio_dev);
+
+ indio_dev->dev.parent = dev;
+ indio_dev->channels = smi230_channels;
+ indio_dev->num_channels = ARRAY_SIZE(smi230_channels);
+ indio_dev->name = MODULE_NAME;
+ indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;
+ indio_dev->info = &smi230_info;
+ indio_dev->trig = devm_iio_trigger_alloc(&indio_dev->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+
+ if (indio_dev->trig == NULL)
+ return -ENOMEM;
+
+ ret = smi230_get_irq(dev, &irq);
+ if (ret) {
+ dev_dbg(dev, "Failed to request GPIO pin");
+ return ret;
+ }
+
+ ret = devm_request_irq(&indio_dev->dev, irq,
+ &iio_trigger_generic_data_rdy_poll,
+ IRQF_TRIGGER_RISING,
+ indio_dev->name,
+ indio_dev->trig);
+
+ if (ret) {
+ dev_dbg(dev, "Failed to request irq for pin %d", irq);
+ return ret;
+ }
+
+ indio_dev->trig->dev.parent = dev;
+ indio_dev->trig->ops = &smi230_trigger_ops;
+ iio_trigger_set_drvdata(indio_dev->trig, indio_dev);
+
+ ret = devm_iio_trigger_register(&indio_dev->dev, indio_dev->trig);
+ if (ret) {
+ dev_dbg(dev, "Failed to register trigger");
+ return ret;
+ }
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ smi230_trigger_handler, NULL);
+ if (ret) {
+ dev_dbg(dev, "Setup triggered buffer failed");
+ return ret;
+ }
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ return ret;
+}
diff --git a/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc_i2c.c b/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc_i2c.c
new file mode 100644
index 0000000..11f1552
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc_i2c.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/**
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * This file is free software licensed under the terms of version 2
+ * of the GNU General Public License, available from the file LICENSE-GPL
+ * in the main directory of this source tree.
+ *
+ * BSD LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "smi230_acc.h"
+
+#define SMI230_MAX_RETRY_I2C_XFER 10
+#define SMI230_I2C_WRITE_DELAY_TIME 10
+
+static struct i2c_adapter *smi230_i2c_adapter;
+
+static struct smi230_dev smi230_i2c_dev;
+
+static int8_t smi230_i2c_read(uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t *data, uint16_t len)
+{
+ int32_t retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = dev_addr,
+ .flags = 0,
+ .len = 1,
+ .buf = ®_addr,
+ },
+
+ {
+ .addr = dev_addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+ for (retry = 0; retry < SMI230_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(smi230_i2c_adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+
+ usleep_range(SMI230_I2C_WRITE_DELAY_TIME * 1000,
+ SMI230_I2C_WRITE_DELAY_TIME * 1000);
+ }
+
+ if (retry >= SMI230_MAX_RETRY_I2C_XFER) {
+ pr_err("I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int8_t smi230_i2c_write(uint8_t dev_addr,
+ uint8_t reg_addr, uint8_t *data, uint16_t len)
+{
+ int32_t retry;
+ struct i2c_msg msg = {
+ .addr = dev_addr,
+ .flags = 0,
+ .len = len + 1,
+ .buf = NULL,
+ };
+
+ msg.buf = kmalloc(len + 1, GFP_KERNEL);
+ if (!msg.buf)
+ return -ENOMEM;
+
+ msg.buf[0] = reg_addr;
+ memcpy(&msg.buf[1], data, len);
+
+ for (retry = 0; retry < SMI230_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(smi230_i2c_adapter, &msg, 1) > 0)
+ break;
+
+ usleep_range(SMI230_I2C_WRITE_DELAY_TIME * 1000,
+ SMI230_I2C_WRITE_DELAY_TIME * 1000);
+ }
+
+ kfree(msg.buf);
+
+ if (retry >= SMI230_MAX_RETRY_I2C_XFER) {
+ pr_err("I2C xfer error");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int smi230_acc_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("i2c_check_functionality error!");
+ err = -EIO;
+ return err;
+ }
+
+ smi230_i2c_adapter = client->adapter;
+ smi230_i2c_dev.accel_id = client->addr;
+
+ err = smi230_acc_init(&smi230_i2c_dev);
+ if (err == SMI230_OK)
+ pr_info("Bosch Sensor Device %s initialized", SENSOR_ACC_NAME);
+ else {
+ pr_err("Bosch Sensor Device %s initialization failed, error %d",
+ SENSOR_ACC_NAME, err);
+ }
+
+ return smi230_acc_probe(&client->dev, &smi230_i2c_dev);
+}
+
+static const struct i2c_device_id smi230_acc_id[] = {
+ { SENSOR_ACC_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, smi230_acc_id);
+
+static const struct of_device_id smi230_acc_of_match[] = {
+ {.compatible = SENSOR_ACC_NAME, },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, smi230_acc_of_match);
+
+struct i2c_driver smi230_acc_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_ACC_NAME,
+ .of_match_table = smi230_acc_of_match,
+ },
+ .class = I2C_CLASS_HWMON,
+ .id_table = smi230_acc_id,
+ .probe = smi230_acc_i2c_probe,
+ .remove = NULL,
+};
+
+static int __init smi230_module_init(void)
+{
+ int err = 0;
+
+ smi230_i2c_dev.delay_ms = smi230_delay;
+ smi230_i2c_dev.read_write_len = 32;
+ smi230_i2c_dev.intf = SMI230_I2C_INTF;
+ smi230_i2c_dev.read = smi230_i2c_read;
+ smi230_i2c_dev.write = smi230_i2c_write;
+
+ err |= i2c_add_driver(&smi230_acc_driver);
+
+ return err;
+}
+
+static void __exit smi230_module_exit(void)
+{
+ i2c_del_driver(&smi230_acc_driver);
+}
+
+module_init(smi230_module_init);
+module_exit(smi230_module_exit);
+
+MODULE_DESCRIPTION("SMI230 ACC SENSOR DRIVER");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc_spi.c b/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc_spi.c
new file mode 100644
index 0000000..1b43ce5
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/iio/accel/smi230_acc_spi.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/**
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * This file is free software licensed under the terms of version 2
+ * of the GNU General Public License, available from the file LICENSE-GPL
+ * in the main directory of this source tree.
+ *
+ * BSD LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include <linux/types.h>
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+
+#include "smi230_acc.h"
+
+#define SMI230_SPI_MAX_BUFFER_SIZE 32
+
+static uint8_t *read_buf;
+static struct spi_device *smi230_acc_device;
+
+static struct smi230_dev smi230_spi_dev;
+
+static int8_t smi230_spi_write(uint8_t dev_addr, uint8_t reg_addr,
+ uint8_t *data, uint16_t len)
+{
+ struct spi_message msg;
+ uint8_t buffer[SMI230_SPI_MAX_BUFFER_SIZE + 1];
+ struct spi_transfer xfer = {
+ .tx_buf = buffer,
+ .len = len + 1,
+ };
+
+ if (len > SMI230_SPI_MAX_BUFFER_SIZE)
+ return -EINVAL;
+
+ buffer[0] = reg_addr;
+ memcpy(&buffer[1], data, len);
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ if (dev_addr == SMI230_ACCEL_CHIP_ID)
+ return spi_sync(smi230_acc_device, &msg);
+ else
+ return -EINVAL;
+}
+
+static int8_t smi230_spi_read(uint8_t dev_addr,
+ uint8_t reg_addr, uint8_t *data, uint16_t len)
+{
+ int ret;
+ uint16_t index;
+ struct spi_message msg;
+ struct spi_transfer xfer[2] = {
+ [0] = {
+ .tx_buf = ®_addr,
+ .len = 1,
+ },
+ [1] = {
+ .rx_buf = read_buf,
+ .len = len,
+ }
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer[0], &msg);
+ spi_message_add_tail(&xfer[1], &msg);
+
+ if (dev_addr == SMI230_ACCEL_CHIP_ID)
+ ret = spi_sync(smi230_acc_device, &msg);
+ else
+ return -EINVAL;
+
+ for (index = 0; index < len; index++)
+ data[index] = read_buf[index];
+
+ return ret;
+}
+
+static int smi230_acc_spi_probe(struct spi_device *device)
+{
+ int err;
+
+ device->bits_per_word = 8;
+ err = spi_setup(device);
+ if (err < 0) {
+ pr_err("spi_setup err!\n");
+ return err;
+ }
+
+ if (read_buf == NULL)
+ read_buf =
+ kmalloc(CONFIG_IIO_SMI230_ACC_MAX_BUFFER_LEN + 1, GFP_KERNEL);
+ if (!read_buf)
+ return SMI230_E_NULL_PTR;
+
+ /* chip_id is used to differentiate acc/gyro on spi read/write */
+ smi230_spi_dev.accel_id = SMI230_ACCEL_CHIP_ID;
+
+ smi230_acc_device = device;
+
+ err = smi230_acc_init(&smi230_spi_dev);
+ if (err == SMI230_OK)
+ pr_info("Bosch Sensor Device %s initialized", SENSOR_ACC_NAME);
+ else {
+ kfree(read_buf);
+ read_buf = NULL;
+ smi230_acc_device = NULL;
+ pr_err("Bosch Sensor Device %s initialization failed, error %d",
+ SENSOR_ACC_NAME, err);
+ return err;
+ }
+
+ return smi230_acc_probe(&device->dev, &smi230_spi_dev);
+}
+
+static int smi230_acc_spi_remove(struct spi_device *device)
+{
+ if (read_buf != NULL) {
+ kfree(read_buf);
+ read_buf = NULL;
+ }
+ return 0;
+}
+
+static const struct spi_device_id smi230_acc_id[] = {
+ { SENSOR_ACC_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(spi, smi230_acc_id);
+
+static const struct of_device_id smi230_acc_of_match[] = {
+ {.compatible = SENSOR_ACC_NAME, },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, smi230_acc_of_match);
+
+static struct spi_driver smi230_acc_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_ACC_NAME,
+ .of_match_table = smi230_acc_of_match,
+ },
+ .id_table = smi230_acc_id,
+ .probe = smi230_acc_spi_probe,
+ .remove = smi230_acc_spi_remove,
+};
+
+static int __init smi230_module_init(void)
+{
+ int err = 0;
+
+ smi230_spi_dev.delay_ms = smi230_delay;
+ smi230_spi_dev.read_write_len = 32;
+ smi230_spi_dev.intf = SMI230_SPI_INTF;
+ smi230_spi_dev.read = smi230_spi_read;
+ smi230_spi_dev.write = smi230_spi_write;
+
+ err |= spi_register_driver(&smi230_acc_driver);
+ return err;
+}
+
+static void __exit smi230_module_exit(void)
+{
+ spi_unregister_driver(&smi230_acc_driver);
+}
+
+module_init(smi230_module_init);
+module_exit(smi230_module_exit);
+
+MODULE_DESCRIPTION("SMI230 ACC SENSOR DRIVER");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/src/kernel/linux/v4.19/drivers/iio/gyro/Kconfig b/src/kernel/linux/v4.19/drivers/iio/gyro/Kconfig
index 3126cf0..b86f56e 100644
--- a/src/kernel/linux/v4.19/drivers/iio/gyro/Kconfig
+++ b/src/kernel/linux/v4.19/drivers/iio/gyro/Kconfig
@@ -139,4 +139,34 @@
Say yes here to add support for the InvenSense ITG3200 digital
3-axis gyroscope sensor.
+config SMI230_GYRO
+ tristate "BOSCH SMI230 Gyro Sensor"
+ depends on (I2C || SPI_MASTER)
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for BOSCH SMI230GYRO Tri-axis Gyro Sensor
+ driver connected via I2C or SPI.
+
+choice
+ prompt "Select communication interface"
+ depends on SMI230_GYRO
+ help
+ Note: SPI and I2C are not supported at the same time, that is to say:
+ Choose either SPI or I2C to build the driver.
+
+ config SMI230_GYRO_SPI
+ bool "Enable SPI connection"
+ depends on SPI_MASTER
+ config SMI230_GYRO_I2C
+ bool "Enable I2C connection"
+ depends on I2C
+endchoice
+
+config SMI230_MAX_BUFFER_LEN
+ int "configue read buffer size"
+ default "1024"
+ help
+ Considering using FIFO, 1024 bytes are big enough for most cases. Do not change this value if not sure.
+
endmenu
diff --git a/src/kernel/linux/v4.19/drivers/iio/gyro/Makefile b/src/kernel/linux/v4.19/drivers/iio/gyro/Makefile
index 295ec78..a1578be 100644
--- a/src/kernel/linux/v4.19/drivers/iio/gyro/Makefile
+++ b/src/kernel/linux/v4.19/drivers/iio/gyro/Makefile
@@ -32,3 +32,14 @@
obj-$(CONFIG_IIO_ST_GYRO_I2C_3AXIS) += st_gyro_i2c.o
obj-$(CONFIG_IIO_ST_GYRO_SPI_3AXIS) += st_gyro_spi.o
+
+#dongyu@2022.12.13 Add imu/smi230 sensor start
+obj-$(CONFIG_SMI230_GYRO) += smi230_gyro.o
+smi230_gyro-objs := smi230_gyro_core.o
+
+ifeq ($(CONFIG_SMI230_GYRO_I2C),y)
+ smi230_gyro-objs += smi230_gyro_i2c.o
+else
+ smi230_gyro-objs += smi230_gyro_spi.o
+endif
+#dongyu@2022.12.13 Add imu/smi230 sensor end
diff --git a/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro.h b/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro.h
new file mode 100644
index 0000000..d0d06bc
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro.h
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/**
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ * Copyright (c) 2022 Bosch Sensortec GmbH. All rights reserved.
+ *
+ * This file is free software licensed under the terms of version 2
+ * of the GNU General Public License, available from the file LICENSE-GPL
+ * in the main directory of this source tree.
+ *
+ * BSD LICENSE
+ * Copyright (c) 2022 Bosch Sensortec GmbH. All rights reserved.
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+/*! \file smi230.h
+ * \brief Sensor Driver for SMI230 sensors */
+#ifndef _SMI230_GYRO_H
+#define _SMI230_GYRO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************************************************************/
+/* header files */
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#define DRIVER_VERSION "1.0.0"
+#define MODULE_NAME "SMI230GYRO"
+#define SENSOR_GYRO_NAME "SMI230GYRO"
+
+enum smi230_intf {
+ /*! I2C interface */
+ SMI230_I2C_INTF,
+
+ /*! SPI interface */
+ SMI230_SPI_INTF
+};
+
+struct smi230_cfg
+{
+ /*! power mode */
+ uint8_t power;
+
+ /*! range */
+ uint8_t range;
+
+ /*! bandwidth */
+ uint8_t bw;
+
+ /*! output data rate */
+ uint8_t odr;
+};
+
+typedef int8_t (*smi230_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t len);
+
+typedef void (*smi230_delay_fptr_t)(uint32_t period);
+
+struct smi230_dev
+{
+
+ /*! Accel chip Id */
+ uint8_t accel_chip_id;
+
+ /*! Gyro chip Id */
+ uint8_t gyro_chip_id;
+
+ /*! Accel device Id */
+ uint8_t accel_id;
+
+ /*! Gyro device Id */
+ uint8_t gyro_id;
+
+ /*! 0 - I2C , 1 - SPI Interface */
+ enum smi230_intf intf;
+
+ /*! Decide SPI or I2C read mechanism */
+ uint8_t dummy_byte;
+
+ /*! Structure to configure gyro sensor */
+ struct smi230_cfg gyro_cfg;
+
+ /*! Config stream data buffer address will be assigned */
+ const uint8_t *config_file_ptr;
+
+ /*! Max read/write length (maximum supported length is 32).
+ * To be set by the user */
+ uint8_t read_write_len;
+
+ /*! Read function pointer */
+ smi230_com_fptr_t read;
+
+ /*! Write function pointer */
+ smi230_com_fptr_t write;
+
+ /*! Delay function pointer */
+ smi230_delay_fptr_t delay_ms;
+};
+
+int smi230_gyro_core_probe(struct device *dev, struct smi230_dev *p_smi230_dev);
+
+static inline void smi230_delay(uint32_t msec)
+{
+ unsigned long mseond = msec;
+ unsigned long min = mseond * (1000);
+ /* if the time less than 20ms */
+ if (msec <= 20)
+ usleep_range(min, (min + 1000));
+ else
+ msleep(msec);
+}
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SMI230_GRYO_H */
+
+/** @}*/
diff --git a/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro_core.c b/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro_core.c
new file mode 100644
index 0000000..1b5eab8
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro_core.c
@@ -0,0 +1,1084 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/**
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * This file is free software licensed under the terms of version 2
+ * of the GNU General Public License, available from the file LICENSE-GPL
+ * in the main directory of this source tree.
+ *
+ * BSD LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include <linux/iio/iio.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/of_gpio.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include "smi230_gyro.h"
+
+#if !defined(UINT8_C) && !defined(INT8_C)
+#define INT8_C(x) S8_C(x)
+#define UINT8_C(x) U8_C(x)
+#endif
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *) 0)
+#endif
+#endif
+
+#ifndef TRUE
+#define TRUE UINT8_C(1)
+#endif
+
+#ifndef FALSE
+#define FALSE UINT8_C(0)
+#endif
+
+/* Gyro registers */
+#define SMI230_GYRO_CHIP_ID_REG UINT8_C(0x00)
+#define SMI230_GYRO_X_LSB_REG UINT8_C(0x02)
+#define SMI230_GYRO_X_MSB_REG UINT8_C(0x03)
+#define SMI230_GYRO_Y_LSB_REG UINT8_C(0x04)
+#define SMI230_GYRO_Y_MSB_REG UINT8_C(0x05)
+#define SMI230_GYRO_Z_LSB_REG UINT8_C(0x06)
+#define SMI230_GYRO_Z_MSB_REG UINT8_C(0x07)
+#define SMI230_GYRO_INT_STAT_1_REG UINT8_C(0x0A)
+#define SMI230_GYRO_RANGE_REG UINT8_C(0x0F)
+#define SMI230_GYRO_BANDWIDTH_REG UINT8_C(0x10)
+#define SMI230_GYRO_LPM1_REG UINT8_C(0x11)
+#define SMI230_GYRO_SOFTRESET_REG UINT8_C(0x14)
+#define SMI230_GYRO_INT_CTRL_REG UINT8_C(0x15)
+#define SMI230_GYRO_INT3_INT4_IO_CONF_REG UINT8_C(0x16)
+#define SMI230_GYRO_INT3_INT4_IO_MAP_REG UINT8_C(0x18)
+#define SMI230_GYRO_WM_INT_REG UINT8_C(0x1E)
+#define SMI230_GYRO_FIFO_EXT_INT_S_REG UINT8_C(0x34)
+#define SMI230_GYRO_SELF_TEST_REG UINT8_C(0x3C)
+#define SMI230_GYRO_CHIP_ID UINT8_C(0x0F)
+#define SMI230_GYRO_I2C_ADDR_PRIMARY UINT8_C(0x68)
+#define SMI230_GYRO_I2C_ADDR_SECONDARY UINT8_C(0x69)
+#define SMI230_GYRO_RANGE_2000_DPS UINT8_C(0x00)
+#define SMI230_GYRO_RANGE_1000_DPS UINT8_C(0x01)
+#define SMI230_GYRO_RANGE_500_DPS UINT8_C(0x02)
+#define SMI230_GYRO_RANGE_250_DPS UINT8_C(0x03)
+#define SMI230_GYRO_RANGE_125_DPS UINT8_C(0x04)
+#define SMI230_GYRO_BW_523_ODR_2000_HZ UINT8_C(0x00)
+#define SMI230_GYRO_BW_230_ODR_2000_HZ UINT8_C(0x01)
+#define SMI230_GYRO_BW_116_ODR_1000_HZ UINT8_C(0x02)
+#define SMI230_GYRO_BW_47_ODR_400_HZ UINT8_C(0x03)
+#define SMI230_GYRO_BW_23_ODR_200_HZ UINT8_C(0x04)
+#define SMI230_GYRO_BW_12_ODR_100_HZ UINT8_C(0x05)
+#define SMI230_GYRO_BW_64_ODR_200_HZ UINT8_C(0x06)
+#define SMI230_GYRO_BW_32_ODR_100_HZ UINT8_C(0x07)
+#define SMI230_GYRO_ODR_RESET_VAL UINT8_C(0x80)
+#define SMI230_GYRO_PM_NORMAL UINT8_C(0x00)
+#define SMI230_GYRO_PM_DEEP_SUSPEND UINT8_C(0x20)
+#define SMI230_GYRO_PM_SUSPEND UINT8_C(0x80)
+#define SMI230_GYRO_DRDY_INT_DISABLE_VAL UINT8_C(0x00)
+#define SMI230_GYRO_DRDY_INT_ENABLE_VAL UINT8_C(0x80)
+#define SMI230_GYRO_FIFO_INT_DISABLE_VAL UINT8_C(0x00)
+#define SMI230_GYRO_FIFO_INT_ENABLE_VAL UINT8_C(0x40)
+#define SMI230_GYRO_MAP_DRDY_TO_INT3 UINT8_C(0x01)
+#define SMI230_GYRO_MAP_DRDY_TO_INT4 UINT8_C(0x80)
+#define SMI230_GYRO_MAP_DRDY_TO_BOTH_INT3_INT4 UINT8_C(0x81)
+#define SMI230_GYRO_MAP_FIFO_TO_BOTH_INT3_INT4 UINT8_C(0x24)
+#define SMI230_GYRO_SOFTRESET_DELAY UINT8_C(30)
+#define SMI230_GYRO_POWER_MODE_CONFIG_DELAY UINT8_C(30)
+#define SMI230_GYRO_RANGE_MASK UINT8_C(0x07)
+#define SMI230_GYRO_BW_MASK UINT8_C(0x0F)
+#define SMI230_GYRO_POWER_MASK UINT8_C(0xA0)
+#define SMI230_GYRO_POWER_POS UINT8_C(5)
+#define SMI230_GYRO_DATA_EN_MASK UINT8_C(0x80)
+#define SMI230_GYRO_DATA_EN_POS UINT8_C(7)
+#define SMI230_GYRO_FIFO_EN_MASK UINT8_C(0x40)
+#define SMI230_GYRO_FIFO_EN_POS UINT8_C(6)
+#define SMI230_GYRO_INT3_LVL_MASK UINT8_C(0x01)
+#define SMI230_GYRO_INT3_OD_MASK UINT8_C(0x02)
+#define SMI230_GYRO_INT4_LVL_MASK UINT8_C(0x04)
+#define SMI230_GYRO_INT4_OD_MASK UINT8_C(0x08)
+#define SMI230_GYRO_INT3_OD_POS UINT8_C(1)
+#define SMI230_GYRO_INT4_LVL_POS UINT8_C(2)
+#define SMI230_GYRO_INT4_OD_POS UINT8_C(3)
+#define SMI230_GYRO_INT_EN_MASK UINT8_C(0x80)
+#define SMI230_GYRO_INT_EN_POS UINT8_C(7)
+#define SMI230_GYRO_INT3_MAP_MASK UINT8_C(0x01)
+#define SMI230_GYRO_INT4_MAP_MASK UINT8_C(0x80)
+#define SMI230_GYRO_FIFO_INT3_MAP_MASK UINT8_C(0x04)
+#define SMI230_GYRO_FIFO_INT4_MAP_MASK UINT8_C(0x20)
+#define SMI230_GYRO_INT3_MAP_POS UINT8_C(0)
+#define SMI230_GYRO_INT4_MAP_POS UINT8_C(7)
+#define SMI230_GYRO_FIFO_INT3_MAP_POS UINT8_C(2)
+#define SMI230_GYRO_FIFO_INT4_MAP_POS UINT8_C(5)
+#define SMI230_GYRO_SELF_TEST_EN_MASK UINT8_C(0x01)
+#define SMI230_GYRO_SELF_TEST_RDY_MASK UINT8_C(0x02)
+#define SMI230_GYRO_SELF_TEST_RESULT_MASK UINT8_C(0x04)
+#define SMI230_GYRO_SELF_TEST_FUNCTION_MASK UINT8_C(0x08)
+#define SMI230_GYRO_SELF_TEST_RDY_POS UINT8_C(1)
+#define SMI230_GYRO_SELF_TEST_RESULT_POS UINT8_C(2)
+#define SMI230_GYRO_SELF_TEST_FUNCTION_POS UINT8_C(3)
+
+#define SMI230_INT_MODE_PUSH_PULL UINT8_C(0)
+#define SMI230_INT_MODE_OPEN_DRAIN UINT8_C(1)
+#define SMI230_INT_ACTIVE_LOW UINT8_C(0)
+#define SMI230_INT_ACTIVE_HIGH UINT8_C(1)
+
+#define SMI230_SPI_RD_MASK UINT8_C(0x80)
+#define SMI230_SPI_WR_MASK UINT8_C(0x7F)
+
+#define SMI230_OK INT8_C(0)
+#define SMI230_E_NULL_PTR INT8_C(-1)
+#define SMI230_E_COM_FAIL INT8_C(-2)
+#define SMI230_E_DEV_NOT_FOUND INT8_C(-3)
+#define SMI230_E_OUT_OF_RANGE INT8_C(-4)
+#define SMI230_E_INVALID_INPUT INT8_C(-5)
+#define SMI230_E_CONFIG_STREAM_ERROR INT8_C(-6)
+#define SMI230_E_RD_WR_LENGTH_INVALID INT8_C(-7)
+#define SMI230_E_INVALID_CONFIG INT8_C(-8)
+#define SMI230_E_FEATURE_NOT_SUPPORTED INT8_C(-9)
+
+#define SMI230_DISABLE UINT8_C(0)
+#define SMI230_ENABLE UINT8_C(1)
+
+#define SMI230_SET_BITS(reg_var, bitname, val) \
+ ((reg_var & ~(bitname##_MASK)) | \
+ ((val << bitname##_POS) & bitname##_MASK))
+
+#define SMI230_GET_BITS(reg_var, bitname) ((reg_var & (bitname##_MASK)) >> \
+ (bitname##_POS))
+
+#define SMI230_SET_BITS_POS_0(reg_var, bitname, val) \
+ ((reg_var & ~(bitname##_MASK)) | \
+ (val & bitname##_MASK))
+
+#define SMI230_GET_BITS_POS_0(reg_var, bitname) (reg_var & (bitname##_MASK))
+
+#define SMI230_SET_BIT_VAL_0(reg_var, bitname) (reg_var & ~(bitname##_MASK))
+
+
+
+
+
+#define SMI230_CHANNEL(_type, _axis, _index) { \
+ .type = _type, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+}
+
+enum smi230_gyro_int_channel {
+ SMI230_INT_CHANNEL_3,
+ SMI230_INT_CHANNEL_4
+};
+
+enum smi230_gyro_int_types {
+ SMI230_GYRO_DATA_RDY_INT,
+ SMI230_GYRO_FIFO_INT
+};
+
+struct smi230_int_pin_cfg
+{
+ uint8_t lvl : 1;
+ uint8_t output_mode : 1;
+ uint8_t enable_int_pin : 1;
+};
+
+struct smi230_gyro_int_channel_cfg
+{
+ enum smi230_gyro_int_channel int_channel;
+ enum smi230_gyro_int_types int_type;
+ struct smi230_int_pin_cfg int_pin_cfg;
+};
+
+struct smi230_int_cfg
+{
+ struct smi230_gyro_int_channel_cfg gyro_int_config_1;
+ struct smi230_gyro_int_channel_cfg gyro_int_config_2;
+};
+
+enum smi230_scan_axis {
+ SMI230_SCAN_GYRO_X = 0,
+ SMI230_SCAN_GYRO_Y,
+ SMI230_SCAN_GYRO_Z,
+ SMI230_SCAN_TIMESTAMP,
+};
+
+static const struct iio_chan_spec smi230_channels[] = {
+ SMI230_CHANNEL(IIO_ANGL_VEL, X, SMI230_SCAN_GYRO_X),
+ SMI230_CHANNEL(IIO_ANGL_VEL, Y, SMI230_SCAN_GYRO_Y),
+ SMI230_CHANNEL(IIO_ANGL_VEL, Z, SMI230_SCAN_GYRO_Z),
+ IIO_CHAN_SOFT_TIMESTAMP(SMI230_SCAN_TIMESTAMP),
+};
+
+struct smi230_sensor_data
+{
+ int16_t x;
+ int16_t y;
+ int16_t z;
+};
+
+static int8_t null_ptr_check(const struct smi230_dev *dev)
+{
+ int8_t rslt;
+
+ if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL))
+ {
+ rslt = SMI230_E_NULL_PTR;
+ }
+ else
+ {
+ rslt = SMI230_OK;
+ }
+
+ return rslt;
+}
+
+static int8_t get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, const struct smi230_dev *dev)
+{
+ int8_t rslt;
+
+ if (dev->intf == SMI230_SPI_INTF)
+ {
+ /* Configuring reg_addr for SPI Interface */
+ reg_addr = (reg_addr | SMI230_SPI_RD_MASK);
+ }
+
+ /* read a gyro register */
+ rslt = dev->read(dev->gyro_id, reg_addr, reg_data, len);
+
+ if (rslt != SMI230_OK)
+ {
+ /* Updating the error */
+ rslt = SMI230_E_COM_FAIL;
+ }
+
+ return rslt;
+}
+
+static int8_t set_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, const struct smi230_dev *dev)
+{
+ int8_t rslt;
+
+ if (dev->intf == SMI230_SPI_INTF)
+ {
+ /* Configuring reg_addr for SPI Interface */
+ reg_addr = (reg_addr & SMI230_SPI_WR_MASK);
+ }
+
+ /* write to a gyro register */
+ rslt = dev->write(dev->gyro_id, reg_addr, reg_data, len);
+
+ if (rslt != SMI230_OK)
+ {
+ /* Updating the error */
+ rslt = SMI230_E_COM_FAIL;
+ }
+
+ return rslt;
+}
+
+int8_t smi230_gyro_chip_id_check(struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t chip_id = 0;
+
+ rslt = null_ptr_check(dev);
+
+ if (rslt == SMI230_OK)
+ {
+ rslt = get_regs(SMI230_GYRO_CHIP_ID_REG, &chip_id, 1, dev);
+
+ if (rslt == SMI230_OK)
+ {
+ if (chip_id == SMI230_GYRO_CHIP_ID)
+ {
+ dev->gyro_chip_id = chip_id;
+ }
+ else
+ {
+ rslt = SMI230_E_DEV_NOT_FOUND;
+ }
+ }
+ }
+
+ return rslt;
+}
+
+int8_t smi230_gyro_get_meas_conf(struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[2];
+
+ rslt = null_ptr_check(dev);
+
+ if (rslt == SMI230_OK)
+ {
+ rslt = get_regs(SMI230_GYRO_RANGE_REG, data, 2, dev);
+
+ if (rslt == SMI230_OK)
+ {
+ dev->gyro_cfg.range = data[0];
+ dev->gyro_cfg.odr = (data[1] & SMI230_GYRO_BW_MASK);
+ dev->gyro_cfg.bw = dev->gyro_cfg.odr;
+ }
+ }
+
+ return rslt;
+}
+
+int8_t smi230_gyro_set_meas_conf(const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data;
+ uint8_t odr, range;
+ uint8_t is_range_invalid = FALSE, is_odr_invalid = FALSE;
+
+ rslt = null_ptr_check(dev);
+
+ if (rslt == SMI230_OK)
+ {
+ odr = dev->gyro_cfg.odr;
+ range = dev->gyro_cfg.range;
+
+ if (odr > SMI230_GYRO_BW_32_ODR_100_HZ)
+ {
+ is_odr_invalid = TRUE;
+ }
+
+ if (range > SMI230_GYRO_RANGE_125_DPS)
+ {
+ is_range_invalid = TRUE;
+ }
+
+ if ((!is_odr_invalid) && (!is_range_invalid))
+ {
+ rslt = get_regs(SMI230_GYRO_BANDWIDTH_REG, &data, 1, dev);
+ if (rslt == SMI230_OK)
+ {
+ data = SMI230_SET_BITS_POS_0(data, SMI230_GYRO_BW, odr);
+ rslt = set_regs(SMI230_GYRO_BANDWIDTH_REG, &data, 1, dev);
+ if (rslt == SMI230_OK)
+ {
+ rslt = get_regs(SMI230_GYRO_RANGE_REG, &data, 1, dev);
+ if (rslt == SMI230_OK)
+ {
+ data = SMI230_SET_BITS_POS_0(data, SMI230_GYRO_RANGE, range);
+ rslt = set_regs(SMI230_GYRO_RANGE_REG, &data, 1, dev);
+ }
+ }
+ }
+
+ }
+ else
+ {
+ rslt = SMI230_E_INVALID_CONFIG;
+ }
+ }
+
+ return rslt;
+}
+
+static int8_t set_int_pin_config(const struct smi230_gyro_int_channel_cfg *int_config, const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data;
+
+ rslt = get_regs(SMI230_GYRO_INT3_INT4_IO_CONF_REG, &data, 1, dev);
+
+ if (rslt == SMI230_OK)
+ {
+ switch (int_config->int_channel)
+ {
+ case SMI230_INT_CHANNEL_3:
+ data = SMI230_SET_BITS_POS_0(data, SMI230_GYRO_INT3_LVL, int_config->int_pin_cfg.lvl);
+ data = SMI230_SET_BITS(data, SMI230_GYRO_INT3_OD, int_config->int_pin_cfg.output_mode);
+ break;
+
+ case SMI230_INT_CHANNEL_4:
+ data = SMI230_SET_BITS(data, SMI230_GYRO_INT4_LVL, int_config->int_pin_cfg.lvl);
+ data = SMI230_SET_BITS(data, SMI230_GYRO_INT4_OD, int_config->int_pin_cfg.output_mode);
+ break;
+
+ default:
+ break;
+ }
+
+ rslt = set_regs(SMI230_GYRO_INT3_INT4_IO_CONF_REG, &data, 1, dev);
+ }
+
+ return rslt;
+}
+
+static int8_t set_gyro_data_ready_int(const struct smi230_gyro_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t conf, data[2] = { 0 };
+
+ rslt = get_regs(SMI230_GYRO_INT3_INT4_IO_MAP_REG, &data[0], 1, dev);
+
+ if (rslt == SMI230_OK)
+ {
+ conf = int_config->int_pin_cfg.enable_int_pin;
+
+ switch (int_config->int_channel)
+ {
+ case SMI230_INT_CHANNEL_3:
+ data[0] = SMI230_SET_BITS_POS_0(data[0], SMI230_GYRO_INT3_MAP, conf);
+ break;
+
+ case SMI230_INT_CHANNEL_4:
+ data[0] = SMI230_SET_BITS(data[0], SMI230_GYRO_INT4_MAP, conf);
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK)
+ {
+ /*condition to check disabling the interrupt in single channel when both
+ * interrupts channels are enabled*/
+ if (data[0] & SMI230_GYRO_MAP_DRDY_TO_BOTH_INT3_INT4)
+ {
+ data[1] = SMI230_GYRO_DRDY_INT_ENABLE_VAL;
+ }
+ else
+ {
+ data[1] = SMI230_GYRO_DRDY_INT_DISABLE_VAL;
+ }
+
+ rslt = set_regs(SMI230_GYRO_INT3_INT4_IO_MAP_REG, &data[0], 1, dev);
+ if (rslt == SMI230_OK)
+ {
+ rslt = set_int_pin_config(int_config, dev);
+ if (rslt == SMI230_OK)
+ rslt = set_regs(SMI230_GYRO_INT_CTRL_REG, &data[1], 1, dev);
+ }
+ }
+
+ }
+
+ return rslt;
+}
+
+static int8_t set_gyro_fifo_int(const struct smi230_gyro_int_channel_cfg *int_config,
+ const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t conf, data[2] = { 0 };
+
+ rslt = get_regs(SMI230_GYRO_INT3_INT4_IO_MAP_REG, &data[0], 1, dev);
+ if (rslt == SMI230_OK)
+ {
+ conf = int_config->int_pin_cfg.enable_int_pin;
+ switch (int_config->int_channel)
+ {
+ case SMI230_INT_CHANNEL_3:
+ data[0] = SMI230_SET_BITS(data[0], SMI230_GYRO_FIFO_INT3_MAP, conf);
+ break;
+
+ case SMI230_INT_CHANNEL_4:
+ data[0] = SMI230_SET_BITS(data[0], SMI230_GYRO_FIFO_INT4_MAP, conf);
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_INPUT;
+ break;
+ }
+
+ if (rslt == SMI230_OK)
+ {
+ if (data[0] & SMI230_GYRO_MAP_FIFO_TO_BOTH_INT3_INT4)
+ {
+ data[1] = SMI230_GYRO_FIFO_INT_ENABLE_VAL;
+ }
+ else
+ {
+ data[1] = SMI230_GYRO_DRDY_INT_DISABLE_VAL;
+ }
+
+ rslt = set_regs(SMI230_GYRO_INT3_INT4_IO_MAP_REG, &data[0], 1, dev);
+ if (rslt == SMI230_OK)
+ {
+ rslt = set_int_pin_config(int_config, dev);
+ if (rslt == SMI230_OK)
+ {
+ rslt = set_regs(SMI230_GYRO_INT_CTRL_REG, &data[1], 1, dev);
+ }
+
+ }
+ }
+
+ }
+
+ return rslt;
+}
+
+int8_t smi230_gyro_set_int_config(const struct smi230_gyro_int_channel_cfg *int_config, const struct smi230_dev *dev)
+{
+ int8_t rslt;
+
+ rslt = null_ptr_check(dev);
+ if ((rslt == SMI230_OK) && (int_config != NULL))
+ {
+ switch (int_config->int_type)
+ {
+ case SMI230_GYRO_DATA_RDY_INT:
+ rslt = set_gyro_data_ready_int(int_config, dev);
+ break;
+ case SMI230_GYRO_FIFO_INT:
+ rslt = set_gyro_fifo_int(int_config, dev);
+ break;
+
+ default:
+ rslt = SMI230_E_INVALID_CONFIG;
+ break;
+ }
+ }
+ else
+ {
+ rslt = SMI230_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+int8_t smi230_gyro_get_data(struct smi230_sensor_data *gyro, const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data[6];
+ uint8_t lsb, msb;
+ uint16_t msblsb;
+
+ rslt = null_ptr_check(dev);
+ if ((rslt == SMI230_OK) && (gyro != NULL))
+ {
+ rslt = get_regs(SMI230_GYRO_X_LSB_REG, data, 6, dev);
+ if (rslt == SMI230_OK)
+ {
+ lsb = data[0];
+ msb = data[1];
+ msblsb = (msb << 8) | lsb;
+ gyro->x = (int16_t)msblsb; /* Data in X axis */
+
+ lsb = data[2];
+ msb = data[3];
+ msblsb = (msb << 8) | lsb;
+ gyro->y = (int16_t)msblsb; /* Data in Y axis */
+
+ lsb = data[4];
+ msb = data[5];
+ msblsb = (msb << 8) | lsb;
+ gyro->z = (int16_t)msblsb; /* Data in Z axis */
+ }
+
+ }
+ else
+ {
+ rslt = SMI230_E_NULL_PTR;
+ }
+
+ return rslt;
+}
+
+int8_t smi230_gyro_set_power_mode(const struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t power_mode, data;
+ uint8_t is_power_switching_mode_valid = TRUE;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK)
+ {
+ rslt = get_regs(SMI230_GYRO_LPM1_REG, &data, 1, dev);
+ if (rslt == SMI230_OK)
+ {
+ power_mode = dev->gyro_cfg.power;
+
+ /*switching between normal mode and the suspend modes is allowed, it is not possible to switch
+ * between suspend and deep suspend and vice versa. Check for invalid power switching (i.e)
+ * deep suspend to suspend */
+ if ((power_mode == SMI230_GYRO_PM_SUSPEND) && (data == SMI230_GYRO_PM_DEEP_SUSPEND))
+ is_power_switching_mode_valid = FALSE;
+
+ /* Check for invalid power switching (i.e) from suspend to deep suspend */
+ if ((power_mode == SMI230_GYRO_PM_DEEP_SUSPEND) && (data == SMI230_GYRO_PM_SUSPEND))
+ is_power_switching_mode_valid = FALSE;
+
+ /* Check if power switching mode is valid*/
+ if (is_power_switching_mode_valid)
+ {
+ rslt = set_regs(SMI230_GYRO_LPM1_REG, &power_mode, 1, dev);
+ if (rslt == SMI230_OK)
+ dev->delay_ms(SMI230_GYRO_POWER_MODE_CONFIG_DELAY);
+
+ }
+ else
+ rslt = SMI230_E_INVALID_INPUT;
+ }
+ }
+
+ return rslt;
+}
+
+
+static int smi230_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret;
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+ struct smi230_sensor_data data = {0};
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = smi230_gyro_get_data(&data, p_smi230_dev);
+ if (ret != SMI230_OK)
+ return 0;
+ switch (chan->channel2) {
+ case IIO_MOD_X:
+ *val = data.x;
+ break;
+ case IIO_MOD_Y:
+ *val = data.y;
+ break;
+ case IIO_MOD_Z:
+ *val = data.z;
+ break;
+ }
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = smi230_gyro_get_meas_conf(p_smi230_dev);
+ if (ret)
+ return ret;
+ switch(p_smi230_dev->gyro_cfg.odr) {
+ case SMI230_GYRO_BW_523_ODR_2000_HZ:
+ *val = 2000;
+ break;
+ case SMI230_GYRO_BW_116_ODR_1000_HZ:
+ *val = 1000;
+ break;
+ case SMI230_GYRO_BW_47_ODR_400_HZ:
+ *val = 400;
+ break;
+ case SMI230_GYRO_BW_64_ODR_200_HZ:
+ *val = 200;
+ break;
+ case SMI230_GYRO_BW_32_ODR_100_HZ:
+ *val = 100;
+ break;
+ default:
+ return -EINVAL;
+ }
+ *val2 = 0;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int smi230_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ int ret;
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch(val) {
+ case 2000:
+ p_smi230_dev->gyro_cfg.odr = SMI230_GYRO_BW_523_ODR_2000_HZ;
+ break;
+ case 1000:
+ p_smi230_dev->gyro_cfg.odr = SMI230_GYRO_BW_116_ODR_1000_HZ;
+ break;
+ case 400:
+ p_smi230_dev->gyro_cfg.odr = SMI230_GYRO_BW_47_ODR_400_HZ;
+ break;
+ case 200:
+ p_smi230_dev->gyro_cfg.odr = SMI230_GYRO_BW_64_ODR_200_HZ;
+ break;
+ case 100:
+ p_smi230_dev->gyro_cfg.odr = SMI230_GYRO_BW_32_ODR_100_HZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = smi230_gyro_set_meas_conf(p_smi230_dev);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+
+}
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 400 1000 2000");
+
+//dongyu@2022.11.03 Add smi230_gyro_get_power_mode start
+int8_t smi230_gyro_get_power_mode(struct smi230_dev *dev)
+{
+ int8_t rslt;
+ uint8_t data;
+
+ rslt = null_ptr_check(dev);
+ if (rslt == SMI230_OK)
+ {
+ rslt = get_regs(SMI230_GYRO_LPM1_REG, &data, 1, dev);
+
+ if (rslt == SMI230_OK)
+ {
+ dev->gyro_cfg.power = data;
+ }
+ }
+
+ return rslt;
+}
+
+static ssize_t smi230_gyro_store_pwr_cfg(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int err = 0;
+ unsigned long pwr_cfg;
+ struct smi230_dev *p_smi230_dev = dev_get_drvdata(dev);
+
+ err = kstrtoul(buf, 10, &pwr_cfg);
+ if (err)
+ return err;
+ if (pwr_cfg == 0) {
+ p_smi230_dev->gyro_cfg.power = SMI230_GYRO_PM_NORMAL;
+ err = smi230_gyro_set_power_mode(p_smi230_dev);
+ }
+ else if (pwr_cfg == 1) {
+ p_smi230_dev->gyro_cfg.power = SMI230_GYRO_PM_SUSPEND;
+ err = smi230_gyro_set_power_mode(p_smi230_dev);
+ }
+ else if (pwr_cfg == 2) {
+ p_smi230_dev->gyro_cfg.power = SMI230_GYRO_PM_DEEP_SUSPEND;
+ err = smi230_gyro_set_power_mode(p_smi230_dev);
+ }
+ else {
+ dev_info(dev, "invalid param");
+ return count;
+ }
+
+
+ dev_info(dev, "set power cfg to %ld, err %d", pwr_cfg, err);
+
+ if (err) {
+ dev_info(dev, "setting power config failed");
+ return err;
+ }
+ return count;
+}
+
+static ssize_t smi230_gyro_show_pwr_cfg(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int err;
+ struct smi230_dev *p_smi230_dev = dev_get_drvdata(dev);
+
+ err = smi230_gyro_get_power_mode(p_smi230_dev);
+ if (err) {
+ dev_info(dev, "read failed");
+ return err;
+ }
+ return snprintf(buf, PAGE_SIZE, "%x (0:active 1:suspend 2:deep suspend)\n", p_smi230_dev->gyro_cfg.power);
+}
+
+static DEVICE_ATTR(pwr_cfg, S_IRUGO|S_IWUSR|S_IWGRP,
+ smi230_gyro_show_pwr_cfg, smi230_gyro_store_pwr_cfg);
+
+static IIO_CONST_ATTR(in_anglvel_scale_available,
+ "0.008 0.004 0.002 0.001 0.0005");
+
+static struct attribute *smi230_attrs[] = {
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_const_attr_in_anglvel_scale_available.dev_attr.attr,
+ &dev_attr_pwr_cfg.attr,
+ NULL,
+};
+//dongyu@2022.11.03 Add smi230_gyro_get_power_mode end
+
+static const struct attribute_group smi230_attrs_group = {
+ .attrs = smi230_attrs,
+};
+
+static const struct iio_info smi230_info = {
+ .read_raw = smi230_read_raw,
+ .write_raw = smi230_write_raw,
+ .attrs = &smi230_attrs_group,
+};
+
+static struct smi230_int_cfg int_config;
+
+static int smi230_gyro_init(struct smi230_dev *dev)
+{
+ int err = 0;
+
+ err = smi230_gyro_chip_id_check(dev);
+
+ dev->gyro_cfg.power = SMI230_GYRO_PM_NORMAL;
+ err |= smi230_gyro_set_power_mode(dev);
+
+ int_config.gyro_int_config_1.int_pin_cfg.enable_int_pin = SMI230_DISABLE;
+ int_config.gyro_int_config_2.int_pin_cfg.enable_int_pin = SMI230_ENABLE;
+
+ dev->gyro_cfg.odr = SMI230_GYRO_BW_32_ODR_100_HZ;
+ dev->gyro_cfg.range = SMI230_GYRO_RANGE_125_DPS;
+
+ err |= smi230_gyro_set_meas_conf(dev);
+ smi230_delay(100);
+
+ int_config.gyro_int_config_2.int_channel = SMI230_INT_CHANNEL_3;
+ int_config.gyro_int_config_2.int_type = SMI230_GYRO_DATA_RDY_INT;
+ int_config.gyro_int_config_2.int_pin_cfg.output_mode = SMI230_INT_MODE_PUSH_PULL;
+ int_config.gyro_int_config_2.int_pin_cfg.lvl = SMI230_INT_ACTIVE_HIGH;
+
+ err |= smi230_gyro_set_int_config(&int_config.gyro_int_config_2, dev);
+
+ smi230_delay(100);
+
+ return err;
+}
+
+static int smi230_read_channel(struct smi230_sensor_data *data, int i, s16 *sample)
+{
+
+ switch (i) {
+ case 0:
+ *sample = data->x;
+ break;
+ case 1:
+ *sample = data->y;
+ break;
+ case 2:
+ *sample = data->z;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static irqreturn_t smi230_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+
+ /* hand code the buffer size for now */
+ s16 buf[8];
+ s16 sample;
+ int ret, i, j = 0;
+
+ struct smi230_sensor_data sensor_data = {0};
+ ret = smi230_gyro_get_data(&sensor_data, p_smi230_dev);
+ if (ret) {
+ dev_dbg(indio_dev->dev.parent, "Reading sensor data failed");
+ goto done;
+ }
+
+ for_each_set_bit(i, indio_dev->active_scan_mask, indio_dev->masklength) {
+ ret = smi230_read_channel(&sensor_data, i, &sample);
+ if (ret) {
+ dev_dbg(indio_dev->dev.parent, "Read channel %d failed", i);
+ goto done;
+ }
+ buf[j++] = sample;
+ }
+
+
+ ret = iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp);
+ if (ret)
+ dev_dbg(indio_dev->dev.parent, "Push to buffer failed");
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int smi230_new_data_trigger_set_state(struct iio_trigger *trig, bool enable)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct smi230_dev *p_smi230_dev = iio_device_get_drvdata(indio_dev);
+ u8 en;
+
+ dev_dbg(indio_dev->dev.parent, "trigger set state %d", enable);
+ if (enable)
+ en = SMI230_ENABLE;
+ else
+ en = SMI230_DISABLE;
+
+ int_config.gyro_int_config_2.int_pin_cfg.enable_int_pin = en;
+ return smi230_gyro_set_int_config(&int_config.gyro_int_config_2, p_smi230_dev);
+}
+
+static const struct iio_trigger_ops smi230_trigger_ops = {
+ .set_trigger_state = &smi230_new_data_trigger_set_state,
+};
+
+static int smi230_get_irq(struct device *dev, int *irq)
+{
+ int gpio_pin, ret;
+
+ gpio_pin = of_get_named_gpio_flags(dev->of_node,
+ "gpio_irq", 0, NULL);
+
+ dev_dbg(dev, "gpio pin %d", gpio_pin);
+ //return 0;
+ ret = gpio_request_one(gpio_pin,
+ GPIOF_IN, "smi230_gyro_interrupt");
+ if (ret) {
+ dev_dbg(dev, "Request GPIO pin %d failed", gpio_pin);
+ return ret;
+ }
+
+ ret = gpio_direction_input(gpio_pin);
+ if (ret)
+ return ret;
+
+ *irq = gpio_to_irq(gpio_pin);
+
+
+ return ret;
+}
+
+int smi230_gyro_core_probe(struct device *dev, struct smi230_dev *p_smi230_dev)
+{
+ int ret = 0;
+ int irq;
+ struct iio_dev *indio_dev;
+
+ ret = smi230_gyro_init(p_smi230_dev);
+ if (ret == SMI230_OK)
+ dev_dbg(dev, "Bosch Sensor %s hardware initialized", SENSOR_GYRO_NAME);
+ else {
+ dev_dbg(dev, "Bosch Sensor %s hardware initialization failed, error %d",
+ SENSOR_GYRO_NAME, ret);
+ }
+
+ indio_dev = devm_iio_device_alloc(dev, 0);
+ if (!indio_dev) {
+ dev_dbg(dev, "Bosch Sensor %s iio device alloc failed", SENSOR_GYRO_NAME);
+ return -ENOMEM;
+ }
+
+ iio_device_set_drvdata(indio_dev, p_smi230_dev);
+ dev_set_drvdata(dev, indio_dev);
+ indio_dev->dev.parent = dev;
+ indio_dev->channels = smi230_channels;
+ indio_dev->num_channels = ARRAY_SIZE(smi230_channels);
+ indio_dev->name = MODULE_NAME;
+ indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_TRIGGERED;
+ indio_dev->info = &smi230_info;
+ indio_dev->trig = devm_iio_trigger_alloc(&indio_dev->dev, "%s-dev%d",
+ indio_dev->name, indio_dev->id);
+
+ if (indio_dev->trig == NULL)
+ return -ENOMEM;
+
+ dev_dbg(dev, "Bosch Sensor %s device alloced", SENSOR_GYRO_NAME);
+
+ ret = smi230_get_irq(dev, &irq);
+ dev_dbg(dev, "irq number %d", irq);
+
+ ret = devm_request_irq(&indio_dev->dev, irq,
+ &iio_trigger_generic_data_rdy_poll,
+ IRQF_TRIGGER_RISING, indio_dev->name,
+ indio_dev->trig);
+
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "Bosch Sensor %s irq alloced", SENSOR_GYRO_NAME);
+
+ indio_dev->trig->dev.parent = dev;
+ indio_dev->trig->ops = &smi230_trigger_ops;
+
+ iio_trigger_set_drvdata(indio_dev->trig, indio_dev);
+
+ ret = devm_iio_trigger_register(&indio_dev->dev, indio_dev->trig);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "Bosch Sensor %s trigger registered", SENSOR_GYRO_NAME);
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ smi230_trigger_handler,
+ NULL);
+ if (ret) {
+ dev_dbg(dev, "Setup triggered buffer failed");
+ return ret;
+ }
+
+ dev_dbg(dev, "Bosch Sensor %s trigger buffer registered", SENSOR_GYRO_NAME);
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ return ret;
+}
+
+MODULE_DESCRIPTION("SMI230 GYRO SENSOR DRIVER");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro_i2c.c b/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro_i2c.c
new file mode 100644
index 0000000..2308af8
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro_i2c.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/**
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * This file is free software licensed under the terms of version 2
+ * of the GNU General Public License, available from the file LICENSE-GPL
+ * in the main directory of this source tree.
+ *
+ * BSD LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "smi230_gyro.h"
+
+#define SMI230_MAX_RETRY_I2C_XFER 10
+#define SMI230_I2C_WRITE_DELAY_TIME 10
+
+static struct i2c_adapter *smi230_i2c_adapter;
+static struct smi230_dev smi230_i2c_dev;
+
+static int8_t smi230_i2c_read(uint8_t dev_addr,
+ uint8_t reg_addr, uint8_t *data, uint16_t len)
+{
+ int32_t retry;
+
+ struct i2c_msg msg[] = {
+ {
+ .addr = dev_addr,
+ .flags = 0,
+ .len = 1,
+ .buf = ®_addr,
+ },
+
+ {
+ .addr = dev_addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+ for (retry = 0; retry < SMI230_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(smi230_i2c_adapter, msg, ARRAY_SIZE(msg)) > 0)
+ break;
+ else
+ usleep_range(SMI230_I2C_WRITE_DELAY_TIME * 1000,
+ SMI230_I2C_WRITE_DELAY_TIME * 1000);
+ }
+
+ if (SMI230_MAX_RETRY_I2C_XFER <= retry) {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int8_t smi230_i2c_write(uint8_t dev_addr,
+ uint8_t reg_addr, uint8_t *data, uint16_t len)
+{
+ int32_t retry;
+ struct i2c_msg msg = {
+ .addr = dev_addr,
+ .flags = 0,
+ .len = len + 1,
+ .buf = NULL,
+ };
+
+ msg.buf = kmalloc(len + 1, GFP_KERNEL);
+ if (!msg.buf) {
+ return -ENOMEM;
+ }
+ msg.buf[0] = reg_addr;
+ memcpy(&msg.buf[1], data, len);
+ for (retry = 0; retry < SMI230_MAX_RETRY_I2C_XFER; retry++) {
+ if (i2c_transfer(smi230_i2c_adapter, &msg, 1) > 0)
+ break;
+ else
+ usleep_range(SMI230_I2C_WRITE_DELAY_TIME * 1000,
+ SMI230_I2C_WRITE_DELAY_TIME * 1000);
+ }
+ kfree(msg.buf);
+ if (SMI230_MAX_RETRY_I2C_XFER <= retry) {
+ dump_stack();
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int smi230_gyro_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_dbg(&client->dev, "i2c_check_functionality error!");
+ return -EIO;
+ }
+
+ smi230_i2c_adapter = client->adapter;
+ dev_dbg(&client->dev, "%s i2c adapter is at %px", SENSOR_GYRO_NAME, client->adapter);
+
+ smi230_i2c_dev.gyro_id = client->addr;
+
+ return smi230_gyro_core_probe(&client->dev, &smi230_i2c_dev);
+}
+
+static const struct i2c_device_id smi230_gyro_id[] = {
+ { SENSOR_GYRO_NAME, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, smi230_gyro_id);
+
+static const struct of_device_id smi230_gyro_of_match[] = {
+ { .compatible = SENSOR_GYRO_NAME, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, smi230_gyro_of_match);
+
+static struct i2c_driver smi230_gyro_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_GYRO_NAME,
+ .of_match_table = smi230_gyro_of_match,
+ },
+ .id_table = smi230_gyro_id,
+ .probe = smi230_gyro_i2c_probe,
+};
+
+static int __init smi230_gyro_module_init(void)
+{
+ int err = 0;
+
+ smi230_i2c_dev.delay_ms = smi230_delay;
+ smi230_i2c_dev.read_write_len = 32;
+ smi230_i2c_dev.intf = SMI230_I2C_INTF;
+ smi230_i2c_dev.read = smi230_i2c_read;
+ smi230_i2c_dev.write = smi230_i2c_write;
+
+ err |= i2c_add_driver(&smi230_gyro_driver);
+
+ return err;
+}
+
+static void __exit smi230_gyro_module_exit(void)
+{
+ i2c_del_driver(&smi230_gyro_driver);
+}
+
+module_init(smi230_gyro_module_init);
+module_exit(smi230_gyro_module_exit);
+
+MODULE_DESCRIPTION("SMI230 GYRO SENSOR I2C DRIVER");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRIVER_VERSION);
diff --git a/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro_spi.c b/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro_spi.c
new file mode 100644
index 0000000..1261735
--- /dev/null
+++ b/src/kernel/linux/v4.19/drivers/iio/gyro/smi230_gyro_spi.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/**
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * This file is free software licensed under the terms of version 2
+ * of the GNU General Public License, available from the file LICENSE-GPL
+ * in the main directory of this source tree.
+ *
+ * BSD LICENSE
+ * Copyright (c) 2022 Robert Bosch GmbH. All rights reserved.
+ *
+ * BSD-3-Clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ **/
+
+#include <linux/types.h>
+#include <linux/spi/spi.h>
+#include <linux/module.h>
+
+#include "smi230_gyro.h"
+#define MODULE_TAG MODULE_NAME
+#define SMI230_SPI_MAX_BUFFER_SIZE 32
+
+static uint8_t *read_buf = NULL;
+static struct spi_device *smi230_gyro_device;
+static struct smi230_dev smi230_spi_dev;
+
+static int8_t smi230_spi_write(uint8_t dev_addr,
+ uint8_t reg_addr, uint8_t *data, uint16_t len)
+{
+ struct spi_message msg;
+ uint8_t buffer[SMI230_SPI_MAX_BUFFER_SIZE + 1];
+ struct spi_transfer xfer = {
+ .tx_buf = buffer,
+ .len = len + 1,
+ };
+
+ if (len > SMI230_SPI_MAX_BUFFER_SIZE)
+ return -EINVAL;
+
+ buffer[0] = reg_addr;
+ memcpy(&buffer[1], data, len);
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer, &msg);
+
+ return spi_sync(smi230_gyro_device, &msg);
+}
+
+static int8_t smi230_spi_read(uint8_t dev_addr,
+ uint8_t reg_addr, uint8_t *data, uint16_t len)
+{
+ int ret;
+ uint16_t index;
+ struct spi_message msg;
+ struct spi_transfer xfer[2] = {
+ [0] = {
+ .tx_buf = ®_addr,
+ .len = 1,
+ },
+ [1] = {
+ .rx_buf = read_buf,
+ .len = len,
+ }
+ };
+
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer[0], &msg);
+ spi_message_add_tail(&xfer[1], &msg);
+
+ ret = spi_sync(smi230_gyro_device, &msg);
+
+ for (index = 0; index < len; index++)
+ {
+ data[index] = read_buf[index];
+ }
+
+ return ret;
+}
+
+static int smi230_gyro_spi_probe(struct spi_device *device)
+{
+ int err;
+
+ dev_dbg(&device->dev, "smi230 gyro spi probe!");
+ device->bits_per_word = 8;
+ err = spi_setup(device);
+ if (err < 0) {
+ dev_dbg(&device->dev, "spi_setup err!");
+ return err;
+ }
+
+ if (read_buf == NULL)
+ read_buf = kmalloc(CONFIG_SMI230_MAX_BUFFER_LEN + 1, GFP_KERNEL);
+ if (!read_buf) {
+ return -ENOMEM;
+ }
+
+ smi230_gyro_device = device;
+
+ return smi230_gyro_core_probe(&device->dev, &smi230_spi_dev);
+}
+
+static int smi230_gyro_spi_remove(struct spi_device *device)
+{
+ if (read_buf != NULL) {
+ kfree(read_buf);
+ read_buf = NULL;
+ }
+ return 0;
+}
+
+static const struct spi_device_id smi230_gyro_id[] = {
+ { SENSOR_GYRO_NAME, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, smi230_gyro_id);
+
+static const struct of_device_id smi230_gyro_of_match[] = {
+ { .compatible = SENSOR_GYRO_NAME, },
+ { }
+};
+MODULE_DEVICE_TABLE(of, smi230_gyro_of_match);
+
+static struct spi_driver smi230_gyro_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_GYRO_NAME,
+ .of_match_table = smi230_gyro_of_match,
+ },
+ .id_table = smi230_gyro_id,
+ .probe = smi230_gyro_spi_probe,
+ .remove = smi230_gyro_spi_remove,
+};
+
+static int __init smi230_module_init(void)
+{
+ int err = 0;
+
+ smi230_spi_dev.delay_ms = smi230_delay;
+ smi230_spi_dev.read_write_len = 32;
+ smi230_spi_dev.intf = SMI230_SPI_INTF;
+ smi230_spi_dev.read = smi230_spi_read;
+ smi230_spi_dev.write = smi230_spi_write;
+
+ err |= spi_register_driver(&smi230_gyro_driver);
+ return err;
+}
+
+static void __exit smi230_module_exit(void)
+{
+ spi_unregister_driver(&smi230_gyro_driver);
+}
+
+module_init(smi230_module_init);
+module_exit(smi230_module_exit);
+
+MODULE_DESCRIPTION("SMI230 GYRO SENSOR SPI DRIVER");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(DRIVER_VERSION);