David Brownell | 9c1600e | 2007-05-01 23:26:31 +0200 | [diff] [blame] | 1 | /* |
| 2 | * i2c-core.h - interfaces internal to the I2C framework |
| 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License as published by |
| 6 | * the Free Software Foundation; either version 2 of the License, or |
| 7 | * (at your option) any later version. |
| 8 | * |
| 9 | * This program is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU General Public License for more details. |
David Brownell | 9c1600e | 2007-05-01 23:26:31 +0200 | [diff] [blame] | 13 | */ |
| 14 | |
Rodolfo Giometti | f18c41d | 2009-06-19 16:58:20 +0200 | [diff] [blame] | 15 | #include <linux/rwsem.h> |
| 16 | |
David Brownell | 9c1600e | 2007-05-01 23:26:31 +0200 | [diff] [blame] | 17 | struct i2c_devinfo { |
| 18 | struct list_head list; |
| 19 | int busnum; |
| 20 | struct i2c_board_info board_info; |
| 21 | }; |
| 22 | |
| 23 | /* board_lock protects board_list and first_dynamic_bus_num. |
| 24 | * only i2c core components are allowed to use these symbols. |
| 25 | */ |
Rodolfo Giometti | f18c41d | 2009-06-19 16:58:20 +0200 | [diff] [blame] | 26 | extern struct rw_semaphore __i2c_board_lock; |
David Brownell | 9c1600e | 2007-05-01 23:26:31 +0200 | [diff] [blame] | 27 | extern struct list_head __i2c_board_list; |
| 28 | extern int __i2c_first_dynamic_bus_num; |
| 29 | |
Wolfram Sang | e4991ec | 2017-05-23 11:14:17 +0200 | [diff] [blame] | 30 | int i2c_check_7bit_addr_validity_strict(unsigned short addr); |
Wolfram Sang | 5bf4fa7 | 2017-05-23 11:50:58 +0200 | [diff] [blame] | 31 | |
Wolfram Sang | bae1d3a | 2019-04-03 14:40:08 +0200 | [diff] [blame] | 32 | /* |
| 33 | * We only allow atomic transfers for very late communication, e.g. to send |
| 34 | * the powerdown command to a PMIC. Atomic transfers are a corner case and not |
| 35 | * for generic use! |
| 36 | */ |
| 37 | static inline bool i2c_in_atomic_xfer_mode(void) |
| 38 | { |
| 39 | return system_state > SYSTEM_RUNNING && irqs_disabled(); |
| 40 | } |
| 41 | |
Wolfram Sang | 83c4221 | 2019-04-03 14:40:09 +0200 | [diff] [blame] | 42 | static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap) |
| 43 | { |
| 44 | int ret = 0; |
| 45 | |
Wolfram Sang | 63b9698 | 2019-04-03 14:40:10 +0200 | [diff] [blame] | 46 | if (i2c_in_atomic_xfer_mode()) { |
| 47 | WARN(!adap->algo->master_xfer_atomic && !adap->algo->smbus_xfer_atomic, |
| 48 | "No atomic I2C transfer handler for '%s'\n", dev_name(&adap->dev)); |
Wolfram Sang | 83c4221 | 2019-04-03 14:40:09 +0200 | [diff] [blame] | 49 | ret = i2c_trylock_bus(adap, I2C_LOCK_SEGMENT) ? 0 : -EAGAIN; |
Wolfram Sang | 63b9698 | 2019-04-03 14:40:10 +0200 | [diff] [blame] | 50 | } else { |
Wolfram Sang | 83c4221 | 2019-04-03 14:40:09 +0200 | [diff] [blame] | 51 | i2c_lock_bus(adap, I2C_LOCK_SEGMENT); |
Wolfram Sang | 63b9698 | 2019-04-03 14:40:10 +0200 | [diff] [blame] | 52 | } |
Wolfram Sang | 83c4221 | 2019-04-03 14:40:09 +0200 | [diff] [blame] | 53 | |
| 54 | return ret; |
| 55 | } |
| 56 | |
Wolfram Sang | 5d75611 | 2019-04-25 16:19:48 +0200 | [diff] [blame^] | 57 | static inline int __i2c_check_suspended(struct i2c_adapter *adap) |
| 58 | { |
| 59 | if (test_bit(I2C_ALF_IS_SUSPENDED, &adap->locked_flags)) { |
| 60 | if (!test_and_set_bit(I2C_ALF_SUSPEND_REPORTED, &adap->locked_flags)) |
| 61 | dev_WARN(&adap->dev, "Transfer while suspended\n"); |
| 62 | return -ESHUTDOWN; |
| 63 | } |
| 64 | |
| 65 | return 0; |
| 66 | } |
| 67 | |
Wolfram Sang | 53f8f7c | 2017-05-23 16:22:23 +0200 | [diff] [blame] | 68 | #ifdef CONFIG_ACPI |
Andy Shevchenko | c64ffff | 2017-07-17 17:13:28 +0300 | [diff] [blame] | 69 | const struct acpi_device_id * |
| 70 | i2c_acpi_match_device(const struct acpi_device_id *matches, |
| 71 | struct i2c_client *client); |
Wolfram Sang | 53f8f7c | 2017-05-23 16:22:23 +0200 | [diff] [blame] | 72 | void i2c_acpi_register_devices(struct i2c_adapter *adap); |
| 73 | #else /* CONFIG_ACPI */ |
| 74 | static inline void i2c_acpi_register_devices(struct i2c_adapter *adap) { } |
Andy Shevchenko | c64ffff | 2017-07-17 17:13:28 +0300 | [diff] [blame] | 75 | static inline const struct acpi_device_id * |
| 76 | i2c_acpi_match_device(const struct acpi_device_id *matches, |
| 77 | struct i2c_client *client) |
| 78 | { |
| 79 | return NULL; |
| 80 | } |
Wolfram Sang | 53f8f7c | 2017-05-23 16:22:23 +0200 | [diff] [blame] | 81 | #endif /* CONFIG_ACPI */ |
| 82 | extern struct notifier_block i2c_acpi_notifier; |
| 83 | |
| 84 | #ifdef CONFIG_ACPI_I2C_OPREGION |
| 85 | int i2c_acpi_install_space_handler(struct i2c_adapter *adapter); |
| 86 | void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter); |
| 87 | #else /* CONFIG_ACPI_I2C_OPREGION */ |
| 88 | static inline int i2c_acpi_install_space_handler(struct i2c_adapter *adapter) { return 0; } |
| 89 | static inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) { } |
| 90 | #endif /* CONFIG_ACPI_I2C_OPREGION */ |
| 91 | |
Wolfram Sang | 5bf4fa7 | 2017-05-23 11:50:58 +0200 | [diff] [blame] | 92 | #ifdef CONFIG_OF |
| 93 | void of_i2c_register_devices(struct i2c_adapter *adap); |
| 94 | #else |
| 95 | static inline void of_i2c_register_devices(struct i2c_adapter *adap) { } |
| 96 | #endif |
| 97 | extern struct notifier_block i2c_of_notifier; |