[PATCH] Add infrastructure for supporting both I2C and SPI in single driver

From: Guenter Roeck
Date: Thu Nov 14 2024 - 20:30:01 EST


Add support for register and unregister functions for drivers supporting
both I2C and SPI. Support situations where only one of the protocols is
enabled.

Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx>
---
include/linux/i2c_spi.h | 81 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
create mode 100644 include/linux/i2c_spi.h

diff --git a/include/linux/i2c_spi.h b/include/linux/i2c_spi.h
new file mode 100644
index 000000000000..3a8d32355338
--- /dev/null
+++ b/include/linux/i2c_spi.h
@@ -0,0 +1,81 @@
+/*---------------------------------------------------------------------------
+ *
+ * i2c_spi.h
+ * Copyright (c) 2024 Guenter Roeck <linux@xxxxxxxxxxxx>
+ *
+ * API functions to support both I2C and SPI in a single driver.
+ */
+
+#ifndef I2C_SPI_H
+#define I2C_SPI_H
+
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+
+/**
+ * i2c_spi_driver_register() - Register an I2C and a SPI driver
+ * @i2cdrv: the I2C driver to register
+ * @spidrv: the SPI driver to register
+ *
+ * This function registers both @i2cdev and @spidev, and fails if one of these
+ * registrations fails. This is mainly useful for devices that support both I2C
+ * and SPI modes.
+ * Note that the function only registers drivers for the enabled protocol(s).
+ * If neither I2C nor SPI are enabled, it does nothing.
+ *
+ * Return: 0 if enabled registrations succeeded, a negative error code otherwise.
+ */
+static inline int i2c_spi_driver_register(struct i2c_driver *i2cdrv,
+ struct spi_driver *spidrv)
+{
+ int ret = 0;
+
+ if (IS_ENABLED(CONFIG_I2C))
+ ret = i2c_add_driver(i2cdrv);
+ if (ret || !IS_ENABLED(CONFIG_SPI))
+ return ret;
+
+ ret = spi_register_driver(spidrv);
+ if (ret && IS_ENABLED(CONFIG_I2C))
+ i2c_del_driver(i2cdrv);
+
+ return ret;
+}
+
+/**
+ * i2c_spi_driver_unregister() - Unregister an I2C and a SPI driver
+ * @i2cdrv: the I2C driver to register
+ * @spidrv: the SPI driver to register
+ *
+ * This function unregisters both @i2cdrv and @i3cdrv.
+ * Note that the function only unregisters drivers for the enabled protocol(s).
+ */
+static inline void i2c_spi_driver_unregister(struct i2c_driver *i2cdrv,
+ struct spi_driver *spidrv)
+{
+ if (IS_ENABLED(CONFIG_SPI))
+ spi_unregister_driver(spidrv);
+
+ if (IS_ENABLED(CONFIG_I2C))
+ i2c_del_driver(i2cdrv);
+}
+
+/**
+ * module_i2c_spi_driver() - Register a module providing an I2C and a SPI
+ * driver
+ * @__i2cdrv: the I2C driver to register
+ * @__spidrv: the SPI driver to register
+ *
+ * Provide generic init/exit functions that simply register/unregister an I2C
+ * and a SPI driver.
+ * This macro can be used even if CONFIG_I2C and/or CONFIG_SPI are disabled,
+ * in this case, only the enabled driver(s) driver will be registered.
+ * Should be used by any driver that does not require extra init/cleanup steps.
+ */
+#define module_i2c_spi_driver(__i2cdrv, __spidrv) \
+ module_driver(__i2cdrv, \
+ i2c_spi_driver_register, \
+ i2c_spi_driver_unregister, \
+ __spidrv)
+
+#endif /* I2C_SPI_H */
--
2.45.2