drivers/periph/i2c: add periph_i2c_reconfigure feature

It is often desireable to re-configure the pins of a bus back to GPIO mode,
either to save power when an external peripheral is turned off and current
would leak, or because a device may need a non-standard in-band signal to
be generated on the bus lines.

To serve those use cases, this patch introduces four new functions to the
I2C API:

 - `i2c_init_pins()`    equivalent to spi_init_pins(), restores I2C pin configuration

 - `i2c_deinit_pins()`  to switch the configuration of the I2C pins back to GPIO
                        mode and block access to the bus.

 - `i2c_pin_sda()`      to get the data pin for a given bus

 - `i2c_pin_scl()`      to get the clock pin for a given bus

Since it's unreasonable to expect having implementations for all platforms
already, those functions are only availiable when the periph_i2c_reconfigure
feature is availiable.

Applications should use FEATURES_REQUIRED += periph_i2c_reconfigure or
FEATURES_OPTIONAL if they want to make use of those functions.
This commit is contained in:
Benjamin Valentin 2020-02-20 05:05:22 +01:00 committed by Benjamin Valentin
parent 1212165222
commit 21958ff531

View File

@ -215,6 +215,67 @@ typedef enum {
*/
void i2c_init(i2c_t dev);
/**
* @brief Initialize the used I2C bus pins
*
* After calling i2c_init, the pins must be initialized (i.e. spi_init is
* calling this function internally). In normal cases, this function will not be
* used. But there are some devices (e.g. ATECC608A), that use I2C bus lines also
* for other purposes and need the option to dynamically re-configure one or
* more of the used pins.
*
* @param[in] dev I2C device the pins are configure for
*/
void i2c_init_pins(i2c_t dev);
/**
* @brief Change the pins of the given I2C bus back to plain GPIO functionality
*
* The pin mux of the SDA and SCL pins of the bus will be changed back to
* default (GPIO) mode and the I2C bus is powered off.
* This allows to use the I2C pins for another function and return to I2C
* functionality again by calling i2c_init_pins()
*
* If you want the pin to be in a defined state, call gpio_init() on it.
*
* The bus MUST not be acquired before initializing it, as this is handled
* internally by the i2c_deinit function!
*
* Calls to i2c_acquire() will block until i2c_init_pins() is called.
*
* @note Until this is implemented on all platforms, this requires the
* periph_i2c_reconfigure feature to be used.
*
* @param[in] dev the device to de-initialize
*/
void i2c_deinit_pins(i2c_t dev);
#if DOXYGEN /* functions to be implemented as `#define` in `periph_cpu.h` */
/**
* @brief Get the SDA pin of the given I2C bus.
*
* @param[in] dev The device to query
*
* @note Until this is implemented on all platforms, this requires the
* periph_i2c_reconfigure feature to be used.
*
* @return The GPIO used for the I2C data line.
*/
gpio_t i2c_pin_sda(i2c_t dev);
/**
* @brief Get the SCL pin of the given I2C bus.
*
* @param[in] dev The device to query
*
* @note Until this is implemented on all platforms, this requires the
* periph_i2c_reconfigure feature to be used.
*
* @return The GPIO used for the I2C clock line.
*/
gpio_t i2c_pin_scl(i2c_t dev);
#endif /* DOXYGEN */
/**
* @brief Get mutually exclusive access to the given I2C bus
*