1  /* SPDX-License-Identifier: GPL-2.0-or-later */
2  /*
3   * i2c-core.h - interfaces internal to the I2C framework
4   */
5  
6  #include <linux/kconfig.h>
7  #include <linux/rwsem.h>
8  
9  struct i2c_devinfo {
10  	struct list_head	list;
11  	int			busnum;
12  	struct i2c_board_info	board_info;
13  };
14  
15  /* board_lock protects board_list and first_dynamic_bus_num.
16   * only i2c core components are allowed to use these symbols.
17   */
18  extern struct rw_semaphore	__i2c_board_lock;
19  extern struct list_head	__i2c_board_list;
20  extern int		__i2c_first_dynamic_bus_num;
21  
22  int i2c_check_7bit_addr_validity_strict(unsigned short addr);
23  int i2c_dev_irq_from_resources(const struct resource *resources,
24  			       unsigned int num_resources);
25  
26  /*
27   * We only allow atomic transfers for very late communication, e.g. to access a
28   * PMIC when powering down. Atomic transfers are a corner case and not for
29   * generic use!
30   */
i2c_in_atomic_xfer_mode(void)31  static inline bool i2c_in_atomic_xfer_mode(void)
32  {
33  	return system_state > SYSTEM_RUNNING &&
34  	       (IS_ENABLED(CONFIG_PREEMPT_COUNT) ? !preemptible() : irqs_disabled());
35  }
36  
__i2c_lock_bus_helper(struct i2c_adapter * adap)37  static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
38  {
39  	int ret = 0;
40  
41  	if (i2c_in_atomic_xfer_mode()) {
42  		WARN(!adap->algo->master_xfer_atomic && !adap->algo->smbus_xfer_atomic,
43  		     "No atomic I2C transfer handler for '%s'\n", dev_name(&adap->dev));
44  		ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT) ? 0 : -EAGAIN;
45  	} else {
46  		i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
47  	}
48  
49  	return ret;
50  }
51  
__i2c_check_suspended(struct i2c_adapter * adap)52  static inline int __i2c_check_suspended(struct i2c_adapter *adap)
53  {
54  	if (test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)) {
55  		if (!test_and_set_bit(I2C_ALF_SUSPEND_REPORTED, &adap->locked_flags))
56  			dev_WARN(&adap->dev, "Transfer while suspended\n");
57  		return -ESHUTDOWN;
58  	}
59  
60  	return 0;
61  }
62  
63  #ifdef CONFIG_ACPI
64  void i2c_acpi_register_devices(struct i2c_adapter *adap);
65  
66  int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable);
67  #else /* CONFIG_ACPI */
i2c_acpi_register_devices(struct i2c_adapter * adap)68  static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
69  
i2c_acpi_get_irq(struct i2c_client * client,bool * wake_capable)70  static inline int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable)
71  {
72  	return 0;
73  }
74  #endif /* CONFIG_ACPI */
75  extern struct notifier_block i2c_acpi_notifier;
76  
77  #ifdef CONFIG_ACPI_I2C_OPREGION
78  int i2c_acpi_install_space_handler(struct i2c_adapter *adapter);
79  void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter);
80  #else /* CONFIG_ACPI_I2C_OPREGION */
i2c_acpi_install_space_handler(struct i2c_adapter * adapter)81  static inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter) { return 0; }
i2c_acpi_remove_space_handler(struct i2c_adapter * adapter)82  static inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) { }
83  #endif /* CONFIG_ACPI_I2C_OPREGION */
84  
85  #ifdef CONFIG_OF
86  void of_i2c_register_devices(struct i2c_adapter *adap);
87  #else
of_i2c_register_devices(struct i2c_adapter * adap)88  static inline void of_i2c_register_devices(struct i2c_adapter *adap) { }
89  #endif
90  extern struct notifier_block i2c_of_notifier;
91  
92  #if IS_ENABLED(CONFIG_I2C_SMBUS)
93  int i2c_setup_smbus_alert(struct i2c_adapter *adap);
94  #else
i2c_setup_smbus_alert(struct i2c_adapter * adap)95  static inline int i2c_setup_smbus_alert(struct i2c_adapter *adap)
96  {
97  	return 0;
98  }
99  #endif
100