summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeka2024-04-04 22:36:32 +0300
committerJeka2024-04-04 22:36:32 +0300
commita9fcf6eb146bb99793f85b26567c1d3b350e5542 (patch)
tree8d60933b0965110cdd206620096683c0e6aa8e58
parent5429f4e1a3b9df2f007432bf0d4096447d3eb22e (diff)
downloadaur-linux-jcore.tar.gz
kernel release 6.6.25
-rw-r--r--.SRCINFO46
-rw-r--r--0000-hid-asus-add-const-to-read-only-outgoing-usb-buffer.patch57
-rw-r--r--0001-OrangePi-Neo-panel-orientation-quirk.patch15
-rw-r--r--0001-ROG-ALLY-bmi323-device.patch2672
-rw-r--r--0001-hid-asus-reset-the-backlight-brightness-level-on-resume.patch59
-rw-r--r--0001-iio-imu_Add_driver_for_BMI323_IMU.patch2810
-rw-r--r--0002-iio-imu-bmi323-Make-the-local-structures-static.patch37
-rw-r--r--0003-iio-imu_Add_ROG_ALLY_bmi323-support.patch54
-rw-r--r--0004-iio-imu-Load_ROG_ALLY_mount_matrix.patch51
-rw-r--r--0005-iio-imu-ASUS-ROG-ALLY-force-INT1-IRQ.patch40
-rw-r--r--0999-patch_realtek.patch2
-rw-r--r--PKGBUILD49
-rw-r--r--config23
-rw-r--r--v14.1-fix-defaults1.patch63
-rw-r--r--v14.7-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch (renamed from v14.1-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch)6
-rw-r--r--v14.7-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch (renamed from v14.1-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch)6
-rw-r--r--v14.7-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch (renamed from v14.1-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch)8
-rw-r--r--v14.7-0004-HID-asus-add-ROG-Ally-xpad-settings.patch (renamed from v14.1-0004-HID-asus-add-ROG-Ally-xpad-settings.patch)270
-rw-r--r--wifi-cfg80211-fix-cqm-for-non-range-use.patch141
-rw-r--r--wifi-nl80211-fix-deadlock-in-nl80211_set_cqm_rssi-6.6.x.patch (renamed from wifi-nl80211-fix-deadlock-in-nl80211_set_cqm_rssi-(6.6.x).patch)0
20 files changed, 3362 insertions, 3047 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 811f50b872a6..a51729e50381 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = linux-jcore
pkgdesc = Kernel for Manjaro/EndeavourOS/Arch (ACS override patch include)
- pkgver = 6.6.6
+ pkgver = 6.6.25
pkgrel = 2
url = https://www.kernel.org/
arch = x86_64
@@ -21,18 +21,15 @@ pkgbase = linux-jcore
replaces = linux-acs-manjaro
replaces = linux-acs-manjaro-headers
options = !strip
- source = https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.6.tar.xz
+ source = https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.25.tar.xz
source = config
source = 0101-ZEN_Add_sysctl_and_CONFIG_to_disallow_unprivileged_CLONE_NEWUSER.patch
source = 0102-drivers-firmware-skip-simpledrm-if-nvidia-drm.modese.patch
source = 0999-patch_realtek.patch
- source = 0000-hid-asus-add-const-to-read-only-outgoing-usb-buffer.patch
- source = 0001-hid-asus-reset-the-backlight-brightness-level-on-resume.patch
- source = v14.1-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch
- source = v14.1-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch
- source = v14.1-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch
- source = v14.1-0004-HID-asus-add-ROG-Ally-xpad-settings.patch
- source = v14.1-fix-defaults1.patch
+ source = v14.7-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch
+ source = v14.7-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch
+ source = v14.7-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch
+ source = v14.7-0004-HID-asus-add-ROG-Ally-xpad-settings.patch
source = 0006-platform-x86-asus-wmi-disable-USB0-hub-on-ROG-Ally-b.patch
source = 0007-mt7921e_Perform_FLR_to_recovery_the_device.patch
source = 0301-drm-Add_GPU_reset_sysfs_event.patch
@@ -41,21 +38,23 @@ pkgbase = linux-jcore
source = 0001-ALSA-hda-cs35l41-Support-ASUS-2023-laptops-with-miss.patch
source = 0001-ALSA-hda-cs35l41-Improve-support-for-ASUS-ROG-Ally.patch
source = ROG-ALLY-NCT6775-PLATFORM.patch
- source = 0001-ROG-ALLY-bmi323-device.patch
+ source = 0001-iio-imu_Add_driver_for_BMI323_IMU.patch
+ source = 0002-iio-imu-bmi323-Make-the-local-structures-static.patch
+ source = 0003-iio-imu_Add_ROG_ALLY_bmi323-support.patch
+ source = 0004-iio-imu-Load_ROG_ALLY_mount_matrix.patch
+ source = 0005-iio-imu-ASUS-ROG-ALLY-force-INT1-IRQ.patch
source = 0001-HID.patch
+ source = 0001-OrangePi-Neo-panel-orientation-quirk.patch
source = 0999-acs.gitpatch
- sha256sums = ebf70a917934b13169e1be5b95c3b6c2fea5bc14e6dc144f1efb8a0016b224c8
- sha256sums = 043ada1688a42e652bb0b339d2f9732c323c22da96bb2ca2bcf144a731c5e981
+ sha256sums = 99d210be87908233a55b0fadc0dccd3b95926c0651b6b82e37350b2029de1f44
+ sha256sums = 9736c7856f4dd543d2172e1cb8a63cabdd6ed6fbf314dfdb5fe4c60b74954a68
sha256sums = 05f04019d4a2ee072238c32860fa80d673687d84d78ef436ae9332b6fb788467
sha256sums = e1d17690dd21e8d5482b63ca66bfe6b478d39e8e8b59eedd53adb0a55ebc308d
- sha256sums = 3aa9f1ca47bb078f3c9a52fe61897cf4fe989068cd7e66bfa6644fd605fa40d2
- sha256sums = fb2cd8a3ea9d47bd78c99b8ece1f3959c20b4de97a7959a12650f989f5c724da
- sha256sums = 7f3194f1a7c5ebc27bbfa4559cfd9a2ccffddbbd2d259c0d9c68631cb66c5855
- sha256sums = 176adde8fc3069bd28393bf0c9d788f1b0f9a186678aec4dc17b0b081c57f97b
- sha256sums = 493fa177cf602f087e981e95fad3764e305f4c486d4c2ef78255388b913be9cf
- sha256sums = 50ea381758fb8a8566f38a509fe7cf0448c77eaec5103066cafc2ecf02db1e9f
- sha256sums = 970687b811034e722befde62bcf6d51c7442a217074ed0fb71460bb1803f4c64
- sha256sums = c00b23162fdbf50de375d8e444b6d59e2e3630cfac55ec1d06114b9dad00e542
+ sha256sums = a99b684fe5bc7fdacc6f5b1f2b6593672fc5d1e676c4de03ec29723747fc574b
+ sha256sums = b099ae83a3b561b8bff8b32b44b6f4835b99eb150c2314177aa0bc8ca96e2ead
+ sha256sums = 10b60663195a65ec3b0f50b49e4c0af952369ee5afe95e11a69ffccefc020eb2
+ sha256sums = 3c8b877dfaf85acf45b54c85a44fa269aa1512ea3781fe551cf6d4e2d69c992d
+ sha256sums = 73aa4be8c1abcf1b24c9a5c5072e68da3da82df807f3ff49660a100d7634da1d
sha256sums = 836e88044263f7bc474ca466b3d0d98c39e265db94925c300d0b138492946a13
sha256sums = d673d034fbcd80426fd8d9c6af56537c5fe5b55fe49d74e313474d7fc285ecc1
sha256sums = 1f62542a889a6c2eafd43acd0699f54720ed891eeda66a4a9261d75b92f28b7f
@@ -64,8 +63,13 @@ pkgbase = linux-jcore
sha256sums = 79970a4729572cb25fd4644d66f38ecd5b3e1610a42ea4bbe436b501f3469fa2
sha256sums = 430a7f971d78d0873708e0ad38fba602ceafefd4da8ebbf9d9c591bc4799acb5
sha256sums = cfcd5c177423df8b7b98b0500fe7ab0757f895ed945c33e205963f0069c7a3be
- sha256sums = 5574a68b1c7733769835bb856a8c32e54398dfde59f264708672b87b73b3c6ea
+ sha256sums = 708a9899f80db35fb0f06e0144c361eac9a9b2d154cf2fa388a0b4810847e24c
+ sha256sums = 514fd03c17245ed0aaee63e8830c9b02b00efa0307f7e0989065edec6ae185f0
+ sha256sums = fccdf24b25620dd8271bb3b52ddc53f8882dec26518258dc47e1469fed33e516
+ sha256sums = c3b901db58288b5cc5d8a947ac8ffec339870b00aba493d68a39f65c4ff3d869
+ sha256sums = 5792a59a0c726a205ae1c1728700ea3e6385231cadc2cfdd2db08295b100638c
sha256sums = 7c948773d758418d8a436067265d678c444827562c46b9fced2ff31ced108481
+ sha256sums = aa2ff6edca0177b864868fdc2752d3a0eaaf5b801bd17e5c59dfd78999226d83
sha256sums = 458d7e024d33d4965b14b9b987f01a2884ff28761cff5da7c6a54132a95e9f36
pkgname = linux-jcore
diff --git a/0000-hid-asus-add-const-to-read-only-outgoing-usb-buffer.patch b/0000-hid-asus-add-const-to-read-only-outgoing-usb-buffer.patch
deleted file mode 100644
index 3bf969bb1709..000000000000
--- a/0000-hid-asus-add-const-to-read-only-outgoing-usb-buffer.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 06ae5afce8cc1f7621cc5c7751e449ce20d68af7 Mon Sep 17 00:00:00 2001
-From: Denis Benato <benato.denis96@gmail.com>
-Date: Fri, 17 Nov 2023 14:15:55 +1300
-Subject: [PATCH] HID: hid-asus: add const to read-only outgoing usb buffer
-
-In the function asus_kbd_set_report the parameter buf is read-only
-as it gets copied in a memory portion suitable for USB transfer,
-but the parameter is not marked as const: add the missing const and mark
-const immutable buffers passed to that function.
-
-Signed-off-by: Denis Benato <benato.denis96@gmail.com>
-Signed-off-by: Luke D. Jones <luke@ljones.dev>
-Signed-off-by: Jiri Kosina <jkosina@suse.cz>
----
- drivers/hid/hid-asus.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
-index fd61dba882338e..b70673a929a1ed 100644
---- a/drivers/hid/hid-asus.c
-+++ b/drivers/hid/hid-asus.c
-@@ -381,7 +381,7 @@ static int asus_raw_event(struct hid_device *hdev,
- return 0;
- }
-
--static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size)
-+static int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t buf_size)
- {
- unsigned char *dmabuf;
- int ret;
-@@ -404,7 +404,7 @@ static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size
-
- static int asus_kbd_init(struct hid_device *hdev)
- {
-- u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
-+ const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
- 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
- int ret;
-
-@@ -418,7 +418,7 @@ static int asus_kbd_init(struct hid_device *hdev)
- static int asus_kbd_get_functions(struct hid_device *hdev,
- unsigned char *kbd_func)
- {
-- u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
-+ const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
- u8 *readbuf;
- int ret;
-
-@@ -449,7 +449,7 @@ static int asus_kbd_get_functions(struct hid_device *hdev,
-
- static int rog_nkey_led_init(struct hid_device *hdev)
- {
-- u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 };
-+ const u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 };
- u8 buf_init2[] = { FEATURE_KBD_LED_REPORT_ID1, 0x41, 0x53, 0x55, 0x53, 0x20,
- 0x54, 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
- u8 buf_init3[] = { FEATURE_KBD_LED_REPORT_ID1,
diff --git a/0001-OrangePi-Neo-panel-orientation-quirk.patch b/0001-OrangePi-Neo-panel-orientation-quirk.patch
new file mode 100644
index 000000000000..ad04ec936ede
--- /dev/null
+++ b/0001-OrangePi-Neo-panel-orientation-quirk.patch
@@ -0,0 +1,15 @@
+--- linux-6.7/drivers/gpu/drm/drm_panel_orientation_quirks.c 2024-02-16 14:35:44.755058457 +0700
++++ linux-6.7/drivers/gpu/drm/drm_panel_orientation_quirks.c 2024-02-16 14:34:26.391114606 +0700
+@@ -396,6 +396,12 @@ static const struct dmi_system_id orient
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"),
+ },
+ .driver_data = (void *)&lcd1600x2560_leftside_up,
++ }, { /* OrangePi Neo */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OrangePi"),
++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "NEO-01"),
++ },
++ .driver_data = (void *)&lcd1200x1920_rightside_up,
+ }, { /* Samsung GalaxyBook 10.6 */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
diff --git a/0001-ROG-ALLY-bmi323-device.patch b/0001-ROG-ALLY-bmi323-device.patch
deleted file mode 100644
index e83d6e3e1830..000000000000
--- a/0001-ROG-ALLY-bmi323-device.patch
+++ /dev/null
@@ -1,2672 +0,0 @@
-From 622ea77bfccd751247b1c08c3126d7ab716f0423 Mon Sep 17 00:00:00 2001
-From: Denis <benato.denis96@gmail.com>
-Date: Mon, 25 Sep 2023 03:38:49 +0200
-Subject: [PATCH] This commit adds support to the bmi323 device on top of the
- pre-existing bmc150 kernel module.
-
-Some new devices for example the ROG Ally and the Air Plus identify this chip in the ACPI table as a bmc150 so previously the original module was loaded,
-but was erroring out as it cannot handle such device.
-
-The device I own does not allow me to use the interrupt part of the device as the interrupt pin is not connected (or not advertised to be connected) hence
-I avoided including on this commit anything related to IRQ.
-
-This driver has already been proved to work well enough to be used in the switch emulator "yuzu".
-
-While designing this module my main focus was not to alter the original driver and not to limit the original author in regard to future mofications,
-and I was mostly able to achive this, except:
-1) I added a new structure on top of the original one and added a field that is responsible for holding information
-on what type of chip the module is currently managing
-2) the previous point required the init function of the original driver to write that field in order to be sure no bmi323 code
-was executed when the old part of the module is managing the device
-3) as the original driver issued an i2c write on some register not really meant to be written in the bmi323 device I have made sure an i2c read to discover
-the bmi323 is performed prior to that code: such read SHOULD fail in the older bmc150 IC for two reasons:
- - the i2c address is not reported in the memory map of the bmc150 in its datasheet
- - the i2c read attempts to get 4 bytes out of a 8-bit device
- - the fourth bit (the one that cannot be read from a bmc150 device) is initialized to 0 and bmi323 presence is signaled with a 1 in the LSB
- that is the fourth coming out of the device in temporal order
----
- drivers/iio/accel/bmc150-accel-core.c | 2307 ++++++++++++++++++++++++-
- drivers/iio/accel/bmc150-accel-i2c.c | 100 +-
- drivers/iio/accel/bmc150-accel.h | 94 +-
- 3 files changed, 2495 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
-index 110591804b4c..9a2c1732c9ef 100644
---- a/drivers/iio/accel/bmc150-accel-core.c
-+++ b/drivers/iio/accel/bmc150-accel-core.c
-@@ -130,6 +130,73 @@
- #define BMC150_ACCEL_REG_FIFO_DATA 0x3F
- #define BMC150_ACCEL_FIFO_LENGTH 32
-
-+#define BMC150_BMI323_TEMPER_CENTER_VAL 23
-+#define BMC150_BMI323_TEMPER_LSB_PER_KELVIN_VAL 512
-+
-+#define BMC150_BMI323_AUTO_SUSPEND_DELAY_MS 2000
-+
-+#define BMC150_BMI323_CHIP_ID_REG 0x00
-+#define BMC150_BMI323_SOFT_RESET_REG 0x7E
-+#define BMC150_BMI323_SOFT_RESET_VAL 0xDEAFU
-+#define BMC150_BMI323_DATA_BASE_REG 0x03
-+#define BMC150_BMI323_TEMPERATURE_DATA_REG 0x09
-+#define BMC150_BMI323_FIFO_FILL_LEVEL_REG 0x15
-+#define BMC150_BMI323_FIFO_DATA_REG 0x16
-+#define BMC150_BMI323_ACC_CONF_REG 0x20
-+#define BMC150_BMI323_GYR_CONF_REG 0x21
-+#define BMC150_BMI323_FIFO_CONF_REG 0x36
-+
-+// these are bits [0:3] of ACC_CONF.acc_odr, sample rate in Hz for the accel part of the chip
-+#define BMC150_BMI323_ACCEL_ODR_0_78123_VAL 0x0001
-+#define BMC150_BMI323_ACCEL_ODR_1_5625_VAL 0x0002
-+#define BMC150_BMI323_ACCEL_ODR_3_125_VAL 0x0003
-+#define BMC150_BMI323_ACCEL_ODR_6_25_VAL 0x0004
-+#define BMC150_BMI323_ACCEL_ODR_12_5_VAL 0x0005
-+#define BMC150_BMI323_ACCEL_ODR_25_VAL 0x0006
-+#define BMC150_BMI323_ACCEL_ODR_50_VAL 0x0007
-+#define BMC150_BMI323_ACCEL_ODR_100_VAL 0x0008
-+#define BMC150_BMI323_ACCEL_ODR_200_VAL 0x0009
-+#define BMC150_BMI323_ACCEL_ODR_400_VAL 0x000A
-+#define BMC150_BMI323_ACCEL_ODR_800_VAL 0x000B
-+#define BMC150_BMI323_ACCEL_ODR_1600_VAL 0x000C
-+#define BMC150_BMI323_ACCEL_ODR_3200_VAL 0x000D
-+#define BMC150_BMI323_ACCEL_ODR_6400_VAL 0x000E
-+
-+#define BMC150_BMI323_ACCEL_BW_ODR_2_VAL 0x0000
-+#define BMC150_BMI323_ACCEL_BW_ODR_4_VAL 0x0001
-+
-+// these are bits [4:6] of ACC_CONF.acc_range, full scale resolution
-+#define BMC150_BMI323_ACCEL_RANGE_2_VAL 0x0000 // +/-2g, 16.38 LSB/mg
-+#define BMC150_BMI323_ACCEL_RANGE_4_VAL 0x0001 // +/-4g, 8.19 LSB/mg
-+#define BMC150_BMI323_ACCEL_RANGE_8_VAL 0x0002 // +/-8g, 4.10 LSB/mg
-+#define BMC150_BMI323_ACCEL_RANGE_16_VAL 0x0003 // +/-4g, 2.05 LSB/mg
-+
-+// these are bits [0:3] of GYR_CONF.gyr_odr, sample rate in Hz for the gyro part of the chip
-+#define BMC150_BMI323_GYRO_ODR_0_78123_VAL 0x0001
-+#define BMC150_BMI323_GYRO_ODR_1_5625_VAL 0x0002
-+#define BMC150_BMI323_GYRO_ODR_3_125_VAL 0x0003
-+#define BMC150_BMI323_GYRO_ODR_6_25_VAL 0x0004
-+#define BMC150_BMI323_GYRO_ODR_12_5_VAL 0x0005
-+#define BMC150_BMI323_GYRO_ODR_25_VAL 0x0006
-+#define BMC150_BMI323_GYRO_ODR_50_VAL 0x0007
-+#define BMC150_BMI323_GYRO_ODR_100_VAL 0x0008
-+#define BMC150_BMI323_GYRO_ODR_200_VAL 0x0009
-+#define BMC150_BMI323_GYRO_ODR_400_VAL 0x000A
-+#define BMC150_BMI323_GYRO_ODR_800_VAL 0x000B
-+#define BMC150_BMI323_GYRO_ODR_1600_VAL 0x000C
-+#define BMC150_BMI323_GYRO_ODR_3200_VAL 0x000D
-+#define BMC150_BMI323_GYRO_ODR_6400_VAL 0x000E
-+
-+#define BMC150_BMI323_GYRO_BW_ODR_2_VAL 0x0000
-+#define BMC150_BMI323_GYRO_BW_ODR_4_VAL 0x0001
-+
-+// these are bits [4:6] of GYR_CONF.gyr_range, full scale resolution
-+#define BMC150_BMI323_GYRO_RANGE_125_VAL 0x0000 // +/-125°/s, 262.144 LSB/°/s
-+#define BMC150_BMI323_GYRO_RANGE_250_VAL 0x0001 // +/-250°/s, 131.2 LSB/°/s
-+#define BMC150_BMI323_GYRO_RANGE_500_VAL 0x0002 // +/-500°/s, 65.6 LSB/°/s
-+#define BMC150_BMI323_GYRO_RANGE_1000_VAL 0x0003 // +/-1000°/s, 32.8 LSB/°/s
-+#define BMC150_BMI323_GYRO_RANGE_2000_VAL 0x0004 // +/-2000°/s, 16.4 LSB/°/s
-+
- enum bmc150_accel_axis {
- AXIS_X,
- AXIS_Y,
-@@ -149,6 +216,654 @@ struct bmc150_scale_info {
- u8 reg_range;
- };
-
-+/*
-+ * This enum MUST not be altered as there are parts in the code that
-+ * uses an int conversion to get the correct device register to read.
-+ */
-+enum bmi323_axis {
-+ BMI323_ACCEL_AXIS_X = 0,
-+ BMI323_ACCEL_AXIS_Y,
-+ BMI323_ACCEL_AXIS_Z,
-+ BMI323_GYRO_AXIS_X,
-+ BMI323_GYRO_AXIS_Y,
-+ BMI323_GYRO_AXIS_Z,
-+ BMI323_TEMP,
-+ BMI323_AXIS_MAX,
-+};
-+
-+static const struct bmi323_scale_accel_info {
-+ u8 hw_val;
-+ int val;
-+ int val2;
-+ int ret_type;
-+} bmi323_accel_scale_map[] = {
-+ {
-+ .hw_val = (u16)BMC150_BMI323_ACCEL_RANGE_2_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 598,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_ACCEL_RANGE_4_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 1196,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_ACCEL_RANGE_8_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 2392,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_ACCEL_RANGE_16_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 4785,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+};
-+
-+static const struct bmi323_scale_gyro_info {
-+ u8 hw_val;
-+ int val;
-+ int val2;
-+ int ret_type;
-+} bmi323_gyro_scale_map[] = {
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_125_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 66545,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_125_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 66,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_250_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 133090,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_250_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 133,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_500_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 266181,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_500_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 266,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_1000_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 532362,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_1000_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 532,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_2000_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 1064724,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ // this shouldn't be necessary, but iio seems to have a wrong rounding of this value...
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_2000_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 1064,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+ {
-+ .hw_val = (u16)BMC150_BMI323_GYRO_RANGE_2000_VAL << (u16)4,
-+ .val = 0,
-+ .val2 = 1065,
-+ .ret_type = IIO_VAL_INT_PLUS_NANO,
-+ },
-+};
-+
-+/*
-+ * this reflects the frequency map that is following.
-+ * For each index i of that map index i*2 and i*2+1 of of this
-+ * holds ODR/2 and ODR/4
-+ */
-+static const struct bmi323_3db_freq_cutoff_accel_info {
-+ int val;
-+ int val2;
-+ int ret_type;
-+} bmi323_accel_3db_freq_cutoff[] = {
-+ {
-+ .val = 0,
-+ .val2 = 390615,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 0,
-+ .val2 = 195308,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 0,
-+ .val2 = 781300,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 0,
-+ .val2 = 390650,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1,
-+ .val2 = 562500,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 0,
-+ .val2 = 78125,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 3,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1,
-+ .val2 = 500000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 6,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 3,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 12,
-+ .val2 = 500000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 6,
-+ .val2 = 250000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 25,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 12,
-+ .val2 = 500000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 50,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 25,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 100,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 50,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 200,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 100,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 400,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 200,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 800,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 400,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1600,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 800,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1600,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 800,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 3200,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1600,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+};
-+
-+static const struct bmi323_freq_accel_info {
-+ u8 hw_val;
-+ int val;
-+ int val2;
-+ s64 time_ns;
-+} bmi323_accel_odr_map[] = {
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_0_78123_VAL,
-+ .val = 0,
-+ .val2 = 781230,
-+ .time_ns = 1280032769,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_1_5625_VAL,
-+ .val = 1,
-+ .val2 = 562600,
-+ .time_ns = 886522247,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_3_125_VAL,
-+ .val = 3,
-+ .val2 = 125000,
-+ .time_ns = 320000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_6_25_VAL,
-+ .val = 6,
-+ .val2 = 250000,
-+ .time_ns = 160000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_12_5_VAL,
-+ .val = 12,
-+ .val2 = 500000,
-+ .time_ns = 80000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_25_VAL,
-+ .val = 25,
-+ .val2 = 0,
-+ .time_ns = 40000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_50_VAL,
-+ .val = 50,
-+ .val2 = 0,
-+ .time_ns = 20000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_100_VAL,
-+ .val = 100,
-+ .val2 = 0,
-+ .time_ns = 10000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_200_VAL,
-+ .val = 200,
-+ .val2 = 0,
-+ .time_ns = 5000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_400_VAL,
-+ .val = 400,
-+ .val2 = 0,
-+ .time_ns = 2500000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_800_VAL,
-+ .val = 800,
-+ .val2 = 0,
-+ .time_ns = 1250000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_1600_VAL,
-+ .val = 1600,
-+ .val2 = 0,
-+ .time_ns = 625000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_3200_VAL,
-+ .val = 3200,
-+ .val2 = 0,
-+ .time_ns = 312500,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_ACCEL_ODR_6400_VAL,
-+ .val = 6400,
-+ .val2 = 0,
-+ .time_ns = 156250,
-+ },
-+};
-+
-+static const struct bmi323_freq_gyro_info {
-+ u8 hw_val;
-+ int val;
-+ int val2;
-+ s64 time_ns;
-+} bmi323_gyro_odr_map[] = {
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_0_78123_VAL,
-+ .val = 0,
-+ .val2 = 781230,
-+ .time_ns = 1280032769,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_1_5625_VAL,
-+ .val = 1,
-+ .val2 = 562600,
-+ .time_ns = 886522247,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_3_125_VAL,
-+ .val = 3,
-+ .val2 = 125000,
-+ .time_ns = 320000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_6_25_VAL,
-+ .val = 6,
-+ .val2 = 250000,
-+ .time_ns = 160000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_12_5_VAL,
-+ .val = 12,
-+ .val2 = 500000,
-+ .time_ns = 80000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_25_VAL,
-+ .val = 25,
-+ .val2 = 0,
-+ .time_ns = 40000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_50_VAL,
-+ .val = 50,
-+ .val2 = 0,
-+ .time_ns = 20000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_100_VAL,
-+ .val = 100,
-+ .val2 = 0,
-+ .time_ns = 10000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_200_VAL,
-+ .val = 200,
-+ .val2 = 0,
-+ .time_ns = 5000000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_400_VAL,
-+ .val = 400,
-+ .val2 = 0,
-+ .time_ns = 2500000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_800_VAL,
-+ .val = 800,
-+ .val2 = 0,
-+ .time_ns = 1250000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_1600_VAL,
-+ .val = 1600,
-+ .val2 = 0,
-+ .time_ns = 625000,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_3200_VAL,
-+ .val = 3200,
-+ .val2 = 0,
-+ .time_ns = 312500,
-+ },
-+ {
-+ .hw_val = BMC150_BMI323_GYRO_ODR_6400_VAL,
-+ .val = 6400,
-+ .val2 = 0,
-+ .time_ns = 156250,
-+ },
-+};
-+
-+static const struct bmi323_3db_freq_cutoff_gyro_info {
-+ int val;
-+ int val2;
-+ int ret_type;
-+} bmi323_gyro_3db_freq_cutoff[] = {
-+ {
-+ .val = 0,
-+ .val2 = 390615,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 0,
-+ .val2 = 1953075, // TODO: check if this gets reported correctly...
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 0,
-+ .val2 = 781300,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 0,
-+ .val2 = 390650,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1,
-+ .val2 = 562500,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 0,
-+ .val2 = 78125,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 3,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1,
-+ .val2 = 500000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 6,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 3,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 12,
-+ .val2 = 500000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 6,
-+ .val2 = 250000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 25,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 12,
-+ .val2 = 500000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 50,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 25,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 100,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 50,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 200,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 100,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 400,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 200,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 800,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 400,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1600,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 800,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1600,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 800,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 3200,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+ {
-+ .val = 1600,
-+ .val2 = 000000,
-+ .ret_type = IIO_VAL_INT_PLUS_MICRO,
-+ },
-+};
-+
-+static const int bmi323_accel_scales[] = {
-+ 0, 598, 0, 1196, 0, 2392, 0, 4785,
-+};
-+
-+static const int bmi323_gyro_scales[] = {
-+ 0, 66545, 0, 133090, 0, 266181, 0, 532362, 0, 1064724,
-+};
-+
-+static const int bmi323_sample_freqs[] = {
-+ 0, 781230, 1, 562600, 3, 125000, 6, 250000, 12, 500000,
-+ 25, 0, 50, 0, 100, 0, 200, 0, 400, 0,
-+ 800, 0, 1600, 0, 3200, 0, 6400, 0,
-+};
-+
-+static const struct {
-+ int val;
-+ int val2; // IIO_VAL_INT_PLUS_MICRO
-+ u8 bw_bits;
-+} bmi323_samp_freq_table[] = { { 15, 620000, 0x08 }, { 31, 260000, 0x09 },
-+ { 62, 500000, 0x0A }, { 125, 0, 0x0B },
-+ { 250, 0, 0x0C }, { 500, 0, 0x0D },
-+ { 1000, 0, 0x0E }, { 2000, 0, 0x0F } };
-+
- struct bmc150_accel_chip_info {
- const char *name;
- u8 chip_id;
-@@ -1113,6 +1828,52 @@ static const struct iio_event_spec bmc150_accel_event = {
- .num_event_specs = 1 \
- }
-
-+#define BMI323_ACCEL_CHANNEL(_axis, bits) \
-+ { \
-+ .type = IIO_ACCEL, .modified = 1, .channel2 = IIO_MOD_##_axis, \
-+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
-+ .info_mask_shared_by_type = \
-+ BIT(IIO_CHAN_INFO_SCALE) | \
-+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
-+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
-+ .info_mask_shared_by_type_available = \
-+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
-+ BIT(IIO_CHAN_INFO_SCALE), \
-+ .scan_index = BMI323_ACCEL_AXIS_##_axis, \
-+ .scan_type = { \
-+ .sign = 's', \
-+ .realbits = (bits), \
-+ .storagebits = 16, \
-+ .shift = 16 - (bits), \
-+ .endianness = IIO_LE, \
-+ }, \
-+ }
-+
-+#define BMI323_GYRO_CHANNEL(_axis, bits) \
-+ { \
-+ .type = IIO_ANGL_VEL, .modified = 1, \
-+ .channel2 = IIO_MOD_##_axis, \
-+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
-+ .info_mask_shared_by_type = \
-+ BIT(IIO_CHAN_INFO_SCALE) | \
-+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
-+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
-+ .info_mask_shared_by_type_available = \
-+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
-+ BIT(IIO_CHAN_INFO_SCALE), \
-+ .scan_index = BMI323_GYRO_AXIS_##_axis, \
-+ .scan_type = { \
-+ .sign = 's', \
-+ .realbits = (bits), \
-+ .storagebits = 16, \
-+ .shift = 16 - (bits), \
-+ .endianness = IIO_LE, \
-+ }, \
-+ /*.ext_info = bmi323_accel_ext_info,*/ \
-+ /*.event_spec = &bmi323_accel_event,*/ \
-+ /*.num_event_specs = 1*/ \
-+ }
-+
- #define BMC150_ACCEL_CHANNELS(bits) { \
- { \
- .type = IIO_TEMP, \
-@@ -1595,7 +2356,7 @@ static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
- struct device *dev = regmap_get_device(data->regmap);
- int ret, i;
- unsigned int val;
--
-+
- /*
- * Reset chip to get it in a known good state. A delay of 1.8ms after
- * reset is required according to the data sheets of supported chips.
-@@ -1677,6 +2438,11 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
- data = iio_priv(indio_dev);
- dev_set_drvdata(dev, indio_dev);
-
-+ /*
-+ * Setting the dev_type here is necessary to avoid having it left uninitialized
-+ * and therefore potentially executing bmi323 functions for the original bmc150 model.
-+ */
-+ data->dev_type = BMC150;
- data->regmap = regmap;
- data->type = type;
-
-@@ -1826,12 +2592,1407 @@ void bmc150_accel_core_remove(struct device *dev)
- }
- EXPORT_SYMBOL_NS_GPL(bmc150_accel_core_remove, IIO_BMC150);
-
--#ifdef CONFIG_PM_SLEEP
--static int bmc150_accel_suspend(struct device *dev)
-+struct device *bmi323_get_managed_device(struct bmi323_private_data *bmi323)
-+{
-+ if (bmi323->i2c_client != NULL)
-+ return &bmi323->i2c_client->dev;
-+
-+ return &bmi323->spi_client->dev;
-+}
-+
-+static int bmi323_set_power_state(struct bmi323_private_data *bmi323, bool on)
-+{
-+#ifdef CONFIG_PM
-+ struct device *dev = bmi323_get_managed_device(bmi323);
-+ int ret;
-+
-+ if (on)
-+ ret = pm_runtime_get_sync(dev);
-+ else {
-+ pm_runtime_mark_last_busy(dev);
-+ ret = pm_runtime_put_autosuspend(dev);
-+ }
-+
-+ if (ret < 0) {
-+ dev_err(dev, "bmi323_set_power_state failed with %d\n", on);
-+
-+ if (on)
-+ pm_runtime_put_noidle(dev);
-+
-+ return ret;
-+ }
-+#endif
-+
-+ return 0;
-+}
-+
-+int bmi323_write_u16(struct bmi323_private_data *bmi323, u8 in_reg,
-+ u16 in_value)
-+{
-+ s32 ret;
-+
-+ if (bmi323->i2c_client != NULL) {
-+ ret = i2c_smbus_write_i2c_block_data(bmi323->i2c_client, in_reg,
-+ sizeof(in_value),
-+ (u8 *)(&in_value));
-+ if (ret != 0) {
-+ return -2;
-+ }
-+
-+ return 0;
-+ } else if (bmi323->spi_client != NULL) {
-+ /*
-+ * To whoever may need this: implementing this should be straightforward:
-+ * it's specular to the i2c part.
-+ */
-+
-+ return -EINVAL; // TODO: change with 0 once implemented
-+ }
-+
-+ return -EINVAL;
-+}
-+EXPORT_SYMBOL_NS_GPL(bmi323_write_u16, IIO_BMC150);
-+
-+int bmi323_read_u16(struct bmi323_private_data *bmi323, u8 in_reg,
-+ u16 *out_value)
-+{
-+ s32 ret;
-+ u8 read_bytes[4];
-+
-+ if (bmi323->i2c_client != NULL) {
-+ ret = i2c_smbus_read_i2c_block_data(bmi323->i2c_client, in_reg,
-+ sizeof(read_bytes),
-+ &read_bytes[0]);
-+ if (ret != 4) {
-+ return ret;
-+ }
-+
-+ // DUMMY = read_bytes[0]
-+ // DUMMY = read_bytes[1]
-+ // LSB = read_bytes[2]
-+ // MSB = read_bytes[3]
-+ u8 *o = (u8 *)out_value;
-+ o[0] = read_bytes[2];
-+ o[1] = read_bytes[3];
-+
-+ return 0;
-+ } else if (bmi323->spi_client != NULL) {
-+ printk(KERN_CRIT
-+ "bmi323: SPI interface is not yet implemented.\n");
-+
-+ /*
-+ * To whoever may need this: implementing this should be straightforward:
-+ * it's specular to the i2c part except that the dummy data is just 1 byte.
-+ */
-+
-+ return -EINVAL; // TODO: change with 0 once implemented
-+ }
-+
-+ return -EINVAL;
-+}
-+EXPORT_SYMBOL_NS_GPL(bmi323_read_u16, IIO_BMC150);
-+
-+int bmi323_chip_check(struct bmi323_private_data *bmi323)
-+{
-+ u16 chip_id;
-+ int ret;
-+
-+ ret = bmi323_read_u16(bmi323, BMC150_BMI323_CHIP_ID_REG, &chip_id);
-+ if (ret != 0) {
-+ return ret;
-+ }
-+
-+ if (((chip_id)&0x00FF) != cpu_to_le16((u16)0x0043U)) {
-+ dev_err(bmi323->dev,
-+ "bmi323_chip_check failed with: %d; chip_id = 0x%04x",
-+ ret, chip_id);
-+
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_NS_GPL(bmi323_chip_check, IIO_BMC150);
-+
-+static int bmi323_buffer_preenable(struct iio_dev *indio_dev)
-+{
-+ struct bmc150_accel_data *data = iio_priv(indio_dev);
-+
-+ const int ret = bmi323_set_power_state(&data->bmi323, true);
-+
-+ if (ret == 0) {
-+ mutex_lock(&data->bmi323.mutex);
-+ data->bmi323.fifo_frame_time_diff_ns =
-+ (data->bmi323.acc_odr_time_ns >=
-+ data->bmi323.gyr_odr_time_ns) ?
-+ data->bmi323.acc_odr_time_ns :
-+ data->bmi323.gyr_odr_time_ns;
-+ mutex_unlock(&data->bmi323.mutex);
-+ }
-+
-+ return ret;
-+}
-+
-+static int bmi323_buffer_postenable(struct iio_dev *indio_dev)
-+{
-+ //struct bmc150_accel_data *data = iio_priv(indio_dev);
-+
-+ /*
-+ * This code is a placeholder until I can get a way to test it
-+ */
-+
-+ return 0;
-+}
-+
-+static int bmi323_buffer_predisable(struct iio_dev *indio_dev)
-+{
-+ //struct bmc150_accel_data *data = iio_priv(indio_dev);
-+
-+ /*
-+ * This code is a placeholder until I can get a way to test it
-+ */
-+
-+ return 0;
-+}
-+
-+static int bmi323_buffer_postdisable(struct iio_dev *indio_dev)
-+{
-+ struct bmc150_accel_data *data = iio_priv(indio_dev);
-+
-+ return bmi323_set_power_state(&data->bmi323, true);
-+}
-+
-+static const struct iio_buffer_setup_ops bmi323_buffer_ops = {
-+ .preenable = bmi323_buffer_preenable,
-+ .postenable = bmi323_buffer_postenable,
-+ .predisable = bmi323_buffer_predisable,
-+ .postdisable = bmi323_buffer_postdisable,
-+};
-+
-+int bmi323_chip_rst(struct bmi323_private_data *bmi323)
-+{
-+ u16 sensor_status = 0x0000, device_status = 0x0000;
-+ int ret;
-+
-+ ret = bmi323_write_u16(bmi323, BMC150_BMI323_SOFT_RESET_REG,
-+ cpu_to_le16((u16)BMC150_BMI323_SOFT_RESET_VAL));
-+ if (ret != 0) {
-+ dev_err(bmi323->dev,
-+ "bmi323: error while issuing the soft-reset command: %d",
-+ ret);
-+ return ret;
-+ }
-+
-+ /* wait the specified amount of time... I agree with the bmc150 module: better safe than sorry. */
-+ msleep(5);
-+
-+ // if the device is connected over SPI a dummy read is to be performed once after each reset
-+ if (bmi323->spi_client != NULL) {
-+ dev_info(bmi323->dev,
-+ "issuing the dummy read to switch mode to SPI");
-+
-+ // do not even check the result of that... it's just a dummy read
-+ bmi323_chip_check(bmi323);
-+ }
-+
-+ ret = bmi323_chip_check(bmi323);
-+ if (ret != 0) {
-+ return ret;
-+ }
-+
-+ /* now check the correct initialization status as per datasheet */
-+ ret = bmi323_read_u16(bmi323, 0x01, &device_status);
-+ if (ret != 0) {
-+ return -EINVAL;
-+ }
-+
-+ if ((device_status & cpu_to_le16((u16)0x00FFU)) !=
-+ cpu_to_le16((u16)0x0000U)) {
-+ dev_err(bmi323->dev,
-+ "bmi323: device_status incorrect: %d; device_status = 0x%04x",
-+ ret, device_status);
-+
-+ /* from the datasheet: power error */
-+ return -EINVAL;
-+ }
-+
-+ /* from the datasheet: power ok */
-+ ret = bmi323_read_u16(bmi323, 0x02, &sensor_status);
-+ if (ret != 0) {
-+ return -EINVAL;
-+ }
-+
-+ if ((sensor_status & cpu_to_le16((u16)0x00FFU)) !=
-+ cpu_to_le16((u16)0x0001U)) {
-+ dev_err(bmi323->dev,
-+ "bmi323: sensor_status incorrect: %d; sensor_status = 0x%04x",
-+ ret, sensor_status);
-+
-+ /* from the datasheet: initialization error */
-+ return -EINVAL;
-+ }
-+
-+ /* from the datasheet: initialization ok */
-+ return 0;
-+}
-+EXPORT_SYMBOL_NS_GPL(bmi323_chip_rst, IIO_BMC150);
-+
-+static const struct iio_chan_spec bmi323_channels[] = {
-+ BMI323_ACCEL_CHANNEL(X, 16),
-+ BMI323_ACCEL_CHANNEL(Y, 16),
-+ BMI323_ACCEL_CHANNEL(Z, 16),
-+ BMI323_GYRO_CHANNEL(X, 16),
-+ BMI323_GYRO_CHANNEL(Y, 16),
-+ BMI323_GYRO_CHANNEL(Z, 16),
-+ {
-+ .type = IIO_TEMP,
-+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
-+ BIT(IIO_CHAN_INFO_SCALE) |
-+ BIT(IIO_CHAN_INFO_OFFSET),
-+ .scan_index = BMI323_TEMP,
-+ },
-+ IIO_CHAN_SOFT_TIMESTAMP(BMI323_AXIS_MAX),
-+};
-+
-+static int bmi323_read_raw(struct iio_dev *indio_dev,
-+ struct iio_chan_spec const *chan, int *val,
-+ int *val2, long mask)
-+{
-+ struct bmc150_accel_data *data = iio_priv(indio_dev);
-+ int ret = -EINVAL, was_sleep_modified = -1;
-+ u16 raw_read = 0x8000;
-+
-+ mutex_lock(&data->bmi323.mutex);
-+
-+ if ((data->bmi323.flags & BMI323_FLAGS_RESET_FAILED) != 0x00U) {
-+ dev_err(data->bmi323.dev,
-+ "bmi323 error: device has not being woken up correctly.");
-+ mutex_unlock(&data->bmi323.mutex);
-+ return -EBUSY;
-+ }
-+
-+ switch (mask) {
-+ case IIO_CHAN_INFO_RAW: {
-+ switch (chan->type) {
-+ case IIO_TEMP:
-+ if (iio_buffer_enabled(indio_dev)) {
-+ ret = -EBUSY;
-+ goto bmi323_read_raw_error;
-+ }
-+
-+ was_sleep_modified =
-+ bmi323_set_power_state(&data->bmi323, true);
-+ if (was_sleep_modified != 0) {
-+ ret = was_sleep_modified;
-+ goto bmi323_read_raw_error_power;
-+ }
-+
-+ ret = iio_device_claim_direct_mode(indio_dev);
-+ if (ret != 0) {
-+ printk(KERN_CRIT
-+ "bmc150 bmi323_read_raw IIO_TEMP iio_device_claim_direct_mode returned %d\n",
-+ ret);
-+ goto bmi323_read_raw_error;
-+ }
-+
-+ ret = bmi323_read_u16(
-+ &data->bmi323,
-+ BMC150_BMI323_TEMPERATURE_DATA_REG, &raw_read);
-+ iio_device_release_direct_mode(indio_dev);
-+ if (ret != 0) {
-+ printk(KERN_CRIT
-+ "bmc150 bmi323_read_raw IIO_TEMP bmi323_read_u16 returned %d\n",
-+ ret);
-+ goto bmi323_read_raw_error;
-+ }
-+
-+ *val = sign_extend32(le16_to_cpu(raw_read), 15);
-+ bmi323_set_power_state(&data->bmi323, false);
-+ mutex_unlock(&data->bmi323.mutex);
-+ return IIO_VAL_INT;
-+
-+ case IIO_ACCEL:
-+ if (iio_buffer_enabled(indio_dev)) {
-+ ret = -EBUSY;
-+ goto bmi323_read_raw_error;
-+ }
-+
-+ was_sleep_modified =
-+ bmi323_set_power_state(&data->bmi323, true);
-+ if (was_sleep_modified != 0) {
-+ ret = was_sleep_modified;
-+ goto bmi323_read_raw_error_power;
-+ }
-+
-+ ret = iio_device_claim_direct_mode(indio_dev);
-+ if (ret != 0) {
-+ printk(KERN_CRIT
-+ "bmc150 bmi323_read_raw IIO_ACCEL iio_device_claim_direct_mode returned %d\n",
-+ ret);
-+ goto bmi323_read_raw_error;
-+ }
-+
-+ ret = bmi323_read_u16(&data->bmi323,
-+ BMC150_BMI323_DATA_BASE_REG +
-+ (u8)(chan->scan_index),
-+ &raw_read);
-+ iio_device_release_direct_mode(indio_dev);
-+ if (ret != 0) {
-+ printk(KERN_CRIT
-+ "bmc150 bmi323_read_raw IIO_ACCEL bmi323_read_u16 returned %d\n",
-+ ret);
-+ goto bmi323_read_raw_error;
-+ }
-+ *val = sign_extend32(le16_to_cpu(raw_read), 15);
-+ bmi323_set_power_state(&data->bmi323, false);
-+ mutex_unlock(&data->bmi323.mutex);
-+ return IIO_VAL_INT;
-+
-+ case IIO_ANGL_VEL:
-+ if (iio_buffer_enabled(indio_dev)) {
-+ ret = -EBUSY;
-+ goto bmi323_read_raw_error;
-+ }
-+
-+ was_sleep_modified =
-+ bmi323_set_power_state(&data->bmi323, true);
-+ if (was_sleep_modified != 0) {
-+ ret = was_sleep_modified;
-+ goto bmi323_read_raw_error_power;
-+ }
-+
-+ ret = iio_device_claim_direct_mode(indio_dev);
-+ if (ret != 0) {
-+ printk(KERN_CRIT
-+ "bmc150 bmi323_read_raw IIO_ANGL_VEL iio_device_claim_direct_mode returned %d\n",
-+ ret);
-+ goto bmi323_read_raw_error;
-+ }
-+
-+ ret = bmi323_read_u16(&data->bmi323,
-+ BMC150_BMI323_DATA_BASE_REG +
-+ (u8)(chan->scan_index),
-+ &raw_read);
-+ iio_device_release_direct_mode(indio_dev);
-+ if (ret != 0) {
-+ printk(KERN_CRIT
-+ "bmc150 bmi323_read_raw IIO_ANGL_VEL bmi323_read_u16 returned %d\n",
-+ ret);
-+ goto bmi323_read_raw_error;
-+ }
-+
-+ *val = sign_extend32(le16_to_cpu(raw_read), 15);
-+ bmi323_set_power_state(&data->bmi323, false);
-+ mutex_unlock(&data->bmi323.mutex);
-+ return IIO_VAL_INT;
-+
-+ default:
-+ goto bmi323_read_raw_error;
-+ }
-+ }
-+ case IIO_CHAN_INFO_OFFSET: {
-+ switch (chan->type) {
-+ case IIO_TEMP:
-+ *val = BMC150_BMI323_TEMPER_CENTER_VAL;
-+ *val2 = 0;
-+ mutex_unlock(&data->bmi323.mutex);
-+ return IIO_VAL_INT;
-+
-+ default:
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ }
-+ case IIO_CHAN_INFO_SCALE:
-+ switch (chan->type) {
-+ case IIO_TEMP: {
-+ *val = 0;
-+ *val2 = BMC150_BMI323_TEMPER_LSB_PER_KELVIN_VAL;
-+ mutex_unlock(&data->bmi323.mutex);
-+ return IIO_VAL_FRACTIONAL;
-+ }
-+ case IIO_ACCEL: {
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323.acc_conf_reg_value;
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_accel_scale_map);
-+ ++s) {
-+ if (((le_raw_read[0]) & ((u16)0b01110000U)) ==
-+ (bmi323_accel_scale_map[s].hw_val)) {
-+ *val = bmi323_accel_scale_map[s].val;
-+ *val2 = bmi323_accel_scale_map[s].val2;
-+
-+ mutex_unlock(&data->bmi323.mutex);
-+ return bmi323_accel_scale_map[s]
-+ .ret_type;
-+ }
-+ }
-+
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ case IIO_ANGL_VEL: {
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323.gyr_conf_reg_value;
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_gyro_scale_map);
-+ ++s) {
-+ if (((le_raw_read[0]) & ((u16)0b01110000U)) ==
-+ (bmi323_gyro_scale_map[s].hw_val)) {
-+ *val = bmi323_gyro_scale_map[s].val;
-+ *val2 = bmi323_gyro_scale_map[s].val2;
-+
-+ mutex_unlock(&data->bmi323.mutex);
-+ return bmi323_gyro_scale_map[s].ret_type;
-+ }
-+ }
-+
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ default:
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
-+ switch (chan->type) {
-+ case IIO_ACCEL: {
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323.acc_conf_reg_value;
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_accel_odr_map);
-+ ++s) {
-+ if (((le_raw_read[0]) & ((u16)0x0FU)) ==
-+ (bmi323_accel_odr_map[s].hw_val)) {
-+ /*
-+ * from tha datasheed: -3dB cut-off frequency can be configured with the bit 7 of GYR_confm,
-+ * also called acc_bw that can either be 0 or 1, where 1 means odr/4 and 0 means odr/2
-+ */
-+ int freq_adj_idx =
-+ (((le_raw_read[0]) &
-+ ((u8)0x80U)) == (u8)0x00U) ?
-+ (s * 2) + 0 :
-+ (s * 2) + 1;
-+ *val = bmi323_accel_3db_freq_cutoff
-+ [freq_adj_idx]
-+ .val;
-+ *val2 = bmi323_accel_3db_freq_cutoff
-+ [freq_adj_idx]
-+ .val2;
-+
-+ mutex_unlock(&data->bmi323.mutex);
-+ return IIO_VAL_INT_PLUS_MICRO;
-+ }
-+ }
-+
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ case IIO_ANGL_VEL: {
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323.gyr_conf_reg_value;
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_gyro_odr_map);
-+ ++s) {
-+ if (((le_raw_read[0]) & ((u16)0x0FU)) ==
-+ (bmi323_gyro_odr_map[s].hw_val)) {
-+ /*
-+ * from tha datasheed: -3dB cut-off frequency can be configured with the bit 7 of GYR_confm,
-+ * also called acc_bw that can either be 0 or 1, where 1 means odr/4 and 0 means odr/2
-+ */
-+ int freq_adj_idx =
-+ (((le_raw_read[0]) &
-+ ((u8)0x80U)) == (u8)0x0000U) ?
-+ (s * 2) + 0 :
-+ (s * 2) + 1;
-+ *val = bmi323_gyro_3db_freq_cutoff
-+ [freq_adj_idx]
-+ .val;
-+ *val2 = bmi323_gyro_3db_freq_cutoff
-+ [freq_adj_idx]
-+ .val2;
-+
-+ mutex_unlock(&data->bmi323.mutex);
-+ return bmi323_gyro_3db_freq_cutoff
-+ [freq_adj_idx]
-+ .ret_type;
-+ }
-+ }
-+
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ default: {
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ }
-+ case IIO_CHAN_INFO_SAMP_FREQ:
-+ switch (chan->type) {
-+ case IIO_TEMP: {
-+
-+ // while in normal or power mode the temperature sensur has a 50Hz sampling frequency
-+ *val = 50;
-+ *val2 = 0;
-+
-+ mutex_unlock(&data->bmi323.mutex);
-+ return IIO_VAL_INT_PLUS_MICRO;
-+ }
-+ case IIO_ACCEL: {
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323.acc_conf_reg_value;
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_accel_odr_map);
-+ ++s) {
-+ if (((le_raw_read[0]) & ((u16)0x0FU)) ==
-+ (bmi323_accel_odr_map[s].hw_val)) {
-+ *val = bmi323_accel_odr_map[s].val;
-+ *val2 = bmi323_accel_odr_map[s].val2;
-+
-+ mutex_unlock(&data->bmi323.mutex);
-+ return IIO_VAL_INT_PLUS_MICRO;
-+ }
-+ }
-+
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ case IIO_ANGL_VEL: {
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323.gyr_conf_reg_value;
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_gyro_odr_map);
-+ ++s) {
-+ if (((le_raw_read[0]) & ((u16)0x0FU)) ==
-+ (bmi323_gyro_odr_map[s].hw_val)) {
-+ *val = bmi323_gyro_odr_map[s].val;
-+ *val2 = bmi323_gyro_odr_map[s].val2;
-+
-+ mutex_unlock(&data->bmi323.mutex);
-+ return IIO_VAL_INT_PLUS_MICRO;
-+ }
-+ }
-+
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ default:
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+ default:
-+ ret = -EINVAL;
-+ goto bmi323_read_raw_error;
-+ }
-+
-+bmi323_read_raw_error:
-+ if (was_sleep_modified == 0) {
-+ bmi323_set_power_state(&data->bmi323, false);
-+ }
-+
-+bmi323_read_raw_error_power:
-+ mutex_unlock(&data->bmi323.mutex);
-+ return ret;
-+}
-+
-+static int bmi323_write_raw(struct iio_dev *indio_dev,
-+ struct iio_chan_spec const *chan, int val, int val2,
-+ long mask)
-+{
-+ struct bmc150_accel_data *data = iio_priv(indio_dev);
-+ int ret = -EINVAL, was_sleep_modified = -1;
-+
-+ mutex_lock(&data->bmi323.mutex);
-+
-+ if ((data->bmi323.flags & BMI323_FLAGS_RESET_FAILED) != 0x00U) {
-+ dev_err(data->bmi323.dev,
-+ "bmi323 error: device has not being woken up correctly.");
-+ mutex_unlock(&data->bmi323.mutex);
-+ return -EBUSY;
-+ }
-+
-+ switch (mask) {
-+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
-+ switch (chan->type) {
-+ default: {
-+ ret = -EINVAL;
-+ goto bmi323_write_raw_error;
-+ }
-+ }
-+ case IIO_CHAN_INFO_SAMP_FREQ:
-+ switch (chan->type) {
-+ case IIO_ACCEL:
-+ if (iio_buffer_enabled(indio_dev)) {
-+ ret = -EBUSY;
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_accel_odr_map);
-+ ++s) {
-+ if ((bmi323_accel_odr_map[s].val == val) &&
-+ (bmi323_accel_odr_map[s].val2 == val2)) {
-+ const u16 conf_backup =
-+ data->bmi323.acc_conf_reg_value;
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323
-+ .acc_conf_reg_value;
-+ le_raw_read[0] &= (u8)0b11110000U;
-+ le_raw_read[0] |=
-+ ((u8)bmi323_gyro_odr_map[s]
-+ .hw_val);
-+
-+ was_sleep_modified =
-+ bmi323_set_power_state(
-+ &data->bmi323, true);
-+ if (was_sleep_modified != 0) {
-+ ret = was_sleep_modified;
-+ data->bmi323.acc_conf_reg_value =
-+ conf_backup;
-+ goto bmi323_write_raw_error_power;
-+ }
-+
-+ ret = bmi323_write_u16(
-+ &data->bmi323,
-+ BMC150_BMI323_ACC_CONF_REG,
-+ data->bmi323.acc_conf_reg_value);
-+ if (ret != 0) {
-+ data->bmi323.acc_conf_reg_value =
-+ conf_backup;
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ data->bmi323.acc_odr_time_ns =
-+ bmi323_accel_odr_map[s].time_ns;
-+ bmi323_set_power_state(&data->bmi323,
-+ false);
-+ mutex_unlock(&data->bmi323.mutex);
-+ return 0;
-+ }
-+ }
-+
-+ ret = -EINVAL;
-+ goto bmi323_write_raw_error;
-+ case IIO_ANGL_VEL:
-+ if (iio_buffer_enabled(indio_dev)) {
-+ ret = -EBUSY;
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_gyro_odr_map);
-+ ++s) {
-+ if ((bmi323_gyro_odr_map[s].val == val) &&
-+ (bmi323_gyro_odr_map[s].val2 == val2)) {
-+ const u16 conf_backup =
-+ data->bmi323.gyr_conf_reg_value;
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323
-+ .gyr_conf_reg_value;
-+ le_raw_read[0] &= (u8)0b11110000U;
-+ le_raw_read[0] |=
-+ ((u8)bmi323_gyro_odr_map[s]
-+ .hw_val);
-+
-+ was_sleep_modified =
-+ bmi323_set_power_state(
-+ &data->bmi323, true);
-+ if (was_sleep_modified != 0) {
-+ ret = was_sleep_modified;
-+ data->bmi323.gyr_conf_reg_value =
-+ conf_backup;
-+ goto bmi323_write_raw_error_power;
-+ }
-+
-+ ret = bmi323_write_u16(
-+ &data->bmi323,
-+ BMC150_BMI323_GYR_CONF_REG,
-+ data->bmi323.gyr_conf_reg_value);
-+ if (ret != 0) {
-+ data->bmi323.gyr_conf_reg_value =
-+ conf_backup;
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ data->bmi323.gyr_odr_time_ns =
-+ bmi323_gyro_odr_map[s].time_ns;
-+ bmi323_set_power_state(&data->bmi323,
-+ false);
-+ mutex_unlock(&data->bmi323.mutex);
-+ return 0;
-+ }
-+ }
-+
-+ ret = -EINVAL;
-+ goto bmi323_write_raw_error;
-+
-+ /* Termometer also ends up here: its sampling frequency depends on the chip configuration and cannot be changed */
-+ default:
-+ ret = -EINVAL;
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ break;
-+ case IIO_CHAN_INFO_SCALE:
-+ switch (chan->type) {
-+ case IIO_ACCEL:
-+ if (iio_buffer_enabled(indio_dev)) {
-+ ret = -EBUSY;
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_accel_scale_map);
-+ ++s) {
-+ if ((bmi323_accel_scale_map[s].val == val) &&
-+ (bmi323_accel_scale_map[s].val2 == val2)) {
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323
-+ .acc_conf_reg_value;
-+ le_raw_read[0] &= (u8)0b10001111U;
-+ le_raw_read[0] |=
-+ ((u8)bmi323_accel_scale_map[s]
-+ .hw_val);
-+
-+ was_sleep_modified =
-+ bmi323_set_power_state(
-+ &data->bmi323, true);
-+ if (was_sleep_modified != 0) {
-+ ret = was_sleep_modified;
-+ goto bmi323_write_raw_error_power;
-+ }
-+
-+ ret = bmi323_write_u16(
-+ &data->bmi323,
-+ BMC150_BMI323_ACC_CONF_REG,
-+ data->bmi323.acc_conf_reg_value);
-+ if (ret != 0) {
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ bmi323_set_power_state(&data->bmi323,
-+ false);
-+ mutex_unlock(&data->bmi323.mutex);
-+ return 0;
-+ }
-+ }
-+
-+ dev_warn(
-+ data->bmi323.dev,
-+ "bmi323 error: accel scale val=%d,val2=%d unavailable: ignoring.",
-+ val, val2);
-+
-+ ret = -EINVAL;
-+ goto bmi323_write_raw_error;
-+ case IIO_ANGL_VEL:
-+ if (iio_buffer_enabled(indio_dev)) {
-+ ret = -EBUSY;
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ for (int s = 0; s < ARRAY_SIZE(bmi323_gyro_scale_map);
-+ ++s) {
-+ if ((bmi323_gyro_scale_map[s].val == val) &&
-+ (bmi323_gyro_scale_map[s].val2 == val2)) {
-+ u8 *le_raw_read =
-+ (u8 *)&data->bmi323
-+ .gyr_conf_reg_value;
-+ le_raw_read[0] &= (u8)0b10001111U;
-+ le_raw_read[0] |=
-+ ((u8)bmi323_gyro_scale_map[s]
-+ .hw_val);
-+
-+ was_sleep_modified =
-+ bmi323_set_power_state(
-+ &data->bmi323, true);
-+ if (was_sleep_modified != 0) {
-+ ret = was_sleep_modified;
-+ goto bmi323_write_raw_error_power;
-+ }
-+
-+ ret = bmi323_write_u16(
-+ &data->bmi323,
-+ BMC150_BMI323_GYR_CONF_REG,
-+ data->bmi323.acc_conf_reg_value);
-+ if (ret != 0) {
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ bmi323_set_power_state(&data->bmi323,
-+ false);
-+ mutex_unlock(&data->bmi323.mutex);
-+ return 0;
-+ }
-+ }
-+
-+ dev_warn(
-+ data->bmi323.dev,
-+ "bmi323 error: gyro scale val=%d,val2=%d unavailable: ignoring.",
-+ val, val2);
-+
-+ ret = -EINVAL;
-+ goto bmi323_write_raw_error;
-+
-+ default:
-+ ret = -EINVAL;
-+ goto bmi323_write_raw_error;
-+ }
-+
-+ default:
-+ ret = -EINVAL;
-+ goto bmi323_write_raw_error;
-+ }
-+
-+bmi323_write_raw_error:
-+ if (was_sleep_modified == 0) {
-+ bmi323_set_power_state(&data->bmi323, false);
-+ }
-+
-+bmi323_write_raw_error_power:
-+ mutex_unlock(&data->bmi323.mutex);
-+ return ret;
-+}
-+
-+static int bmi323_read_avail(struct iio_dev *indio_dev,
-+ struct iio_chan_spec const *chan, const int **vals,
-+ int *type, int *length, long mask)
-+{
-+ switch (mask) {
-+ case IIO_CHAN_INFO_SCALE:
-+ switch (chan->type) {
-+ case IIO_ACCEL:
-+ *type = IIO_VAL_INT_PLUS_MICRO;
-+ *vals = bmi323_accel_scales;
-+ *length = ARRAY_SIZE(bmi323_accel_scales);
-+ return IIO_AVAIL_LIST;
-+ case IIO_ANGL_VEL:
-+ *type = IIO_VAL_INT_PLUS_NANO;
-+ *vals = bmi323_gyro_scales;
-+ *length = ARRAY_SIZE(bmi323_gyro_scales);
-+ return IIO_AVAIL_LIST;
-+ default:
-+ return -EINVAL;
-+ }
-+ case IIO_CHAN_INFO_SAMP_FREQ:
-+ *type = IIO_VAL_INT_PLUS_MICRO;
-+ *vals = bmi323_sample_freqs;
-+ *length = ARRAY_SIZE(bmi323_sample_freqs);
-+ return IIO_AVAIL_LIST;
-+ default:
-+ return -EINVAL;
-+ }
-+}
-+
-+static const struct iio_info bmi323_accel_info = {
-+ .read_raw = bmi323_read_raw,
-+ .write_raw = bmi323_write_raw,
-+ .read_avail = bmi323_read_avail,
-+ //.hwfifo_flush_to_buffer = bmi323_fifo_flush,
-+};
-+
-+static int bmi323_fifo_flush(struct iio_dev *indio_dev)
-+{
-+ struct bmc150_accel_data *data = iio_priv(indio_dev);
-+ int ret;
-+
-+ ret = bmi323_write_u16(&data->bmi323, 0x37, cpu_to_le16(0x01));
-+
-+ return ret;
-+}
-+
-+static const u16 stub_value = 0x8000;
-+
-+#define ADVANCE_AT_REQ_OR_AVAIL(req, avail, dst, dst_offset, src, src_offset) \
-+ if (req) { \
-+ if (gyr_avail) { \
-+ memcpy((void *)(dst + dst_offset), \
-+ (const void *)(src + src_offset), 2); \
-+ src_offset += 2; \
-+ } else { \
-+ memcpy((void *)(dst + dst_offset), \
-+ (const void *)((const u8 *)(&stub_value)), 2); \
-+ } \
-+ dst_offset += 2; \
-+ } else { \
-+ if (avail) { \
-+ src_offset += 2; \
-+ } \
-+ }
-+
-+static irqreturn_t iio_bmi323_trigger_h(int irq, void *p)
-+{
-+ printk(KERN_WARNING "bmi323 executed iio_bmi323_trigger_h");
-+
-+ struct iio_poll_func *pf = p;
-+ struct iio_dev *indio_dev = pf->indio_dev;
-+ struct bmc150_accel_data *indio_data = iio_priv(indio_dev);
-+
-+ mutex_lock(&indio_data->bmi323.mutex);
-+
-+ const bool temp_avail = ((indio_data->bmi323.fifo_conf_reg_value &
-+ (cpu_to_le16(0b0000100000000000))) != 0);
-+ const bool gyr_avail = ((indio_data->bmi323.fifo_conf_reg_value &
-+ (cpu_to_le16(0b0000010000000000))) != 0);
-+ const bool acc_avail = ((indio_data->bmi323.fifo_conf_reg_value &
-+ (cpu_to_le16(0b0000001000000000))) != 0);
-+ const bool time_avail = ((indio_data->bmi323.fifo_conf_reg_value &
-+ (cpu_to_le16(0b0000000100000000))) != 0);
-+
-+ /* Calculate the number of bytes for a frame */
-+ const u16 frames_aggregate_size_in_words =
-+ /* 2 * */ ((temp_avail ? 1 : 0) + (gyr_avail ? 3 : 0) +
-+ (acc_avail ? 3 : 0) + (time_avail ? 1 : 0));
-+
-+ u16 available_words = 0;
-+ const int available_words_read_res = bmi323_read_u16(
-+ &indio_data->bmi323, BMC150_BMI323_FIFO_FILL_LEVEL_REG,
-+ &available_words);
-+ if (available_words_read_res != 0) {
-+ goto bmi323_irq_done;
-+ }
-+
-+ const u16 available_frame_aggregates = (le16_to_cpu(available_words)) /
-+ (frames_aggregate_size_in_words);
-+
-+ const s64 current_timestamp_ns = iio_get_time_ns(indio_dev);
-+ const s64 fifo_frame_time_ns =
-+ indio_data->bmi323.fifo_frame_time_diff_ns;
-+ const s64 first_sample_timestamp_ns =
-+ current_timestamp_ns -
-+ (fifo_frame_time_ns * (s64)(available_frame_aggregates));
-+
-+ /* This can hold one full block */
-+ u8 temp_data[16];
-+
-+ /* This is fifo data as read from the sensor */
-+ u8 fifo_data[32];
-+
-+ /*
-+ | CHANNEL | scan_index
-+ |============================
-+ | | |
-+ | ACCEL_X | 0 |
-+ | ACCEL_Y | 1 |
-+ | ACCEL_Y | 2 |
-+ | GYRO_X | 3 |
-+ | GYRO_Y | 4 |
-+ | GYRO_Z | 5 |
-+ | TEMP | 6 |
-+ | TIMESTAMP | ? |
-+ */
-+ bool accel_x_requested = false;
-+ bool accel_y_requested = false;
-+ bool accel_z_requested = false;
-+ bool gyro_x_requested = false;
-+ bool gyro_y_requested = false;
-+ bool gyro_z_requested = false;
-+ bool temp_requested = false;
-+
-+ int j = 0;
-+ for_each_set_bit(j, indio_dev->active_scan_mask,
-+ indio_dev->masklength) {
-+ switch (j) {
-+ case 0:
-+ accel_x_requested = true;
-+ break;
-+ case 1:
-+ accel_y_requested = true;
-+ break;
-+ case 2:
-+ accel_z_requested = true;
-+ break;
-+ case 3:
-+ gyro_x_requested = true;
-+ break;
-+ case 4:
-+ gyro_y_requested = true;
-+ break;
-+ case 5:
-+ gyro_z_requested = true;
-+ break;
-+ case 6:
-+ temp_requested = true;
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+
-+ u16 current_fifo_buffer_offset_bytes = 0;
-+ for (u16 f = 0; f < available_frame_aggregates; ++f) {
-+ u16 current_sample_buffer_offset = 0;
-+
-+ /* Read data from the raw device */
-+ if (indio_data->bmi323.i2c_client != NULL) {
-+ const int bytes_to_read =
-+ 2 + (2 * frames_aggregate_size_in_words);
-+ int read_block_ret = i2c_smbus_read_i2c_block_data(
-+ indio_data->bmi323.i2c_client,
-+ BMC150_BMI323_FIFO_DATA_REG, bytes_to_read,
-+ &fifo_data[0]);
-+ if (read_block_ret < bytes_to_read) {
-+ dev_warn(
-+ &indio_data->bmi323.i2c_client->dev,
-+ "bmi323: i2c_smbus_read_i2c_block_data wrong return: expected %d bytes, %d arrived. Doing what is possible with recovered data.\n",
-+ bytes_to_read, read_block_ret);
-+
-+ /* at this point FIFO buffer must be flushed to avoid interpreting data incorrectly the next trigger */
-+ const int flush_res =
-+ bmi323_fifo_flush(indio_dev);
-+ if (flush_res != 0) {
-+ dev_err(&indio_data->bmi323.i2c_client
-+ ->dev,
-+ "bmi323: Could not flush FIFO (%d). Following buffer data might be corrupted.\n",
-+ flush_res);
-+ }
-+
-+ goto bmi323_irq_done;
-+ }
-+
-+ /* Discard 2-bytes dummy data from I2C */
-+ current_fifo_buffer_offset_bytes = 2;
-+ } else if (indio_data->bmi323.spi_client != NULL) {
-+ printk(KERN_CRIT
-+ "bmi323: SPI interface is not yet implemented.\n");
-+
-+ /*
-+ * To whoever may need this: implementing this should be straightforward:
-+ * it's specular to the i2c part.
-+ */
-+
-+ /* Discard 1-byte dummy data from SPI */
-+ current_fifo_buffer_offset_bytes = 1;
-+
-+ goto bmi323_irq_done;
-+ }
-+
-+ ADVANCE_AT_REQ_OR_AVAIL(accel_x_requested, acc_avail,
-+ (u8 *)&temp_data[0],
-+ current_sample_buffer_offset,
-+ (u8 *)&fifo_data[0],
-+ current_fifo_buffer_offset_bytes);
-+ ADVANCE_AT_REQ_OR_AVAIL(accel_y_requested, acc_avail,
-+ (u8 *)&temp_data[0],
-+ current_sample_buffer_offset,
-+ (u8 *)&fifo_data[0],
-+ current_fifo_buffer_offset_bytes);
-+ ADVANCE_AT_REQ_OR_AVAIL(accel_z_requested, acc_avail,
-+ (u8 *)&temp_data[0],
-+ current_sample_buffer_offset,
-+ (u8 *)&fifo_data[0],
-+ current_fifo_buffer_offset_bytes);
-+ ADVANCE_AT_REQ_OR_AVAIL(gyro_x_requested, gyr_avail,
-+ (u8 *)&temp_data[0],
-+ current_sample_buffer_offset,
-+ (u8 *)&fifo_data[0],
-+ current_fifo_buffer_offset_bytes);
-+ ADVANCE_AT_REQ_OR_AVAIL(gyro_y_requested, gyr_avail,
-+ (u8 *)&temp_data[0],
-+ current_sample_buffer_offset,
-+ (u8 *)&fifo_data[0],
-+ current_fifo_buffer_offset_bytes);
-+ ADVANCE_AT_REQ_OR_AVAIL(gyro_z_requested, gyr_avail,
-+ (u8 *)&temp_data[0],
-+ current_sample_buffer_offset,
-+ (u8 *)&fifo_data[0],
-+ current_fifo_buffer_offset_bytes);
-+ ADVANCE_AT_REQ_OR_AVAIL(temp_requested, temp_avail,
-+ (u8 *)&temp_data[0],
-+ current_sample_buffer_offset,
-+ (u8 *)&fifo_data[0],
-+ current_fifo_buffer_offset_bytes);
-+
-+#ifdef BMC150_BMI232_DEBUG_EN
-+ /* The following is code only used for debugging */
-+ u16 timestamp = 0;
-+ if (time_avail) {
-+ memcpy((u8 *)&timestamp,
-+ (const u8
-+ *)(&fifo_data
-+ [current_fifo_buffer_offset_bytes]),
-+ 2);
-+ current_fifo_buffer_offset_bytes += 2;
-+ }
-+
-+ u16 *debg = (u16 *)&temp_data[0];
-+ if (!time_avail) {
-+ printk(KERN_WARNING
-+ "bmi323 pushing to buffer %d/%d -- accel: %d %d %d gyro: %d %d %d",
-+ (int)(f + 1), (int)available_frame_aggregates,
-+ (int)(*((s16 *)&debg[0])),
-+ (int)(*((s16 *)&debg[1])),
-+ (int)(*((s16 *)&debg[2])),
-+ (int)(*((s16 *)&debg[3])),
-+ (int)(*((s16 *)&debg[4])),
-+ (int)(*((s16 *)&debg[5])));
-+ } else {
-+ printk(KERN_WARNING
-+ "bmi323 pushing to buffer %d/%d -- time: %d accel: %d %d %d gyro: %d %d %d",
-+ (int)(f + 1), (int)available_frame_aggregates,
-+ (int)timestamp, (int)(*((s16 *)&debg[0])),
-+ (int)(*((s16 *)&debg[1])),
-+ (int)(*((s16 *)&debg[2])),
-+ (int)(*((s16 *)&debg[3])),
-+ (int)(*((s16 *)&debg[4])),
-+ (int)(*((s16 *)&debg[5])));
-+ }
-+#endif
-+
-+ iio_push_to_buffers_with_timestamp(
-+ indio_dev, &temp_data[0],
-+ first_sample_timestamp_ns +
-+ (fifo_frame_time_ns * (s64)j));
-+ }
-+
-+bmi323_irq_done:
-+ mutex_unlock(&indio_data->bmi323.mutex);
-+
-+ /*
-+ * Tell the core we are done with this trigger and ready for the
-+ * next one.
-+ */
-+ iio_trigger_notify_done(indio_dev->trig);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+int bmi323_set_trigger_state(struct iio_trigger *trig, bool state)
-+{
-+ return 0;
-+}
-+
-+/*
-+// The following is meant to be used in a IRQ-enabled hardware
-+static const struct iio_trigger_ops time_trigger_ops = {
-+ .set_trigger_state = &bmi323_set_trigger_state,
-+ //.reenable = NULL,
-+ .validate_device = &iio_trigger_validate_own_device,
-+};
-+*/
-+
-+/*
-+ * A very basic scan mask: everything can work in conjunction with everything else so no need to worry about
-+ * managing conbinations of mutually exclusive data sources...
-+ */
-+static const unsigned long bmi323_accel_scan_masks[] = {
-+ BIT(BMI323_ACCEL_AXIS_X) | BIT(BMI323_ACCEL_AXIS_Y) |
-+ BIT(BMI323_ACCEL_AXIS_Z) | BIT(BMI323_GYRO_AXIS_X) |
-+ BIT(BMI323_GYRO_AXIS_Y) |
-+ BIT(BMI323_GYRO_AXIS_Z) /*| BIT(BMI323_TEMP)*/,
-+ 0
-+};
-+
-+int bmi323_iio_init(struct iio_dev *indio_dev)
-+{
-+ struct bmc150_accel_data *data = iio_priv(indio_dev);
-+ struct irq_data *irq_desc = NULL;
-+
-+ if (data->bmi323.i2c_client != NULL) {
-+ data->bmi323.dev = &data->bmi323.i2c_client->dev;
-+ } else if (data->bmi323.spi_client != NULL) {
-+ data->bmi323.dev = &data->bmi323.spi_client->dev;
-+ } else {
-+ return -ENODEV;
-+ }
-+
-+ int ret = 0;
-+
-+ /* change to 8 for a default 200Hz sampling rate */
-+ const int gyr_odr_conf_idx = 7;
-+ const int acc_odr_conf_idx = 7;
-+
-+ mutex_init(&data->bmi323.mutex);
-+
-+ data->bmi323.acc_odr_time_ns =
-+ bmi323_accel_odr_map[acc_odr_conf_idx].time_ns;
-+ data->bmi323.gyr_odr_time_ns =
-+ bmi323_gyro_odr_map[gyr_odr_conf_idx].time_ns;
-+
-+ // FIFO enabled for gyro, accel and temp. Overwrite older samples.
-+ data->bmi323.fifo_conf_reg_value = cpu_to_le16((u16)0x0F00U);
-+ //data->bmi323.fifo_conf_reg_value = cpu_to_le16((u16)0x0E00U);
-+ //data->bmi323.fifo_conf_reg_value = cpu_to_le16((u16)0x0600U); // working
-+
-+ // now set the (default) normal mode...
-+ // normal mode: 0x4000
-+ // no averaging: 0x0000
-+ data->bmi323.acc_conf_reg_value = cpu_to_le16(
-+ 0x4000 | ((u16)BMC150_BMI323_ACCEL_RANGE_2_VAL << (u16)4U) |
-+ ((u16)bmi323_accel_odr_map[acc_odr_conf_idx].hw_val));
-+
-+ // now set the (default) normal mode...
-+ // normal mode: 0x4000
-+ // no averaging: 0x0000
-+ // filtering to ODR/2: 0x0000
-+ data->bmi323.gyr_conf_reg_value = cpu_to_le16(
-+ 0x4000 | ((u16)BMC150_BMI323_GYRO_RANGE_125_VAL << (u16)4U) |
-+ ((u16)bmi323_gyro_odr_map[gyr_odr_conf_idx].hw_val));
-+
-+ // the datasheet states that FIFO buffer MUST be enabled before enabling any sensor
-+ ret = bmi323_write_u16(&data->bmi323, BMC150_BMI323_FIFO_CONF_REG,
-+ data->bmi323.fifo_conf_reg_value);
-+ if (ret != 0) {
-+ return -1;
-+ }
-+
-+ ret = bmi323_write_u16(&data->bmi323, BMC150_BMI323_ACC_CONF_REG,
-+ data->bmi323.acc_conf_reg_value);
-+ if (ret != 0) {
-+ return -1;
-+ }
-+
-+ ret = bmi323_write_u16(&data->bmi323, BMC150_BMI323_GYR_CONF_REG,
-+ data->bmi323.gyr_conf_reg_value);
-+ if (ret != 0) {
-+ return -2;
-+ }
-+
-+ indio_dev->channels = bmi323_channels;
-+ indio_dev->num_channels = ARRAY_SIZE(bmi323_channels);
-+ indio_dev->name = "bmi323";
-+ indio_dev->available_scan_masks = bmi323_accel_scan_masks;
-+ indio_dev->modes = INDIO_DIRECT_MODE;
-+ indio_dev->info = &bmi323_accel_info;
-+ indio_dev->label = "bmi323-accel_base";
-+
-+ if (data->bmi323.irq > 0) {
-+ dev_info(data->bmi323.dev, "IRQ pin reported as connected: %d",
-+ data->bmi323.irq);
-+
-+ irq_desc = irq_get_irq_data(data->bmi323.irq);
-+ if (!irq_desc) {
-+ dev_err(data->bmi323.dev,
-+ "Could not find IRQ %d. ignoring it.\n",
-+ data->bmi323.irq);
-+ goto bmi323_iio_init_missing_irq_pin;
-+ }
-+
-+ //data->bmi323.trig[0] = devm_iio_trigger_alloc(data->bmi323.dev, "trig-fifo_full-%s-%d", indio_dev->name, iio_device_id(indio_dev));
-+ //if (data->bmi323.trig[0] == NULL) {
-+ // ret = -ENOMEM;
-+ // goto bmi323_iio_init_err_trigger_unregister;
-+ //}
-+ //
-+ //data->bmi323.trig[0]->ops = &time_trigger_ops;
-+ //iio_trigger_set_drvdata(data->bmi323.trig[0], indio_dev);
-+ //ret = devm_iio_trigger_register(data->bmi323.dev, data->bmi323.trig[0]);
-+ //if (ret) {
-+ // dev_err(data->bmi323.dev, "iio trigger register failed\n");
-+ // goto bmi323_iio_init_err_trigger_unregister;
-+ //}
-+
-+ /*
-+ * register triggers BEFORE buffer setup so that they are cleared
-+ * on emergence exit by bmi323_iio_init_err_trigger_unregister.
-+ *
-+ * This is just a placeholder until I can get my hands on a bmi323
-+ * device that has the IRQ pin actually connected to the CPU.
-+ */
-+
-+ /* here resume operation with the module part common to irq and non-irq enabled code. */
-+ goto bmi323_iio_init_common_irq_and_not_irq;
-+ }
-+
-+bmi323_iio_init_missing_irq_pin:
-+ dev_info(
-+ data->bmi323.dev,
-+ "IRQ pin NOT connected (irq=%d). Will continue normally without triggers.",
-+ data->bmi323.irq);
-+
-+bmi323_iio_init_common_irq_and_not_irq:
-+
-+ /* Once orientation matrix is implemented switch this to iio_triggered_buffer_setup_ext. */
-+ ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
-+ iio_bmi323_trigger_h,
-+ &bmi323_buffer_ops);
-+ if (ret < 0) {
-+ dev_err(data->bmi323.dev,
-+ "Failed: iio triggered buffer setup: %d\n", ret);
-+ goto bmi323_iio_init_err_trigger_unregister;
-+ }
-+
-+ ret = pm_runtime_set_active(data->bmi323.dev);
-+ if (ret) {
-+ dev_err(data->bmi323.dev,
-+ "bmi323 unable to initialize runtime PD: pm_runtime_set_active returned %d\n",
-+ ret);
-+ goto bmi323_iio_init_err_buffer_cleanup;
-+ }
-+
-+ pm_runtime_enable(data->bmi323.dev);
-+ pm_runtime_set_autosuspend_delay(data->bmi323.dev,
-+ BMC150_BMI323_AUTO_SUSPEND_DELAY_MS);
-+ pm_runtime_use_autosuspend(data->bmi323.dev);
-+
-+ ret = iio_device_register(indio_dev);
-+ if (ret < 0) {
-+ dev_err(data->bmi323.dev,
-+ "bmi323 unable to register iio device: %d\n", ret);
-+ goto bmi323_iio_init_err_pm_cleanup;
-+ }
-+
-+ return 0;
-+
-+bmi323_iio_init_err_pm_cleanup:
-+ pm_runtime_dont_use_autosuspend(data->bmi323.dev);
-+ pm_runtime_disable(data->bmi323.dev);
-+bmi323_iio_init_err_buffer_cleanup:
-+ iio_triggered_buffer_cleanup(indio_dev);
-+bmi323_iio_init_err_trigger_unregister:
-+ /*
-+ * unregister triggers if they have been setup already.
-+ * iio_trigger_unregister shall be used in that regard.
-+ *
-+ * This is just a placeholder until I can get my hands on a bmi323
-+ * device that has the IRQ pin actually connected to the CPU.
-+ */
-+ //if (data->bmi323.trig[0] != NULL) {
-+ // iio_trigger_unregister(data->bmi323.trig[0]);
-+ //}
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL_NS_GPL(bmi323_iio_init, IIO_BMC150);
-+
-+void bmi323_iio_deinit(struct iio_dev *indio_dev)
-+{
-+ struct bmc150_accel_data *data = iio_priv(indio_dev);
-+ struct device *dev = bmi323_get_managed_device(&data->bmi323);
-+
-+ iio_device_unregister(indio_dev);
-+
-+ pm_runtime_disable(dev);
-+ pm_runtime_set_suspended(dev);
-+ pm_runtime_put_noidle(dev);
-+
-+ iio_triggered_buffer_cleanup(indio_dev);
-+
-+ //iio_device_free(indio_dev); // this isn't done in the bmg160 driver nor in other drivers so I guess I shouldn't do it too
-+
-+ mutex_unlock(&data->bmi323.mutex);
-+ bmi323_chip_rst(&data->bmi323);
-+ mutex_unlock(&data->bmi323.mutex);
-+}
-+EXPORT_SYMBOL_NS_GPL(bmi323_iio_deinit, IIO_BMC150);
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int bmc150_accel_suspend(struct device *dev)
- {
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct bmc150_accel_data *data = iio_priv(indio_dev);
-
-+ if (data->dev_type == BMI323) {
-+ int ret;
-+
-+ //dev_warn(dev, "bmi323 suspending driver...");
-+
-+ // here push the register GYRO & ACCEL configuration and issue a reset so that chip goes to sleep mode (the default one after a reset)
-+ mutex_unlock(&data->bmi323.mutex);
-+
-+ ret = bmi323_chip_rst(&data->bmi323);
-+ mutex_unlock(&data->bmi323.mutex);
-+ if (ret != 0) {
-+ dev_err(dev,
-+ "bmi323 error in suspend on bmi323_chip_rst: %d\n",
-+ ret);
-+ data->bmi323.flags |= BMI323_FLAGS_RESET_FAILED;
-+ return -EAGAIN;
-+ }
-+
-+ return 0;
-+ }
-+
- mutex_lock(&data->mutex);
- bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
- mutex_unlock(&data->mutex);
-@@ -1844,6 +4005,63 @@ static int bmc150_accel_resume(struct device *dev)
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct bmc150_accel_data *data = iio_priv(indio_dev);
-
-+ if (data->dev_type == BMI323) {
-+ int ret;
-+
-+ //dev_warn(dev, "bmi323 resuming driver...");
-+
-+ // here pop the register GYRO & ACCEL configuration and issue a reset so that chip goes to sleep mode (the default one after a reset)
-+ mutex_lock(&data->bmi323.mutex);
-+
-+ // this was done already in runtime_sleep function.
-+ if ((data->bmi323.flags & BMI323_FLAGS_RESET_FAILED) != 0x00U) {
-+ ret = bmi323_chip_rst(&data->bmi323);
-+ if (ret == 0) {
-+ data->bmi323.flags &=
-+ ~BMI323_FLAGS_RESET_FAILED;
-+ } else {
-+ goto bmi323_bmc150_accel_resume_terminate;
-+ }
-+ }
-+
-+ ret = bmi323_write_u16(&data->bmi323,
-+ BMC150_BMI323_FIFO_CONF_REG,
-+ data->bmi323.fifo_conf_reg_value);
-+ if (ret != 0) {
-+ goto bmi323_bmc150_accel_resume_terminate;
-+ }
-+
-+ ret = bmi323_write_u16(&data->bmi323,
-+ BMC150_BMI323_GYR_CONF_REG,
-+ data->bmi323.gyr_conf_reg_value);
-+ if (ret != 0) {
-+ goto bmi323_bmc150_accel_resume_terminate;
-+ }
-+
-+ ret = bmi323_write_u16(&data->bmi323,
-+ BMC150_BMI323_ACC_CONF_REG,
-+ data->bmi323.acc_conf_reg_value);
-+ if (ret != 0) {
-+ goto bmi323_bmc150_accel_resume_terminate;
-+ }
-+
-+bmi323_bmc150_accel_resume_terminate:
-+ mutex_unlock(&data->bmi323.mutex);
-+ if (ret != 0) {
-+ return -EAGAIN;
-+ }
-+
-+ /*
-+ * datasheet says "Start-up time": suspend to high performance mode is tipically 30ms,
-+ * however when setting this to 32 or even higher the first reading from the gyro (unlike accel part)
-+ * is actually the (wrong) default value 0x8000 so it is better to sleep a bit longer
-+ * to prevent issues and give time to the sensor to pick up first readings...
-+ */
-+ msleep_interruptible(64);
-+
-+ return 0;
-+ }
-+
- mutex_lock(&data->mutex);
- bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
- bmc150_accel_fifo_set_mode(data);
-@@ -1863,6 +4081,25 @@ static int bmc150_accel_runtime_suspend(struct device *dev)
- struct bmc150_accel_data *data = iio_priv(indio_dev);
- int ret;
-
-+ if (data->dev_type == BMI323) {
-+ //dev_warn(dev, "bmi323 suspending runtime...");
-+
-+ /*
-+ * Every operation requiring this function have the mutex locked already:
-+ * with mutex_lock(&data->bmi323.mutex);
-+ */
-+ ret = bmi323_chip_rst(&data->bmi323);
-+ if (ret != 0) {
-+ dev_err(dev,
-+ "bmi323 error in runtime_suspend on bmi323_chip_rst: %d\n",
-+ ret);
-+ data->bmi323.flags |= BMI323_FLAGS_RESET_FAILED;
-+ return -EAGAIN;
-+ }
-+
-+ return 0;
-+ }
-+
- ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_SUSPEND, 0);
- if (ret < 0)
- return -EAGAIN;
-@@ -1877,6 +4114,70 @@ static int bmc150_accel_runtime_resume(struct device *dev)
- int ret;
- int sleep_val;
-
-+ if (data->dev_type == BMI323) {
-+ //dev_warn(dev, "bmi323 resuming runtime...");
-+
-+ /*
-+ * Every operation requiring this function have the mutex locked already:
-+ * with mutex_lock(&data->bmi323.mutex);
-+ */
-+
-+ // recover from a bad state if it was left that way on reuntime_suspend
-+ if ((data->bmi323.flags & BMI323_FLAGS_RESET_FAILED) != 0x00U) {
-+ ret = bmi323_chip_rst(&data->bmi323);
-+ if (ret == 0) {
-+ data->bmi323.flags &=
-+ ~BMI323_FLAGS_RESET_FAILED;
-+ } else {
-+ goto bmi323_bmc150_accel_runtime_resume_terminate;
-+ }
-+ }
-+
-+ ret = bmi323_write_u16(&data->bmi323,
-+ BMC150_BMI323_FIFO_CONF_REG,
-+ data->bmi323.fifo_conf_reg_value);
-+ if (ret != 0) {
-+ dev_err(dev,
-+ "bmi323 writing to GYR_CONF register failed");
-+ goto bmi323_bmc150_accel_runtime_resume_terminate;
-+ }
-+
-+ ret = bmi323_write_u16(&data->bmi323,
-+ BMC150_BMI323_GYR_CONF_REG,
-+ data->bmi323.gyr_conf_reg_value);
-+ if (ret != 0) {
-+ dev_err(dev,
-+ "bmi323 writing to GYR_CONF register failed");
-+ goto bmi323_bmc150_accel_runtime_resume_terminate;
-+ }
-+
-+ ret = bmi323_write_u16(&data->bmi323,
-+ BMC150_BMI323_ACC_CONF_REG,
-+ data->bmi323.acc_conf_reg_value);
-+ if (ret != 0) {
-+ dev_err(dev,
-+ "bmi323 writing to ACC_CONF register failed");
-+ goto bmi323_bmc150_accel_runtime_resume_terminate;
-+ }
-+
-+bmi323_bmc150_accel_runtime_resume_terminate:
-+ if (ret != 0) {
-+ dev_err(dev,
-+ "bmi323 bmc150_accel_runtime_resume -EAGAIN");
-+ return -EAGAIN;
-+ }
-+
-+ /*
-+ * datasheet says "Start-up time": suspend to high performance mode is tipically 30ms,
-+ * however when setting this to 32 or even higher the first reading from the gyro (unlike accel part)
-+ * is actually the (wrong) default value 0x8000 so it is better to sleep a bit longer
-+ * to prevent issues and give time to the sensor to pick up first readings...
-+ */
-+ msleep_interruptible(64);
-+
-+ return 0;
-+ }
-+
- ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
- if (ret < 0)
- return ret;
-diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
-index ee1ba134ad42..0d6ee304b3e7 100644
---- a/drivers/iio/accel/bmc150-accel-i2c.c
-+++ b/drivers/iio/accel/bmc150-accel-i2c.c
-@@ -173,15 +173,102 @@ static void bmc150_acpi_dual_accel_remove(struct i2c_client *client) {}
-
- static int bmc150_accel_probe(struct i2c_client *client)
- {
-+ int ret;
-+ u8 chip_id_first[4] = { 0x00, 0x00, 0x00, 0x00 };
-+ enum bmc150_device_type dev_type = BMC150;
- const struct i2c_device_id *id = i2c_client_get_device_id(client);
- struct regmap *regmap;
- const char *name = NULL;
- enum bmc150_type type = BOSCH_UNKNOWN;
-+
-+ /* reads 4 bytes (2 dummy + 2 good) from the i2c CHIP_ID device register */
-+ ret = i2c_smbus_read_i2c_block_data(client, 0x00, 4, &chip_id_first[0]);
-+ if (ret != 4) {
-+ dev_info(
-+ &client->dev,
-+ "error checking if the bmc150 is in fact a bmi323: i2c_smbus_read_i2c_block_data = %d: reg = 0x%02x.\n\tIt probably is a bmc150 as correctly reported by the ACPI entry.",
-+ (int)ret, 0x00);
-+ goto bmi150_old_probe;
-+ }
-+
-+ // at this point we have enough data to know what chip we are handling
-+ dev_type = (chip_id_first[2] == 0x43) ? BMI323 : dev_type;
-+
-+ if (dev_type == BMI323) {
-+ dev_warn(
-+ &client->dev,
-+ "bmc323: what the ACPI table reported as a bmc150 is in fact a bmc323\n");
-+
-+ struct iio_dev *indio_dev = devm_iio_device_alloc(
-+ &client->dev, sizeof(struct bmc150_accel_data));
-+ if (!indio_dev) {
-+ dev_err(&client->dev,
-+ "bmc323 init process failed: out of memory\n");
-+
-+ return -ENOMEM;
-+ }
-+
-+ dev_set_drvdata(&client->dev, indio_dev);
-+ struct bmc150_accel_data *data = iio_priv(indio_dev);
-+ data->dev_type = dev_type;
-+
-+ struct bmi323_private_data *bmi323_data = &data->bmi323;
-+ bmi323_data->i2c_client = client;
-+ bmi323_data->spi_client = NULL;
-+ bmi323_data->irq = client->irq;
-+
-+ /*
-+ * VDD is the analog and digital domain voltage supply
-+ * VDDIO is the digital I/O voltage supply
-+ */
-+ bmi323_data->regulators[0].supply = "vdd";
-+ bmi323_data->regulators[1].supply = "vddio";
-+ ret = devm_regulator_bulk_get(
-+ &client->dev, ARRAY_SIZE(bmi323_data->regulators),
-+ bmi323_data->regulators);
-+ if (ret) {
-+ return dev_err_probe(&client->dev, ret,
-+ "failed to get regulators\n");
-+ }
-+
-+ ret = regulator_bulk_enable(ARRAY_SIZE(bmi323_data->regulators),
-+ bmi323_data->regulators);
-+ if (ret) {
-+ iio_device_free(indio_dev);
-+
-+ dev_err(&client->dev,
-+ "failed to enable regulators: %d\n", ret);
-+ return ret;
-+ }
-+
-+ ret = bmi323_chip_rst(bmi323_data);
-+ if (ret != 0) {
-+ dev_err(&client->dev,
-+ "bmc323: error issuing the chip reset: %d\n",
-+ ret);
-+ return ret;
-+ }
-+
-+ dev_info(
-+ &client->dev,
-+ "bmc323: chip reset success: starting the iio subsystem binding\n");
-+
-+ ret = bmi323_iio_init(indio_dev);
-+ if (ret != 0) {
-+ return ret;
-+ }
-+
-+ return 0;
-+ }
-+
-+bmi150_old_probe:
-+ dev_info(&client->dev,
-+ "executing the normal procedure for a bmc150...");
-+
- bool block_supported =
- i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
- i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_I2C_BLOCK);
-- int ret;
-
- regmap = devm_regmap_init_i2c(client, &bmc150_regmap_conf);
- if (IS_ERR(regmap)) {
-@@ -198,7 +285,7 @@ static int bmc150_accel_probe(struct i2c_client *client)
- type, name, block_supported);
- if (ret)
- return ret;
--
-+
- /*
- * The !id check avoids recursion when probe() gets called
- * for the second client.
-@@ -211,6 +298,15 @@ static int bmc150_accel_probe(struct i2c_client *client)
-
- static void bmc150_accel_remove(struct i2c_client *client)
- {
-+ struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
-+ struct bmc150_accel_data *data = iio_priv(indio_dev);
-+
-+ if (data->dev_type == BMI323) {
-+ bmi323_iio_deinit(indio_dev);
-+
-+ return;
-+ }
-+
- bmc150_acpi_dual_accel_remove(client);
-
- bmc150_accel_core_remove(&client->dev);
-diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h
-index 7775c5edaeef..65ec208960df 100644
---- a/drivers/iio/accel/bmc150-accel.h
-+++ b/drivers/iio/accel/bmc150-accel.h
-@@ -8,6 +8,14 @@
- #include <linux/regulator/consumer.h>
- #include <linux/workqueue.h>
-
-+/*
-+ * the bmi323 needs raw access to spi and i2c: I cannot use regmap
-+ * as this device expects i2c writes to be 2 bytes,
-+ * spi reads to be 3 bytes and i2c reads to be 4 bytes.
-+ */
-+#include <linux/i2c.h>
-+#include <linux/spi/spi.h>
-+
- struct regmap;
- struct i2c_client;
- struct bmc150_accel_chip_info;
-@@ -34,6 +42,11 @@ struct bmc150_accel_interrupt {
- atomic_t users;
- };
-
-+enum bmc150_device_type {
-+ BMC150,
-+ BMI323,
-+};
-+
- struct bmc150_accel_trigger {
- struct bmc150_accel_data *data;
- struct iio_trigger *indio_trig;
-@@ -55,6 +68,25 @@ enum bmc150_accel_trigger_id {
- BMC150_ACCEL_TRIGGERS,
- };
-
-+#define BMI323_FLAGS_RESET_FAILED 0x00000001U
-+
-+struct bmi323_private_data {
-+ struct regulator_bulk_data regulators[2];
-+ struct i2c_client *i2c_client;
-+ struct spi_device *spi_client;
-+ struct device *dev; /* pointer at i2c_client->dev or spi_client->dev */
-+ struct mutex mutex;
-+ int irq;
-+ u32 flags;
-+ u16 acc_conf_reg_value;
-+ u16 gyr_conf_reg_value;
-+ u16 fifo_conf_reg_value;
-+ struct iio_trigger *trig[1];
-+ s64 fifo_frame_time_diff_ns;
-+ s64 acc_odr_time_ns;
-+ s64 gyr_odr_time_ns;
-+};
-+
- struct bmc150_accel_data {
- struct regmap *regmap;
- struct regulator_bulk_data regulators[2];
-@@ -83,7 +115,67 @@ struct bmc150_accel_data {
- void (*resume_callback)(struct device *dev);
- struct delayed_work resume_work;
- struct iio_mount_matrix orientation;
--};
-+ enum bmc150_device_type dev_type;
-+ struct bmi323_private_data bmi323;
-+ };
-+
-+/**
-+ * This function performs a write of a u16 little-endian (regardless of CPU architecture) integer
-+ * to a device register. Returns 0 on success or an error code otherwise.
-+ *
-+ * PRE: in_value holds the data to be sent to the sensor, in little endian format even on big endian
-+ * architectures.
-+ *
-+ * NOTE: bmi323->dev can be NULL (not yet initialized) when this function is called
-+ * therefore it is not needed and is not used inside the function
-+ *
-+ * WARNING: this function does not lock any mutex and synchronization MUST be performed by the caller
-+ */
-+int bmi323_write_u16(struct bmi323_private_data *bmi323, u8 in_reg, u16 in_value);
-+
-+/**
-+ * This function performs a read of "good" values from the bmi323 discarding what
-+ * in the datasheet is described as "dummy data": additional useles bytes.
-+ *
-+ * PRE: bmi323 has been partially initialized: i2c_device and spi_devices MUST be set to either
-+ * the correct value or NULL
-+ *
-+ * NOTE: bmi323->dev can be NULL (not yet initialized) when this function is called
-+ * therefore it is not needed and is not used inside the function
-+ *
-+ * POST: on success out_value is written with data from the sensor, as it came out, so the
-+ * content is little-endian even on big endian architectures
-+ *
-+ * WARNING: this function does not lock any mutex and synchronization MUST be performed by the caller
-+ */
-+int bmi323_read_u16(struct bmi323_private_data *bmi323, u8 in_reg, u16* out_value);
-+
-+int bmi323_chip_check(struct bmi323_private_data *bmi323);
-+
-+/**
-+ * Reset the chip in a known state that is ready to accept commands, but is not configured therefore after calling this function
-+ * it is required to load a new configuration to start data acquisition.
-+ *
-+ * PRE: bmi323 has been fully identified and partially initialized
-+ *
-+ * NOTE: after issuing a reset the the chip will be in what it is called "suspended mode" and the feature angine is
-+ * ready to be set. This mode has everything disabled and consumes aroud 15uA.
-+ *
-+ * When removing the driver or suspend has been requested it's best to reset the chip so that power consumption
-+ * will be the lowest possible.
-+ */
-+int bmi323_chip_rst(struct bmi323_private_data *bmi323);
-+
-+/**
-+ * This function MUST be called in probe and is responsible for registering the userspace sysfs.
-+ *
-+ * The indio_dev MUST have been allocated but not registered. This function will perform userspace registration.
-+ *
-+ * @param indio_dev the industrual io device already allocated but not yet registered
-+ */
-+int bmi323_iio_init(struct iio_dev *indio_dev);
-+
-+void bmi323_iio_deinit(struct iio_dev *indio_dev);
-
- int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
- enum bmc150_type type, const char *name,
---
-2.42.0
-
diff --git a/0001-hid-asus-reset-the-backlight-brightness-level-on-resume.patch b/0001-hid-asus-reset-the-backlight-brightness-level-on-resume.patch
deleted file mode 100644
index 59698ca0f7cc..000000000000
--- a/0001-hid-asus-reset-the-backlight-brightness-level-on-resume.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From ca054bb924b349c586d783e4473c4cab404c40a1 Mon Sep 17 00:00:00 2001
-From: Denis Benato <benato.denis96@gmail.com>
-Date: Fri, 17 Nov 2023 14:15:56 +1300
-Subject: [PATCH] HID: hid-asus: reset the backlight brightness level on resume
-
-Some devices managed by this driver automatically set brightness to 0
-before entering a suspended state and reset it back to a default
-brightness level after the resume:
-this has the effect of having the kernel report wrong brightness
-status after a sleep, and on some devices (like the Asus RC71L) that
-brightness is the intensity of LEDs directly facing the user.
-
-Fix the above issue by setting back brightness to the level it had
-before entering a sleep state.
-
-Signed-off-by: Denis Benato <benato.denis96@gmail.com>
-Signed-off-by: Luke D. Jones <luke@ljones.dev>
-Signed-off-by: Jiri Kosina <jkosina@suse.cz>
----
- drivers/hid/hid-asus.c | 19 +++++++++++++++++++
- 1 file changed, 19 insertions(+)
-
-diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
-index b70673a929a1ed..78cdfb8b9a7aeb 100644
---- a/drivers/hid/hid-asus.c
-+++ b/drivers/hid/hid-asus.c
-@@ -1000,6 +1000,24 @@ static int asus_start_multitouch(struct hid_device *hdev)
- return 0;
- }
-
-+static int __maybe_unused asus_resume(struct hid_device *hdev) {
-+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
-+ int ret = 0;
-+
-+ if (drvdata->kbd_backlight) {
-+ const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4,
-+ drvdata->kbd_backlight->cdev.brightness };
-+ ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
-+ if (ret < 0) {
-+ hid_err(hdev, "Asus failed to set keyboard backlight: %d\n", ret);
-+ goto asus_resume_err;
-+ }
-+ }
-+
-+asus_resume_err:
-+ return ret;
-+}
-+
- static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
- {
- struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
-@@ -1294,6 +1312,7 @@ static struct hid_driver asus_driver = {
- .input_configured = asus_input_configured,
- #ifdef CONFIG_PM
- .reset_resume = asus_reset_resume,
-+ .resume = asus_resume,
- #endif
- .event = asus_event,
- .raw_event = asus_raw_event
diff --git a/0001-iio-imu_Add_driver_for_BMI323_IMU.patch b/0001-iio-imu_Add_driver_for_BMI323_IMU.patch
new file mode 100644
index 000000000000..bf53ac8652ef
--- /dev/null
+++ b/0001-iio-imu_Add_driver_for_BMI323_IMU.patch
@@ -0,0 +1,2810 @@
+Add devicetree description document for Bosch BMI323, a 6-Axis IMU.
+
+Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+---
+ .../bindings/iio/imu/bosch,bmi323.yaml | 77 +++++++++++++++++++
+ 1 file changed, 77 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/iio/imu/bosch,bmi323.yaml
+
+diff --git a/Documentation/devicetree/bindings/iio/imu/bosch,bmi323.yaml b/Documentation/devicetree/bindings/iio/imu/bosch,bmi323.yaml
+new file mode 100644
+index 000000000000..64ef26e19669
+--- /dev/null
++++ b/Documentation/devicetree/bindings/iio/imu/bosch,bmi323.yaml
+@@ -0,0 +1,77 @@
++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/iio/imu/bosch,bmi323.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Bosch BMI323 6-Axis IMU
++
++maintainers:
++ - Jagath Jog J <jagathjog1996@gmail.com>
++
++description:
++ BMI323 is a 6-axis inertial measurement unit that supports acceleration and
++ gyroscopic measurements with hardware fifo buffering. Sensor also provides
++ events information such as motion, steps, orientation, single and double
++ tap detection.
++
++properties:
++ compatible:
++ const: bosch,bmi323
++
++ reg:
++ maxItems: 1
++
++ vdd-supply: true
++ vddio-supply: true
++
++ interrupts:
++ minItems: 1
++ maxItems: 2
++
++ interrupt-names:
++ minItems: 1
++ maxItems: 2
++ items:
++ enum:
++ - INT1
++ - INT2
++
++ drive-open-drain:
++ description:
++ set if the specified interrupt pin should be configured as
++ open drain. If not set, defaults to push-pull.
++
++ mount-matrix:
++ description:
++ an optional 3x3 mounting rotation matrix.
++
++required:
++ - compatible
++ - reg
++ - vdd-supply
++ - vddio-supply
++
++allOf:
++ - $ref: /schemas/spi/spi-peripheral-props.yaml#
++
++unevaluatedProperties: false
++
++examples:
++ - |
++ // Example for I2C
++ #include <dt-bindings/interrupt-controller/irq.h>
++ i2c {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ imu@68 {
++ compatible = "bosch,bmi323";
++ reg = <0x68>;
++ vddio-supply = <&vddio>;
++ vdd-supply = <&vdd>;
++ interrupt-parent = <&gpio1>;
++ interrupts = <29 IRQ_TYPE_EDGE_RISING>;
++ interrupt-names = "INT1";
++ };
++ };
+From: Jagath Jog J <jagathjog1996@gmail.com>
+To: jic23@kernel.org, andriy.shevchenko@linux.intel.com,
+ lars@metafoo.de, robh+dt@kernel.org,
+ krzysztof.kozlowski+dt@linaro.org
+Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org,
+ linux-kernel@vger.kernel.org
+Subject: [RFC 2/2] iio: imu: Add driver for BMI323 IMU
+Date: Mon, 18 Sep 2023 13:33:14 +0530 [thread overview]
+Message-ID: <20230918080314.11959-3-jagathjog1996@gmail.com> (raw)
+In-Reply-To: <20230918080314.11959-1-jagathjog1996@gmail.com>
+
+The Bosch BMI323 is a 6-axis low-power IMU that provide measurements for
+acceleration, angular rate, and temperature. This sensor includes
+motion-triggered interrupt features, such as a step counter, tap detection,
+and activity/inactivity interrupt capabilities.
+
+The driver supports various functionalities, including data ready, FIFO
+data handling, and events such as tap detection, step counting, and
+activity interrupts.
+
+Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
+---
+ MAINTAINERS | 7 +
+ drivers/iio/imu/Kconfig | 1 +
+ drivers/iio/imu/Makefile | 1 +
+ drivers/iio/imu/bmi323/Kconfig | 33 +
+ drivers/iio/imu/bmi323/Makefile | 7 +
+ drivers/iio/imu/bmi323/bmi323.h | 209 +++
+ drivers/iio/imu/bmi323/bmi323_core.c | 2139 +++++++++++++++++++++++
+ drivers/iio/imu/bmi323/bmi323_i2c.c | 121 ++
+ drivers/iio/imu/bmi323/bmi323_spi.c | 92 +
+ 10 files changed, 2628 insertions(+)
+ create mode 100644 drivers/iio/imu/bmi323/Kconfig
+ create mode 100644 drivers/iio/imu/bmi323/Makefile
+ create mode 100644 drivers/iio/imu/bmi323/bmi323.h
+ create mode 100644 drivers/iio/imu/bmi323/bmi323_core.c
+ create mode 100644 drivers/iio/imu/bmi323/bmi323_i2c.c
+ create mode 100644 drivers/iio/imu/bmi323/bmi323_spi.c
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 4e07c032d06a..47ca415212a7 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3595,6 +3595,13 @@ S: Maintained
+ F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml
+ F: drivers/iio/accel/bma400*
+
++BOSCH SENSORTEC BMI323 IMU IIO DRIVER
++M: Jagath Jog J <jagathjog1996@gmail.com>
++L: linux-iio@vger.kernel.org
++S: Maintained
++F: Documentation/devicetree/bindings/iio/imu/bosch,bma400.yaml
++F: drivers/iio/imu/bmi323/
++
+ BPF JIT for ARM
+ M: Shubham Bansal <illusionist.neo@gmail.com>
+ L: bpf@vger.kernel.org
+diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
+index c2f97629e9cd..6c9a85294bc1 100644
+--- a/drivers/iio/imu/Kconfig
++++ b/drivers/iio/imu/Kconfig
+@@ -54,6 +54,7 @@ config ADIS16480
+
+ source "drivers/iio/imu/bmi160/Kconfig"
+ source "drivers/iio/imu/bno055/Kconfig"
++source "drivers/iio/imu/bmi323/Kconfig"
+
+ config FXOS8700
+ tristate
+diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
+index 6eb612034722..627406476357 100644
+--- a/drivers/iio/imu/Makefile
++++ b/drivers/iio/imu/Makefile
+@@ -16,6 +16,7 @@ obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
+
+ obj-y += bmi160/
+ obj-y += bno055/
++obj-y += bmi323/
+
+ obj-$(CONFIG_FXOS8700) += fxos8700_core.o
+ obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o
+diff --git a/drivers/iio/imu/bmi323/Kconfig b/drivers/iio/imu/bmi323/Kconfig
+new file mode 100644
+index 000000000000..ab37b285393c
+--- /dev/null
++++ b/drivers/iio/imu/bmi323/Kconfig
+@@ -0,0 +1,33 @@
++# SPDX-License-Identifier: GPL-2.0
++#
++# BMI323 IMU driver
++#
++
++config BMI323
++ tristate
++ select IIO_BUFFER
++ select IIO_TRIGGERED_BUFFER
++
++config BMI323_I2C
++ tristate "Bosch BMI323 I2C driver"
++ depends on I2C
++ select BMI323
++ select REGMAP_I2C
++ help
++ Enable support for the Bosch BMI323 6-Axis IMU connected to I2C
++ interface.
++
++ This driver can also be built as a module. If so, the module will be
++ called bmi323_i2c.
++
++config BMI323_SPI
++ tristate "Bosch BMI323 SPI driver"
++ depends on SPI
++ select BMI323
++ select REGMAP_SPI
++ help
++ Enable support for the Bosch BMI323 6-Axis IMU connected to SPI
++ interface.
++
++ This driver can also be built as a module. If so, the module will be
++ called bmi323_spi.
+diff --git a/drivers/iio/imu/bmi323/Makefile b/drivers/iio/imu/bmi323/Makefile
+new file mode 100644
+index 000000000000..a6a6dc0207c9
+--- /dev/null
++++ b/drivers/iio/imu/bmi323/Makefile
+@@ -0,0 +1,7 @@
++# SPDX-License-Identifier: GPL-2.0
++#
++# Makefile for Bosch BMI323 IMU
++#
++obj-$(CONFIG_BMI323) += bmi323_core.o
++obj-$(CONFIG_BMI323_I2C) += bmi323_i2c.o
++obj-$(CONFIG_BMI323_SPI) += bmi323_spi.o
+diff --git a/drivers/iio/imu/bmi323/bmi323.h b/drivers/iio/imu/bmi323/bmi323.h
+new file mode 100644
+index 000000000000..dff126d41658
+--- /dev/null
++++ b/drivers/iio/imu/bmi323/bmi323.h
+@@ -0,0 +1,209 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * IIO driver for Bosch BMI323 6-Axis IMU
++ *
++ * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com>
++ */
++
++#ifndef _BMI323_H_
++#define _BMI323_H_
++
++#include <linux/bits.h>
++#include <linux/regmap.h>
++#include <linux/units.h>
++
++#define BMI323_I2C_DUMMY 2
++#define BMI323_SPI_DUMMY 1
++
++/* Register map */
++
++#define BMI323_CHIP_ID_REG 0x00
++#define BMI323_CHIP_ID_VAL 0x0043
++#define BMI323_CHIP_ID_MSK GENMASK(7, 0)
++#define BMI323_ERR_REG 0x01
++#define BMI323_STATUS_REG 0x02
++#define BMI323_STATUS_POR_MSK BIT(0)
++
++/* Accelero/Gyro/Temp data registers */
++#define BMI323_ACCEL_X_REG 0x03
++#define BMI323_GYRO_X_REG 0x06
++#define BMI323_TEMP_REG 0x09
++#define BMI323_ALL_CHAN_MSK GENMASK(5, 0)
++
++/* Status registers */
++#define BMI323_STATUS_INT1_REG 0x0D
++#define BMI323_STATUS_INT2_REG 0x0E
++#define BMI323_STATUS_NOMOTION_MSK BIT(0)
++#define BMI323_STATUS_MOTION_MSK BIT(1)
++#define BMI323_STATUS_STP_WTR_MSK BIT(5)
++#define BMI323_STATUS_TAP_MSK BIT(8)
++#define BMI323_STATUS_ERROR_MSK BIT(10)
++#define BMI323_STATUS_TMP_DRDY_MSK BIT(11)
++#define BMI323_STATUS_GYR_DRDY_MSK BIT(12)
++#define BMI323_STATUS_ACC_DRDY_MSK BIT(13)
++#define BMI323_STATUS_ACC_GYR_DRDY_MSK GENMASK(13, 12)
++#define BMI323_STATUS_FIFO_WTRMRK_MSK BIT(14)
++#define BMI323_STATUS_FIFO_FULL_MSK BIT(15)
++
++/* Feature registers */
++#define BMI323_FEAT_IO0_REG 0x10
++#define BMI323_FEAT_IO0_XYZ_NOMOTION_MSK GENMASK(2, 0)
++#define BMI323_FEAT_IO0_XYZ_MOTION_MSK GENMASK(5, 3)
++#define BMI323_FEAT_XYZ_MSK GENMASK(2, 0)
++#define BMI323_FEAT_IO0_STP_CNT_MSK BIT(9)
++#define BMI323_FEAT_IO0_S_TAP_MSK BIT(12)
++#define BMI323_FEAT_IO0_D_TAP_MSK BIT(13)
++#define BMI323_FEAT_IO1_REG 0x11
++#define BMI323_FEAT_IO1_ERR_MSK GENMASK(3, 0)
++#define BMI323_FEAT_IO2_REG 0x12
++#define BMI323_FEAT_IO_STATUS_REG 0x14
++#define BMI323_FEAT_IO_STATUS_MSK BIT(0)
++#define BMI323_FEAT_ENG_POLL 2000
++#define BMI323_FEAT_ENG_TIMEOUT 10000
++
++/* FIFO registers */
++#define BMI323_FIFO_FILL_LEVEL_REG 0x15
++#define BMI323_FIFO_DATA_REG 0x16
++
++/* Accelero/Gyro config registers */
++#define BMI323_ACC_CONF_REG 0x20
++#define BMI323_GYRO_CONF_REG 0x21
++#define BMI323_ACC_GYRO_CONF_MODE_MSK GENMASK(14, 12)
++#define BMI323_ACC_GYRO_CONF_ODR_MSK GENMASK(3, 0)
++#define BMI323_ACC_GYRO_CONF_SCL_MSK GENMASK(6, 4)
++#define BMI323_ACC_GYRO_CONF_BW_MSK BIT(7)
++#define BMI323_ACC_GYRO_CONF_AVG_MSK GENMASK(10, 8)
++
++/* FIFO registers */
++#define BMI323_FIFO_WTRMRK_REG 0x35
++#define BMI323_FIFO_CONF_REG 0x36
++#define BMI323_FIFO_CONF_STP_FUL_MSK BIT(0)
++#define BMI323_FIFO_CONF_ACC_GYR_EN_MSK GENMASK(10, 9)
++#define BMI323_FIFO_ACC_GYR_MSK GENMASK(1, 0)
++#define BMI323_FIFO_CTRL_REG 0x37
++#define BMI323_FIFO_FLUSH_MSK BIT(0)
++
++/* Interrupt pin config registers */
++#define BMI323_IO_INT_CTR_REG 0x38
++#define BMI323_IO_INT1_LVL_MSK BIT(0)
++#define BMI323_IO_INT1_OD_MSK BIT(1)
++#define BMI323_IO_INT1_OP_EN_MSK BIT(2)
++#define BMI323_IO_INT1_LVL_OD_OP_MSK GENMASK(2, 0)
++#define BMI323_IO_INT2_LVL_MSK BIT(8)
++#define BMI323_IO_INT2_OD_MSK BIT(9)
++#define BMI323_IO_INT2_OP_EN_MSK BIT(10)
++#define BMI323_IO_INT2_LVL_OD_OP_MSK GENMASK(10, 8)
++#define BMI323_IO_INT_CONF_REG 0x39
++#define BMI323_IO_INT_LTCH_MSK BIT(0)
++#define BMI323_INT_MAP1_REG 0x3A
++#define BMI323_INT_MAP2_REG 0x3B
++#define BMI323_NOMOTION_MSK GENMASK(1, 0)
++#define BMI323_MOTION_MSK GENMASK(3, 2)
++#define BMI323_STEP_CNT_MSK GENMASK(11, 10)
++#define BMI323_TAP_MSK GENMASK(1, 0)
++#define BMI323_TMP_DRDY_MSK GENMASK(7, 6)
++#define BMI323_GYR_DRDY_MSK GENMASK(9, 8)
++#define BMI323_ACC_DRDY_MSK GENMASK(11, 10)
++#define BMI323_FIFO_WTRMRK_MSK GENMASK(13, 12)
++#define BMI323_FIFO_FULL_MSK GENMASK(15, 14)
++
++/* Feature registers */
++#define BMI323_FEAT_CTRL_REG 0x40
++#define BMI323_FEAT_ENG_EN_MSK BIT(0)
++#define BMI323_FEAT_DATA_ADDR 0x41
++#define BMI323_FEAT_DATA_TX 0x42
++#define BMI323_FEAT_DATA_STATUS 0x43
++#define BMI323_FEAT_DATA_TX_RDY_MSK BIT(1)
++#define BMI323_FEAT_EVNT_EXT_REG 0x47
++#define BMI323_FEAT_EVNT_EXT_S_MSK BIT(3)
++#define BMI323_FEAT_EVNT_EXT_D_MSK BIT(4)
++
++#define BMI323_CMD_REG 0x7E
++#define BMI323_RST_VAL 0xDEAF
++#define BMI323_CFG_RES_REG 0x7F
++
++/* Extended registers */
++#define BMI323_GEN_SET1_REG 0x02
++#define BMI323_GEN_SET1_MODE_MSK BIT(0)
++#define BMI323_GEN_HOLD_DUR_MSK GENMASK(4, 1)
++
++/* Any Motion/No Motion config registers */
++#define BMI323_ANYMO1_REG 0x05
++#define BMI323_NOMO1_REG 0x08
++#define BMI323_MO2_OFFSET 0x01
++#define BMI323_MO3_OFFSET 0x02
++#define BMI323_MO1_REF_UP_MSK BIT(12)
++#define BMI323_MO1_SLOPE_TH_MSK GENMASK(11, 0)
++#define BMI323_MO2_HYSTR_MSK GENMASK(9, 0)
++#define BMI323_MO3_DURA_MSK GENMASK(12, 0)
++
++/* Step counter config registers */
++#define BMI323_STEP_SC1_REG 0x10
++#define BMI323_STEP_SC1_WTRMRK_MSK GENMASK(9, 0)
++#define BMI323_STEP_SC1_RST_CNT_MSK BIT(10)
++#define BMI323_STEP_SC1_REG 0x10
++#define BMI323_STEP_LEN 2
++
++/* Tap gesture config registers */
++#define BMI323_TAP1_REG 0x1E
++#define BMI323_TAP1_AXIS_SEL_MSK GENMASK(1, 0)
++#define BMI323_AXIS_XYZ_MSK GENMASK(1, 0)
++#define BMI323_TAP1_TIMOUT_MSK BIT(2)
++#define BMI323_TAP1_MAX_PEAKS_MSK GENMASK(5, 3)
++#define BMI323_TAP1_MODE_MSK GENMASK(7, 6)
++#define BMI323_TAP2_REG 0x1F
++#define BMI323_TAP2_THRES_MSK GENMASK(9, 0)
++#define BMI323_TAP2_MAX_DUR_MSK GENMASK(15, 10)
++#define BMI323_TAP3_REG 0x20
++#define BMI323_TAP3_QUIET_TIM_MSK GENMASK(15, 12)
++#define BMI323_TAP3_QT_BW_TAP_MSK GENMASK(11, 8)
++#define BMI323_TAP3_QT_AFT_GES_MSK GENMASK(15, 12)
++
++#define BMI323_MOTION_THRES_SCALE 512
++#define BMI323_MOTION_HYSTR_SCALE 512
++#define BMI323_MOTION_DURAT_SCALE 50
++#define BMI323_TAP_THRES_SCALE 512
++#define BMI323_DUR_BW_TAP_SCALE 200
++#define BMI323_QUITE_TIM_GES_SCALE 25
++#define BMI323_MAX_GES_DUR_SCALE 25
++
++/*
++ * The formula to calculate temperature in C.
++ * See datasheet section 6.1.1, Register Map Overview
++ *
++ * T_C = (temp_raw / 512) + 23
++ */
++#define BMI323_TEMP_OFFSET 11776
++#define BMI323_TEMP_SCALE 1953125
++
++/*
++ * The BMI323 features a FIFO with a capacity of 2048 bytes. Each frame
++ * consists of accelerometer (X, Y, Z) data and gyroscope (X, Y, Z) data,
++ * totaling 6 words or 12 bytes. The FIFO buffer can hold a total of
++ * 170 frames.
++ *
++ * If a watermark interrupt is configured for 170 frames, the interrupt will
++ * trigger when the FIFO reaches 169 frames, so limit the maximum watermark
++ * level to 169 frames. In terms of data, 169 frames would equal 1014 bytes,
++ * which is approximately 2 frames before the FIFO reaches its full capacity.
++ * See datasheet section 5.7.3 FIFO Buffer Interrupts
++ */
++#define BMI323_BYTES_PER_SAMPLE 2
++#define BMI323_FIFO_LENGTH_IN_BYTES 2048
++#define BMI323_FIFO_FRAME_LENGTH 6
++#define BMI323_FIFO_FULL_IN_FRAMES \
++ ((BMI323_FIFO_LENGTH_IN_BYTES / \
++ (BMI323_BYTES_PER_SAMPLE * BMI323_FIFO_FRAME_LENGTH)) - 1)
++#define BMI323_FIFO_FULL_IN_WORDS \
++ (BMI323_FIFO_FULL_IN_FRAMES * BMI323_FIFO_FRAME_LENGTH)
++
++#define BMI323_INT_MICRO_TO_RAW(val, val2, scale) ((val) * (scale) + \
++ ((val2) * (scale)) / MEGA)
++
++#define BMI323_RAW_TO_MICRO(raw, scale) ((((raw) % (scale)) * MEGA) / scale)
++
++struct device;
++int bmi323_core_probe(struct device *dev);
++extern const struct regmap_config bmi323_regmap_config;
++
++#endif
+diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c
+new file mode 100644
+index 000000000000..0bd5dedd9a63
+--- /dev/null
++++ b/drivers/iio/imu/bmi323/bmi323_core.c
+@@ -0,0 +1,2139 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * IIO core driver for Bosch BMI323 6-Axis IMU.
++ *
++ * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com>
++ *
++ * Datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi323-ds000.pdf
++ */
++
++#include <linux/bitfield.h>
++#include <linux/cleanup.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/minmax.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/property.h>
++#include <linux/regmap.h>
++#include <linux/regulator/consumer.h>
++#include <linux/units.h>
++
++#include <asm/unaligned.h>
++
++#include <linux/iio/buffer.h>
++#include <linux/iio/events.h>
++#include <linux/iio/iio.h>
++#include <linux/iio/sysfs.h>
++#include <linux/iio/trigger.h>
++#include <linux/iio/trigger_consumer.h>
++#include <linux/iio/triggered_buffer.h>
++
++#include "bmi323.h"
++
++enum bmi323_sensor_type {
++ BMI323_ACCEL,
++ BMI323_GYRO,
++ BMI323_SENSORS_CNT,
++};
++
++enum bmi323_opr_mode {
++ ACC_GYRO_MODE_DISABLE = 0x00,
++ GYRO_DRIVE_MODE_ENABLED = 0x01,
++ ACC_GYRO_MODE_DUTYCYCLE = 0x03,
++ ACC_GYRO_MODE_CONTINOUS = 0x04,
++ ACC_GYRO_MODE_HIGH_PERF = 0x07,
++};
++
++enum bmi323_state {
++ BMI323_IDLE,
++ BMI323_BUFFER_DRDY_TRIGGERED,
++ BMI323_BUFFER_FIFO,
++};
++
++enum bmi323_irq_pin {
++ BMI323_IRQ_DISABLED,
++ BMI323_IRQ_INT1,
++ BMI323_IRQ_INT2,
++};
++
++enum bmi323_3db_bw {
++ BMI323_BW_ODR_BY_2,
++ BMI323_BW_ODR_BY_4,
++};
++
++enum bmi323_scan {
++ BMI323_ACCEL_X,
++ BMI323_ACCEL_Y,
++ BMI323_ACCEL_Z,
++ BMI323_GYRO_X,
++ BMI323_GYRO_Y,
++ BMI323_GYRO_Z,
++ BMI323_CHAN_MAX
++};
++
++struct bmi323_hw {
++ u8 data;
++ u8 config;
++ const int (*scale_table)[2];
++ int scale_table_len;
++};
++
++/*
++ * The accelerometer supports +-2G/4G/8G/16G ranges, and the resolution of
++ * each sample is 16 bits, signed.
++ * At +-8G the scale can calculated by
++ * ((8 + 8) * 9.80665 / (2^16 - 1)) * 10^6 = 2394.23819 scale in micro
++ *
++ */
++static const int bmi323_accel_scale[][2] = {
++ { 0, 598 },
++ { 0, 1197 },
++ { 0, 2394 },
++ { 0, 4788 },
++};
++
++static const int bmi323_gyro_scale[][2] = {
++ { 0, 66 },
++ { 0, 133 },
++ { 0, 266 },
++ { 0, 532 },
++ { 0, 1065 },
++};
++
++static const int bmi323_accel_gyro_avrg[] = {0, 2, 4, 8, 16, 32, 64};
++
++static const struct bmi323_hw bmi323_hw[2] = {
++ [BMI323_ACCEL] = {
++ .data = BMI323_ACCEL_X_REG,
++ .config = BMI323_ACC_CONF_REG,
++ .scale_table = bmi323_accel_scale,
++ .scale_table_len = ARRAY_SIZE(bmi323_accel_scale),
++ },
++ [BMI323_GYRO] = {
++ .data = BMI323_GYRO_X_REG,
++ .config = BMI323_GYRO_CONF_REG,
++ .scale_table = bmi323_gyro_scale,
++ .scale_table_len = ARRAY_SIZE(bmi323_gyro_scale),
++ },
++};
++
++struct bmi323_data {
++ struct device *dev;
++ struct regmap *regmap;
++ struct iio_mount_matrix orientation;
++ enum bmi323_irq_pin irq_pin;
++ struct iio_trigger *trig;
++ bool drdy_trigger_enabled;
++ enum bmi323_state state;
++ s64 fifo_tstamp, old_fifo_tstamp;
++ u32 odrns[BMI323_SENSORS_CNT];
++ u32 odrhz[BMI323_SENSORS_CNT];
++ unsigned int feature_events;
++
++ /*
++ * Lock to protect the members of device's private data from concurrent
++ * access and also to serialize the access of extended registers.
++ * See bmi323_write_ext_reg(..) for more info.
++ */
++ struct mutex mutex;
++ int watermark;
++ __le16 fifo_buff[BMI323_FIFO_FULL_IN_WORDS] __aligned(IIO_DMA_MINALIGN);
++ struct {
++ __le16 channels[BMI323_CHAN_MAX];
++ s64 ts __aligned(8);
++ } buffer;
++ __le16 steps_count[BMI323_STEP_LEN];
++};
++
++static const struct iio_mount_matrix *
++bmi323_get_mount_matrix(const struct iio_dev *idev,
++ const struct iio_chan_spec *chan)
++{
++ struct bmi323_data *data = iio_priv(idev);
++
++ return &data->orientation;
++}
++
++static const struct iio_chan_spec_ext_info bmi323_ext_info[] = {
++ IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, bmi323_get_mount_matrix),
++ { }
++};
++
++static const struct iio_event_spec bmi323_step_wtrmrk_event = {
++ .type = IIO_EV_TYPE_CHANGE,
++ .dir = IIO_EV_DIR_NONE,
++ .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
++ BIT(IIO_EV_INFO_VALUE),
++};
++
++static const struct iio_event_spec bmi323_accel_event[] = {
++ {
++ .type = IIO_EV_TYPE_MAG,
++ .dir = IIO_EV_DIR_FALLING,
++ .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
++ BIT(IIO_EV_INFO_PERIOD) |
++ BIT(IIO_EV_INFO_HYSTERESIS) |
++ BIT(IIO_EV_INFO_ENABLE),
++ },
++ {
++ .type = IIO_EV_TYPE_MAG,
++ .dir = IIO_EV_DIR_RISING,
++ .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
++ BIT(IIO_EV_INFO_PERIOD) |
++ BIT(IIO_EV_INFO_HYSTERESIS) |
++ BIT(IIO_EV_INFO_ENABLE),
++ },
++ {
++ .type = IIO_EV_TYPE_GESTURE,
++ .dir = IIO_EV_DIR_SINGLETAP,
++ .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
++ BIT(IIO_EV_INFO_VALUE) |
++ BIT(IIO_EV_INFO_RESET_TIMEOUT),
++ },
++ {
++ .type = IIO_EV_TYPE_GESTURE,
++ .dir = IIO_EV_DIR_DOUBLETAP,
++ .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
++ BIT(IIO_EV_INFO_VALUE) |
++ BIT(IIO_EV_INFO_RESET_TIMEOUT) |
++ BIT(IIO_EV_INFO_TAP2_MIN_DELAY),
++ },
++};
++
++#define BMI323_ACCEL_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) | \
++ BIT(IIO_CHAN_INFO_SCALE) | \
++ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
++ .info_mask_shared_by_type_available = \
++ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
++ BIT(IIO_CHAN_INFO_SCALE) | \
++ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
++ .scan_index = _index, \
++ .scan_type = { \
++ .sign = 's', \
++ .realbits = 16, \
++ .storagebits = 16, \
++ .endianness = IIO_LE, \
++ }, \
++ .ext_info = bmi323_ext_info, \
++ .event_spec = bmi323_accel_event, \
++ .num_event_specs = ARRAY_SIZE(bmi323_accel_event), \
++}
++
++#define BMI323_GYRO_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) | \
++ BIT(IIO_CHAN_INFO_SCALE) | \
++ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
++ .info_mask_shared_by_type_available = \
++ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
++ BIT(IIO_CHAN_INFO_SCALE) | \
++ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
++ .scan_index = _index, \
++ .scan_type = { \
++ .sign = 's', \
++ .realbits = 16, \
++ .storagebits = 16, \
++ .endianness = IIO_LE, \
++ }, \
++ .ext_info = bmi323_ext_info, \
++}
++
++static const struct iio_chan_spec bmi323_channels[] = {
++ BMI323_ACCEL_CHANNEL(IIO_ACCEL, X, BMI323_ACCEL_X),
++ BMI323_ACCEL_CHANNEL(IIO_ACCEL, Y, BMI323_ACCEL_Y),
++ BMI323_ACCEL_CHANNEL(IIO_ACCEL, Z, BMI323_ACCEL_Z),
++ BMI323_GYRO_CHANNEL(IIO_ANGL_VEL, X, BMI323_GYRO_X),
++ BMI323_GYRO_CHANNEL(IIO_ANGL_VEL, Y, BMI323_GYRO_Y),
++ BMI323_GYRO_CHANNEL(IIO_ANGL_VEL, Z, BMI323_GYRO_Z),
++ {
++ .type = IIO_TEMP,
++ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
++ BIT(IIO_CHAN_INFO_OFFSET) |
++ BIT(IIO_CHAN_INFO_SCALE),
++ .scan_index = -1,
++ },
++ {
++ .type = IIO_STEPS,
++ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
++ BIT(IIO_CHAN_INFO_ENABLE),
++ .scan_index = -1,
++ .event_spec = &bmi323_step_wtrmrk_event,
++ .num_event_specs = 1,
++
++ },
++ IIO_CHAN_SOFT_TIMESTAMP(BMI323_CHAN_MAX),
++};
++
++static const int bmi323_acc_gyro_odr[][2] = {
++ { 0, 781250 },
++ { 1, 562500 },
++ { 3, 125000 },
++ { 6, 250000 },
++ { 12, 500000 },
++ { 25, 0 },
++ { 50, 0 },
++ { 100, 0 },
++ { 200, 0 },
++ { 400, 0 },
++ { 800, 0 },
++};
++
++static const int bmi323_acc_gyro_odrns[] = {
++ 1280 * MEGA,
++ 640 * MEGA,
++ 320 * MEGA,
++ 160 * MEGA,
++ 80 * MEGA,
++ 40 * MEGA,
++ 20 * MEGA,
++ 10 * MEGA,
++ 5 * MEGA,
++ 2500 * KILO,
++ 1250 * KILO,
++};
++
++static enum bmi323_sensor_type bmi323_iio_to_sensor(enum iio_chan_type iio_type)
++{
++ switch (iio_type) {
++ case IIO_ACCEL:
++ return BMI323_ACCEL;
++ case IIO_ANGL_VEL:
++ return BMI323_GYRO;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int bmi323_set_mode(struct bmi323_data *data,
++ enum bmi323_sensor_type sensor,
++ enum bmi323_opr_mode mode)
++{
++ guard(mutex)(&data->mutex);
++ return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,
++ BMI323_ACC_GYRO_CONF_MODE_MSK,
++ FIELD_PREP(BMI323_ACC_GYRO_CONF_MODE_MSK,
++ mode));
++}
++
++/*
++ * When writing data to extended register there must be no communication to
++ * any other register before write transaction is complete.
++ * See datasheet section 6.2 Extended Register Map Description.
++ */
++static int bmi323_write_ext_reg(struct bmi323_data *data, unsigned int ext_addr,
++ unsigned int ext_data)
++{
++ int ret, feature_status;
++
++ ret = regmap_read(data->regmap, BMI323_FEAT_DATA_STATUS,
++ &feature_status);
++ if (ret)
++ return ret;
++
++ if (!FIELD_GET(BMI323_FEAT_DATA_TX_RDY_MSK, feature_status))
++ return -EBUSY;
++
++ ret = regmap_write(data->regmap, BMI323_FEAT_DATA_ADDR, ext_addr);
++ if (ret)
++ return ret;
++
++ return regmap_write(data->regmap, BMI323_FEAT_DATA_TX, ext_data);
++}
++
++/*
++ * When reading data from extended register there must be no communication to
++ * any other register before read transaction is complete.
++ * See datasheet section 6.2 Extended Register Map Description.
++ */
++static int bmi323_read_ext_reg(struct bmi323_data *data, unsigned int ext_addr,
++ unsigned int *ext_data)
++{
++ int ret, feature_status;
++
++ ret = regmap_read(data->regmap, BMI323_FEAT_DATA_STATUS,
++ &feature_status);
++ if (ret)
++ return ret;
++
++ if (!FIELD_GET(BMI323_FEAT_DATA_TX_RDY_MSK, feature_status))
++ return -EBUSY;
++
++ ret = regmap_write(data->regmap, BMI323_FEAT_DATA_ADDR, ext_addr);
++ if (ret)
++ return ret;
++
++ return regmap_read(data->regmap, BMI323_FEAT_DATA_TX, ext_data);
++}
++
++static int bmi323_update_ext_reg(struct bmi323_data *data,
++ unsigned int ext_addr,
++ unsigned int mask, unsigned int ext_data)
++{
++ unsigned int value;
++ int ret;
++
++ ret = bmi323_read_ext_reg(data, ext_addr, &value);
++ if (ret)
++ return ret;
++
++ set_mask_bits(&value, mask, ext_data);
++
++ return bmi323_write_ext_reg(data, ext_addr, value);
++}
++
++static int bmi323_get_error_status(struct bmi323_data *data)
++{
++ int error, ret;
++
++ guard(mutex)(&data->mutex);
++ ret = regmap_read(data->regmap, BMI323_ERR_REG, &error);
++ if (ret)
++ return ret;
++
++ if (error)
++ dev_err(data->dev, "Sensor error 0x%x\n", error);
++
++ return error;
++}
++
++static int bmi323_feature_engine_events(struct bmi323_data *data,
++ const unsigned int event_mask,
++ bool state)
++{
++ unsigned int value;
++ int ret;
++
++ ret = regmap_read(data->regmap, BMI323_FEAT_IO0_REG, &value);
++ if (ret)
++ return ret;
++
++ /* Register must be cleared before changing an active config */
++ ret = regmap_write(data->regmap, BMI323_FEAT_IO0_REG, 0);
++ if (ret)
++ return ret;
++
++ if (state)
++ value |= event_mask;
++ else
++ value &= ~event_mask;
++
++ ret = regmap_write(data->regmap, BMI323_FEAT_IO0_REG, value);
++ if (ret)
++ return ret;
++
++ return regmap_write(data->regmap, BMI323_FEAT_IO_STATUS_REG,
++ BMI323_FEAT_IO_STATUS_MSK);
++}
++
++static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state)
++{
++ enum bmi323_irq_pin step_irq;
++ int ret;
++
++ guard(mutex)(&data->mutex);
++ if (!FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK, data->feature_events))
++ return -EINVAL;
++
++ if (state)
++ step_irq = data->irq_pin;
++ else
++ step_irq = BMI323_IRQ_DISABLED;
++
++ ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,
++ BMI323_STEP_SC1_WTRMRK_MSK,
++ FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK,
++ state ? 1 : 0));
++ if (ret)
++ return ret;
++
++ return regmap_update_bits(data->regmap, BMI323_INT_MAP1_REG,
++ BMI323_STEP_CNT_MSK,
++ FIELD_PREP(BMI323_STEP_CNT_MSK, step_irq));
++}
++
++static int bmi323_motion_config_reg(enum iio_event_direction dir)
++{
++ switch (dir) {
++ case IIO_EV_DIR_RISING:
++ return BMI323_ANYMO1_REG;
++ case IIO_EV_DIR_FALLING:
++ return BMI323_NOMO1_REG;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int bmi323_motion_event_en(struct bmi323_data *data,
++ enum iio_event_direction dir, int state)
++{
++ unsigned int state_value = state ? BMI323_FEAT_XYZ_MSK : 0;
++ int config, ret, msk, raw, field_value;
++ enum bmi323_irq_pin motion_irq;
++ int irq_msk, irq_field_val;
++
++ if (state)
++ motion_irq = data->irq_pin;
++ else
++ motion_irq = BMI323_IRQ_DISABLED;
++
++ switch (dir) {
++ case IIO_EV_DIR_RISING:
++ msk = BMI323_FEAT_IO0_XYZ_MOTION_MSK;
++ raw = 512;
++ config = BMI323_ANYMO1_REG;
++ irq_msk = BMI323_MOTION_MSK;
++ irq_field_val = FIELD_PREP(BMI323_MOTION_MSK, motion_irq);
++ field_value = FIELD_PREP(BMI323_FEAT_IO0_XYZ_MOTION_MSK,
++ state_value);
++ break;
++ case IIO_EV_DIR_FALLING:
++ msk = BMI323_FEAT_IO0_XYZ_NOMOTION_MSK;
++ raw = 0;
++ config = BMI323_NOMO1_REG;
++ irq_msk = BMI323_NOMOTION_MSK;
++ irq_field_val = FIELD_PREP(BMI323_NOMOTION_MSK, motion_irq);
++ field_value = FIELD_PREP(BMI323_FEAT_IO0_XYZ_NOMOTION_MSK,
++ state_value);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ guard(mutex)(&data->mutex);
++ ret = bmi323_feature_engine_events(data, msk, state);
++ if (ret)
++ return ret;
++
++ ret = bmi323_update_ext_reg(data, config,
++ BMI323_MO1_REF_UP_MSK,
++ FIELD_PREP(BMI323_MO1_REF_UP_MSK, 0));
++ if (ret)
++ return ret;
++
++ /* Set initial value to avoid interrupts while enabling*/
++ ret = bmi323_update_ext_reg(data, config,
++ BMI323_MO1_SLOPE_TH_MSK,
++ FIELD_PREP(BMI323_MO1_SLOPE_TH_MSK, raw));
++ if (ret)
++ return ret;
++
++ ret = regmap_update_bits(data->regmap, BMI323_INT_MAP1_REG, irq_msk,
++ irq_field_val);
++ if (ret)
++ return ret;
++
++ set_mask_bits(&data->feature_events, msk, field_value);
++
++ return 0;
++}
++
++static int bmi323_tap_event_en(struct bmi323_data *data,
++ enum iio_event_direction dir, int state)
++{
++ enum bmi323_irq_pin tap_irq;
++ int ret, tap_enabled;
++
++ guard(mutex)(&data->mutex);
++
++ if (data->odrhz[BMI323_ACCEL] < 200) {
++ dev_err(data->dev, "Invalid accelrometer parameter\n");
++ return -EINVAL;
++ }
++
++ switch (dir) {
++ case IIO_EV_DIR_SINGLETAP:
++ ret = bmi323_feature_engine_events(data,
++ BMI323_FEAT_IO0_S_TAP_MSK,
++ state);
++ if (ret)
++ return ret;
++
++ set_mask_bits(&data->feature_events, BMI323_FEAT_IO0_S_TAP_MSK,
++ FIELD_PREP(BMI323_FEAT_IO0_S_TAP_MSK, state));
++ break;
++ case IIO_EV_DIR_DOUBLETAP:
++ ret = bmi323_feature_engine_events(data,
++ BMI323_FEAT_IO0_D_TAP_MSK,
++ state);
++ if (ret)
++ return ret;
++
++ set_mask_bits(&data->feature_events, BMI323_FEAT_IO0_D_TAP_MSK,
++ FIELD_PREP(BMI323_FEAT_IO0_D_TAP_MSK, state));
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ tap_enabled = FIELD_GET(BMI323_FEAT_IO0_S_TAP_MSK |
++ BMI323_FEAT_IO0_D_TAP_MSK,
++ data->feature_events);
++
++ if (tap_enabled)
++ tap_irq = data->irq_pin;
++ else
++ tap_irq = BMI323_IRQ_DISABLED;
++
++ ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,
++ BMI323_TAP_MSK,
++ FIELD_PREP(BMI323_TAP_MSK, tap_irq));
++ if (ret)
++ return ret;
++
++ if (!state)
++ return 0;
++
++ ret = bmi323_update_ext_reg(data, BMI323_TAP1_REG,
++ BMI323_TAP1_MAX_PEAKS_MSK,
++ FIELD_PREP(BMI323_TAP1_MAX_PEAKS_MSK,
++ 0x04));
++ if (ret)
++ return ret;
++
++ ret = bmi323_update_ext_reg(data, BMI323_TAP1_REG,
++ BMI323_TAP1_AXIS_SEL_MSK,
++ FIELD_PREP(BMI323_TAP1_AXIS_SEL_MSK,
++ BMI323_AXIS_XYZ_MSK));
++ if (ret)
++ return ret;
++
++ return bmi323_update_ext_reg(data, BMI323_TAP1_REG,
++ BMI323_TAP1_TIMOUT_MSK,
++ FIELD_PREP(BMI323_TAP1_TIMOUT_MSK,
++ 0));
++}
++
++static ssize_t in_accel_gesture_tap_wait_dur_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
++ struct bmi323_data *data = iio_priv(indio_dev);
++ unsigned int reg_value, raw;
++ int ret, val[2];
++
++ scoped_guard(mutex, &data->mutex) {
++ ret = bmi323_read_ext_reg(data, BMI323_TAP2_REG, &reg_value);
++ if (ret)
++ return ret;
++ }
++
++ raw = FIELD_GET(BMI323_TAP2_MAX_DUR_MSK, reg_value);
++ val[0] = raw / BMI323_MAX_GES_DUR_SCALE;
++ val[1] = BMI323_RAW_TO_MICRO(raw, BMI323_MAX_GES_DUR_SCALE);
++
++ return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, ARRAY_SIZE(val),
++ val);
++}
++
++static ssize_t in_accel_gesture_tap_wait_dur_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t len)
++{
++ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
++ struct bmi323_data *data = iio_priv(indio_dev);
++ int ret, val_int, val_fract, raw;
++
++ ret = iio_str_to_fixpoint(buf, 100000, &val_int, &val_fract);
++ if (ret)
++ return ret;
++
++ raw = BMI323_INT_MICRO_TO_RAW(val_int, val_fract,
++ BMI323_MAX_GES_DUR_SCALE);
++ if (!in_range(raw, 0, 64))
++ return -EINVAL;
++
++ guard(mutex)(&data->mutex);
++ ret = bmi323_update_ext_reg(data, BMI323_TAP2_REG,
++ BMI323_TAP2_MAX_DUR_MSK,
++ FIELD_PREP(BMI323_TAP2_MAX_DUR_MSK, raw));
++ if (ret)
++ return ret;
++
++ return len;
++}
++
++/*
++ * Maximum duration from first tap within the second tap is expected to happen.
++ * This timeout is applicable only if gesture_tap_wait_timeout is enabled.
++ */
++static IIO_DEVICE_ATTR_RW(in_accel_gesture_tap_wait_dur, 0);
++
++static ssize_t in_accel_gesture_tap_wait_timeout_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
++ struct bmi323_data *data = iio_priv(indio_dev);
++ unsigned int reg_value, raw;
++ int ret;
++
++ scoped_guard(mutex, &data->mutex) {
++ ret = bmi323_read_ext_reg(data, BMI323_TAP1_REG, &reg_value);
++ if (ret)
++ return ret;
++ }
++
++ raw = FIELD_GET(BMI323_TAP1_TIMOUT_MSK, reg_value);
++
++ return iio_format_value(buf, IIO_VAL_INT, 1, &raw);
++}
++
++static ssize_t in_accel_gesture_tap_wait_timeout_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf,
++ size_t len)
++{
++ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
++ struct bmi323_data *data = iio_priv(indio_dev);
++ bool val;
++ int ret;
++
++ ret = kstrtobool(buf, &val);
++ if (ret)
++ return ret;
++
++ guard(mutex)(&data->mutex);
++ ret = bmi323_update_ext_reg(data, BMI323_TAP1_REG,
++ BMI323_TAP1_TIMOUT_MSK,
++ FIELD_PREP(BMI323_TAP1_TIMOUT_MSK, val));
++ if (ret)
++ return ret;
++
++ return len;
++}
++
++/* Enable/disable gesture confirmation with wait time */
++static IIO_DEVICE_ATTR_RW(in_accel_gesture_tap_wait_timeout, 0);
++
++static IIO_CONST_ATTR(in_accel_gesture_tap_wait_dur_available,
++ "[0.0 0.04 2.52]");
++
++static IIO_CONST_ATTR(in_accel_gesture_doubletap_tap2_min_delay_available,
++ "[0.005 0.005 0.075]");
++
++static IIO_CONST_ATTR(in_accel_gesture_tap_reset_timeout_available,
++ "[0.04 0.04 0.6]");
++
++static IIO_CONST_ATTR(in_accel_gesture_tap_value_available, "[0.0 0.002 1.99]");
++
++static IIO_CONST_ATTR(in_accel_mag_value_available, "[0.0 0.002 7.99]");
++
++static IIO_CONST_ATTR(in_accel_mag_period_available, "[0.0 0.02 162.0]");
++
++static IIO_CONST_ATTR(in_accel_mag_hysteresis_available, "[0.0 0.002 1.99]");
++
++static struct attribute *bmi323_event_attributes[] = {
++ &iio_const_attr_in_accel_gesture_tap_value_available.dev_attr.attr,
++ &iio_const_attr_in_accel_gesture_tap_reset_timeout_available.dev_attr.attr,
++ &iio_const_attr_in_accel_gesture_doubletap_tap2_min_delay_available.dev_attr.attr,
++ &iio_const_attr_in_accel_gesture_tap_wait_dur_available.dev_attr.attr,
++ &iio_dev_attr_in_accel_gesture_tap_wait_timeout.dev_attr.attr,
++ &iio_dev_attr_in_accel_gesture_tap_wait_dur.dev_attr.attr,
++ &iio_const_attr_in_accel_mag_value_available.dev_attr.attr,
++ &iio_const_attr_in_accel_mag_period_available.dev_attr.attr,
++ &iio_const_attr_in_accel_mag_hysteresis_available.dev_attr.attr,
++ NULL
++};
++
++static const struct attribute_group bmi323_event_attribute_group = {
++ .attrs = bmi323_event_attributes,
++};
++
++static int bmi323_write_event_config(struct iio_dev *indio_dev,
++ const struct iio_chan_spec *chan,
++ enum iio_event_type type,
++ enum iio_event_direction dir, int state)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++
++ switch (type) {
++ case IIO_EV_TYPE_MAG:
++ return bmi323_motion_event_en(data, dir, state);
++ case IIO_EV_TYPE_GESTURE:
++ return bmi323_tap_event_en(data, dir, state);
++ case IIO_EV_TYPE_CHANGE:
++ return bmi323_step_wtrmrk_en(data, state);
++ default:
++ return -EINVAL;
++ }
++}
++
++static int bmi323_read_event_config(struct iio_dev *indio_dev,
++ const struct iio_chan_spec *chan,
++ enum iio_event_type type,
++ enum iio_event_direction dir)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++ int ret, value, reg_val;
++
++ guard(mutex)(&data->mutex);
++
++ switch (chan->type) {
++ case IIO_ACCEL:
++ switch (dir) {
++ case IIO_EV_DIR_SINGLETAP:
++ ret = FIELD_GET(BMI323_FEAT_IO0_S_TAP_MSK,
++ data->feature_events);
++ break;
++ case IIO_EV_DIR_DOUBLETAP:
++ ret = FIELD_GET(BMI323_FEAT_IO0_D_TAP_MSK,
++ data->feature_events);
++ break;
++ case IIO_EV_DIR_RISING:
++ value = FIELD_GET(BMI323_FEAT_IO0_XYZ_MOTION_MSK,
++ data->feature_events);
++ ret = value ? 1 : 0;
++ break;
++ case IIO_EV_DIR_FALLING:
++ value = FIELD_GET(BMI323_FEAT_IO0_XYZ_NOMOTION_MSK,
++ data->feature_events);
++ ret = value ? 1 : 0;
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++ return ret;
++ case IIO_STEPS:
++ ret = regmap_read(data->regmap, BMI323_INT_MAP1_REG, &reg_val);
++ if (ret)
++ return ret;
++
++ return FIELD_GET(BMI323_STEP_CNT_MSK, reg_val) ? 1 : 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int bmi323_write_event_value(struct iio_dev *indio_dev,
++ const struct iio_chan_spec *chan,
++ enum iio_event_type type,
++ enum iio_event_direction dir,
++ enum iio_event_info info,
++ int val, int val2)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++ unsigned int raw;
++ int reg;
++
++ guard(mutex)(&data->mutex);
++
++ switch (type) {
++ case IIO_EV_TYPE_GESTURE:
++ switch (info) {
++ case IIO_EV_INFO_VALUE:
++ if (!in_range(val, 0, 2))
++ return -EINVAL;
++
++ raw = BMI323_INT_MICRO_TO_RAW(val, val2,
++ BMI323_TAP_THRES_SCALE);
++
++ return bmi323_update_ext_reg(data, BMI323_TAP2_REG,
++ BMI323_TAP2_THRES_MSK,
++ FIELD_PREP(BMI323_TAP2_THRES_MSK,
++ raw));
++ case IIO_EV_INFO_RESET_TIMEOUT:
++ if (val || !in_range(val2, 40000, 560001))
++ return -EINVAL;
++
++ raw = BMI323_INT_MICRO_TO_RAW(val, val2,
++ BMI323_QUITE_TIM_GES_SCALE);
++
++ return bmi323_update_ext_reg(data, BMI323_TAP3_REG,
++ BMI323_TAP3_QT_AFT_GES_MSK,
++ FIELD_PREP(BMI323_TAP3_QT_AFT_GES_MSK,
++ raw));
++ case IIO_EV_INFO_TAP2_MIN_DELAY:
++ if (val || !in_range(val2, 5000, 70001))
++ return -EINVAL;
++
++ raw = BMI323_INT_MICRO_TO_RAW(val, val2,
++ BMI323_DUR_BW_TAP_SCALE);
++
++ return bmi323_update_ext_reg(data, BMI323_TAP3_REG,
++ BMI323_TAP3_QT_BW_TAP_MSK,
++ FIELD_PREP(BMI323_TAP3_QT_BW_TAP_MSK,
++ raw));
++ default:
++ return -EINVAL;
++ }
++ case IIO_EV_TYPE_MAG:
++ reg = bmi323_motion_config_reg(dir);
++ if (reg < 0)
++ return -EINVAL;
++
++ switch (info) {
++ case IIO_EV_INFO_VALUE:
++ if (!in_range(val, 0, 8))
++ return -EINVAL;
++
++ raw = BMI323_INT_MICRO_TO_RAW(val, val2,
++ BMI323_MOTION_THRES_SCALE);
++
++ return bmi323_update_ext_reg(data, reg,
++ BMI323_MO1_SLOPE_TH_MSK,
++ FIELD_PREP(BMI323_MO1_SLOPE_TH_MSK,
++ raw));
++ case IIO_EV_INFO_PERIOD:
++ if (!in_range(val, 0, 163))
++ return -EINVAL;
++
++ raw = BMI323_INT_MICRO_TO_RAW(val, val2,
++ BMI323_MOTION_DURAT_SCALE);
++
++ return bmi323_update_ext_reg(data,
++ reg + BMI323_MO3_OFFSET,
++ BMI323_MO3_DURA_MSK,
++ FIELD_PREP(BMI323_MO3_DURA_MSK,
++ raw));
++ case IIO_EV_INFO_HYSTERESIS:
++ if (!in_range(val, 0, 2))
++ return -EINVAL;
++
++ raw = BMI323_INT_MICRO_TO_RAW(val, val2,
++ BMI323_MOTION_HYSTR_SCALE);
++
++ return bmi323_update_ext_reg(data,
++ reg + BMI323_MO2_OFFSET,
++ BMI323_MO2_HYSTR_MSK,
++ FIELD_PREP(BMI323_MO2_HYSTR_MSK,
++ raw));
++ default:
++ return -EINVAL;
++ }
++ case IIO_EV_TYPE_CHANGE:
++ if (!in_range(val, 0, 20461))
++ return -EINVAL;
++
++ raw = val / 20;
++ return bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,
++ BMI323_STEP_SC1_WTRMRK_MSK,
++ FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK,
++ raw));
++ default:
++ return -EINVAL;
++ }
++}
++
++static int bmi323_read_event_value(struct iio_dev *indio_dev,
++ const struct iio_chan_spec *chan,
++ enum iio_event_type type,
++ enum iio_event_direction dir,
++ enum iio_event_info info,
++ int *val, int *val2)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++ unsigned int raw, reg_value;
++ int ret, reg;
++
++ guard(mutex)(&data->mutex);
++
++ switch (type) {
++ case IIO_EV_TYPE_GESTURE:
++ switch (info) {
++ case IIO_EV_INFO_VALUE:
++ ret = bmi323_read_ext_reg(data, BMI323_TAP2_REG,
++ &reg_value);
++ if (ret)
++ return ret;
++
++ raw = FIELD_GET(BMI323_TAP2_THRES_MSK, reg_value);
++ *val = raw / BMI323_TAP_THRES_SCALE;
++ *val2 = BMI323_RAW_TO_MICRO(raw, BMI323_TAP_THRES_SCALE);
++ return IIO_VAL_INT_PLUS_MICRO;
++ case IIO_EV_INFO_RESET_TIMEOUT:
++ ret = bmi323_read_ext_reg(data, BMI323_TAP3_REG,
++ &reg_value);
++ if (ret)
++ return ret;
++
++ raw = FIELD_GET(BMI323_TAP3_QT_AFT_GES_MSK, reg_value);
++ *val = 0;
++ *val2 = BMI323_RAW_TO_MICRO(raw,
++ BMI323_QUITE_TIM_GES_SCALE);
++ return IIO_VAL_INT_PLUS_MICRO;
++ case IIO_EV_INFO_TAP2_MIN_DELAY:
++ ret = bmi323_read_ext_reg(data, BMI323_TAP3_REG,
++ &reg_value);
++ if (ret)
++ return ret;
++
++ raw = FIELD_GET(BMI323_TAP3_QT_BW_TAP_MSK, reg_value);
++ *val = 0;
++ *val2 = BMI323_RAW_TO_MICRO(raw,
++ BMI323_DUR_BW_TAP_SCALE);
++ return IIO_VAL_INT_PLUS_MICRO;
++ default:
++ return -EINVAL;
++ }
++ case IIO_EV_TYPE_MAG:
++ reg = bmi323_motion_config_reg(dir);
++ if (reg < 0)
++ return -EINVAL;
++
++ switch (info) {
++ case IIO_EV_INFO_VALUE:
++ ret = bmi323_read_ext_reg(data, reg, &reg_value);
++ if (ret)
++ return ret;
++
++ raw = FIELD_GET(BMI323_MO1_SLOPE_TH_MSK, reg_value);
++ *val = raw / BMI323_MOTION_THRES_SCALE;
++ *val2 = BMI323_RAW_TO_MICRO(raw,
++ BMI323_MOTION_THRES_SCALE);
++ return IIO_VAL_INT_PLUS_MICRO;
++ case IIO_EV_INFO_PERIOD:
++ ret = bmi323_read_ext_reg(data,
++ reg + BMI323_MO3_OFFSET,
++ &reg_value);
++ if (ret)
++ return ret;
++
++ raw = FIELD_GET(BMI323_MO3_DURA_MSK, reg_value);
++ *val = raw / BMI323_MOTION_DURAT_SCALE;
++ *val2 = BMI323_RAW_TO_MICRO(raw,
++ BMI323_MOTION_DURAT_SCALE);
++ return IIO_VAL_INT_PLUS_MICRO;
++ case IIO_EV_INFO_HYSTERESIS:
++ ret = bmi323_read_ext_reg(data,
++ reg + BMI323_MO2_OFFSET,
++ &reg_value);
++ if (ret)
++ return ret;
++
++ raw = FIELD_GET(BMI323_MO2_HYSTR_MSK, reg_value);
++ *val = raw / BMI323_MOTION_HYSTR_SCALE;
++ *val2 = BMI323_RAW_TO_MICRO(raw,
++ BMI323_MOTION_HYSTR_SCALE);
++ return IIO_VAL_INT_PLUS_MICRO;
++ default:
++ return -EINVAL;
++ }
++ case IIO_EV_TYPE_CHANGE:
++ ret = bmi323_read_ext_reg(data, BMI323_STEP_SC1_REG,
++ &reg_value);
++ if (ret)
++ return ret;
++
++ raw = FIELD_GET(BMI323_STEP_SC1_WTRMRK_MSK, reg_value);
++ *val = raw * 20;
++ return IIO_VAL_INT;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int __bmi323_fifo_flush(struct iio_dev *indio_dev)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++ int i, ret, fifo_lvl, frame_count, bit, index;
++ __le16 *frame, *pchannels;
++ u64 sample_period;
++ s64 tstamp;
++
++ guard(mutex)(&data->mutex);
++ ret = regmap_read(data->regmap, BMI323_FIFO_FILL_LEVEL_REG, &fifo_lvl);
++ if (ret)
++ return ret;
++
++ fifo_lvl = min(fifo_lvl, BMI323_FIFO_FULL_IN_WORDS);
++
++ frame_count = fifo_lvl / BMI323_FIFO_FRAME_LENGTH;
++ if (!frame_count)
++ return -EINVAL;
++
++ if (fifo_lvl % BMI323_FIFO_FRAME_LENGTH)
++ dev_warn(data->dev, "Bad FIFO alignment\n");
++
++ /*
++ * Approximate timestamps for each of the sample based on the sampling
++ * frequency, timestamp for last sample and number of samples.
++ */
++ if (data->old_fifo_tstamp) {
++ sample_period = data->fifo_tstamp - data->old_fifo_tstamp;
++ do_div(sample_period, frame_count);
++ } else {
++ sample_period = data->odrns[BMI323_ACCEL];
++ }
++
++ tstamp = data->fifo_tstamp - (frame_count - 1) * sample_period;
++
++ ret = regmap_noinc_read(data->regmap, BMI323_FIFO_DATA_REG,
++ &data->fifo_buff[0],
++ fifo_lvl * BMI323_BYTES_PER_SAMPLE);
++ if (ret)
++ return ret;
++
++ for (i = 0; i < frame_count; i++) {
++ frame = &data->fifo_buff[i * BMI323_FIFO_FRAME_LENGTH];
++ pchannels = &data->buffer.channels[0];
++
++ index = 0;
++ for_each_set_bit(bit, indio_dev->active_scan_mask,
++ BMI323_CHAN_MAX)
++ pchannels[index++] = frame[bit];
++
++ iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
++ tstamp);
++
++ tstamp += sample_period;
++ }
++
++ return frame_count;
++}
++
++static int bmi323_set_watermark(struct iio_dev *indio_dev, unsigned int val)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++
++ val = min(val, (u32)BMI323_FIFO_FULL_IN_FRAMES);
++
++ guard(mutex)(&data->mutex);
++ data->watermark = val;
++
++ return 0;
++}
++
++static int bmi323_fifo_disable(struct bmi323_data *data)
++{
++ int ret;
++
++ guard(mutex)(&data->mutex);
++ ret = regmap_write(data->regmap, BMI323_FIFO_CONF_REG, 0);
++ if (ret)
++ return ret;
++
++ ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,
++ BMI323_FIFO_WTRMRK_MSK,
++ FIELD_PREP(BMI323_FIFO_WTRMRK_MSK, 0));
++ if (ret)
++ return ret;
++
++ data->fifo_tstamp = 0;
++ data->state = BMI323_IDLE;
++
++ return 0;
++}
++
++static int bmi323_buffer_predisable(struct iio_dev *indio_dev)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++
++ if (iio_device_get_current_mode(indio_dev) == INDIO_BUFFER_TRIGGERED)
++ return 0;
++
++ return bmi323_fifo_disable(data);
++}
++
++static int bmi323_update_watermark(struct bmi323_data *data)
++{
++ int wtrmrk;
++
++ wtrmrk = data->watermark * BMI323_FIFO_FRAME_LENGTH;
++
++ return regmap_write(data->regmap, BMI323_FIFO_WTRMRK_REG, wtrmrk);
++}
++
++static int bmi323_fifo_enable(struct bmi323_data *data)
++{
++ int ret;
++
++ guard(mutex)(&data->mutex);
++ ret = regmap_update_bits(data->regmap, BMI323_FIFO_CONF_REG,
++ BMI323_FIFO_CONF_ACC_GYR_EN_MSK,
++ FIELD_PREP(BMI323_FIFO_CONF_ACC_GYR_EN_MSK,
++ BMI323_FIFO_ACC_GYR_MSK));
++ if (ret)
++ return ret;
++
++ ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,
++ BMI323_FIFO_WTRMRK_MSK,
++ FIELD_PREP(BMI323_FIFO_WTRMRK_MSK,
++ data->irq_pin));
++ if (ret)
++ return ret;
++
++ ret = bmi323_update_watermark(data);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(data->regmap, BMI323_FIFO_CTRL_REG,
++ BMI323_FIFO_FLUSH_MSK);
++ if (ret)
++ return ret;
++
++ data->state = BMI323_BUFFER_FIFO;
++
++ return 0;
++}
++
++static int bmi323_buffer_preenable(struct iio_dev *indio_dev)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++
++ guard(mutex)(&data->mutex);
++ /*
++ * When the ODR of the accelerometer and gyroscope do not match, the
++ * maximum ODR value between the accelerometer and gyroscope is used
++ * for FIFO and the signal with lower ODR will insert dummy frame.
++ * So allow buffer read only when ODR's of accelero and gyro are equal.
++ * See datasheet section 5.7 "FIFO Data Buffering".
++ */
++ if (data->odrns[BMI323_ACCEL] != data->odrns[BMI323_GYRO]) {
++ dev_err(data->dev, "Accelero and Gyro ODR doesn't match\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int bmi323_buffer_postenable(struct iio_dev *indio_dev)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++
++ if (iio_device_get_current_mode(indio_dev) == INDIO_BUFFER_TRIGGERED)
++ return 0;
++
++ return bmi323_fifo_enable(data);
++}
++
++static ssize_t hwfifo_watermark_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
++ struct bmi323_data *data = iio_priv(indio_dev);
++ int wm;
++
++ scoped_guard(mutex, &data->mutex)
++ wm = data->watermark;
++
++ return sysfs_emit(buf, "%d\n", wm);
++}
++static IIO_DEVICE_ATTR_RO(hwfifo_watermark, 0);
++
++static ssize_t hwfifo_enabled_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
++ struct bmi323_data *data = iio_priv(indio_dev);
++ bool state;
++
++ scoped_guard(mutex, &data->mutex)
++ state = data->state == BMI323_BUFFER_FIFO;
++
++ return sysfs_emit(buf, "%d\n", state);
++}
++static IIO_DEVICE_ATTR_RO(hwfifo_enabled, 0);
++
++static const struct iio_dev_attr *bmi323_fifo_attributes[] = {
++ &iio_dev_attr_hwfifo_watermark,
++ &iio_dev_attr_hwfifo_enabled,
++ NULL
++};
++
++static const struct iio_buffer_setup_ops bmi323_buffer_ops = {
++ .preenable = bmi323_buffer_preenable,
++ .postenable = bmi323_buffer_postenable,
++ .predisable = bmi323_buffer_predisable,
++};
++
++static irqreturn_t bmi323_irq_thread_handler(int irq, void *private)
++{
++ struct iio_dev *indio_dev = private;
++ struct bmi323_data *data = iio_priv(indio_dev);
++ unsigned int status_addr, status, feature_event;
++ s64 timestamp = iio_get_time_ns(indio_dev);
++ int ret;
++
++ if (data->irq_pin == BMI323_IRQ_INT1)
++ status_addr = BMI323_STATUS_INT1_REG;
++ else
++ status_addr = BMI323_STATUS_INT2_REG;
++
++ scoped_guard(mutex, &data->mutex) {
++ ret = regmap_read(data->regmap, status_addr, &status);
++ if (ret)
++ return IRQ_NONE;
++ }
++
++ if (!status || FIELD_GET(BMI323_STATUS_ERROR_MSK, status))
++ return IRQ_NONE;
++
++ if (FIELD_GET(BMI323_STATUS_FIFO_WTRMRK_MSK, status)) {
++ data->old_fifo_tstamp = data->fifo_tstamp;
++ data->fifo_tstamp = iio_get_time_ns(indio_dev);
++ ret = __bmi323_fifo_flush(indio_dev);
++ if (ret < 0)
++ return IRQ_NONE;
++ }
++
++ if (FIELD_GET(BMI323_STATUS_ACC_GYR_DRDY_MSK, status))
++ iio_trigger_poll_nested(data->trig);
++
++ if (FIELD_GET(BMI323_STATUS_MOTION_MSK, status))
++ iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
++ IIO_MOD_X_OR_Y_OR_Z,
++ IIO_EV_TYPE_MAG,
++ IIO_EV_DIR_RISING),
++ timestamp);
++
++ if (FIELD_GET(BMI323_STATUS_NOMOTION_MSK, status))
++ iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
++ IIO_MOD_X_OR_Y_OR_Z,
++ IIO_EV_TYPE_MAG,
++ IIO_EV_DIR_FALLING),
++ timestamp);
++
++ if (FIELD_GET(BMI323_STATUS_STP_WTR_MSK, status))
++ iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_STEPS, 0,
++ IIO_NO_MOD,
++ IIO_EV_TYPE_CHANGE,
++ IIO_EV_DIR_NONE),
++ timestamp);
++
++ if (FIELD_GET(BMI323_STATUS_TAP_MSK, status)) {
++ scoped_guard(mutex, &data->mutex) {
++ ret = regmap_read(data->regmap,
++ BMI323_FEAT_EVNT_EXT_REG,
++ &feature_event);
++ if (ret)
++ return IRQ_NONE;
++ }
++
++ if (FIELD_GET(BMI323_FEAT_EVNT_EXT_S_MSK, feature_event)) {
++ iio_push_event(indio_dev,
++ IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
++ IIO_MOD_X_OR_Y_OR_Z,
++ IIO_EV_TYPE_GESTURE,
++ IIO_EV_DIR_SINGLETAP),
++ timestamp);
++ }
++
++ if (FIELD_GET(BMI323_FEAT_EVNT_EXT_D_MSK, feature_event))
++ iio_push_event(indio_dev,
++ IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
++ IIO_MOD_X_OR_Y_OR_Z,
++ IIO_EV_TYPE_GESTURE,
++ IIO_EV_DIR_DOUBLETAP),
++ timestamp);
++ }
++
++ return IRQ_HANDLED;
++}
++
++static int bmi323_set_drdy_irq(struct bmi323_data *data,
++ enum bmi323_irq_pin irq_pin)
++{
++ int ret;
++
++ ret = regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,
++ BMI323_GYR_DRDY_MSK,
++ FIELD_PREP(BMI323_GYR_DRDY_MSK, irq_pin));
++ if (ret)
++ return ret;
++
++ return regmap_update_bits(data->regmap, BMI323_INT_MAP2_REG,
++ BMI323_ACC_DRDY_MSK,
++ FIELD_PREP(BMI323_ACC_DRDY_MSK, irq_pin));
++}
++
++static int bmi323_data_rdy_trigger_set_state(struct iio_trigger *trig,
++ bool state)
++{
++ struct bmi323_data *data = iio_trigger_get_drvdata(trig);
++ enum bmi323_irq_pin irq_pin;
++
++ guard(mutex)(&data->mutex);
++
++ if (data->state == BMI323_BUFFER_FIFO) {
++ dev_warn(data->dev, "Can't set trigger when FIFO enabled\n");
++ return -EBUSY;
++ }
++
++ if (state) {
++ data->state = BMI323_BUFFER_DRDY_TRIGGERED;
++ irq_pin = data->irq_pin;
++ } else {
++ data->state = BMI323_IDLE;
++ irq_pin = BMI323_IRQ_DISABLED;
++ }
++
++ return bmi323_set_drdy_irq(data, irq_pin);
++}
++
++static const struct iio_trigger_ops bmi323_trigger_ops = {
++ .set_trigger_state = &bmi323_data_rdy_trigger_set_state,
++};
++
++static irqreturn_t bmi323_trigger_handler(int irq, void *p)
++{
++ struct iio_poll_func *pf = p;
++ struct iio_dev *indio_dev = pf->indio_dev;
++ struct bmi323_data *data = iio_priv(indio_dev);
++ int ret, bit, index = 0;
++
++ /* Lock to protect the data->buffer */
++ guard(mutex)(&data->mutex);
++
++ if (*indio_dev->active_scan_mask == BMI323_ALL_CHAN_MSK) {
++ ret = regmap_bulk_read(data->regmap, BMI323_ACCEL_X_REG,
++ &data->buffer.channels,
++ ARRAY_SIZE(data->buffer.channels));
++ if (ret)
++ return IRQ_NONE;
++ } else {
++ for_each_set_bit(bit, indio_dev->active_scan_mask,
++ BMI323_CHAN_MAX) {
++ ret = regmap_raw_read(data->regmap,
++ BMI323_ACCEL_X_REG + bit,
++ &data->buffer.channels[index++],
++ BMI323_BYTES_PER_SAMPLE);
++ if (ret)
++ return IRQ_NONE;
++ }
++ }
++
++ iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
++ iio_get_time_ns(indio_dev));
++
++ iio_trigger_notify_done(indio_dev->trig);
++
++ return IRQ_HANDLED;
++}
++
++static int bmi323_set_average(struct bmi323_data *data,
++ enum bmi323_sensor_type sensor, int avg)
++{
++ int raw = ARRAY_SIZE(bmi323_accel_gyro_avrg);
++
++ while (raw--)
++ if (avg == bmi323_accel_gyro_avrg[raw])
++ break;
++ if (raw < 0)
++ return -EINVAL;
++
++ guard(mutex)(&data->mutex);
++ return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,
++ BMI323_ACC_GYRO_CONF_AVG_MSK,
++ FIELD_PREP(BMI323_ACC_GYRO_CONF_AVG_MSK,
++ raw));
++}
++
++static int bmi323_get_average(struct bmi323_data *data,
++ enum bmi323_sensor_type sensor, int *avg)
++{
++ int ret, value, raw;
++
++ scoped_guard(mutex, &data->mutex) {
++ ret = regmap_read(data->regmap, bmi323_hw[sensor].config, &value);
++ if (ret)
++ return ret;
++ }
++
++ raw = FIELD_GET(BMI323_ACC_GYRO_CONF_AVG_MSK, value);
++ *avg = bmi323_accel_gyro_avrg[raw];
++
++ return IIO_VAL_INT;
++}
++
++static int bmi323_enable_steps(struct bmi323_data *data, int val)
++{
++ int ret;
++
++ guard(mutex)(&data->mutex);
++ if (data->odrhz[BMI323_ACCEL] < 200) {
++ dev_err(data->dev, "Invalid accelrometer parameter\n");
++ return -EINVAL;
++ }
++
++ ret = bmi323_feature_engine_events(data, BMI323_FEAT_IO0_STP_CNT_MSK,
++ val ? 1 : 0);
++ if (ret)
++ return ret;
++
++ set_mask_bits(&data->feature_events, BMI323_FEAT_IO0_STP_CNT_MSK,
++ FIELD_PREP(BMI323_FEAT_IO0_STP_CNT_MSK, val ? 1 : 0));
++
++ return 0;
++}
++
++static int bmi323_read_steps(struct bmi323_data *data, int *val)
++{
++ int ret;
++
++ guard(mutex)(&data->mutex);
++ if (!FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK, data->feature_events))
++ return -EINVAL;
++
++ ret = regmap_bulk_read(data->regmap, BMI323_FEAT_IO2_REG,
++ data->steps_count,
++ ARRAY_SIZE(data->steps_count));
++ if (ret)
++ return ret;
++
++ *val = get_unaligned_le32(data->steps_count);
++
++ return IIO_VAL_INT;
++}
++
++static int bmi323_read_axis(struct bmi323_data *data,
++ struct iio_chan_spec const *chan, int *val)
++{
++ enum bmi323_sensor_type sensor;
++ unsigned int value;
++ u8 addr;
++ int ret;
++
++ ret = bmi323_get_error_status(data);
++ if (ret)
++ return -EINVAL;
++
++ sensor = bmi323_iio_to_sensor(chan->type);
++ addr = bmi323_hw[sensor].data + (chan->channel2 - IIO_MOD_X);
++
++ scoped_guard(mutex, &data->mutex) {
++ ret = regmap_read(data->regmap, addr, &value);
++ if (ret)
++ return ret;
++ }
++
++ *val = sign_extend32(value, chan->scan_type.realbits - 1);
++
++ return IIO_VAL_INT;
++}
++
++static int bmi323_get_temp_data(struct bmi323_data *data, int *val)
++{
++ unsigned int value;
++ int ret;
++
++ ret = bmi323_get_error_status(data);
++ if (ret)
++ return -EINVAL;
++
++ scoped_guard(mutex, &data->mutex) {
++ ret = regmap_read(data->regmap, BMI323_TEMP_REG, &value);
++ if (ret)
++ return ret;
++ }
++
++ *val = sign_extend32(value, 15);
++
++ return IIO_VAL_INT;
++}
++
++static int bmi323_get_odr(struct bmi323_data *data,
++ enum bmi323_sensor_type sensor, int *odr, int *uodr)
++{
++ int ret, value, odr_raw;
++
++ scoped_guard(mutex, &data->mutex) {
++ ret = regmap_read(data->regmap, bmi323_hw[sensor].config, &value);
++ if (ret)
++ return ret;
++ }
++
++ odr_raw = FIELD_GET(BMI323_ACC_GYRO_CONF_ODR_MSK, value);
++ *odr = bmi323_acc_gyro_odr[odr_raw - 1][0];
++ *uodr = bmi323_acc_gyro_odr[odr_raw - 1][1];
++
++ return IIO_VAL_INT_PLUS_MICRO;
++}
++
++static int bmi323_configure_power_mode(struct bmi323_data *data,
++ enum bmi323_sensor_type sensor,
++ int odr_index)
++{
++ enum bmi323_opr_mode mode;
++
++ if (bmi323_acc_gyro_odr[odr_index][0] > 25)
++ mode = ACC_GYRO_MODE_CONTINOUS;
++ else
++ mode = ACC_GYRO_MODE_DUTYCYCLE;
++
++ return bmi323_set_mode(data, sensor, mode);
++}
++
++static int bmi323_set_odr(struct bmi323_data *data,
++ enum bmi323_sensor_type sensor, int odr, int uodr)
++{
++ int odr_raw, ret;
++
++ odr_raw = ARRAY_SIZE(bmi323_acc_gyro_odr);
++
++ while (odr_raw--)
++ if (odr == bmi323_acc_gyro_odr[odr_raw][0] &&
++ uodr == bmi323_acc_gyro_odr[odr_raw][1])
++ break;
++ if (odr_raw < 0)
++ return -EINVAL;
++
++ ret = bmi323_configure_power_mode(data, sensor, odr_raw);
++ if (ret)
++ return -EINVAL;
++
++ guard(mutex)(&data->mutex);
++ data->odrhz[sensor] = bmi323_acc_gyro_odr[odr_raw][0];
++ data->odrns[sensor] = bmi323_acc_gyro_odrns[odr_raw];
++
++ odr_raw++;
++
++ return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,
++ BMI323_ACC_GYRO_CONF_ODR_MSK,
++ FIELD_PREP(BMI323_ACC_GYRO_CONF_ODR_MSK,
++ odr_raw));
++}
++
++static int bmi323_get_scale(struct bmi323_data *data,
++ enum bmi323_sensor_type sensor, int *val2)
++{
++ int ret, value, scale_raw;
++
++ scoped_guard(mutex, &data->mutex) {
++ ret = regmap_read(data->regmap, bmi323_hw[sensor].config,
++ &value);
++ if (ret)
++ return ret;
++ }
++
++ scale_raw = FIELD_GET(BMI323_ACC_GYRO_CONF_SCL_MSK, value);
++ *val2 = bmi323_hw[sensor].scale_table[scale_raw][1];
++
++ return IIO_VAL_INT_PLUS_MICRO;
++}
++
++static int bmi323_set_scale(struct bmi323_data *data,
++ enum bmi323_sensor_type sensor, int val, int val2)
++{
++ int scale_raw;
++
++ scale_raw = bmi323_hw[sensor].scale_table_len;
++
++ while (scale_raw--)
++ if (val == bmi323_hw[sensor].scale_table[scale_raw][0] &&
++ val2 == bmi323_hw[sensor].scale_table[scale_raw][1])
++ break;
++ if (scale_raw < 0)
++ return -EINVAL;
++
++ guard(mutex)(&data->mutex);
++ return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,
++ BMI323_ACC_GYRO_CONF_SCL_MSK,
++ FIELD_PREP(BMI323_ACC_GYRO_CONF_SCL_MSK,
++ scale_raw));
++}
++
++static int bmi323_read_avail(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan,
++ const int **vals, int *type, int *length,
++ long mask)
++{
++ enum bmi323_sensor_type sensor;
++
++ switch (mask) {
++ case IIO_CHAN_INFO_SAMP_FREQ:
++ *type = IIO_VAL_INT_PLUS_MICRO;
++ *vals = (const int *)bmi323_acc_gyro_odr;
++ *length = ARRAY_SIZE(bmi323_acc_gyro_odr) * 2;
++ return IIO_AVAIL_LIST;
++ case IIO_CHAN_INFO_SCALE:
++ sensor = bmi323_iio_to_sensor(chan->type);
++ *type = IIO_VAL_INT_PLUS_MICRO;
++ *vals = (const int *)bmi323_hw[sensor].scale_table;
++ *length = bmi323_hw[sensor].scale_table_len * 2;
++ return IIO_AVAIL_LIST;
++ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
++ *type = IIO_VAL_INT;
++ *vals = (const int *)bmi323_accel_gyro_avrg;
++ *length = ARRAY_SIZE(bmi323_accel_gyro_avrg);
++ return IIO_AVAIL_LIST;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int bmi323_write_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan, int val,
++ int val2, long mask)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++ int ret;
++
++ switch (mask) {
++ case IIO_CHAN_INFO_SAMP_FREQ:
++ ret = iio_device_claim_direct_mode(indio_dev);
++ if (ret)
++ return ret;
++
++ ret = bmi323_set_odr(data, bmi323_iio_to_sensor(chan->type),
++ val, val2);
++ iio_device_release_direct_mode(indio_dev);
++ return ret;
++ case IIO_CHAN_INFO_SCALE:
++ ret = iio_device_claim_direct_mode(indio_dev);
++ if (ret)
++ return ret;
++
++ ret = bmi323_set_scale(data, bmi323_iio_to_sensor(chan->type),
++ val, val2);
++ iio_device_release_direct_mode(indio_dev);
++ return ret;
++ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
++ ret = iio_device_claim_direct_mode(indio_dev);
++ if (ret)
++ return ret;
++
++ ret = bmi323_set_average(data, bmi323_iio_to_sensor(chan->type),
++ val);
++
++ iio_device_release_direct_mode(indio_dev);
++ return ret;
++ case IIO_CHAN_INFO_ENABLE:
++ return bmi323_enable_steps(data, val);
++ case IIO_CHAN_INFO_PROCESSED:
++ scoped_guard(mutex, &data->mutex) {
++ if (val || !FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK,
++ data->feature_events))
++ return -EINVAL;
++
++ /* Clear step counter value */
++ ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,
++ BMI323_STEP_SC1_RST_CNT_MSK,
++ FIELD_PREP(BMI323_STEP_SC1_RST_CNT_MSK,
++ 1));
++ }
++ return ret;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int bmi323_read_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan, int *val,
++ int *val2, long mask)
++{
++ struct bmi323_data *data = iio_priv(indio_dev);
++ int ret;
++
++ switch (mask) {
++ case IIO_CHAN_INFO_PROCESSED:
++ return bmi323_read_steps(data, val);
++ case IIO_CHAN_INFO_RAW:
++ switch (chan->type) {
++ case IIO_ACCEL:
++ case IIO_ANGL_VEL:
++ ret = iio_device_claim_direct_mode(indio_dev);
++ if (ret)
++ return ret;
++
++ ret = bmi323_read_axis(data, chan, val);
++
++ iio_device_release_direct_mode(indio_dev);
++ return ret;
++ case IIO_TEMP:
++ return bmi323_get_temp_data(data, val);
++ default:
++ return -EINVAL;
++ }
++ case IIO_CHAN_INFO_SAMP_FREQ:
++ return bmi323_get_odr(data, bmi323_iio_to_sensor(chan->type),
++ val, val2);
++ case IIO_CHAN_INFO_SCALE:
++ switch (chan->type) {
++ case IIO_ACCEL:
++ case IIO_ANGL_VEL:
++ *val = 0;
++ return bmi323_get_scale(data,
++ bmi323_iio_to_sensor(chan->type),
++ val2);
++ case IIO_TEMP:
++ *val = BMI323_TEMP_SCALE / MEGA;
++ *val2 = BMI323_TEMP_SCALE % MEGA;
++ return IIO_VAL_INT_PLUS_MICRO;
++ default:
++ return -EINVAL;
++ }
++ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
++ return bmi323_get_average(data,
++ bmi323_iio_to_sensor(chan->type),
++ val);
++ case IIO_CHAN_INFO_OFFSET:
++ switch (chan->type) {
++ case IIO_TEMP:
++ *val = BMI323_TEMP_OFFSET;
++ return IIO_VAL_INT;
++ default:
++ return -EINVAL;
++ }
++ case IIO_CHAN_INFO_ENABLE:
++ scoped_guard(mutex, &data->mutex)
++ *val = FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK,
++ data->feature_events);
++ return IIO_VAL_INT;
++ default:
++ return -EINVAL;
++ }
++}
++
++static const struct iio_info bmi323_info = {
++ .read_raw = bmi323_read_raw,
++ .write_raw = bmi323_write_raw,
++ .read_avail = bmi323_read_avail,
++ .hwfifo_set_watermark = bmi323_set_watermark,
++ .write_event_config = bmi323_write_event_config,
++ .read_event_config = bmi323_read_event_config,
++ .write_event_value = bmi323_write_event_value,
++ .read_event_value = bmi323_read_event_value,
++ .event_attrs = &bmi323_event_attribute_group,
++};
++
++#define BMI323_SCAN_MASK_ACCEL_3AXIS \
++ (BIT(BMI323_ACCEL_X) | BIT(BMI323_ACCEL_Y) | BIT(BMI323_ACCEL_Z))
++
++#define BMI323_SCAN_MASK_GYRO_3AXIS \
++ (BIT(BMI323_GYRO_X) | BIT(BMI323_GYRO_Y) | BIT(BMI323_GYRO_Z))
++
++static const unsigned long bmi323_avail_scan_masks[] = {
++ /* 3-axis accel */
++ BMI323_SCAN_MASK_ACCEL_3AXIS,
++ /* 3-axis gyro */
++ BMI323_SCAN_MASK_GYRO_3AXIS,
++ /* 3-axis accel + 3-axis gyro */
++ BMI323_SCAN_MASK_ACCEL_3AXIS | BMI323_SCAN_MASK_GYRO_3AXIS,
++ 0
++};
++
++static int bmi323_int_pin_config(struct bmi323_data *data,
++ enum bmi323_irq_pin irq_pin,
++ bool active_high, bool open_drain, bool latch)
++{
++ unsigned int mask, field_value;
++ int ret;
++
++ ret = regmap_update_bits(data->regmap, BMI323_IO_INT_CONF_REG,
++ BMI323_IO_INT_LTCH_MSK,
++ FIELD_PREP(BMI323_IO_INT_LTCH_MSK, latch));
++ if (ret)
++ return ret;
++
++ ret = bmi323_update_ext_reg(data, BMI323_GEN_SET1_REG,
++ BMI323_GEN_HOLD_DUR_MSK,
++ FIELD_PREP(BMI323_GEN_HOLD_DUR_MSK, 0));
++ if (ret)
++ return ret;
++
++ switch (irq_pin) {
++ case BMI323_IRQ_INT1:
++ mask = BMI323_IO_INT1_LVL_OD_OP_MSK;
++
++ field_value = FIELD_PREP(BMI323_IO_INT1_LVL_MSK, active_high) |
++ FIELD_PREP(BMI323_IO_INT1_OD_MSK, open_drain) |
++ FIELD_PREP(BMI323_IO_INT1_OP_EN_MSK, 1);
++ break;
++ case BMI323_IRQ_INT2:
++ mask = BMI323_IO_INT2_LVL_OD_OP_MSK;
++
++ field_value = FIELD_PREP(BMI323_IO_INT2_LVL_MSK, active_high) |
++ FIELD_PREP(BMI323_IO_INT2_OD_MSK, open_drain) |
++ FIELD_PREP(BMI323_IO_INT2_OP_EN_MSK, 1);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return regmap_update_bits(data->regmap, BMI323_IO_INT_CTR_REG, mask,
++ field_value);
++}
++
++static int bmi323_trigger_probe(struct bmi323_data *data,
++ struct iio_dev *indio_dev)
++{
++ bool open_drain, active_high, latch;
++ struct fwnode_handle *fwnode;
++ enum bmi323_irq_pin irq_pin;
++ int ret, irq, irq_type;
++ struct irq_data *desc;
++
++ fwnode = dev_fwnode(data->dev);
++ if (!fwnode)
++ return -ENODEV;
++
++ irq = fwnode_irq_get_byname(fwnode, "INT1");
++ if (irq > 0) {
++ irq_pin = BMI323_IRQ_INT1;
++ } else {
++ irq = fwnode_irq_get_byname(fwnode, "INT2");
++ if (irq < 0)
++ return 0;
++
++ irq_pin = BMI323_IRQ_INT2;
++ }
++
++ desc = irq_get_irq_data(irq);
++ if (!desc)
++ return dev_err_probe(data->dev, -EINVAL,
++ "Could not find IRQ %d\n", irq);
++
++ irq_type = irqd_get_trigger_type(desc);
++ switch (irq_type) {
++ case IRQF_TRIGGER_RISING:
++ latch = false;
++ active_high = true;
++ break;
++ case IRQF_TRIGGER_HIGH:
++ latch = true;
++ active_high = true;
++ break;
++ case IRQF_TRIGGER_FALLING:
++ latch = false;
++ active_high = false;
++ break;
++ case IRQF_TRIGGER_LOW:
++ latch = true;
++ active_high = false;
++ break;
++ default:
++ return dev_err_probe(data->dev, -EINVAL,
++ "Invalid interrupt type 0x%x specified\n",
++ irq_type);
++ }
++
++ open_drain = fwnode_property_read_bool(fwnode, "drive-open-drain");
++
++ ret = bmi323_int_pin_config(data, irq_pin, active_high, open_drain,
++ latch);
++ if (ret)
++ return dev_err_probe(data->dev, ret,
++ "Failed to configure irq line\n");
++
++ data->trig = devm_iio_trigger_alloc(data->dev, "%s-trig-%d",
++ indio_dev->name, irq_pin);
++ if (!data->trig)
++ return -ENOMEM;
++
++ data->trig->ops = &bmi323_trigger_ops;
++ iio_trigger_set_drvdata(data->trig, data);
++
++ ret = devm_request_threaded_irq(data->dev, irq, NULL,
++ bmi323_irq_thread_handler,
++ IRQF_ONESHOT, "bmi323-int", indio_dev);
++ if (ret)
++ return dev_err_probe(data->dev, ret, "Failed to request IRQ\n");
++
++ ret = devm_iio_trigger_register(data->dev, data->trig);
++ if (ret)
++ return dev_err_probe(data->dev, ret,
++ "Trigger registration failed\n");
++
++ data->irq_pin = irq_pin;
++
++ return 0;
++}
++
++static int bmi323_feature_engine_enable(struct bmi323_data *data, bool en)
++{
++ unsigned int feature_status;
++ int ret;
++
++ if (!en)
++ return regmap_write(data->regmap, BMI323_FEAT_CTRL_REG, 0);
++
++ ret = regmap_write(data->regmap, BMI323_FEAT_IO2_REG, 0x012c);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(data->regmap, BMI323_FEAT_IO_STATUS_REG,
++ BMI323_FEAT_IO_STATUS_MSK);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(data->regmap, BMI323_FEAT_CTRL_REG,
++ BMI323_FEAT_ENG_EN_MSK);
++ if (ret)
++ return ret;
++
++ /*
++ * It takes around 4 msec to enable the Feature engine, so check
++ * the status of the feature engine every 2 msec for a maximum
++ * of 5 trials.
++ */
++ ret = regmap_read_poll_timeout(data->regmap, BMI323_FEAT_IO1_REG,
++ feature_status,
++ FIELD_GET(BMI323_FEAT_IO1_ERR_MSK,
++ feature_status) == 1,
++ BMI323_FEAT_ENG_POLL,
++ BMI323_FEAT_ENG_TIMEOUT);
++ if (ret)
++ return dev_err_probe(data->dev, -EINVAL,
++ "Failed to enable feature engine\n");
++
++ return 0;
++}
++
++static void bmi323_disable(void *data_ptr)
++{
++ struct bmi323_data *data = data_ptr;
++
++ bmi323_set_mode(data, BMI323_ACCEL, ACC_GYRO_MODE_DISABLE);
++ bmi323_set_mode(data, BMI323_GYRO, ACC_GYRO_MODE_DISABLE);
++}
++
++static int bmi323_set_bw(struct bmi323_data *data,
++ enum bmi323_sensor_type sensor, enum bmi323_3db_bw bw)
++{
++ return regmap_update_bits(data->regmap, bmi323_hw[sensor].config,
++ BMI323_ACC_GYRO_CONF_BW_MSK,
++ FIELD_PREP(BMI323_ACC_GYRO_CONF_BW_MSK, bw));
++}
++
++static int bmi323_init(struct bmi323_data *data)
++{
++ int ret, val;
++
++ /*
++ * Perform soft reset to make sure the device is in a known state after
++ * start up. A delay of 1.5 ms is required after reset.
++ * See datasheet section 5.17 "Soft Reset".
++ */
++ ret = regmap_write(data->regmap, BMI323_CMD_REG, BMI323_RST_VAL);
++ if (ret)
++ return ret;
++
++ usleep_range(1500, 2000);
++
++ /*
++ * Dummy read is required to enable SPI interface after reset.
++ * See datasheet section 7.2.1 "Protocol Selection".
++ */
++ regmap_read(data->regmap, BMI323_CHIP_ID_REG, &val);
++
++ ret = regmap_read(data->regmap, BMI323_STATUS_REG, &val);
++ if (ret)
++ return ret;
++
++ if (!FIELD_GET(BMI323_STATUS_POR_MSK, val))
++ return dev_err_probe(data->dev, -EINVAL,
++ "Sensor initialization error\n");
++
++ ret = regmap_read(data->regmap, BMI323_CHIP_ID_REG, &val);
++ if (ret)
++ return ret;
++
++ if (FIELD_GET(BMI323_CHIP_ID_MSK, val) != BMI323_CHIP_ID_VAL)
++ return dev_err_probe(data->dev, -EINVAL, "Chip ID mismatch\n");
++
++ ret = bmi323_feature_engine_enable(data, true);
++ if (ret)
++ return ret;
++
++ ret = regmap_read(data->regmap, BMI323_ERR_REG, &val);
++ if (ret)
++ return ret;
++
++ if (val)
++ return dev_err_probe(data->dev, -EINVAL,
++ "Sensor power error = 0x%x\n", val);
++
++ /*
++ * Set the Bandwidth coefficient which defines the 3 dB cutoff
++ * frequency in relation to the ODR.
++ */
++ ret = bmi323_set_bw(data, BMI323_ACCEL, BMI323_BW_ODR_BY_2);
++ if (ret)
++ return ret;
++
++ ret = bmi323_set_bw(data, BMI323_GYRO, BMI323_BW_ODR_BY_2);
++ if (ret)
++ return ret;
++
++ ret = bmi323_set_odr(data, BMI323_ACCEL, 25, 0);
++ if (ret)
++ return ret;
++
++ ret = bmi323_set_odr(data, BMI323_GYRO, 25, 0);
++ if (ret)
++ return ret;
++
++ return devm_add_action_or_reset(data->dev, bmi323_disable, data);
++}
++
++int bmi323_core_probe(struct device *dev)
++{
++ static const char * const regulator_names[] = { "vdd", "vddio" };
++ struct iio_dev *indio_dev;
++ struct bmi323_data *data;
++ struct regmap *regmap;
++ int ret;
++
++ regmap = dev_get_regmap(dev, NULL);
++ if (!regmap)
++ return dev_err_probe(dev, -ENODEV, "Failed to get regmap\n");
++
++ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
++ if (!indio_dev)
++ return dev_err_probe(dev, -ENOMEM,
++ "Failed to allocate device\n");
++
++ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),
++ regulator_names);
++ if (ret)
++ return dev_err_probe(dev, ret, "Failed to enable regulators\n");
++
++ data = iio_priv(indio_dev);
++ data->dev = dev;
++ data->regmap = regmap;
++ mutex_init(&data->mutex);
++
++ ret = bmi323_init(data);
++ if (ret)
++ return -EINVAL;
++
++ ret = iio_read_mount_matrix(dev, &data->orientation);
++ if (ret)
++ return ret;
++
++ indio_dev->name = "bmi323-imu";
++ indio_dev->info = &bmi323_info;
++ indio_dev->channels = bmi323_channels;
++ indio_dev->num_channels = ARRAY_SIZE(bmi323_channels);
++ indio_dev->available_scan_masks = bmi323_avail_scan_masks;
++ indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
++ dev_set_drvdata(data->dev, indio_dev);
++
++ ret = bmi323_trigger_probe(data, indio_dev);
++ if (ret)
++ return -EINVAL;
++
++ ret = devm_iio_triggered_buffer_setup_ext(data->dev, indio_dev,
++ &iio_pollfunc_store_time,
++ bmi323_trigger_handler,
++ IIO_BUFFER_DIRECTION_IN,
++ &bmi323_buffer_ops,
++ bmi323_fifo_attributes);
++ if (ret)
++ return dev_err_probe(data->dev, ret,
++ "Failed to setup trigger buffer\n");
++
++ ret = devm_iio_device_register(data->dev, indio_dev);
++ if (ret)
++ return dev_err_probe(data->dev, ret,
++ "Unable to register iio device\n");
++
++ return 0;
++}
++EXPORT_SYMBOL_NS_GPL(bmi323_core_probe, IIO_BMI323);
++
++MODULE_DESCRIPTION("Bosch BMI323 IMU driver");
++MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/iio/imu/bmi323/bmi323_i2c.c b/drivers/iio/imu/bmi323/bmi323_i2c.c
+new file mode 100644
+index 000000000000..0008e186367d
+--- /dev/null
++++ b/drivers/iio/imu/bmi323/bmi323_i2c.c
+@@ -0,0 +1,121 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * I2C driver for Bosch BMI323 6-Axis IMU.
++ *
++ * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com>
++ */
++
++#include <linux/i2c.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/regmap.h>
++
++#include "bmi323.h"
++
++struct bmi323_i2c_priv {
++ struct i2c_client *i2c;
++ u8 i2c_rx_buffer[BMI323_FIFO_LENGTH_IN_BYTES + BMI323_I2C_DUMMY];
++};
++
++/*
++ * From BMI323 datasheet section 4: Notes on the Serial Interface Support.
++ * Each I2C register read operation requires to read two dummy bytes before
++ * the actual payload.
++ */
++static int bmi323_regmap_i2c_read(void *context, const void *reg_buf,
++ size_t reg_size, void *val_buf,
++ size_t val_size)
++{
++ struct bmi323_i2c_priv *priv = context;
++ struct i2c_msg msgs[2];
++ int ret;
++
++ msgs[0].addr = priv->i2c->addr;
++ msgs[0].flags = priv->i2c->flags;
++ msgs[0].len = reg_size;
++ msgs[0].buf = (u8 *)reg_buf;
++
++ msgs[1].addr = priv->i2c->addr;
++ msgs[1].len = val_size + BMI323_I2C_DUMMY;
++ msgs[1].buf = priv->i2c_rx_buffer;
++ msgs[1].flags = priv->i2c->flags | I2C_M_RD;
++
++ ret = i2c_transfer(priv->i2c->adapter, msgs, ARRAY_SIZE(msgs));
++ if (ret < 0)
++ return -EIO;
++
++ memcpy(val_buf, priv->i2c_rx_buffer + BMI323_I2C_DUMMY, val_size);
++
++ return 0;
++}
++
++static int bmi323_regmap_i2c_write(void *context, const void *data,
++ size_t count)
++{
++ struct bmi323_i2c_priv *priv = context;
++ u8 reg;
++
++ reg = *(u8 *)data;
++ return i2c_smbus_write_i2c_block_data(priv->i2c, reg,
++ count - sizeof(u8),
++ data + sizeof(u8));
++}
++
++static struct regmap_bus bmi323_regmap_bus = {
++ .read = bmi323_regmap_i2c_read,
++ .write = bmi323_regmap_i2c_write,
++};
++
++const struct regmap_config bmi323_i2c_regmap_config = {
++ .reg_bits = 8,
++ .val_bits = 16,
++ .max_register = BMI323_CFG_RES_REG,
++ .val_format_endian = REGMAP_ENDIAN_LITTLE,
++};
++
++static int bmi323_i2c_probe(struct i2c_client *i2c)
++{
++ struct device *dev = &i2c->dev;
++ struct bmi323_i2c_priv *priv;
++ struct regmap *regmap;
++
++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ priv->i2c = i2c;
++ regmap = devm_regmap_init(dev, &bmi323_regmap_bus, priv,
++ &bmi323_i2c_regmap_config);
++ if (IS_ERR(regmap))
++ return dev_err_probe(dev, PTR_ERR(regmap),
++ "Failed to initialize I2C Regmap\n");
++
++ return bmi323_core_probe(dev);
++}
++
++static const struct i2c_device_id bmi323_i2c_ids[] = {
++ { "bmi323" },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, bmi323_i2c_ids);
++
++static const struct of_device_id bmi323_of_i2c_match[] = {
++ { .compatible = "bosch,bmi323" },
++ { }
++};
++MODULE_DEVICE_TABLE(of, bmi323_of_i2c_match);
++
++static struct i2c_driver bmi323_i2c_driver = {
++ .driver = {
++ .name = "bmi323",
++ .of_match_table = bmi323_of_i2c_match,
++ },
++ .probe = bmi323_i2c_probe,
++ .id_table = bmi323_i2c_ids,
++};
++module_i2c_driver(bmi323_i2c_driver);
++
++MODULE_DESCRIPTION("Bosch BMI323 IMU driver");
++MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>");
++MODULE_LICENSE("GPL");
++MODULE_IMPORT_NS(IIO_BMI323);
+diff --git a/drivers/iio/imu/bmi323/bmi323_spi.c b/drivers/iio/imu/bmi323/bmi323_spi.c
+new file mode 100644
+index 000000000000..6dc3352dd714
+--- /dev/null
++++ b/drivers/iio/imu/bmi323/bmi323_spi.c
+@@ -0,0 +1,92 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * SPI driver for Bosch BMI323 6-Axis IMU.
++ *
++ * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com>
++ */
++
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/regmap.h>
++#include <linux/spi/spi.h>
++
++#include "bmi323.h"
++
++/*
++ * From BMI323 datasheet section 4: Notes on the Serial Interface Support.
++ * Each SPI register read operation requires to read one dummy byte before
++ * the actual payload.
++ */
++static int bmi323_regmap_spi_read(void *context, const void *reg_buf,
++ size_t reg_size, void *val_buf,
++ size_t val_size)
++{
++ struct spi_device *spi = context;
++
++ return spi_write_then_read(spi, reg_buf, reg_size, val_buf, val_size);
++}
++
++static int bmi323_regmap_spi_write(void *context, const void *data,
++ size_t count)
++{
++ struct spi_device *spi = context;
++ u8 *data_buff = (u8 *)data;
++
++ data_buff[1] = data_buff[0];
++ return spi_write(spi, data_buff + 1, count - 1);
++}
++
++static struct regmap_bus bmi323_regmap_bus = {
++ .read = bmi323_regmap_spi_read,
++ .write = bmi323_regmap_spi_write,
++};
++
++const struct regmap_config bmi323_spi_regmap_config = {
++ .reg_bits = 8,
++ .val_bits = 16,
++ .pad_bits = 8,
++ .read_flag_mask = BIT(7),
++ .max_register = BMI323_CFG_RES_REG,
++ .val_format_endian = REGMAP_ENDIAN_LITTLE,
++};
++
++static int bmi323_spi_probe(struct spi_device *spi)
++{
++ struct device *dev = &spi->dev;
++ struct regmap *regmap;
++
++ regmap = devm_regmap_init(dev, &bmi323_regmap_bus, dev,
++ &bmi323_spi_regmap_config);
++ if (IS_ERR(regmap))
++ return dev_err_probe(dev, PTR_ERR(regmap),
++ "Failed to initialize SPI Regmap\n");
++
++ return bmi323_core_probe(dev);
++}
++
++static const struct spi_device_id bmi323_spi_ids[] = {
++ { "bmi323" },
++ { }
++};
++MODULE_DEVICE_TABLE(spi, bmi323_spi_ids);
++
++static const struct of_device_id bmi323_of_spi_match[] = {
++ { .compatible = "bosch,bmi323" },
++ { }
++};
++MODULE_DEVICE_TABLE(of, bmi323_of_spi_match);
++
++static struct spi_driver bmi323_spi_driver = {
++ .driver = {
++ .name = "bmi323",
++ .of_match_table = bmi323_of_spi_match,
++ },
++ .probe = bmi323_spi_probe,
++ .id_table = bmi323_spi_ids,
++};
++module_spi_driver(bmi323_spi_driver);
++
++MODULE_DESCRIPTION("Bosch BMI323 IMU driver");
++MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>");
++MODULE_LICENSE("GPL");
++MODULE_IMPORT_NS(IIO_BMI323);
diff --git a/0002-iio-imu-bmi323-Make-the-local-structures-static.patch b/0002-iio-imu-bmi323-Make-the-local-structures-static.patch
new file mode 100644
index 000000000000..decd8c43e675
--- /dev/null
+++ b/0002-iio-imu-bmi323-Make-the-local-structures-static.patch
@@ -0,0 +1,37 @@
+Make the local structures static within their respective driver files.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202311070530.qKhLTz1Y-lkp@intel.com/
+Fixes: b512c767e7bc ("iio: imu: Add driver for BMI323 IMU")
+Signed-off-by: Jagath Jog J <jagathjog1996@gmail.com>
+---
+ drivers/iio/imu/bmi323/bmi323_i2c.c | 2 +-
+ drivers/iio/imu/bmi323/bmi323_spi.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/imu/bmi323/bmi323_i2c.c b/drivers/iio/imu/bmi323/bmi323_i2c.c
+index 0008e186367d..20a8001b9956 100644
+--- a/drivers/iio/imu/bmi323/bmi323_i2c.c
++++ b/drivers/iio/imu/bmi323/bmi323_i2c.c
+@@ -66,7 +66,7 @@ static struct regmap_bus bmi323_regmap_bus = {
+ .write = bmi323_regmap_i2c_write,
+ };
+
+-const struct regmap_config bmi323_i2c_regmap_config = {
++static const struct regmap_config bmi323_i2c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = BMI323_CFG_RES_REG,
+diff --git a/drivers/iio/imu/bmi323/bmi323_spi.c b/drivers/iio/imu/bmi323/bmi323_spi.c
+index 6dc3352dd714..7b1e8127d0dd 100644
+--- a/drivers/iio/imu/bmi323/bmi323_spi.c
++++ b/drivers/iio/imu/bmi323/bmi323_spi.c
+@@ -41,7 +41,7 @@ static struct regmap_bus bmi323_regmap_bus = {
+ .write = bmi323_regmap_spi_write,
+ };
+
+-const struct regmap_config bmi323_spi_regmap_config = {
++static const struct regmap_config bmi323_spi_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .pad_bits = 8,
diff --git a/0003-iio-imu_Add_ROG_ALLY_bmi323-support.patch b/0003-iio-imu_Add_ROG_ALLY_bmi323-support.patch
new file mode 100644
index 000000000000..4111417f6ac9
--- /dev/null
+++ b/0003-iio-imu_Add_ROG_ALLY_bmi323-support.patch
@@ -0,0 +1,54 @@
+diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
+index 1105918..d665a6e 100644
+--- a/drivers/iio/accel/bmc150-accel-core.c
++++ b/drivers/iio/accel/bmc150-accel-core.c
+@@ -10,6 +10,7 @@
+ #include <linux/delay.h>
+ #include <linux/slab.h>
+ #include <linux/acpi.h>
++#include <linux/dmi.h>
+ #include <linux/of_irq.h>
+ #include <linux/pm.h>
+ #include <linux/pm_runtime.h>
+@@ -1670,6 +1671,8 @@ int bmc150_accel_core_probe(struct device *dev, struct regmap *regmap, int irq,
+ struct iio_dev *indio_dev;
+ int ret;
+
++ if (dmi_match(DMI_BOARD_NAME, "RC71L") || (dmi_match(DMI_BOARD_NAME, "AB05-AMD") && dmi_match(DMI_PRODUCT_NAME, "AIR Plus")))
++ return -ENODEV; // Abort loading bmc150 for ASUS ROG ALLY, Ayaneo Air Plus
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+diff --git a/drivers/iio/imu/bmi323/bmi323_i2c.c b/drivers/iio/imu/bmi323/bmi323_i2c.c
+index 20a8001..346ba2d 100644
+--- a/drivers/iio/imu/bmi323/bmi323_i2c.c
++++ b/drivers/iio/imu/bmi323/bmi323_i2c.c
+@@ -5,6 +5,7 @@
+ * Copyright (C) 2023, Jagath Jog J <jagathjog1996@gmail.com>
+ */
+
++#include <linux/acpi.h>
+ #include <linux/i2c.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/module.h>
+@@ -93,6 +94,12 @@ static int bmi323_i2c_probe(struct i2c_client *i2c)
+ return bmi323_core_probe(dev);
+ }
+
++static const struct acpi_device_id bmi323_acpi_match[] = {
++ {"BOSC0200"},
++ { },
++};
++MODULE_DEVICE_TABLE(acpi, bmi323_acpi_match);
++
+ static const struct i2c_device_id bmi323_i2c_ids[] = {
+ { "bmi323" },
+ { }
+@@ -109,6 +116,7 @@ static struct i2c_driver bmi323_i2c_driver = {
+ .driver = {
+ .name = "bmi323",
+ .of_match_table = bmi323_of_i2c_match,
++ .acpi_match_table = ACPI_PTR(bmi323_acpi_match),
+ },
+ .probe = bmi323_i2c_probe,
+ .id_table = bmi323_i2c_ids,
diff --git a/0004-iio-imu-Load_ROG_ALLY_mount_matrix.patch b/0004-iio-imu-Load_ROG_ALLY_mount_matrix.patch
new file mode 100644
index 000000000000..7e8153b867ef
--- /dev/null
+++ b/0004-iio-imu-Load_ROG_ALLY_mount_matrix.patch
@@ -0,0 +1,51 @@
+diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
+index d752e9c..b495dba 100644
+--- a/drivers/iio/industrialio-core.c
++++ b/drivers/iio/industrialio-core.c
+@@ -13,6 +13,7 @@
+ #include <linux/cdev.h>
+ #include <linux/debugfs.h>
+ #include <linux/device.h>
++#include <linux/dmi.h>
+ #include <linux/err.h>
+ #include <linux/fs.h>
+ #include <linux/idr.h>
+@@ -571,6 +572,14 @@ static const struct iio_mount_matrix iio_mount_idmatrix = {
+ }
+ };
+
++static const struct iio_mount_matrix iio_mount_flip_x_z_matrix = {
++ .rotation = {
++ "-1", "0", "0",
++ "0", "1", "0",
++ "0", "0", "-1"
++ }
++};
++
+ static int iio_setup_mount_idmatrix(const struct device *dev,
+ struct iio_mount_matrix *matrix)
+ {
+@@ -579,6 +588,14 @@ static int iio_setup_mount_idmatrix(const struct device *dev,
+ return 0;
+ }
+
++static int iio_setup_mount_flip_x_z_matrix(const struct device *dev,
++ struct iio_mount_matrix *matrix)
++{
++ *matrix = iio_mount_flip_x_z_matrix;
++ dev_info(dev, "using flipped X-axis and flipped Z-axis mounting matrix...\n");
++ return 0;
++}
++
+ ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv,
+ const struct iio_chan_spec *chan, char *buf)
+ {
+@@ -615,6 +632,8 @@ int iio_read_mount_matrix(struct device *dev, struct iio_mount_matrix *matrix)
+ int err;
+
+ err = device_property_read_string_array(dev, "mount-matrix", matrix->rotation, len);
++ if (dmi_match(DMI_BOARD_NAME, "RC71L"))
++ return iio_setup_mount_flip_x_z_matrix(dev, matrix);
+ if (err == len)
+ return 0;
+
diff --git a/0005-iio-imu-ASUS-ROG-ALLY-force-INT1-IRQ.patch b/0005-iio-imu-ASUS-ROG-ALLY-force-INT1-IRQ.patch
new file mode 100644
index 000000000000..292c7bebb453
--- /dev/null
+++ b/0005-iio-imu-ASUS-ROG-ALLY-force-INT1-IRQ.patch
@@ -0,0 +1,40 @@
+diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c
+index 0bd5ded..eae7756 100644
+--- a/drivers/iio/imu/bmi323/bmi323_core.c
++++ b/drivers/iio/imu/bmi323/bmi323_core.c
+@@ -10,6 +10,7 @@
+ #include <linux/bitfield.h>
+ #include <linux/cleanup.h>
+ #include <linux/device.h>
++#include <linux/dmi.h>
+ #include <linux/interrupt.h>
+ #include <linux/minmax.h>
+ #include <linux/module.h>
+@@ -1870,6 +1871,8 @@ static int bmi323_trigger_probe(struct bmi323_data *data,
+ return -ENODEV;
+
+ irq = fwnode_irq_get_byname(fwnode, "INT1");
++ if (dmi_match(DMI_BOARD_NAME, "RC71L"))
++ irq = 1; // force IRQ INT1 for ASUS ROG ALLY
+ if (irq > 0) {
+ irq_pin = BMI323_IRQ_INT1;
+ } else {
+@@ -1886,6 +1889,8 @@ static int bmi323_trigger_probe(struct bmi323_data *data,
+ "Could not find IRQ %d\n", irq);
+
+ irq_type = irqd_get_trigger_type(desc);
++ if (dmi_match(DMI_BOARD_NAME, "RC71L"))
++ irq_type = IRQF_TRIGGER_RISING; // forcing trigger type for ASUS ROG ALLY
+ switch (irq_type) {
+ case IRQF_TRIGGER_RISING:
+ latch = false;
+@@ -1910,7 +1915,8 @@ static int bmi323_trigger_probe(struct bmi323_data *data,
+ }
+
+ open_drain = fwnode_property_read_bool(fwnode, "drive-open-drain");
+-
++ if (dmi_match(DMI_BOARD_NAME, "RC71L"))
++ open_drain = false; // forcing whether open drain (true) or push-pull (false) for ROG ALLY
+ ret = bmi323_int_pin_config(data, irq_pin, active_high, open_drain,
+ latch);
+ if (ret)
diff --git a/0999-patch_realtek.patch b/0999-patch_realtek.patch
index 2513ec48db10..81f7ee33f9bf 100644
--- a/0999-patch_realtek.patch
+++ b/0999-patch_realtek.patch
@@ -5,6 +5,6 @@
SND_PCI_QUIRK(0x103c, 0x87f6, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
+ SND_PCI_QUIRK(0x103c, 0x89da, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
+ SND_PCI_QUIRK(0x103c, 0x87fe, "HP Laptop 15s-fq2xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8805, "HP ProBook 650 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
- SND_PCI_QUIRK(0x103c, 0x8811, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
diff --git a/PKGBUILD b/PKGBUILD
index 31d04ac05fda..c086f5e9d42b 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -12,7 +12,7 @@ pkgbase=linux-jcore
pkgname=('linux-jcore' 'linux-jcore-headers')
_kernelname=-jcore
_hostname=jcore
-pkgver=6.6.6
+pkgver=6.6.25
pkgrel=2
pkgdesc="Kernel for Manjaro/EndeavourOS/Arch (ACS override patch include)"
arch=('x86_64')
@@ -22,7 +22,7 @@ makedepends=(bc docbook-xsl libelf pahole python-sphinx git inetutils kmod xmlto
replaces=('linux-acs-manjaro' 'linux-acs-manjaro-headers')
options=('!strip')
-source=("https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$pkgver.tar.xz"
+source=(https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$pkgver.tar.xz
config
# Upstream Patches
# ARCH Patches
@@ -32,13 +32,10 @@ source=("https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$pkgver.tar.xz"
# Realtek patch
0999-patch_realtek.patch
# ROG ALLY Patches
- 0000-hid-asus-add-const-to-read-only-outgoing-usb-buffer.patch
- 0001-hid-asus-reset-the-backlight-brightness-level-on-resume.patch
- v14.1-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch
- v14.1-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch
- v14.1-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch
- v14.1-0004-HID-asus-add-ROG-Ally-xpad-settings.patch
- v14.1-fix-defaults1.patch
+ v14.7-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch
+ v14.7-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch
+ v14.7-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch
+ v14.7-0004-HID-asus-add-ROG-Ally-xpad-settings.patch
0006-platform-x86-asus-wmi-disable-USB0-hub-on-ROG-Ally-b.patch
0007-mt7921e_Perform_FLR_to_recovery_the_device.patch
# AMD GPU reset patches
@@ -50,24 +47,27 @@ source=("https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$pkgver.tar.xz"
0001-ALSA-hda-cs35l41-Improve-support-for-ASUS-ROG-Ally.patch
# Additional ALLY patches
ROG-ALLY-NCT6775-PLATFORM.patch
- 0001-ROG-ALLY-bmi323-device.patch
+ 0001-iio-imu_Add_driver_for_BMI323_IMU.patch
+ 0002-iio-imu-bmi323-Make-the-local-structures-static.patch
+ 0003-iio-imu_Add_ROG_ALLY_bmi323-support.patch
+ 0004-iio-imu-Load_ROG_ALLY_mount_matrix.patch
+ 0005-iio-imu-ASUS-ROG-ALLY-force-INT1-IRQ.patch
# Steamdeck HID patches
0001-HID.patch
+ # OrangePi Neo patches
+ 0001-OrangePi-Neo-panel-orientation-quirk.patch
# ACS override patch
- '0999-acs.gitpatch')
+ 0999-acs.gitpatch)
-sha256sums=('ebf70a917934b13169e1be5b95c3b6c2fea5bc14e6dc144f1efb8a0016b224c8'
- '043ada1688a42e652bb0b339d2f9732c323c22da96bb2ca2bcf144a731c5e981'
+sha256sums=('99d210be87908233a55b0fadc0dccd3b95926c0651b6b82e37350b2029de1f44'
+ '9736c7856f4dd543d2172e1cb8a63cabdd6ed6fbf314dfdb5fe4c60b74954a68'
'05f04019d4a2ee072238c32860fa80d673687d84d78ef436ae9332b6fb788467'
'e1d17690dd21e8d5482b63ca66bfe6b478d39e8e8b59eedd53adb0a55ebc308d'
- '3aa9f1ca47bb078f3c9a52fe61897cf4fe989068cd7e66bfa6644fd605fa40d2'
- 'fb2cd8a3ea9d47bd78c99b8ece1f3959c20b4de97a7959a12650f989f5c724da'
- '7f3194f1a7c5ebc27bbfa4559cfd9a2ccffddbbd2d259c0d9c68631cb66c5855'
- '176adde8fc3069bd28393bf0c9d788f1b0f9a186678aec4dc17b0b081c57f97b'
- '493fa177cf602f087e981e95fad3764e305f4c486d4c2ef78255388b913be9cf'
- '50ea381758fb8a8566f38a509fe7cf0448c77eaec5103066cafc2ecf02db1e9f'
- '970687b811034e722befde62bcf6d51c7442a217074ed0fb71460bb1803f4c64'
- 'c00b23162fdbf50de375d8e444b6d59e2e3630cfac55ec1d06114b9dad00e542'
+ 'a99b684fe5bc7fdacc6f5b1f2b6593672fc5d1e676c4de03ec29723747fc574b'
+ 'b099ae83a3b561b8bff8b32b44b6f4835b99eb150c2314177aa0bc8ca96e2ead'
+ '10b60663195a65ec3b0f50b49e4c0af952369ee5afe95e11a69ffccefc020eb2'
+ '3c8b877dfaf85acf45b54c85a44fa269aa1512ea3781fe551cf6d4e2d69c992d'
+ '73aa4be8c1abcf1b24c9a5c5072e68da3da82df807f3ff49660a100d7634da1d'
'836e88044263f7bc474ca466b3d0d98c39e265db94925c300d0b138492946a13'
'd673d034fbcd80426fd8d9c6af56537c5fe5b55fe49d74e313474d7fc285ecc1'
'1f62542a889a6c2eafd43acd0699f54720ed891eeda66a4a9261d75b92f28b7f'
@@ -76,8 +76,13 @@ sha256sums=('ebf70a917934b13169e1be5b95c3b6c2fea5bc14e6dc144f1efb8a0016b224c8'
'79970a4729572cb25fd4644d66f38ecd5b3e1610a42ea4bbe436b501f3469fa2'
'430a7f971d78d0873708e0ad38fba602ceafefd4da8ebbf9d9c591bc4799acb5'
'cfcd5c177423df8b7b98b0500fe7ab0757f895ed945c33e205963f0069c7a3be'
- '5574a68b1c7733769835bb856a8c32e54398dfde59f264708672b87b73b3c6ea'
+ '708a9899f80db35fb0f06e0144c361eac9a9b2d154cf2fa388a0b4810847e24c'
+ '514fd03c17245ed0aaee63e8830c9b02b00efa0307f7e0989065edec6ae185f0'
+ 'fccdf24b25620dd8271bb3b52ddc53f8882dec26518258dc47e1469fed33e516'
+ 'c3b901db58288b5cc5d8a947ac8ffec339870b00aba493d68a39f65c4ff3d869'
+ '5792a59a0c726a205ae1c1728700ea3e6385231cadc2cfdd2db08295b100638c'
'7c948773d758418d8a436067265d678c444827562c46b9fced2ff31ced108481'
+ 'aa2ff6edca0177b864868fdc2752d3a0eaaf5b801bd17e5c59dfd78999226d83'
'458d7e024d33d4965b14b9b987f01a2884ff28761cff5da7c6a54132a95e9f36')
prepare() {
diff --git a/config b/config
index e6be5e9d349a..85c27889b82d 100644
--- a/config
+++ b/config
@@ -1,24 +1,25 @@
#
# Automatically generated file; DO NOT EDIT.
-# Linux/x86 6.6.5-1 Kernel Configuration
+# Linux/x86 6.6.24-1 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="gcc (GCC) 13.2.1 20230801"
CONFIG_CC_IS_GCC=y
CONFIG_GCC_VERSION=130201
CONFIG_CLANG_VERSION=0
CONFIG_AS_IS_GNU=y
-CONFIG_AS_VERSION=24100
+CONFIG_AS_VERSION=24200
CONFIG_LD_IS_BFD=y
-CONFIG_LD_VERSION=24100
+CONFIG_LD_VERSION=24200
CONFIG_LLD_VERSION=0
CONFIG_CC_CAN_LINK=y
CONFIG_CC_CAN_LINK_STATIC=y
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT=y
+CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
CONFIG_TOOLS_SUPPORT_RELR=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
-CONFIG_PAHOLE_VERSION=125
+CONFIG_PAHOLE_VERSION=126
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y
@@ -205,7 +206,7 @@ CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
CONFIG_CC_HAS_INT128=y
CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
-CONFIG_GCC11_NO_ARRAY_BOUNDS=y
+CONFIG_GCC10_NO_ARRAY_BOUNDS=y
CONFIG_CC_NO_ARRAY_BOUNDS=y
CONFIG_ARCH_SUPPORTS_INT128=y
CONFIG_NUMA_BALANCING=y
@@ -469,7 +470,6 @@ CONFIG_X86_DIRECT_GBPAGES=y
CONFIG_X86_CPA_STATISTICS=y
CONFIG_X86_MEM_ENCRYPT=y
CONFIG_AMD_MEM_ENCRYPT=y
-# CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT is not set
CONFIG_NUMA=y
CONFIG_AMD_NUMA=y
CONFIG_X86_64_ACPI_NUMA=y
@@ -563,6 +563,7 @@ CONFIG_CPU_IBRS_ENTRY=y
CONFIG_CPU_SRSO=y
CONFIG_SLS=y
# CONFIG_GDS_FORCE_MITIGATION is not set
+CONFIG_MITIGATION_RFDS=y
CONFIG_ARCH_HAS_ADD_PAGES=y
#
@@ -1985,7 +1986,6 @@ CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_CMTP=m
CONFIG_BT_HIDP=m
-# CONFIG_BT_HS is not set
CONFIG_BT_LE=y
CONFIG_BT_LE_L2CAP_ECRED=y
CONFIG_BT_6LOWPAN=m
@@ -3504,7 +3504,6 @@ CONFIG_STMMAC_ETH=m
CONFIG_STMMAC_PLATFORM=m
CONFIG_DWMAC_GENERIC=m
CONFIG_DWMAC_INTEL=m
-CONFIG_DWMAC_LOONGSON=m
CONFIG_STMMAC_PCI=m
CONFIG_NET_VENDOR_SUN=y
CONFIG_HAPPYMEAL=m
@@ -4374,7 +4373,6 @@ CONFIG_TOUCHSCREEN_PENMOUNT=m
CONFIG_TOUCHSCREEN_EDT_FT5X06=m
CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
CONFIG_TOUCHSCREEN_TOUCHWIN=m
-CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
CONFIG_TOUCHSCREEN_PIXCIR=m
CONFIG_TOUCHSCREEN_WDT87XX_I2C=m
CONFIG_TOUCHSCREEN_WM831X=m
@@ -5684,7 +5682,6 @@ CONFIG_MFD_SM501=m
CONFIG_MFD_SM501_GPIO=y
CONFIG_MFD_SKY81452=m
CONFIG_MFD_SYSCON=y
-CONFIG_MFD_TI_AM335X_TSCADC=m
CONFIG_MFD_LP3943=m
CONFIG_MFD_LP8788=y
CONFIG_MFD_TI_LMU=m
@@ -9558,7 +9555,6 @@ CONFIG_TI_ADS8344=m
CONFIG_TI_ADS8688=m
CONFIG_TI_ADS124S08=m
CONFIG_TI_ADS131E08=m
-CONFIG_TI_AM335X_ADC=m
CONFIG_TI_LMP92064=m
CONFIG_TI_TLC4541=m
CONFIG_TI_TSC2046=m
@@ -9800,6 +9796,9 @@ CONFIG_BMI160_SPI=m
CONFIG_BOSCH_BNO055=m
CONFIG_BOSCH_BNO055_SERIAL=m
CONFIG_BOSCH_BNO055_I2C=m
+CONFIG_BMI323=m
+CONFIG_BMI323_I2C=m
+CONFIG_BMI323_SPI=m
CONFIG_FXOS8700=m
CONFIG_FXOS8700_I2C=m
CONFIG_FXOS8700_SPI=m
@@ -11424,8 +11423,6 @@ CONFIG_DEBUG_LIST=y
# CONFIG_DEBUG_MAPLE_TREE is not set
# end of Debug kernel data structures
-# CONFIG_DEBUG_CREDENTIALS is not set
-
#
# RCU Debugging
#
diff --git a/v14.1-fix-defaults1.patch b/v14.1-fix-defaults1.patch
deleted file mode 100644
index a057f043c432..000000000000
--- a/v14.1-fix-defaults1.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-diff --git a/drivers/hid/hid-asus-rog.c b/drivers/hid/hid-asus-rog.c
-index 91f3a7786893..d765ca7fc3a9 100644
---- a/drivers/hid/hid-asus-rog.c
-+++ b/drivers/hid/hid-asus-rog.c
-@@ -1396,31 +1396,33 @@ static int asus_rog_ally_probe(struct hid_device *hdev, const struct rog_ops *op
- }
- // TODO: move these to functions
- drvdata->rog_ally_data->mode = xpad_mode_game;
-- drvdata->rog_ally_data->deadzones[xpad_mode_game][0][1] = 64;
-- drvdata->rog_ally_data->deadzones[xpad_mode_game][0][3] = 64;
-- drvdata->rog_ally_data->deadzones[xpad_mode_game][1][1] = 64;
-- drvdata->rog_ally_data->deadzones[xpad_mode_game][1][3] = 64;
--
-- drvdata->rog_ally_data->anti_deadzones[xpad_mode_game][0] = 64;
-- drvdata->rog_ally_data->anti_deadzones[xpad_mode_game][1] = 64;
--
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][0][0] = 0x14;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][0][1] = 0x14;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][0][2] = 0x28;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][0][3] = 0x28;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][0][4] = 0x3c;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][0][5] = 0x3c;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][0][6] = 0x50;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][0][7] = 0x50;
--
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][1][0] = 0x14;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][1][1] = 0x14;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][1][2] = 0x28;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][1][3] = 0x28;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][1][4] = 0x3c;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][1][5] = 0x3c;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][1][6] = 0x50;
-- drvdata->rog_ally_data->response_curve[xpad_mode_game][1][7] = 0x50;
-+ for (int i = 0; i < xpad_mode_mouse; i++) {
-+ drvdata->rog_ally_data->deadzones[i][0][1] = 64;
-+ drvdata->rog_ally_data->deadzones[i][0][3] = 64;
-+ drvdata->rog_ally_data->deadzones[i][1][1] = 64;
-+ drvdata->rog_ally_data->deadzones[i][1][3] = 64;
-+
-+ drvdata->rog_ally_data->response_curve[i][0][0] = 0x14;
-+ drvdata->rog_ally_data->response_curve[i][0][1] = 0x14;
-+ drvdata->rog_ally_data->response_curve[i][0][2] = 0x28;
-+ drvdata->rog_ally_data->response_curve[i][0][3] = 0x28;
-+ drvdata->rog_ally_data->response_curve[i][0][4] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[i][0][5] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[i][0][6] = 0x50;
-+ drvdata->rog_ally_data->response_curve[i][0][7] = 0x50;
-+
-+ drvdata->rog_ally_data->response_curve[i][1][0] = 0x14;
-+ drvdata->rog_ally_data->response_curve[i][1][1] = 0x14;
-+ drvdata->rog_ally_data->response_curve[i][1][2] = 0x28;
-+ drvdata->rog_ally_data->response_curve[i][1][3] = 0x28;
-+ drvdata->rog_ally_data->response_curve[i][1][4] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[i][1][5] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[i][1][6] = 0x50;
-+ drvdata->rog_ally_data->response_curve[i][1][7] = 0x50;
-+
-+ drvdata->rog_ally_data->vibration_intensity[i][0] = 64;
-+ drvdata->rog_ally_data->vibration_intensity[i][1] = 64;
-+ }
-
- ret = __gamepad_set_mode(&hdev->dev, xpad_mode_game);
- if (ret < 0)
diff --git a/v14.1-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch b/v14.7-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch
index b5fb39f5f4ae..3aa05b55031f 100644
--- a/v14.1-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch
+++ b/v14.7-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch
@@ -1,7 +1,7 @@
-From f311b6a3ff32c8221a0003c4a154aecbf04fb12c Mon Sep 17 00:00:00 2001
+From 5efbf21a6dc030b27e32cd632cfde1c3c7801075 Mon Sep 17 00:00:00 2001
From: "Luke D. Jones" <luke@ljones.dev>
Date: Sat, 2 Dec 2023 17:27:23 +1300
-Subject: [PATCH v14.1 1/4] HID: asus: fix more n-key report descriptors if
+Subject: [PATCH v14.7 1/4] HID: asus: fix more n-key report descriptors if
n-key quirked
Adjusts the report descriptor for N-Key devices to
@@ -85,5 +85,5 @@ index 78cdfb8b9a7a..855972a4470f 100644
}
--
-2.41.0
+2.43.0
diff --git a/v14.1-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch b/v14.7-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch
index 2a2fa5ba18ce..f0f49674ceb1 100644
--- a/v14.1-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch
+++ b/v14.7-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch
@@ -1,7 +1,7 @@
-From 119615a0034ee5f8d7a949c1c9d992b1be125fcb Mon Sep 17 00:00:00 2001
+From d6b33439281d1b8cf93b0c5c5ecabcd9c6e7baad Mon Sep 17 00:00:00 2001
From: "Luke D. Jones" <luke@ljones.dev>
Date: Sat, 2 Dec 2023 17:47:59 +1300
-Subject: [PATCH v14.1 2/4] HID: asus: make asus_kbd_init() generic, remove
+Subject: [PATCH v14.7 2/4] HID: asus: make asus_kbd_init() generic, remove
rog_nkey_led_init()
Some of the n-key stuff is old and outdated, so
@@ -126,5 +126,5 @@ index 855972a4470f..cdd998a761fe 100644
return ret;
--
-2.41.0
+2.43.0
diff --git a/v14.1-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch b/v14.7-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch
index a40a650b018d..a2a2785f1268 100644
--- a/v14.1-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch
+++ b/v14.7-0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch
@@ -1,7 +1,7 @@
-From 2b1a33a519668105eb7261c2d8964da576be6146 Mon Sep 17 00:00:00 2001
+From 646c1ffacd59555825734bbcd2fa6e38100570c5 Mon Sep 17 00:00:00 2001
From: "Luke D. Jones" <luke@ljones.dev>
Date: Wed, 29 Nov 2023 22:18:11 +1300
-Subject: [PATCH v14.1 3/4] HID: asus: add ROG Ally N-Key ID and keycodes
+Subject: [PATCH v14.7 3/4] HID: asus: add ROG Ally N-Key ID and keycodes
---
drivers/hid/hid-asus.c | 7 +++++++
@@ -34,7 +34,7 @@ index cdd998a761fe..3a1a6024d299 100644
USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD),
QUIRK_ROG_CLAYMORE_II_KEYBOARD },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
-index c6e4e0d1f214..6debff9ad678 100644
+index 72046039d1be..ec9a41050446 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -208,6 +208,7 @@
@@ -46,5 +46,5 @@ index c6e4e0d1f214..6debff9ad678 100644
#define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869
--
-2.41.0
+2.43.0
diff --git a/v14.1-0004-HID-asus-add-ROG-Ally-xpad-settings.patch b/v14.7-0004-HID-asus-add-ROG-Ally-xpad-settings.patch
index 13bfbd78c677..0d4d43d19751 100644
--- a/v14.1-0004-HID-asus-add-ROG-Ally-xpad-settings.patch
+++ b/v14.7-0004-HID-asus-add-ROG-Ally-xpad-settings.patch
@@ -1,7 +1,7 @@
-From fc88194fbc824967cce666a6e2ab4b47722f8d01 Mon Sep 17 00:00:00 2001
+From 9fd3de7abd22d7e67a8757e3f67410302359fec7 Mon Sep 17 00:00:00 2001
From: "Luke D. Jones" <luke@ljones.dev>
Date: Fri, 1 Dec 2023 16:57:19 +1300
-Subject: [PATCH v14.1 4/4] HID: asus: add ROG Ally xpad settings
+Subject: [PATCH v14.7 4/4] HID: asus: add ROG Ally xpad settings
- move ROG specific stuff to new .c
- add a header for common parts
@@ -18,10 +18,10 @@ Subject: [PATCH v14.1 4/4] HID: asus: add ROG Ally xpad settings
.../ABI/testing/sysfs-driver-hid-asus | 85 +
drivers/hid/Makefile | 2 +
drivers/hid/{hid-asus.c => hid-asus-core.c} | 71 +-
- drivers/hid/hid-asus-rog.c | 1457 +++++++++++++++++
+ drivers/hid/hid-asus-rog.c | 1469 +++++++++++++++++
drivers/hid/hid-asus-rog.h | 482 ++++++
drivers/hid/hid-asus.h | 58 +
- 6 files changed, 2114 insertions(+), 41 deletions(-)
+ 6 files changed, 2126 insertions(+), 41 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-asus
rename drivers/hid/{hid-asus.c => hid-asus-core.c} (96%)
create mode 100644 drivers/hid/hid-asus-rog.c
@@ -30,7 +30,7 @@ Subject: [PATCH v14.1 4/4] HID: asus: add ROG Ally xpad settings
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-asus b/Documentation/ABI/testing/sysfs-driver-hid-asus
new file mode 100644
-index 000000000000..736233ebb38f
+index 000000000000..df5b0c5b0702
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-asus
@@ -0,0 +1,85 @@
@@ -73,6 +73,12 @@ index 000000000000..736233ebb38f
+Contact: linux-input@vger.kernel.org
+Description: Descriptive labels for joystick deadzone array.
+
++What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y>_<left/right>/anti-deadzone
++Date: December 2023
++Contact: linux-input@vger.kernel.org
++Description: Set the joystick anti-deadzone feature:
++ - range 0-32 (corresponds to 0-50%)
++
+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y/z>_<left/right>/calibration
+Date: December 2023
+Contact: linux-input@vger.kernel.org
@@ -84,12 +90,6 @@ index 000000000000..736233ebb38f
+Contact: linux-input@vger.kernel.org
+Description: Descriptive labels for joystick and triggers calibration array.
+
-+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y>_<left/right>/anti-deadzone
-+Date: December 2023
-+Contact: linux-input@vger.kernel.org
-+Description: Set the joystick anti-deadzone feature:
-+ - range 0-64 (corresponds to 0-100%)
-+
+What: /sys/bus/usb/devices/1-3:1.0/0003:0B05:1ABE.0001/axis_<x/y>_<left/right>/rc_point<n>
+Date: December 2023
+Contact: linux-input@vger.kernel.org
@@ -297,10 +297,10 @@ index 3a1a6024d299..026705c43ee1 100644
QUIRK_ROG_CLAYMORE_II_KEYBOARD },
diff --git a/drivers/hid/hid-asus-rog.c b/drivers/hid/hid-asus-rog.c
new file mode 100644
-index 000000000000..f0a2b366a298
+index 000000000000..94b7c986576c
--- /dev/null
+++ b/drivers/hid/hid-asus-rog.c
-@@ -0,0 +1,1457 @@
+@@ -0,0 +1,1469 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * HID driver for Asus ROG laptops and Ally
@@ -481,7 +481,7 @@ index 000000000000..f0a2b366a298
+ STR_TO_CODE_ELIF(2, 0x32, KB_B)
+ STR_TO_CODE_ELIF(2, 0x31, KB_N)
+ STR_TO_CODE_ELIF(2, 0x3a, KB_M)
-+ STR_TO_CODE_ELIF(2, 0x41, KB_COMA)
++ STR_TO_CODE_ELIF(2, 0x41, KB_COMMA)
+ STR_TO_CODE_ELIF(2, 0x49, KB_PERIOD)
+ STR_TO_CODE_ELIF(2, 0x4a, KB_FWDSLASH)
+ STR_TO_CODE_ELIF(2, 0x89, KB_RSHIFT)
@@ -509,9 +509,9 @@ index 000000000000..f0a2b366a298
+ STR_TO_CODE_ELIF(2, 0x91, KB_LEFT_ARROW)
+ STR_TO_CODE_ELIF(2, 0x9b, KB_RIGHT_ARROW)
+
-+ STR_TO_CODE_ELIF(2, 0x77, NUMPAD_LCK)
++ STR_TO_CODE_ELIF(2, 0x77, NUMPAD_LOCK)
+ STR_TO_CODE_ELIF(2, 0x90, NUMPAD_FWDSLASH)
-+ STR_TO_CODE_ELIF(2, 0x7c, NUMPAD_STAR)
++ STR_TO_CODE_ELIF(2, 0x7c, NUMPAD_ASTERISK)
+ STR_TO_CODE_ELIF(2, 0x7b, NUMPAD_HYPHEN)
+ STR_TO_CODE_ELIF(2, 0x70, NUMPAD_0)
+ STR_TO_CODE_ELIF(2, 0x69, NUMPAD_1)
@@ -664,7 +664,7 @@ index 000000000000..f0a2b366a298
+ CODE_TO_STR_IF(2, 0x32, KB_B)
+ CODE_TO_STR_IF(2, 0x31, KB_N)
+ CODE_TO_STR_IF(2, 0x3a, KB_M)
-+ CODE_TO_STR_IF(2, 0x41, KB_COMA)
++ CODE_TO_STR_IF(2, 0x41, KB_COMMA)
+ CODE_TO_STR_IF(2, 0x49, KB_PERIOD)
+ CODE_TO_STR_IF(2, 0x4a, KB_FWDSLASH)
+ CODE_TO_STR_IF(2, 0x89, KB_RSHIFT)
@@ -692,9 +692,9 @@ index 000000000000..f0a2b366a298
+ CODE_TO_STR_IF(2, 0x91, KB_LEFT_ARROW)
+ CODE_TO_STR_IF(2, 0x9b, KB_RIGHT_ARROW)
+
-+ CODE_TO_STR_IF(2, 0x77, NUMPAD_LCK)
++ CODE_TO_STR_IF(2, 0x77, NUMPAD_LOCK)
+ CODE_TO_STR_IF(2, 0x90, NUMPAD_FWDSLASH)
-+ CODE_TO_STR_IF(2, 0x7c, NUMPAD_STAR)
++ CODE_TO_STR_IF(2, 0x7c, NUMPAD_ASTERISK)
+ CODE_TO_STR_IF(2, 0x7b, NUMPAD_HYPHEN)
+ CODE_TO_STR_IF(2, 0x70, NUMPAD_0)
+ CODE_TO_STR_IF(2, 0x69, NUMPAD_1)
@@ -738,36 +738,38 @@ index 000000000000..f0a2b366a298
+static int __gamepad_check_ready(struct hid_device *hdev)
+{
+ u8 *hidbuf;
-+ int ret;
++ int ret, count;
+
+ hidbuf = kzalloc(FEATURE_ROG_ALLY_REPORT_SIZE, GFP_KERNEL);
+ if (!hidbuf)
+ return -ENOMEM;
+
-+ hidbuf[0] = FEATURE_KBD_REPORT_ID;
-+ hidbuf[1] = 0xD1;
-+ hidbuf[2] = xpad_cmd_check_ready;
-+ hidbuf[3] = 01;
-+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ hidbuf[0] = hidbuf[1] = hidbuf[2] = hidbuf[3] = 0;
-+ ret = asus_kbd_get_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
-+ if (ret < 0)
-+ goto report_fail;
-+
-+ ret = hidbuf[2] == xpad_cmd_check_ready;
-+ if (!ret) {
-+ hid_warn(hdev, "ROG Ally not ready\n");
-+ ret = -ENOMSG;
++ for (count = 0; count < 3; count++) {
++ hidbuf[0] = FEATURE_KBD_REPORT_ID;
++ hidbuf[1] = 0xD1;
++ hidbuf[2] = xpad_cmd_check_ready;
++ hidbuf[3] = 01;
++ ret = asus_kbd_set_report(hdev, hidbuf,
++ FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ hid_warn(hdev, "ROG Ally check failed set report: %d\n", ret);
++
++ hidbuf[0] = hidbuf[1] = hidbuf[2] = hidbuf[3] = 0;
++ ret = asus_kbd_get_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
++ if (ret < 0)
++ hid_warn(hdev, "ROG Ally check failed get report: %d\n", ret);
++
++ ret = hidbuf[2] == xpad_cmd_check_ready;
++ if (!ret)
++ hid_warn(hdev, "ROG Ally not ready, retry %d\n", count);
++ else
++ break;
++ msleep(2); // don't spam the entire loop in less than USB response time
+ }
+
-+ kfree(hidbuf);
-+ return ret;
++ if (count == 3)
++ hid_err(hdev, "ROG Ally never responded with a ready\n");
+
-+report_fail:
-+ hid_dbg(hdev, "ROG Ally check failed get report: %d\n", ret);
+ kfree(hidbuf);
+ return ret;
+}
@@ -841,7 +843,7 @@ index 000000000000..f0a2b366a298
+static int __gamepad_turbo_show(struct device *raw_dev, enum btn_pair pair, int side)
+{
+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
-+ return rog_ally->turbo_btns[rog_ally->mode][__gamepad_turbo_index(pair, side)];
++ return rog_ally->turbo_btns[rog_ally->mode - 1][__gamepad_turbo_index(pair, side)];
+};
+
+static int __gamepad_turbo_store(struct device *raw_dev, const char *buf, enum btn_pair pair,
@@ -856,7 +858,7 @@ index 000000000000..f0a2b366a298
+ if (val < 0 || val > 16)
+ return -EINVAL;
+
-+ rog_ally->turbo_btns[rog_ally->mode][__gamepad_turbo_index(pair, side)] = val;
++ rog_ally->turbo_btns[rog_ally->mode - 1][__gamepad_turbo_index(pair, side)] = val;
+
+ return 0;
+};
@@ -949,6 +951,10 @@ index 000000000000..f0a2b366a298
+ hidbuf[3] = 0x01;
+ hidbuf[4] = val;
+
++ ret = __gamepad_check_ready(hdev);
++ if (ret < 0)
++ goto report_fail;
++
+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
+ if (ret < 0)
+ goto report_fail;
@@ -1020,8 +1026,8 @@ index 000000000000..f0a2b366a298
+ hidbuf[1] = 0xD1;
+ hidbuf[2] = xpad_cmd_set_vibe_intensity;
+ hidbuf[3] = 0x02; // length
-+ hidbuf[4] = rog_ally->anti_deadzones[rog_ally->mode][btn_pair_side_left];
-+ hidbuf[5] = rog_ally->anti_deadzones[rog_ally->mode][btn_pair_side_right];
++ hidbuf[4] = rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_left];
++ hidbuf[5] = rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_right];
+
+ ret = __gamepad_check_ready(hdev);
+ if (ret < 0)
@@ -1041,8 +1047,8 @@ index 000000000000..f0a2b366a298
+{
+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
+ return sysfs_emit(buf, "%d %d\n",
-+ rog_ally->anti_deadzones[rog_ally->mode][btn_pair_side_left],
-+ rog_ally->anti_deadzones[rog_ally->mode][btn_pair_side_right]);
++ rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_left],
++ rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_right]);
+}
+
+static ssize_t gamepad_vibration_intensity_store(struct device *raw_dev,
@@ -1051,6 +1057,7 @@ index 000000000000..f0a2b366a298
+{
+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
+ u32 left, right;
++ int ret;
+
+ if (sscanf(buf, "%d %d", &left, &right) != 2)
+ return -EINVAL;
@@ -1058,8 +1065,12 @@ index 000000000000..f0a2b366a298
+ if (left > 64 || right > 64)
+ return -EINVAL;
+
-+ rog_ally->vibration_intensity[rog_ally->mode][btn_pair_side_left] = left;
-+ rog_ally->vibration_intensity[rog_ally->mode][btn_pair_side_right] = right;
++ rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_left] = left;
++ rog_ally->vibration_intensity[rog_ally->mode - 1][btn_pair_side_right] = right;
++
++ ret = __gamepad_write_vibe_intensity_to_mcu(raw_dev);
++ if (ret < 0)
++ return ret;
+
+ return count;
+}
@@ -1098,20 +1109,20 @@ index 000000000000..f0a2b366a298
+ hidbuf[1] = 0xD1;
+ hidbuf[2] = xpad_cmd_set_js_dz;
+ hidbuf[3] = 0x04; // length
-+ hidbuf[4] = rog_ally->deadzones[rog_ally->mode][0][0];
-+ hidbuf[5] = rog_ally->deadzones[rog_ally->mode][0][1];
-+ hidbuf[6] = rog_ally->deadzones[rog_ally->mode][0][2];
-+ hidbuf[7] = rog_ally->deadzones[rog_ally->mode][0][3];
++ hidbuf[4] = rog_ally->deadzones[rog_ally->mode - 1][0][0];
++ hidbuf[5] = rog_ally->deadzones[rog_ally->mode - 1][0][1];
++ hidbuf[6] = rog_ally->deadzones[rog_ally->mode - 1][0][2];
++ hidbuf[7] = rog_ally->deadzones[rog_ally->mode - 1][0][3];
+
+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
+ if (ret < 0)
+ goto end;
+
+ hidbuf[2] = xpad_cmd_set_tr_dz;
-+ hidbuf[4] = rog_ally->deadzones[rog_ally->mode][1][0];
-+ hidbuf[5] = rog_ally->deadzones[rog_ally->mode][1][1];
-+ hidbuf[6] = rog_ally->deadzones[rog_ally->mode][1][2];
-+ hidbuf[7] = rog_ally->deadzones[rog_ally->mode][1][3];
++ hidbuf[4] = rog_ally->deadzones[rog_ally->mode - 1][1][0];
++ hidbuf[5] = rog_ally->deadzones[rog_ally->mode - 1][1][1];
++ hidbuf[6] = rog_ally->deadzones[rog_ally->mode - 1][1][2];
++ hidbuf[7] = rog_ally->deadzones[rog_ally->mode - 1][1][3];
+
+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
+ if (ret < 0)
@@ -1139,8 +1150,8 @@ index 000000000000..f0a2b366a298
+ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 2 : 0;
+ cmd = is_tr ? xpad_cmd_set_js_dz : xpad_cmd_set_tr_dz;
+
-+ rog_ally->deadzones[rog_ally->mode][is_tr][side] = inner;
-+ rog_ally->deadzones[rog_ally->mode][is_tr][side + 1] = outer;
++ rog_ally->deadzones[rog_ally->mode - 1][is_tr][side] = inner;
++ rog_ally->deadzones[rog_ally->mode - 1][is_tr][side + 1] = outer;
+
+ return 0;
+}
@@ -1178,8 +1189,8 @@ index 000000000000..f0a2b366a298
+ hidbuf[1] = 0xD1;
+ hidbuf[2] = xpad_cmd_set_adz;
+ hidbuf[3] = 0x02; // length
-+ hidbuf[4] = rog_ally->anti_deadzones[rog_ally->mode][btn_pair_side_left];
-+ hidbuf[5] = rog_ally->anti_deadzones[rog_ally->mode][btn_pair_side_right];
++ hidbuf[4] = rog_ally->anti_deadzones[rog_ally->mode - 1][btn_pair_side_left];
++ hidbuf[5] = rog_ally->anti_deadzones[rog_ally->mode - 1][btn_pair_side_right];
+
+ ret = __gamepad_check_ready(hdev);
+ if (ret < 0)
@@ -1204,10 +1215,10 @@ index 000000000000..f0a2b366a298
+ if (ret)
+ return ret;
+
-+ if (val < 0 || val > 64)
++ if (val < 0 || val > 32)
+ return -EINVAL;
+
-+ rog_ally->anti_deadzones[rog_ally->mode][side] = val;
++ rog_ally->anti_deadzones[rog_ally->mode - 1][side] = val;
+
+ return ret;
+}
@@ -1217,7 +1228,7 @@ index 000000000000..f0a2b366a298
+{
+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
+ return sysfs_emit(buf, "%d\n",
-+ rog_ally->anti_deadzones[rog_ally->mode][btn_pair_side_left]);
++ rog_ally->anti_deadzones[rog_ally->mode - 1][btn_pair_side_left]);
+}
+
+static ssize_t xpad_axis_xy_left_ADZ_store(struct device *raw_dev, struct device_attribute *attr,
@@ -1237,7 +1248,7 @@ index 000000000000..f0a2b366a298
+{
+ struct asus_rog_ally *rog_ally = __rog_ally_data(raw_dev);
+ return sysfs_emit(buf, "%d\n",
-+ rog_ally->anti_deadzones[rog_ally->mode][btn_pair_side_right]);
++ rog_ally->anti_deadzones[rog_ally->mode - 1][btn_pair_side_right]);
+}
+
+static ssize_t xpad_axis_xy_right_ADZ_store(struct device *raw_dev, struct device_attribute *attr,
@@ -1280,14 +1291,14 @@ index 000000000000..f0a2b366a298
+ hidbuf[2] = xpad_cmd_set_response_curve;
+ hidbuf[3] = 0x09; // length
+ hidbuf[4] = 0x01;
-+ memcpy(&hidbuf[5], &rog_ally->response_curve[rog_ally->mode][btn_pair_side_left], 8);
++ memcpy(&hidbuf[5], &rog_ally->response_curve[rog_ally->mode - 1][btn_pair_side_left], 8);
+
+ ret = __gamepad_check_ready(hdev);
+ if (ret < 0)
+ goto report_fail;
+
+ hidbuf[4] = 0x02;
-+ memcpy(&hidbuf[5], &rog_ally->response_curve[rog_ally->mode][btn_pair_side_right], 8);
++ memcpy(&hidbuf[5], &rog_ally->response_curve[rog_ally->mode - 1][btn_pair_side_right], 8);
+
+ ret = __gamepad_check_ready(hdev);
+ if (ret < 0)
@@ -1315,8 +1326,8 @@ index 000000000000..f0a2b366a298
+ if (move > 64 || response > 64)
+ return -EINVAL;
+
-+ rog_ally->response_curve[rog_ally->mode][side][idx] = move;
-+ rog_ally->response_curve[rog_ally->mode][side][idx + 1] = response;
++ rog_ally->response_curve[rog_ally->mode - 1][side][idx] = move;
++ rog_ally->response_curve[rog_ally->mode - 1][side][idx + 1] = response;
+
+ return 0;
+}
@@ -1361,10 +1372,7 @@ index 000000000000..f0a2b366a298
+ c = &hidbuf[6]; // pointer
+
+ for (size_t i = 0; i < data_len; i++) {
-+ if (axis == xpad_axis_xy_left || axis == xpad_axis_xy_right)
-+ cal = rog_ally->js_calibrations[side][i];
-+ else
-+ cal = rog_ally->tr_calibrations[side][i];
++ cal = rog_ally->js_calibrations[side][i];
+ *c = (u8)((cal & 0xff00) >> 8);
+ checksum += *c;
+ c += 1;
@@ -1428,6 +1436,7 @@ index 000000000000..f0a2b366a298
+ //TODO: validate input
+
+ side = axis == xpad_axis_xy_right || axis == xpad_axis_z_right ? 1 : 0;
++ /* stored in reverse order for easy copy to packet */
+ rog_ally->tr_calibrations[side][0] = x_stable;
+ rog_ally->tr_calibrations[side][1] = x_max;
+
@@ -1663,7 +1672,7 @@ index 000000000000..f0a2b366a298
+ hidbuf[1] = 0xD1;
+ hidbuf[2] = xpad_cmd_set_turbo;
+ hidbuf[3] = 0x20; // length
-+ memcpy(&hidbuf[4], rog_ally->turbo_btns[rog_ally->mode], TURBO_BLOCK_LEN);
++ memcpy(&hidbuf[4], rog_ally->turbo_btns[rog_ally->mode - 1], TURBO_BLOCK_LEN);
+ ret = asus_kbd_set_report(hdev, hidbuf, FEATURE_ROG_ALLY_REPORT_SIZE);
+
+ kfree(hidbuf);
@@ -1673,7 +1682,7 @@ index 000000000000..f0a2b366a298
+static int asus_rog_ally_probe(struct hid_device *hdev, const struct rog_ops *ops)
+{
+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
-+ int ret;
++ int ret = 0;
+
+ /* all ROG devices have this HID interface but we will focus on Ally for now */
+ if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD && hid_is_usb(hdev)) {
@@ -1697,41 +1706,44 @@ index 000000000000..f0a2b366a298
+ }
+ // TODO: move these to functions
+ drvdata->rog_ally_data->mode = xpad_mode_game;
-+ drvdata->rog_ally_data->deadzones[xpad_mode_game][0][1] = 64;
-+ drvdata->rog_ally_data->deadzones[xpad_mode_game][0][3] = 64;
-+ drvdata->rog_ally_data->deadzones[xpad_mode_game][1][1] = 64;
-+ drvdata->rog_ally_data->deadzones[xpad_mode_game][1][3] = 64;
-+
-+ drvdata->rog_ally_data->anti_deadzones[xpad_mode_game][0] = 64;
-+ drvdata->rog_ally_data->anti_deadzones[xpad_mode_game][1] = 64;
-+
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][0][0] = 0x14;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][0][1] = 0x14;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][0][2] = 0x28;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][0][3] = 0x28;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][0][4] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][0][5] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][0][6] = 0x50;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][0][7] = 0x50;
-+
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][1][0] = 0x14;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][1][1] = 0x14;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][1][2] = 0x28;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][1][3] = 0x28;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][1][4] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][1][5] = 0x3c;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][1][6] = 0x50;
-+ drvdata->rog_ally_data->response_curve[xpad_mode_game][1][7] = 0x50;
++ for (int i = 0; i < xpad_mode_mouse; i++) {
++ drvdata->rog_ally_data->deadzones[i][0][1] = 64;
++ drvdata->rog_ally_data->deadzones[i][0][3] = 64;
++ drvdata->rog_ally_data->deadzones[i][1][1] = 64;
++ drvdata->rog_ally_data->deadzones[i][1][3] = 64;
++
++ drvdata->rog_ally_data->response_curve[i][0][0] = 0x14;
++ drvdata->rog_ally_data->response_curve[i][0][1] = 0x14;
++ drvdata->rog_ally_data->response_curve[i][0][2] = 0x28;
++ drvdata->rog_ally_data->response_curve[i][0][3] = 0x28;
++ drvdata->rog_ally_data->response_curve[i][0][4] = 0x3c;
++ drvdata->rog_ally_data->response_curve[i][0][5] = 0x3c;
++ drvdata->rog_ally_data->response_curve[i][0][6] = 0x50;
++ drvdata->rog_ally_data->response_curve[i][0][7] = 0x50;
++
++ drvdata->rog_ally_data->response_curve[i][1][0] = 0x14;
++ drvdata->rog_ally_data->response_curve[i][1][1] = 0x14;
++ drvdata->rog_ally_data->response_curve[i][1][2] = 0x28;
++ drvdata->rog_ally_data->response_curve[i][1][3] = 0x28;
++ drvdata->rog_ally_data->response_curve[i][1][4] = 0x3c;
++ drvdata->rog_ally_data->response_curve[i][1][5] = 0x3c;
++ drvdata->rog_ally_data->response_curve[i][1][6] = 0x50;
++ drvdata->rog_ally_data->response_curve[i][1][7] = 0x50;
++
++ drvdata->rog_ally_data->vibration_intensity[i][0] = 64;
++ drvdata->rog_ally_data->vibration_intensity[i][1] = 64;
++ }
+
++ /* ignore all errors for this as they are related to USB HID I/O */
+ __gamepad_mapping_xpad_default(drvdata->rog_ally_data);
++ __gamepad_mapping_wasd_default(drvdata->rog_ally_data);
+ // these calls will never error so ignore the return
+ __gamepad_mapping_store(&hdev->dev, "kb_f14", btn_pair_m1_m2,
+ btn_pair_side_left, false); // M2
+ __gamepad_mapping_store(&hdev->dev, "kb_f15", btn_pair_m1_m2,
+ btn_pair_side_right, false); // M1
-+ ret = __gamepad_set_mode(&hdev->dev, xpad_mode_game);
-+ if (ret < 0)
-+ return ret;
++ __gamepad_set_mapping(&hdev->dev, btn_pair_m1_m2);
++ __gamepad_set_mode(&hdev->dev, xpad_mode_game);
+ }
+
+ if (sysfs_create_groups(&hdev->dev.kobj, gamepad_device_attr_groups))
@@ -1760,7 +1772,7 @@ index 000000000000..f0a2b366a298
+};
diff --git a/drivers/hid/hid-asus-rog.h b/drivers/hid/hid-asus-rog.h
new file mode 100644
-index 000000000000..4d81f0ce8c59
+index 000000000000..efad0b041d5d
--- /dev/null
+++ b/drivers/hid/hid-asus-rog.h
@@ -0,0 +1,482 @@
@@ -1816,7 +1828,7 @@ index 000000000000..4d81f0ce8c59
+#define KB_F14 "kb_f14"
+#define KB_F15 "kb_f15"
+
-+#define KB_BACKTICK "kb_`"
++#define KB_BACKTICK "kb_backtick"
+#define KB_1 "kb_1"
+#define KB_2 "kb_2"
+#define KB_3 "kb_3"
@@ -1827,8 +1839,8 @@ index 000000000000..4d81f0ce8c59
+#define KB_8 "kb_8"
+#define KB_9 "kb_9"
+#define KB_0 "kb_0"
-+#define KB_HYPHEN "kb_-"
-+#define KB_EQUALS "kb_="
++#define KB_HYPHEN "kb_hyphen"
++#define KB_EQUALS "kb_equals"
+#define KB_BACKSPACE "kb_backspace"
+
+#define KB_TAB "kb_tab"
@@ -1842,8 +1854,8 @@ index 000000000000..4d81f0ce8c59
+#define KB_I "kb_i"
+#define KB_O "kb_o"
+#define KB_P "kb_p"
-+#define KB_LBRACKET "kb_["
-+#define KB_RBRACKET "kb_]"
++#define KB_LBRACKET "kb_lbracket"
++#define KB_RBRACKET "kb_rbracket"
+#define KB_BACKSLASH "kb_bkslash"
+
+#define KB_CAPS "kb_caps"
@@ -1856,8 +1868,8 @@ index 000000000000..4d81f0ce8c59
+#define KB_J "kb_j"
+#define KB_K "kb_k"
+#define KB_L "kb_l"
-+#define KB_SEMI "kb_;"
-+#define KB_QUOTE "kb_'"
++#define KB_SEMI "kb_semicolon"
++#define KB_QUOTE "kb_quote"
+#define KB_RET "kb_enter"
+
+#define KB_LSHIFT "kb_lshift"
@@ -1868,9 +1880,9 @@ index 000000000000..4d81f0ce8c59
+#define KB_B "kb_b"
+#define KB_N "kb_n"
+#define KB_M "kb_m"
-+#define KB_COMA "kb_,"
-+#define KB_PERIOD "kb_."
-+#define KB_FWDSLASH "kb_/"
++#define KB_COMMA "kb_comma"
++#define KB_PERIOD "kb_period"
++#define KB_FWDSLASH "kb_fwdslash"
+#define KB_RSHIFT "kb_rshift"
+
+#define KB_LCTL "kb_lctl"
@@ -1896,10 +1908,10 @@ index 000000000000..4d81f0ce8c59
+#define KB_LEFT_ARROW "kb_left_arrow"
+#define KB_RIGHT_ARROW "kb_right_arrow"
+
-+#define NUMPAD_LCK "numpad_lck"
-+#define NUMPAD_FWDSLASH "numpad_/"
-+#define NUMPAD_STAR "numpad_*"
-+#define NUMPAD_HYPHEN "numpad_-"
++#define NUMPAD_LOCK "numpad_lock"
++#define NUMPAD_FWDSLASH "numpad_fwdslash"
++#define NUMPAD_ASTERISK "numpad_asterisk"
++#define NUMPAD_HYPHEN "numpad_hyphen"
+#define NUMPAD_0 "numpad_0"
+#define NUMPAD_1 "numpad_1"
+#define NUMPAD_2 "numpad_2"
@@ -1910,7 +1922,7 @@ index 000000000000..4d81f0ce8c59
+#define NUMPAD_7 "numpad_7"
+#define NUMPAD_8 "numpad_8"
+#define NUMPAD_9 "numpad_9"
-+#define NUMPAD_PLUS "numpad_+"
++#define NUMPAD_PLUS "numpad_plus"
+#define NUMPAD_ENTER "numpad_enter"
+#define NUMPAD_PERIOD "numpad_."
+
@@ -2193,12 +2205,17 @@ index 000000000000..4d81f0ce8c59
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
++/*
++ * the xpad_mode is used inside the mode setting packet and is used
++ * for indexing (xpad_mode - 1)
++ */
+enum xpad_mode {
+ xpad_mode_game = 0x01,
+ xpad_mode_wasd = 0x02,
+ xpad_mode_mouse = 0x03,
+};
+
++/* the xpad_cmd determines which feature is set or queried */
+enum xpad_cmd {
+ xpad_cmd_set_mode = 0x01,
+ xpad_cmd_set_mapping = 0x02,
@@ -2212,6 +2229,10 @@ index 000000000000..4d81f0ce8c59
+ xpad_cmd_set_adz = 0x18,
+};
+
++/*
++ * the xpad_mode is used in various set and query HID packets and is
++ * used for indexing (xpad_axis - 1)
++ */
+enum xpad_axis {
+ xpad_axis_xy_left = 0x01,
+ xpad_axis_xy_right = 0x02,
@@ -2219,15 +2240,6 @@ index 000000000000..4d81f0ce8c59
+ xpad_axis_z_right = 0x04,
+};
+
-+enum mcu_output_dev {
-+ mcu_output_dev_blank = 0x00,
-+ mcu_output_dev_xpad = 0x01,
-+ mcu_output_dev_keyboard = 0x02,
-+ mcu_output_dev_mouse = 0x03,
-+ mcu_output_dev_macro = 0x04,
-+ mcu_output_dev_media = 0x05,
-+};
-+
+enum btn_pair {
+ btn_pair_dpad_u_d = 0x01,
+ btn_pair_dpad_l_r = 0x02,
@@ -2313,5 +2325,5 @@ index 000000000000..18317cad7110
+extern const struct rog_ops rog_ally;
\ No newline at end of file
--
-2.41.0
+2.43.0
diff --git a/wifi-cfg80211-fix-cqm-for-non-range-use.patch b/wifi-cfg80211-fix-cqm-for-non-range-use.patch
new file mode 100644
index 000000000000..933cea1700a8
--- /dev/null
+++ b/wifi-cfg80211-fix-cqm-for-non-range-use.patch
@@ -0,0 +1,141 @@
+From 7e7efdda6adb385fbdfd6f819d76bc68c923c394 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Mon, 6 Nov 2023 23:17:16 +0100
+Subject: wifi: cfg80211: fix CQM for non-range use
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 7e7efdda6adb385fbdfd6f819d76bc68c923c394 upstream.
+
+My prior race fix here broke CQM when ranges aren't used, as
+the reporting worker now requires the cqm_config to be set in
+the wdev, but isn't set when there's no range configured.
+
+Rather than continuing to special-case the range version, set
+the cqm_config always and configure accordingly, also tracking
+if range was used or not to be able to clear the configuration
+appropriately with the same API, which was actually not right
+if both were implemented by a driver for some reason, as is
+the case with mac80211 (though there the implementations are
+equivalent so it doesn't matter.)
+
+Also, the original multiple-RSSI commit lost checking for the
+callback, so might have potentially crashed if a driver had
+neither implementation, and userspace tried to use it despite
+not being advertised as supported.
+
+Cc: stable@vger.kernel.org
+Fixes: 4a4b8169501b ("cfg80211: Accept multiple RSSI thresholds for CQM")
+Fixes: 37c20b2effe9 ("wifi: cfg80211: fix cqm_config access race")
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/wireless/core.h | 1
+ net/wireless/nl80211.c | 50 ++++++++++++++++++++++++++++++-------------------
+ 2 files changed, 32 insertions(+), 19 deletions(-)
+
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -299,6 +299,7 @@ struct cfg80211_cqm_config {
+ u32 rssi_hyst;
+ s32 last_rssi_event_value;
+ enum nl80211_cqm_rssi_threshold_event last_rssi_event_type;
++ bool use_range_api;
+ int n_rssi_thresholds;
+ s32 rssi_thresholds[] __counted_by(n_rssi_thresholds);
+ };
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -12824,10 +12824,6 @@ static int cfg80211_cqm_rssi_update(stru
+ int i, n, low_index;
+ int err;
+
+- /* RSSI reporting disabled? */
+- if (!cqm_config)
+- return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
+-
+ /*
+ * Obtain current RSSI value if possible, if not and no RSSI threshold
+ * event has been received yet, we should receive an event after a
+@@ -12902,18 +12898,6 @@ static int nl80211_set_cqm_rssi(struct g
+ wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+ return -EOPNOTSUPP;
+
+- if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) {
+- if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */
+- return rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
+-
+- return rdev_set_cqm_rssi_config(rdev, dev,
+- thresholds[0], hysteresis);
+- }
+-
+- if (!wiphy_ext_feature_isset(&rdev->wiphy,
+- NL80211_EXT_FEATURE_CQM_RSSI_LIST))
+- return -EOPNOTSUPP;
+-
+ if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */
+ n_thresholds = 0;
+
+@@ -12921,6 +12905,20 @@ static int nl80211_set_cqm_rssi(struct g
+ old = rcu_dereference_protected(wdev->cqm_config,
+ lockdep_is_held(&wdev->mtx));
+
++ /* if already disabled just succeed */
++ if (!n_thresholds && !old)
++ return 0;
++
++ if (n_thresholds > 1) {
++ if (!wiphy_ext_feature_isset(&rdev->wiphy,
++ NL80211_EXT_FEATURE_CQM_RSSI_LIST) ||
++ !rdev->ops->set_cqm_rssi_range_config)
++ return -EOPNOTSUPP;
++ } else {
++ if (!rdev->ops->set_cqm_rssi_config)
++ return -EOPNOTSUPP;
++ }
++
+ if (n_thresholds) {
+ cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds,
+ n_thresholds),
+@@ -12935,13 +12933,26 @@ static int nl80211_set_cqm_rssi(struct g
+ memcpy(cqm_config->rssi_thresholds, thresholds,
+ flex_array_size(cqm_config, rssi_thresholds,
+ n_thresholds));
++ cqm_config->use_range_api = n_thresholds > 1 ||
++ !rdev->ops->set_cqm_rssi_config;
+
+ rcu_assign_pointer(wdev->cqm_config, cqm_config);
++
++ if (cqm_config->use_range_api)
++ err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
++ else
++ err = rdev_set_cqm_rssi_config(rdev, dev,
++ thresholds[0],
++ hysteresis);
+ } else {
+ RCU_INIT_POINTER(wdev->cqm_config, NULL);
++ /* if enabled as range also disable via range */
++ if (old->use_range_api)
++ err = rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
++ else
++ err = rdev_set_cqm_rssi_config(rdev, dev, 0, 0);
+ }
+
+- err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config);
+ if (err) {
+ rcu_assign_pointer(wdev->cqm_config, old);
+ kfree_rcu(cqm_config, rcu_head);
+@@ -19131,10 +19142,11 @@ void cfg80211_cqm_rssi_notify_work(struc
+ wdev_lock(wdev);
+ cqm_config = rcu_dereference_protected(wdev->cqm_config,
+ lockdep_is_held(&wdev->mtx));
+- if (!wdev->cqm_config)
++ if (!cqm_config)
+ goto unlock;
+
+- cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config);
++ if (cqm_config->use_range_api)
++ cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config);
+
+ rssi_level = cqm_config->last_rssi_event_value;
+ rssi_event = cqm_config->last_rssi_event_type;
diff --git a/wifi-nl80211-fix-deadlock-in-nl80211_set_cqm_rssi-(6.6.x).patch b/wifi-nl80211-fix-deadlock-in-nl80211_set_cqm_rssi-6.6.x.patch
index 372271120e30..372271120e30 100644
--- a/wifi-nl80211-fix-deadlock-in-nl80211_set_cqm_rssi-(6.6.x).patch
+++ b/wifi-nl80211-fix-deadlock-in-nl80211_set_cqm_rssi-6.6.x.patch