Topics

[RFC PATCH 5/6] sensor: mcp9808: support multiple devices


Vlad Dogaru <vlad.dogaru@...>
 

Until now, MCP9808 device configuration was done in Kconfig. This
imposed a limit on the number of identical devices the driver could
handle (1, in this case). Additionally, Kconfig snippets could not be
reliably generated by an external tool.

Move the MCP9808 driver to a configuration language based on C
structures that are easier to generate externally and impose no
limitations on the number of devices. Application code is now expected
to define its own device, device_config and device_data structures and
fill them in with relevant information.

The trigger code is still conditionally compiled. If no triggers are
needed, the driver is reduced to a bare minimum. If a global fiber is
used, the only extra space needed is the null-filled fiber_config
structure. This also has the secondary benefit that trigger code is now
ifdef-free, because the decision of how to handle an interrupt is taken
at runtime.

Change-Id: I80a9f015199e8e2ae91253103e25df64d93afc0c
Signed-off-by: Vlad Dogaru <vlad.dogaru(a)intel.com>
---
drivers/sensor/Kconfig.mcp9808 | 78 ++---------------------------
drivers/sensor/sample.c | 32 ++++++++++++
drivers/sensor/sensor_mcp9808.c | 12 ++---
drivers/sensor/sensor_mcp9808.h | 29 +++++++----
drivers/sensor/sensor_mcp9808_trigger.c | 89 ++++++++++++++++-----------------
5 files changed, 103 insertions(+), 137 deletions(-)
create mode 100644 drivers/sensor/sample.c

diff --git a/drivers/sensor/Kconfig.mcp9808 b/drivers/sensor/Kconfig.mcp9808
index ac6e74b..f83377d 100644
--- a/drivers/sensor/Kconfig.mcp9808
+++ b/drivers/sensor/Kconfig.mcp9808
@@ -16,86 +16,16 @@
# limitations under the License.
#

-menuconfig MCP9808
+config MCP9808
bool "MCP9808 temperature sensor"
depends on SENSOR && I2C
default n
help
Enable driver for MCP9808 temperature sensor.

