hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/hid/hid-cp2112.c
....@@ -1,16 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * hid-cp2112.c - Silicon Labs HID USB to SMBus master bridge
34 * Copyright (c) 2013,2014 Uplogix, Inc.
45 * David Barksdale <dbarksdale@uplogix.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify it
7
- * under the terms and conditions of the GNU General Public License,
8
- * version 2, as published by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope it will be useful, but WITHOUT
11
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
- * more details.
146 */
157
168 /*
....@@ -19,12 +11,13 @@
1911 * host communicates with the CP2112 via raw HID reports.
2012 *
2113 * Data Sheet:
22
- * http://www.silabs.com/Support%20Documents/TechnicalDocs/CP2112.pdf
14
+ * https://www.silabs.com/Support%20Documents/TechnicalDocs/CP2112.pdf
2315 * Programming Interface Specification:
2416 * https://www.silabs.com/documents/public/application-notes/an495-cp2112-interface-specification.pdf
2517 */
2618
27
-#include <linux/gpio.h>
19
+#include <linux/gpio/consumer.h>
20
+#include <linux/gpio/machine.h>
2821 #include <linux/gpio/driver.h>
2922 #include <linux/hid.h>
3023 #include <linux/hidraw.h>
....@@ -168,6 +161,7 @@
168161 atomic_t read_avail;
169162 atomic_t xfer_avail;
170163 struct gpio_chip gc;
164
+ struct irq_chip irq;
171165 u8 *in_out_buffer;
172166 struct mutex lock;
173167
....@@ -794,6 +788,11 @@
794788 data->word = le16_to_cpup((__le16 *)buf);
795789 break;
796790 case I2C_SMBUS_I2C_BLOCK_DATA:
791
+ if (read_length > I2C_SMBUS_BLOCK_MAX) {
792
+ ret = -EINVAL;
793
+ goto power_normal;
794
+ }
795
+
797796 memcpy(data->block + 1, buf, read_length);
798797 break;
799798 case I2C_SMBUS_BLOCK_DATA:
....@@ -1182,16 +1181,6 @@
11821181 return 0;
11831182 }
11841183
1185
-static struct irq_chip cp2112_gpio_irqchip = {
1186
- .name = "cp2112-gpio",
1187
- .irq_startup = cp2112_gpio_irq_startup,
1188
- .irq_shutdown = cp2112_gpio_irq_shutdown,
1189
- .irq_ack = cp2112_gpio_irq_ack,
1190
- .irq_mask = cp2112_gpio_irq_mask,
1191
- .irq_unmask = cp2112_gpio_irq_unmask,
1192
- .irq_set_type = cp2112_gpio_irq_type,
1193
-};
1194
-
11951184 static int __maybe_unused cp2112_allocate_irq(struct cp2112_device *dev,
11961185 int pin)
11971186 {
....@@ -1201,7 +1190,9 @@
12011190 return -EINVAL;
12021191
12031192 dev->desc[pin] = gpiochip_request_own_desc(&dev->gc, pin,
1204
- "HID/I2C:Event");
1193
+ "HID/I2C:Event",
1194
+ GPIO_ACTIVE_HIGH,
1195
+ GPIOD_IN);
12051196 if (IS_ERR(dev->desc[pin])) {
12061197 dev_err(dev->gc.parent, "Failed to request GPIO\n");
12071198 return PTR_ERR(dev->desc[pin]);
....@@ -1240,6 +1231,7 @@
12401231 struct cp2112_device *dev;
12411232 u8 buf[3];
12421233 struct cp2112_smbus_config_report config;
1234
+ struct gpio_irq_chip *girq;
12431235 int ret;
12441236
12451237 dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
....@@ -1343,6 +1335,25 @@
13431335 dev->gc.can_sleep = 1;
13441336 dev->gc.parent = &hdev->dev;
13451337
1338
+ dev->irq.name = "cp2112-gpio";
1339
+ dev->irq.irq_startup = cp2112_gpio_irq_startup;
1340
+ dev->irq.irq_shutdown = cp2112_gpio_irq_shutdown;
1341
+ dev->irq.irq_ack = cp2112_gpio_irq_ack;
1342
+ dev->irq.irq_mask = cp2112_gpio_irq_mask;
1343
+ dev->irq.irq_unmask = cp2112_gpio_irq_unmask;
1344
+ dev->irq.irq_set_type = cp2112_gpio_irq_type;
1345
+ dev->irq.flags = IRQCHIP_MASK_ON_SUSPEND;
1346
+
1347
+ girq = &dev->gc.irq;
1348
+ girq->chip = &dev->irq;
1349
+ /* The event comes from the outside so no parent handler */
1350
+ girq->parent_handler = NULL;
1351
+ girq->num_parents = 0;
1352
+ girq->parents = NULL;
1353
+ girq->default_type = IRQ_TYPE_NONE;
1354
+ girq->handler = handle_simple_irq;
1355
+ girq->threaded = true;
1356
+
13461357 ret = gpiochip_add_data(&dev->gc, dev);
13471358 if (ret < 0) {
13481359 hid_err(hdev, "error registering gpio chip\n");
....@@ -1358,17 +1369,8 @@
13581369 chmod_sysfs_attrs(hdev);
13591370 hid_hw_power(hdev, PM_HINT_NORMAL);
13601371
1361
- ret = gpiochip_irqchip_add(&dev->gc, &cp2112_gpio_irqchip, 0,
1362
- handle_simple_irq, IRQ_TYPE_NONE);
1363
- if (ret) {
1364
- dev_err(dev->gc.parent, "failed to add IRQ chip\n");
1365
- goto err_sysfs_remove;
1366
- }
1367
-
13681372 return ret;
13691373
1370
-err_sysfs_remove:
1371
- sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group);
13721374 err_gpiochip_remove:
13731375 gpiochip_remove(&dev->gc);
13741376 err_free_i2c: