hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/hwmon/applesmc.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * drivers/hwmon/applesmc.c - driver for Apple's SMC (accelerometer, temperature
34 * sensors, fan control, keyboard backlight control) used in Intel-based Apple
....@@ -12,26 +13,13 @@
1213 *
1314 * Fan control based on smcFanControl:
1415 * Copyright (C) 2006 Hendrik Holtmann <holtmann@mac.com>
15
- *
16
- * This program is free software; you can redistribute it and/or modify it
17
- * under the terms of the GNU General Public License v2 as published by the
18
- * Free Software Foundation.
19
- *
20
- * This program is distributed in the hope that it will be useful, but WITHOUT
21
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
23
- * more details.
24
- *
25
- * You should have received a copy of the GNU General Public License along with
26
- * this program; if not, write to the Free Software Foundation, Inc.,
27
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
2816 */
2917
3018 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3119
3220 #include <linux/delay.h>
3321 #include <linux/platform_device.h>
34
-#include <linux/input-polldev.h>
22
+#include <linux/input.h>
3523 #include <linux/kernel.h>
3624 #include <linux/slab.h>
3725 #include <linux/module.h>
....@@ -44,6 +32,7 @@
4432 #include <linux/hwmon.h>
4533 #include <linux/workqueue.h>
4634 #include <linux/err.h>
35
+#include <linux/bits.h>
4736
4837 /* data port used by Apple SMC */
4938 #define APPLESMC_DATA_PORT 0x300
....@@ -54,10 +43,13 @@
5443
5544 #define APPLESMC_MAX_DATA_LENGTH 32
5645
57
-/* wait up to 128 ms for a status change. */
58
-#define APPLESMC_MIN_WAIT 0x0010
59
-#define APPLESMC_RETRY_WAIT 0x0100
60
-#define APPLESMC_MAX_WAIT 0x20000
46
+/* Apple SMC status bits */
47
+#define SMC_STATUS_AWAITING_DATA BIT(0) /* SMC has data waiting to be read */
48
+#define SMC_STATUS_IB_CLOSED BIT(1) /* Will ignore any input */
49
+#define SMC_STATUS_BUSY BIT(2) /* Command in progress */
50
+
51
+/* Initial wait is 8us */
52
+#define APPLESMC_MIN_WAIT 0x0008
6153
6254 #define APPLESMC_READ_CMD 0x10
6355 #define APPLESMC_WRITE_CMD 0x11
....@@ -152,7 +144,7 @@
152144 static u8 backlight_state[2];
153145
154146 static struct device *hwmon_dev;
155
-static struct input_polled_dev *applesmc_idev;
147
+static struct input_dev *applesmc_idev;
156148
157149 /*
158150 * Last index written to key_at_index sysfs file, and value to use for all other
....@@ -163,59 +155,84 @@
163155 static struct workqueue_struct *applesmc_led_wq;
164156
165157 /*
166
- * wait_read - Wait for a byte to appear on SMC port. Callers must
167
- * hold applesmc_lock.
158
+ * Wait for specific status bits with a mask on the SMC.
159
+ * Used before all transactions.
160
+ * This does 10 fast loops of 8us then exponentially backs off for a
161
+ * minimum total wait of 262ms. Depending on usleep_range this could
162
+ * run out past 500ms.
168163 */
169
-static int wait_read(void)
164
+
165
+static int wait_status(u8 val, u8 mask)
170166 {
171167 u8 status;
172168 int us;
173
- for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
174
- udelay(us);
175
- status = inb(APPLESMC_CMD_PORT);
176
- /* read: wait for smc to settle */
177
- if (status & 0x01)
178
- return 0;
179
- }
169
+ int i;
180170
181
- pr_warn("wait_read() fail: 0x%02x\n", status);
171
+ us = APPLESMC_MIN_WAIT;
172
+ for (i = 0; i < 24 ; i++) {
173
+ status = inb(APPLESMC_CMD_PORT);
174
+ if ((status & mask) == val)
175
+ return 0;
176
+ usleep_range(us, us * 2);
177
+ if (i > 9)
178
+ us <<= 1;
179
+ }
182180 return -EIO;
183181 }
184182
185
-/*
186
- * send_byte - Write to SMC port, retrying when necessary. Callers
187
- * must hold applesmc_lock.
188
- */
183
+/* send_byte - Write to SMC data port. Callers must hold applesmc_lock. */
184
+
189185 static int send_byte(u8 cmd, u16 port)
190186 {
191
- u8 status;
192
- int us;
187
+ int status;
188
+
189
+ status = wait_status(0, SMC_STATUS_IB_CLOSED);
190
+ if (status)
191
+ return status;
192
+ /*
193
+ * This needs to be a separate read looking for bit 0x04
194
+ * after bit 0x02 falls. If consolidated with the wait above
195
+ * this extra read may not happen if status returns both
196
+ * simultaneously and this would appear to be required.
197
+ */
198
+ status = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY);
199
+ if (status)
200
+ return status;
193201
194202 outb(cmd, port);
195
- for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
196
- udelay(us);
197
- status = inb(APPLESMC_CMD_PORT);
198
- /* write: wait for smc to settle */
199
- if (status & 0x02)
200
- continue;
201
- /* ready: cmd accepted, return */
202
- if (status & 0x04)
203
- return 0;
204
- /* timeout: give up */
205
- if (us << 1 == APPLESMC_MAX_WAIT)
206
- break;
207
- /* busy: long wait and resend */
208
- udelay(APPLESMC_RETRY_WAIT);
209
- outb(cmd, port);
210
- }
211
-
212
- pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status);
213
- return -EIO;
203
+ return 0;
214204 }
205
+
206
+/* send_command - Write a command to the SMC. Callers must hold applesmc_lock. */
215207
216208 static int send_command(u8 cmd)
217209 {
218
- return send_byte(cmd, APPLESMC_CMD_PORT);
210
+ int ret;
211
+
212
+ ret = wait_status(0, SMC_STATUS_IB_CLOSED);
213
+ if (ret)
214
+ return ret;
215
+ outb(cmd, APPLESMC_CMD_PORT);
216
+ return 0;
217
+}
218
+
219
+/*
220
+ * Based on logic from the Apple driver. This is issued before any interaction
221
+ * If busy is stuck high, issue a read command to reset the SMC state machine.
222
+ * If busy is stuck high after the command then the SMC is jammed.
223
+ */
224
+
225
+static int smc_sane(void)
226
+{
227
+ int ret;
228
+
229
+ ret = wait_status(0, SMC_STATUS_BUSY);
230
+ if (!ret)
231
+ return ret;
232
+ ret = send_command(APPLESMC_READ_CMD);
233
+ if (ret)
234
+ return ret;
235
+ return wait_status(0, SMC_STATUS_BUSY);
219236 }
220237
221238 static int send_argument(const char *key)
....@@ -232,6 +249,11 @@
232249 {
233250 u8 status, data = 0;
234251 int i;
252
+ int ret;
253
+
254
+ ret = smc_sane();
255
+ if (ret)
256
+ return ret;
235257
236258 if (send_command(cmd) || send_argument(key)) {
237259 pr_warn("%.4s: read arg fail\n", key);
....@@ -245,7 +267,8 @@
245267 }
246268
247269 for (i = 0; i < len; i++) {
248
- if (wait_read()) {
270
+ if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
271
+ SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY)) {
249272 pr_warn("%.4s: read data[%d] fail\n", key, i);
250273 return -EIO;
251274 }
....@@ -256,19 +279,24 @@
256279 for (i = 0; i < 16; i++) {
257280 udelay(APPLESMC_MIN_WAIT);
258281 status = inb(APPLESMC_CMD_PORT);
259
- if (!(status & 0x01))
282
+ if (!(status & SMC_STATUS_AWAITING_DATA))
260283 break;
261284 data = inb(APPLESMC_DATA_PORT);
262285 }
263286 if (i)
264287 pr_warn("flushed %d bytes, last value is: %d\n", i, data);
265288
266
- return 0;
289
+ return wait_status(0, SMC_STATUS_BUSY);
267290 }
268291
269292 static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
270293 {
271294 int i;
295
+ int ret;
296
+
297
+ ret = smc_sane();
298
+ if (ret)
299
+ return ret;
272300
273301 if (send_command(cmd) || send_argument(key)) {
274302 pr_warn("%s: write arg fail\n", key);
....@@ -287,7 +315,7 @@
287315 }
288316 }
289317
290
- return 0;
318
+ return wait_status(0, SMC_STATUS_BUSY);
291319 }
292320
293321 static int read_register_count(unsigned int *count)
....@@ -693,9 +721,8 @@
693721 rest_x = -rest_x;
694722 }
695723
696
-static void applesmc_idev_poll(struct input_polled_dev *dev)
724
+static void applesmc_idev_poll(struct input_dev *idev)
697725 {
698
- struct input_dev *idev = dev->input;
699726 s16 x, y;
700727
701728 if (applesmc_read_s16(MOTION_SENSOR_X_KEY, &x))
....@@ -1129,7 +1156,7 @@
11291156 attr = &node->sda.dev_attr.attr;
11301157 sysfs_attr_init(attr);
11311158 attr->name = node->name;
1132
- attr->mode = S_IRUGO | (grp->store ? S_IWUSR : 0);
1159
+ attr->mode = 0444 | (grp->store ? 0200 : 0);
11331160 ret = sysfs_create_file(&pdev->dev.kobj, attr);
11341161 if (ret) {
11351162 attr->name = NULL;
....@@ -1147,7 +1174,6 @@
11471174 /* Create accelerometer resources */
11481175 static int applesmc_create_accelerometer(void)
11491176 {
1150
- struct input_dev *idev;
11511177 int ret;
11521178
11531179 if (!smcreg.has_accelerometer)
....@@ -1157,37 +1183,38 @@
11571183 if (ret)
11581184 goto out;
11591185
1160
- applesmc_idev = input_allocate_polled_device();
1186
+ applesmc_idev = input_allocate_device();
11611187 if (!applesmc_idev) {
11621188 ret = -ENOMEM;
11631189 goto out_sysfs;
11641190 }
11651191
1166
- applesmc_idev->poll = applesmc_idev_poll;
1167
- applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL;
1168
-
11691192 /* initial calibrate for the input device */
11701193 applesmc_calibrate();
11711194
11721195 /* initialize the input device */
1173
- idev = applesmc_idev->input;
1174
- idev->name = "applesmc";
1175
- idev->id.bustype = BUS_HOST;
1176
- idev->dev.parent = &pdev->dev;
1177
- idev->evbit[0] = BIT_MASK(EV_ABS);
1178
- input_set_abs_params(idev, ABS_X,
1196
+ applesmc_idev->name = "applesmc";
1197
+ applesmc_idev->id.bustype = BUS_HOST;
1198
+ applesmc_idev->dev.parent = &pdev->dev;
1199
+ input_set_abs_params(applesmc_idev, ABS_X,
11791200 -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
1180
- input_set_abs_params(idev, ABS_Y,
1201
+ input_set_abs_params(applesmc_idev, ABS_Y,
11811202 -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
11821203
1183
- ret = input_register_polled_device(applesmc_idev);
1204
+ ret = input_setup_polling(applesmc_idev, applesmc_idev_poll);
1205
+ if (ret)
1206
+ goto out_idev;
1207
+
1208
+ input_set_poll_interval(applesmc_idev, APPLESMC_POLL_INTERVAL);
1209
+
1210
+ ret = input_register_device(applesmc_idev);
11841211 if (ret)
11851212 goto out_idev;
11861213
11871214 return 0;
11881215
11891216 out_idev:
1190
- input_free_polled_device(applesmc_idev);
1217
+ input_free_device(applesmc_idev);
11911218
11921219 out_sysfs:
11931220 applesmc_destroy_nodes(accelerometer_group);
....@@ -1202,8 +1229,7 @@
12021229 {
12031230 if (!smcreg.has_accelerometer)
12041231 return;
1205
- input_unregister_polled_device(applesmc_idev);
1206
- input_free_polled_device(applesmc_idev);
1232
+ input_unregister_device(applesmc_idev);
12071233 applesmc_destroy_nodes(accelerometer_group);
12081234 }
12091235