-config MCP9808_DEV_NAME
- string "MCP9808 device name"
- depends on MCP9808
- default "MCP9808"
-
-config MCP9808_INIT_PRIORITY
- int
- depends on MCP9808
- default 70
- prompt "Init priority"
- help
- Device driver initialization priority.
-
-config MCP9808_I2C_ADDR
- hex "MCP9808 I2C slave address"
- depends on MCP9808
- default 0x18
- help
- Specify the I2C slave address for the MCP9808.
-
-config MCP9808_I2C_DEV_NAME
- string "I2C master where MCP9808 is connected"
- depends on MCP9808
- default "I2C0"
- help
- Specify the device name of the I2C master device to which MCP9808 is
- connected.
-
-choice
- prompt "MCP9808 trigger mode"
- depends on MCP9808
- default MCP9808_TRIGGER_NONE
-
-config MCP9808_TRIGGER_NONE
- bool "No trigger"
-
-config MCP9808_TRIGGER_GLOBAL_FIBER
- depends on GPIO
- select MCP9808_TRIGGER
- select SENSOR_DELAYED_WORK
- bool "Use global fiber"
-
-config MCP9808_TRIGGER_OWN_FIBER
- depends on GPIO
- select MCP9808_TRIGGER
- bool "Use own fiber"
-
-endchoice
-
config MCP9808_TRIGGER
- bool
+ bool "MCP9808 trigger support"
depends on MCP9808
-
-config MCP9808_GPIO_CONTROLLER
- string "GPIO controller for MCP9808 interrupt"
- depends on MCP9808 && MCP9808_TRIGGER
- default "GPIO_0"
- help
- The GPIO controller the MCP9808 interrupt is connected to.
-
-config MCP9808_GPIO_PIN
- int "GPIO pin for MCP9808 interrupt"
- depends on MCP9808 && MCP9808_TRIGGER
- default 3
+ default n
help
- The GPIO pin the MCP9808 interrupt is connected to.
-
-config MCP9808_FIBER_STACK_SIZE
- int "Sensor delayed work fiber stack size"
- depends on MCP9808 && MCP9808_TRIGGER_OWN_FIBER
- default 1024
-
-config MCP9808_FIBER_PRIORITY
- int "MCP9808 fiber priority"
- depends on MCP9808 && MCP9808_TRIGGER_OWN_FIBER
- default 10
+ Enable trigger support for MCP9808.
diff --git a/drivers/sensor/sample.c b/drivers/sensor/sample.c
new file mode 100644
index 0000000..97bed61
--- /dev/null
+++ b/drivers/sensor/sample.c
@@ -0,0 +1,32 @@
+/* Sensor instance 0. */
+
+static __stack char mcp9808_fiber_stack[1024];
+static struct mcp9808_data mcp9808_0_data;
+
+static struct mcp9808_config mcp9808_0_config = {
+ .i2c_client = I2C_CLIENT("I2C0", 0x18),
+#ifdef CONFIG_MCP9808_TRIGGER
+ .gpio_int = GPIO_PIN("GPIO_0", 8),
+ .trig_mode = SENSOR_TRIG_MODE_OWN,
+ .fiber = FIBER_CONFIG(mcp9808_fiber_stack, 10),
+#endif /* CONFIG_MCP9808_TRIGGER */
+};
+
+DEVICE_INIT(mcp9808_0, "MCP9808_0", mcp9808_init,
+ &mcp9808_0_data, &mcp9808_0_config, SECONDARY, 70);
+
+/* Sensor instance 1 */
+
+static struct mcp9808_data mcp9808_1_data;
+
+static struct mcp9808_config mcp9808_1_config = {
+ .i2c_client = I2C_CLIENT("I2C0", 0x19),
+#ifdef CONFIG_MCP9808_TRIGGER
+ .gpio_int = GPIO_PIN("GPIO_0", 9),
+ .trig_mode = SENSOR_TRIG_MODE_GLOBAL,
+ .fiber = SENSOR_NO_FIBER,
+#endif /* CONFIG_MCP9808_TRIGGER */
+};
+
+DEVICE_INIT(mcp9808_1, "MCP9808_1", mcp9808_init,
+ &mcp9808_1_data, &mcp9808_1_config, SECONDARY, 70);
diff --git a/drivers/sensor/sensor_mcp9808.c b/drivers/sensor/sensor_mcp9808.c
index 40695c2..9476530 100644
--- a/drivers/sensor/sensor_mcp9808.c
+++ b/drivers/sensor/sensor_mcp9808.c
@@ -24,8 +24,6 @@
#include <misc/byteorder.h>
#include "sensor_mcp9808.h"

-struct mcp9808_data mcp9808_data;
-
int mcp9808_reg_read(struct mcp9808_data *data, uint8_t reg, uint16_t *val)
{
int ret;
@@ -95,22 +93,20 @@ static struct sensor_driver_api mcp9808_api_funcs = {
int mcp9808_init(struct device *dev)
{
struct mcp9808_data *data = dev->driver_data;
+ struct mcp9808_config *config = dev->config->config_info;

dev->driver_api = &mcp9808_api_funcs;

- data->i2c_master = device_get_binding(CONFIG_MCP9808_I2C_DEV_NAME);
+ data->i2c_master = device_get_binding(GET_I2C_MASTER(config));
if (!data->i2c_master) {
DBG("mcp9808: i2c master not found: %s\n",
- CONFIG_MCP9808_I2C_DEV_NAME);
+ GET_I2C_MASTER(config));
return -EINVAL;
}

- data->i2c_slave_addr = CONFIG_MCP9808_I2C_ADDR;
+ data->i2c_slave_addr = GET_I2C_ADDR(config);

mcp9808_setup_interrupt(dev);

return 0;
}
-
-DEVICE_INIT(mcp9808, CONFIG_MCP9808_DEV_NAME, mcp9808_init, &mcp9808_data,
- NULL, SECONDARY, CONFIG_MCP9808_INIT_PRIORITY);
diff --git a/drivers/sensor/sensor_mcp9808.h b/drivers/sensor/sensor_mcp9808.h
index 2b6188f..ec6e675 100644
--- a/drivers/sensor/sensor_mcp9808.h
+++ b/drivers/sensor/sensor_mcp9808.h
@@ -22,6 +22,8 @@
#include <stdint.h>
#include <device.h>
#include <sensor.h>
+#include <gpio.h>
+#include <i2c.h>
#include <misc/util.h>

#ifndef CONFIG_SENSOR_DEBUG
@@ -48,23 +50,30 @@

#define MCP9808_TEMP_MAX 0xffc

+struct mcp9808_config {
+ DECLARE_I2C_CLIENT_CONFIG;
+#ifdef CONFIG_MCP9808_TRIGGER
+ DECLARE_SENSOR_TRIG_CONFIG;
+ DECLARE_GPIO_PIN_CONFIG;
+#endif
+};
+
struct mcp9808_data {
struct device *i2c_master;
uint16_t i2c_slave_addr;

uint16_t reg_val;

-#ifdef CONFIG_MCP9808_TRIGGER_OWN_FIBER
- struct nano_sem sem;
-#endif
-
-#ifdef CONFIG_MCP9808_TRIGGER_GLOBAL_FIBER
- struct sensor_work work;
-#endif
-
#ifdef CONFIG_MCP9808_TRIGGER
+ union {
+ struct nano_sem sem;
+ struct sensor_work work;
+ };
+
+ enum sensor_trigger_mode trig_mode;
struct sensor_trigger trig;
sensor_trigger_handler_t trigger_handler;
+ struct gpio_callback gpio_cb;
#endif
};

@@ -94,9 +103,11 @@ static inline int mcp9808_trigger_set(struct device *dev,
return -ENOTSUP;
}

-static void mcp9808_setup_interrupt(struct device *dev)
+static inline void mcp9808_setup_interrupt(struct device *dev)
{
}
#endif /* CONFIG_MCP9808_TRIGGER */

+extern int mcp9808_init(struct device *dev);
+
#endif /* __SENSOR_MCP9808_H__ */
diff --git a/drivers/sensor/sensor_mcp9808_trigger.c b/drivers/sensor/sensor_mcp9808_trigger.c
index 380ae23..957c61a 100644
--- a/drivers/sensor/sensor_mcp9808_trigger.c
+++ b/drivers/sensor/sensor_mcp9808_trigger.c
@@ -20,7 +20,6 @@

#include <nanokernel.h>
#include <i2c.h>
-#include <gpio.h>
#include <misc/byteorder.h>
#include "sensor_mcp9808.h"

@@ -124,41 +123,21 @@ int mcp9808_trigger_set(struct device *dev,
handler == NULL ? 0 : MCP9808_ALERT_CNT);
}

-#ifdef CONFIG_MCP9808_TRIGGER_OWN_FIBER
-
-static void mcp9808_gpio_cb(struct device *dev, uint32_t pin)
+static void mcp9808_gpio_cb(struct device *dev,
+ struct gpio_callback *cb, uint32_t pins)
{
- struct mcp9808_data *data = &mcp9808_data;
-
- nano_isr_sem_give(&data->sem);
-}
+ struct mcp9808_data *data =
+ CONTAINER_OF(cb, struct mcp9808_data, gpio_cb);

