162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * i2c-core.h - interfaces internal to the I2C framework
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/kconfig.h>
762306a36Sopenharmony_ci#include <linux/rwsem.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistruct i2c_devinfo {
1062306a36Sopenharmony_ci	struct list_head	list;
1162306a36Sopenharmony_ci	int			busnum;
1262306a36Sopenharmony_ci	struct i2c_board_info	board_info;
1362306a36Sopenharmony_ci};
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/* board_lock protects board_list and first_dynamic_bus_num.
1662306a36Sopenharmony_ci * only i2c core components are allowed to use these symbols.
1762306a36Sopenharmony_ci */
1862306a36Sopenharmony_ciextern struct rw_semaphore	__i2c_board_lock;
1962306a36Sopenharmony_ciextern struct list_head	__i2c_board_list;
2062306a36Sopenharmony_ciextern int		__i2c_first_dynamic_bus_num;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ciint i2c_check_7bit_addr_validity_strict(unsigned short addr);
2362306a36Sopenharmony_ciint i2c_dev_irq_from_resources(const struct resource *resources,
2462306a36Sopenharmony_ci			       unsigned int num_resources);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/*
2762306a36Sopenharmony_ci * We only allow atomic transfers for very late communication, e.g. to access a
2862306a36Sopenharmony_ci * PMIC when powering down. Atomic transfers are a corner case and not for
2962306a36Sopenharmony_ci * generic use!
3062306a36Sopenharmony_ci */
3162306a36Sopenharmony_cistatic inline bool i2c_in_atomic_xfer_mode(void)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	return system_state > SYSTEM_RUNNING &&
3462306a36Sopenharmony_ci	       (IS_ENABLED(CONFIG_PREEMPT_COUNT) ? !preemptible() : irqs_disabled());
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	int ret = 0;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (i2c_in_atomic_xfer_mode()) {
4262306a36Sopenharmony_ci		WARN(!adap->algo->master_xfer_atomic && !adap->algo->smbus_xfer_atomic,
4362306a36Sopenharmony_ci		     "No atomic I2C transfer handler for '%s'\n", dev_name(&adap->dev));
4462306a36Sopenharmony_ci		ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT) ? 0 : -EAGAIN;
4562306a36Sopenharmony_ci	} else {
4662306a36Sopenharmony_ci		i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	return ret;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic inline int __i2c_check_suspended(struct i2c_adapter *adap)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	if (test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)) {
5562306a36Sopenharmony_ci		if (!test_and_set_bit(I2C_ALF_SUSPEND_REPORTED, &adap->locked_flags))
5662306a36Sopenharmony_ci			dev_WARN(&adap->dev, "Transfer while suspended\n");
5762306a36Sopenharmony_ci		return -ESHUTDOWN;
5862306a36Sopenharmony_ci	}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return 0;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#ifdef CONFIG_ACPI
6462306a36Sopenharmony_civoid i2c_acpi_register_devices(struct i2c_adapter *adap);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ciint i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable);
6762306a36Sopenharmony_ci#else /* CONFIG_ACPI */
6862306a36Sopenharmony_cistatic inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { }
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic inline int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	return 0;
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci#endif /* CONFIG_ACPI */
7562306a36Sopenharmony_ciextern struct notifier_block i2c_acpi_notifier;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci#ifdef CONFIG_ACPI_I2C_OPREGION
7862306a36Sopenharmony_ciint i2c_acpi_install_space_handler(struct i2c_adapter *adapter);
7962306a36Sopenharmony_civoid i2c_acpi_remove_space_handler(struct i2c_adapter *adapter);
8062306a36Sopenharmony_ci#else /* CONFIG_ACPI_I2C_OPREGION */
8162306a36Sopenharmony_cistatic inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter) { return 0; }
8262306a36Sopenharmony_cistatic inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) { }
8362306a36Sopenharmony_ci#endif /* CONFIG_ACPI_I2C_OPREGION */
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#ifdef CONFIG_OF
8662306a36Sopenharmony_civoid of_i2c_register_devices(struct i2c_adapter *adap);
8762306a36Sopenharmony_ci#else
8862306a36Sopenharmony_cistatic inline void of_i2c_register_devices(struct i2c_adapter *adap) { }
8962306a36Sopenharmony_ci#endif
9062306a36Sopenharmony_ciextern struct notifier_block i2c_of_notifier;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SMBUS)
9362306a36Sopenharmony_ciint i2c_setup_smbus_alert(struct i2c_adapter *adap);
9462306a36Sopenharmony_ci#else
9562306a36Sopenharmony_cistatic inline int i2c_setup_smbus_alert(struct i2c_adapter *adap)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	return 0;
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci#endif
100