1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
From: Jonathan LoBue <jlobue10@gmail.com>
Adds a description of the duplicate ACPI identifier issue
between devices using bmc150 and bmi323.
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Co-developed-by: Luke D. Jones <luke@ljones.dev>
Signed-off-by: Luke D. Jones <luke@ljones.dev>
Co-developed-by: Denis Benato <benato.denis96@gmail.com>
Signed-off-by: Denis Benato <benato.denis96@gmail.com>
Co-developed-by: Antheas Kapenekakis <lkml@antheas.dev>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
Signed-off-by: Jonathan LoBue <jlobue10@gmail.com>
---
drivers/iio/accel/bmc150-accel-i2c.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
index ee1ba134ad42..353271e23235 100644
--- a/drivers/iio/accel/bmc150-accel-i2c.c
+++ b/drivers/iio/accel/bmc150-accel-i2c.c
@@ -224,6 +224,19 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = {
{"BMA250E"},
{"BMC150A"},
{"BMI055A"},
+ /*
+ * The "BOSC0200" identifier used here is not unique to devices using
+ * bmc150. The same "BOSC0200" identifier is found in the ACPI tables of
+ * the ASUS ROG ALLY and Ayaneo AIR Plus which both use a Bosch BMI323
+ * chip. This creates a conflict with duplicate ACPI identifiers which
+ * multiple drivers want to use. Fortunately, when the bmc150 driver
+ * starts to load on the ASUS ROG ALLY, the chip ID check portion fails
+ * (correctly) because the chip IDs received (via i2c) are unique between
+ * bmc150 and bmi323 and a dmesg output similar to this:
+ * "bmc150_accel_i2c i2c-BOSC0200:00: Invalid chip 0" can be seen.
+ * This allows the bmi323 driver to take over for ASUS ROG ALLY, and
+ * other devices using the bmi323 chip.
+ */
{"BOSC0200"},
{"BSBA0150"},
{"DUAL250E"},
From: Jonathan LoBue <jlobue10@gmail.com>
Adds the ACPI match table for ASUS ROG ALLY to load the bmi323
driver with an ACPI match of "BOSC0200", and a comment about duplicate
ACPI identifiers between devices using the bmc150 and bmi323 chips.
Tested-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Co-developed-by: Luke D. Jones <luke@ljones.dev>
Signed-off-by: Luke D. Jones <luke@ljones.dev>
Co-developed-by: Denis Benato <benato.denis96@gmail.com>
Signed-off-by: Denis Benato <benato.denis96@gmail.com>
Co-developed-by: Antheas Kapenekakis <lkml@antheas.dev>
Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
Signed-off-by: Jonathan LoBue <jlobue10@gmail.com>
---
drivers/iio/imu/bmi323/bmi323_i2c.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/iio/imu/bmi323/bmi323_i2c.c b/drivers/iio/imu/bmi323/bmi323_i2c.c
index 20a8001b9956..f7550503e47e 100644
--- a/drivers/iio/imu/bmi323/bmi323_i2c.c
+++ b/drivers/iio/imu/bmi323/bmi323_i2c.c
@@ -93,6 +93,25 @@ static int bmi323_i2c_probe(struct i2c_client *i2c)
return bmi323_core_probe(dev);
}
+static const struct acpi_device_id bmi323_acpi_match[] = {
+ /*
+ * The "BOSC0200" identifier used here is not unique to bmi323 devices.
+ * The same "BOSC0200" identifier is found in the ACPI tables of devices
+ * using the bmc150 chip. This creates a conflict with duplicate ACPI
+ * identifiers which multiple drivers want to use. If a non-bmi323 device
+ * starts to load with this "BOSC0200" ACPI match here, then the chip
+ * ID check portion should fail because the chip IDs received (via i2c) are
+ * unique between bmc150 and bmi323 and the driver should relinquish the
+ * device. If and when a different driver (such as bmc150) starts to load
+ * with the "BOSC0200" ACPI match, a short reset should ensure that the
+ * device is not in a bad state during that driver initialization. This
+ * device reset does occur in both the bmi323 and bmc150 init sequences.
+ */
+ { "BOSC0200" },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, bmi323_acpi_match);
+
static const struct i2c_device_id bmi323_i2c_ids[] = {
{ "bmi323" },
{ }
@@ -109,6 +128,7 @@ static struct i2c_driver bmi323_i2c_driver = {
.driver = {
.name = "bmi323",
.of_match_table = bmi323_of_i2c_match,
+ .acpi_match_table = bmi323_acpi_match,
},
.probe = bmi323_i2c_probe,
.id_table = bmi323_i2c_ids,
From: Jonathan LoBue <jlobue10@gmail.com>
Date: Sun, 25 Feb 2024 14:43:01 -0800
Subject: [PATCH] iio: imu: bmi323: Implement ACPI method ROTM for mount matrix
Retrieve mount matrix from ACPI ROTM table.
---
drivers/iio/imu/bmi323/bmi323_core.c | 79 ++++++++++++++++++++++++++--
1 file changed, 76 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c
index 183af482828f..bb9f05183814 100644
--- a/drivers/iio/imu/bmi323/bmi323_core.c
+++ b/drivers/iio/imu/bmi323/bmi323_core.c
@@ -7,6 +7,7 @@
* Datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi323-ds000.pdf
*/
+#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/device.h>
@@ -1997,6 +1998,76 @@ static int bmi323_set_bw(struct bmi323_data *data,
FIELD_PREP(BMI323_ACC_GYRO_CONF_BW_MSK, bw));
}
+static bool bmi323_acpi_orientation(struct device *dev,
+ struct iio_mount_matrix *orientation)
+{
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+ char *str;
+ union acpi_object *obj, *elements;
+ acpi_status status;
+ int i, j, val[3];
+ bool ret = false;
+
+ if (!acpi_has_method(adev->handle, "ROTM"))
+ return false;
+
+ status = acpi_evaluate_object(adev->handle, "ROTM", NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+ dev_err(dev, "Failed to get ACPI mount matrix: %d\n", status);
+ return false;
+ }
+
+ obj = buffer.pointer;
+ if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 3) {
+ dev_err(dev, "Unknown ACPI mount matrix package format\n");
+ goto out_free_buffer;
+ }
+
+ elements = obj->package.elements;
+ for (i = 0; i < 3; i++) {
+ if (elements[i].type != ACPI_TYPE_STRING) {
+ dev_err(dev, "Unknown ACPI mount matrix element format\n");
+ goto out_free_buffer;
+ }
+
+ str = elements[i].string.pointer;
+ if (sscanf(str, "%d %d %d", &val[0], &val[1], &val[2]) != 3) {
+ dev_err(dev, "Incorrect ACPI mount matrix string format\n");
+ goto out_free_buffer;
+ }
+
+ for (j = 0; j < 3; j++) {
+ switch (val[j]) {
+ case -1: str = "-1"; break;
+ case 0: str = "0"; break;
+ case 1: str = "1"; break;
+ default:
+ dev_err(dev, "Invalid value in ACPI mount matrix: %d\n", val[j]);
+ goto out_free_buffer;
+ }
+ orientation->rotation[i * 3 + j] = str;
+ }
+ }
+
+ ret = true;
+
+out_free_buffer:
+ kfree(buffer.pointer);
+ return ret;
+}
+
+static bool bmi323_apply_acpi_orientation(struct device *dev,
+ struct iio_mount_matrix *orientation)
+{
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+
+ if (adev)
+ return bmi323_acpi_orientation(dev, orientation);
+
+ return false;
+}
+
static int bmi323_init(struct bmi323_data *data)
{
int ret, val;
@@ -2099,9 +2170,11 @@ int bmi323_core_probe(struct device *dev)
if (ret)
return -EINVAL;
- ret = iio_read_mount_matrix(dev, &data->orientation);
- if (ret)
- return ret;
+ if (!bmi323_apply_acpi_orientation(dev, &data->orientation)) {
+ ret = iio_read_mount_matrix(dev, &data->orientation);
+ if (ret)
+ return ret;
+ }
indio_dev->name = "bmi323-imu";
indio_dev->info = &bmi323_info;
diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c
index 0bd5ded..ded8596 100644
--- a/drivers/iio/imu/bmi323/bmi323_core.c
+++ b/drivers/iio/imu/bmi323/bmi323_core.c
@@ -285,6 +286,9 @@ static const int bmi323_acc_gyro_odr[][2] = {
{ 200, 0 },
{ 400, 0 },
{ 800, 0 },
+ { 1600, 0},
+ { 3200, 0},
+ { 6400, 0},
};
static const int bmi323_acc_gyro_odrns[] = {
|