-static void mcp9808_fiber_main(int arg1, int arg2)
-{
- struct device *dev = INT_TO_POINTER(arg1);
- struct mcp9808_data *data = dev->driver_data;
-
- ARG_UNUSED(arg2);
+ ARG_UNUSED(pins);

- while (1) {
- nano_fiber_sem_take(&data->sem, TICKS_UNLIMITED);
- data->trigger_handler(dev, &data->trig);
- mcp9808_reg_update(data, MCP9808_REG_CONFIG,
- MCP9808_INT_CLEAR, MCP9808_INT_CLEAR);
+ if (data->trig_mode == SENSOR_TRIG_MODE_OWN) {
+ nano_isr_sem_give(&data->sem);
+ } else if (data->trig_mode == SENSOR_TRIG_MODE_GLOBAL) {
+ nano_isr_fifo_put(sensor_get_work_fifo(), &data->work);
}
}

-static char __stack mcp9808_fiber_stack[CONFIG_MCP9808_FIBER_STACK_SIZE];
-
-#else /* CONFIG_MCP9808_TRIGGER_GLOBAL_FIBER */
-
-static void mcp9808_gpio_cb(struct device *dev, uint32_t pin)
-{
- struct mcp9808_data *data = &mcp9808_data;
-
- nano_isr_fifo_put(sensor_get_work_fifo(), &data->work);
-}
-
static void mcp9808_gpio_fiber_cb(void *arg)
{
struct device *dev = arg;
@@ -169,35 +148,53 @@ static void mcp9808_gpio_fiber_cb(void *arg)
MCP9808_INT_CLEAR, MCP9808_INT_CLEAR);
}

-#endif /* CONFIG_MCP9808_TRIGGER_GLOBAL_FIBER */
+static void mcp9808_fiber_main(int arg1, int arg2)
+{
+ struct device *dev = INT_TO_POINTER(arg1);
+ struct mcp9808_data *data = dev->driver_data;
+
+ ARG_UNUSED(arg2);
+
+ while (1) {
+ nano_fiber_sem_take(&data->sem, TICKS_UNLIMITED);
+ mcp9808_gpio_fiber_cb(dev);
+ }
+}

void mcp9808_setup_interrupt(struct device *dev)
{
struct mcp9808_data *data = dev->driver_data;
+ struct mcp9808_config *config = dev->config->config_info;
+ uint32_t gpio_pin = GET_GPIO_PIN(config);
struct device *gpio;

+ data->trig_mode = GET_SENSOR_TRIG_MODE(config);
+ if (data->trig_mode == SENSOR_TRIG_MODE_NONE) {
+ return;
+ }
+
mcp9808_reg_update(data, MCP9808_REG_CONFIG, MCP9808_ALERT_INT,
MCP9808_ALERT_INT);
mcp9808_reg_write(data, MCP9808_REG_CRITICAL, MCP9808_TEMP_MAX);
mcp9808_reg_update(data, MCP9808_REG_CONFIG, MCP9808_INT_CLEAR,
MCP9808_INT_CLEAR);

-#ifdef CONFIG_MCP9808_TRIGGER_OWN_FIBER
- nano_sem_init(&data->sem);
-
- fiber_fiber_start(mcp9808_fiber_stack,
- CONFIG_MCP9808_FIBER_STACK_SIZE,
- mcp9808_fiber_main, POINTER_TO_INT(dev), 0,
- CONFIG_MCP9808_FIBER_PRIORITY, 0);
-#else /* CONFIG_MCP9808_TRIGGER_GLOBAL_FIBER */
- data->work.handler = mcp9808_gpio_fiber_cb;
- data->work.arg = dev;
-#endif
+ if (data->trig_mode == SENSOR_TRIG_MODE_OWN) {
+ nano_sem_init(&data->sem);
+ sensor_fiber_start(&GET_SENSOR_FIBER_CONFIG(config),
+ mcp9808_fiber_main,
+ POINTER_TO_INT(dev), 0, 0);
+ } else {
+ data->work.handler = mcp9808_gpio_fiber_cb;
+ data->work.arg = dev;
+ }

- gpio = device_get_binding(CONFIG_MCP9808_GPIO_CONTROLLER);
- gpio_pin_configure(gpio, CONFIG_MCP9808_GPIO_PIN,
+ gpio = device_get_binding(GET_GPIO_CONTROLLER(config));
+ gpio_pin_configure(gpio, gpio_pin,
GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE);
- gpio_set_callback(gpio, mcp9808_gpio_cb);
- gpio_pin_enable_callback(gpio, CONFIG_MCP9808_GPIO_PIN);
+
+ gpio_init_callback(&data->gpio_cb, mcp9808_gpio_cb, BIT(gpio_pin));
+ gpio_register_callback(gpio, &data->gpio_cb);
+ gpio_pin_enable_callback(gpio, gpio_pin);
}
--
1.9.1