xref: /openbmc/linux/drivers/i2c/i2c-core.h (revision 59f5a149f5072f4da79656cde9972ba2b616634f)
1c942fddfSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
29c1600edSDavid Brownell /*
39c1600edSDavid Brownell  * i2c-core.h - interfaces internal to the I2C framework
49c1600edSDavid Brownell  */
59c1600edSDavid Brownell 
6*b240a3efSBenjamin Bara #include <linux/kconfig.h>
7f18c41daSRodolfo Giometti #include <linux/rwsem.h>
8f18c41daSRodolfo Giometti 
99c1600edSDavid Brownell struct i2c_devinfo {
109c1600edSDavid Brownell 	struct list_head	list;
119c1600edSDavid Brownell 	int			busnum;
129c1600edSDavid Brownell 	struct i2c_board_info	board_info;
139c1600edSDavid Brownell };
149c1600edSDavid Brownell 
159c1600edSDavid Brownell /* board_lock protects board_list and first_dynamic_bus_num.
169c1600edSDavid Brownell  * only i2c core components are allowed to use these symbols.
179c1600edSDavid Brownell  */
18f18c41daSRodolfo Giometti extern struct rw_semaphore	__i2c_board_lock;
199c1600edSDavid Brownell extern struct list_head	__i2c_board_list;
209c1600edSDavid Brownell extern int		__i2c_first_dynamic_bus_num;
219c1600edSDavid Brownell 
22e4991ecdSWolfram Sang int i2c_check_7bit_addr_validity_strict(unsigned short addr);
231d7534b6SCharles Keepax int i2c_dev_irq_from_resources(const struct resource *resources,
241d7534b6SCharles Keepax 			       unsigned int num_resources);
255bf4fa7dSWolfram Sang 
26bae1d3a0SWolfram Sang /*
27df7b4d6fSWolfram Sang  * We only allow atomic transfers for very late communication, e.g. to access a
28df7b4d6fSWolfram Sang  * PMIC when powering down. Atomic transfers are a corner case and not for
29df7b4d6fSWolfram Sang  * generic use!
30bae1d3a0SWolfram Sang  */
i2c_in_atomic_xfer_mode(void)31bae1d3a0SWolfram Sang static inline bool i2c_in_atomic_xfer_mode(void)
32bae1d3a0SWolfram Sang {
33*b240a3efSBenjamin Bara 	return system_state > SYSTEM_RUNNING &&
34*b240a3efSBenjamin Bara 	       (IS_ENABLED(CONFIG_PREEMPT_COUNT) ? !preemptible() : irqs_disabled());
35bae1d3a0SWolfram Sang }
36bae1d3a0SWolfram Sang 
__i2c_lock_bus_helper(struct i2c_adapter * adap)3783c42212SWolfram Sang static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
3883c42212SWolfram Sang {
3983c42212SWolfram Sang 	int ret = 0;
4083c42212SWolfram Sang 
4163b96983SWolfram Sang 	if (i2c_in_atomic_xfer_mode()) {
4263b96983SWolfram Sang 		WARN(!adap->algo->master_xfer_atomic && !adap->algo->smbus_xfer_atomic,
4363b96983SWolfram Sang 		     "No atomic I2C transfer handler for '%s'\n", dev_name(&adap->dev));
4483c42212SWolfram Sang 		ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT) ? 0 : -EAGAIN;
4563b96983SWolfram Sang 	} else {
4683c42212SWolfram Sang 		i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
4763b96983SWolfram Sang 	}
4883c42212SWolfram Sang 
4983c42212SWolfram Sang 	return ret;
5083c42212SWolfram Sang }
5183c42212SWolfram Sang 
__i2c_check_suspended(struct i2c_adapter * adap)525d756112SWolfram Sang static inline int __i2c_check_suspended(struct i2c_adapter *adap)
535d756112SWolfram Sang {
545d756112SWolfram Sang 	if (test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)) {
555d756112SWolfram Sang 		if (!test_and_set_bit(I2C_ALF_SUSPEND_REPORTED, &adap->locked_flags))
565d756112SWolfram Sang 			dev_WARN(&adap->dev, "Transfer while suspended\n");
575d756112SWolfram Sang 		return -ESHUTDOWN;
585d756112SWolfram Sang 	}
595d756112SWolfram Sang 
605d756112SWolfram Sang 	return 0;
615d756112SWolfram Sang }
625d756112SWolfram Sang 
6353f8f7c5SWolfram Sang #ifdef CONFIG_ACPI
6453f8f7c5SWolfram Sang void i2c_acpi_register_devices(struct i2c_adapter *adap);
6516c9db1dSCharles Keepax 
66b38f2d5dSRaul E Rangel int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable);
6753f8f7c5SWolfram Sang #else /* CONFIG_ACPI */
i2c_acpi_register_devices(struct i2c_adapter * adap)6853f8f7c5SWolfram Sang static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
6916c9db1dSCharles Keepax 
i2c_acpi_get_irq(struct i2c_client * client,bool * wake_capable)70b38f2d5dSRaul E Rangel static inline int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable)
7116c9db1dSCharles Keepax {
7216c9db1dSCharles Keepax 	return 0;
7316c9db1dSCharles Keepax }
7453f8f7c5SWolfram Sang #endif /* CONFIG_ACPI */
7553f8f7c5SWolfram Sang extern struct notifier_block i2c_acpi_notifier;
7653f8f7c5SWolfram Sang 
7753f8f7c5SWolfram Sang #ifdef CONFIG_ACPI_I2C_OPREGION
7853f8f7c5SWolfram Sang int i2c_acpi_install_space_handler(struct i2c_adapter *adapter);
7953f8f7c5SWolfram Sang void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter);
8053f8f7c5SWolfram Sang #else /* CONFIG_ACPI_I2C_OPREGION */
i2c_acpi_install_space_handler(struct i2c_adapter * adapter)8153f8f7c5SWolfram Sang static inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter) { return 0; }
i2c_acpi_remove_space_handler(struct i2c_adapter * adapter)8253f8f7c5SWolfram Sang static inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) { }
8353f8f7c5SWolfram Sang #endif /* CONFIG_ACPI_I2C_OPREGION */
8453f8f7c5SWolfram Sang 
855bf4fa7dSWolfram Sang #ifdef CONFIG_OF
865bf4fa7dSWolfram Sang void of_i2c_register_devices(struct i2c_adapter *adap);
875bf4fa7dSWolfram Sang #else
of_i2c_register_devices(struct i2c_adapter * adap)885bf4fa7dSWolfram Sang static inline void of_i2c_register_devices(struct i2c_adapter *adap) { }
895bf4fa7dSWolfram Sang #endif
905bf4fa7dSWolfram Sang extern struct notifier_block i2c_of_notifier;
9148115399SWolfram Sang 
9248115399SWolfram Sang #if IS_ENABLED(CONFIG_I2C_SMBUS)
9348115399SWolfram Sang int i2c_setup_smbus_alert(struct i2c_adapter *adap);
9448115399SWolfram Sang #else
i2c_setup_smbus_alert(struct i2c_adapter * adap)9548115399SWolfram Sang static inline int i2c_setup_smbus_alert(struct i2c_adapter *adap)
9648115399SWolfram Sang {
9748115399SWolfram Sang 	return 0;
9848115399SWolfram Sang }
9948115399SWolfram Sang #endif
100