hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/i2c/i2c-core-smbus.c
....@@ -1,24 +1,22 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Linux I2C core SMBus and SMBus emulation code
34 *
45 * This file contains the SMBus functions which are always included in the I2C
56 * core because they can be emulated via I2C. SMBus specific extensions
6
- * (e.g. smbalert) are handled in a seperate i2c-smbus module.
7
+ * (e.g. smbalert) are handled in a separate i2c-smbus module.
78 *
89 * All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
910 * SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and
1011 * Jean Delvare <jdelvare@suse.de>
11
- *
12
- * This program is free software; you can redistribute it and/or modify it
13
- * under the terms of the GNU General Public License as published by the Free
14
- * Software Foundation; either version 2 of the License, or (at your option)
15
- * any later version.
1612 */
1713 #include <linux/device.h>
1814 #include <linux/err.h>
1915 #include <linux/i2c.h>
2016 #include <linux/i2c-smbus.h>
2117 #include <linux/slab.h>
18
+
19
+#include "i2c-core.h"
2220
2321 #define CREATE_TRACE_POINTS
2422 #include <trace/events/smbus.h>
....@@ -537,7 +535,10 @@
537535 {
538536 s32 res;
539537
540
- i2c_lock_bus(adapter, I2C_LOCK_SEGMENT);
538
+ res = __i2c_lock_bus_helper(adapter);
539
+ if (res)
540
+ return res;
541
+
541542 res = __i2c_smbus_xfer(adapter, addr, flags, read_write,
542543 command, protocol, data);
543544 i2c_unlock_bus(adapter, I2C_LOCK_SEGMENT);
....@@ -550,9 +551,16 @@
550551 unsigned short flags, char read_write,
551552 u8 command, int protocol, union i2c_smbus_data *data)
552553 {
554
+ int (*xfer_func)(struct i2c_adapter *adap, u16 addr,
555
+ unsigned short flags, char read_write,
556
+ u8 command, int size, union i2c_smbus_data *data);
553557 unsigned long orig_jiffies;
554558 int try;
555559 s32 res;
560
+
561
+ res = __i2c_check_suspended(adapter);
562
+ if (res)
563
+ return res;
556564
557565 /* If enabled, the following two tracepoints are conditional on
558566 * read_write and protocol.
....@@ -564,13 +572,20 @@
564572
565573 flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
566574
567
- if (adapter->algo->smbus_xfer) {
575
+ xfer_func = adapter->algo->smbus_xfer;
576
+ if (i2c_in_atomic_xfer_mode()) {
577
+ if (adapter->algo->smbus_xfer_atomic)
578
+ xfer_func = adapter->algo->smbus_xfer_atomic;
579
+ else if (adapter->algo->master_xfer_atomic)
580
+ xfer_func = NULL; /* fallback to I2C emulation */
581
+ }
582
+
583
+ if (xfer_func) {
568584 /* Retry automatically on arbitration loss */
569585 orig_jiffies = jiffies;
570586 for (res = 0, try = 0; try <= adapter->retries; try++) {
571
- res = adapter->algo->smbus_xfer(adapter, addr, flags,
572
- read_write, command,
573
- protocol, data);
587
+ res = xfer_func(adapter, addr, flags, read_write,
588
+ command, protocol, data);
574589 if (res != -EAGAIN)
575590 break;
576591 if (time_after(jiffies,
....@@ -592,7 +607,7 @@
592607 trace:
593608 /* If enabled, the reply tracepoint is conditional on read_write. */
594609 trace_smbus_reply(adapter, addr, flags, read_write,
595
- command, protocol, data);
610
+ command, protocol, data, res);
596611 trace_smbus_result(adapter, addr, flags, read_write,
597612 command, protocol, res);
598613
....@@ -658,7 +673,7 @@
658673 EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data_or_emulated);
659674
660675 /**
661
- * i2c_setup_smbus_alert - Setup SMBus alert support
676
+ * i2c_new_smbus_alert_device - get ara client for SMBus alert support
662677 * @adapter: the target adapter
663678 * @setup: setup data for the SMBus alert handler
664679 * Context: can sleep
....@@ -668,31 +683,25 @@
668683 * Handling can be done either through our IRQ handler, or by the
669684 * adapter (from its handler, periodic polling, or whatever).
670685 *
671
- * NOTE that if we manage the IRQ, we *MUST* know if it's level or
672
- * edge triggered in order to hand it to the workqueue correctly.
673
- * If triggering the alert seems to wedge the system, you probably
674
- * should have said it's level triggered.
675
- *
676686 * This returns the ara client, which should be saved for later use with
677
- * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL
678
- * to indicate an error.
687
+ * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or an
688
+ * ERRPTR to indicate an error.
679689 */
680
-struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter,
681
- struct i2c_smbus_alert_setup *setup)
690
+struct i2c_client *i2c_new_smbus_alert_device(struct i2c_adapter *adapter,
691
+ struct i2c_smbus_alert_setup *setup)
682692 {
683693 struct i2c_board_info ara_board_info = {
684694 I2C_BOARD_INFO("smbus_alert", 0x0c),
685695 .platform_data = setup,
686696 };
687697
688
- return i2c_new_device(adapter, &ara_board_info);
698
+ return i2c_new_client_device(adapter, &ara_board_info);
689699 }
690
-EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
700
+EXPORT_SYMBOL_GPL(i2c_new_smbus_alert_device);
691701
692702 #if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
693703 int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter)
694704 {
695
- struct i2c_client *client;
696705 int irq;
697706
698707 irq = of_property_match_string(adapter->dev.of_node, "interrupt-names",
....@@ -702,11 +711,7 @@
702711 else if (irq < 0)
703712 return irq;
704713
705
- client = i2c_setup_smbus_alert(adapter, NULL);
706
- if (!client)
707
- return -ENODEV;
708
-
709
- return 0;
714
+ return PTR_ERR_OR_ZERO(i2c_new_smbus_alert_device(adapter, NULL));
710715 }
711716 EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert);
712717 #endif