From f6af5a531f4b9995a6fd1ecd3829a89840d923c0 Mon Sep 17 00:00:00 2001 From: "Dylan (Luberry) Kozicki" Date: Sun, 13 Mar 2022 12:53:23 -0400 Subject: [PATCH] add kconfig and initial dts binding files --- app/drivers/sensor/Kconfig | 3 +- app/drivers/sensor/pmw3389/Kconfig | 49 ++++++ app/drivers/sensor/pmw3389/pmw3389.c | 164 +++++++----------- app/drivers/sensor/pmw3389/pmw3389.h | 4 +- app/drivers/sensor/pmw3389/pmw3389_trigger.c | 35 ++-- .../dts/bindings/sensor/pixart,pmw3389.yaml | 22 +++ 6 files changed, 155 insertions(+), 122 deletions(-) create mode 100644 app/drivers/sensor/pmw3389/Kconfig create mode 100644 app/drivers/zephyr/dts/bindings/sensor/pixart,pmw3389.yaml diff --git a/app/drivers/sensor/Kconfig b/app/drivers/sensor/Kconfig index a828f6c6..d47c7fea 100644 --- a/app/drivers/sensor/Kconfig +++ b/app/drivers/sensor/Kconfig @@ -2,4 +2,5 @@ # SPDX-License-Identifier: MIT rsource "battery/Kconfig" -rsource "ec11/Kconfig" \ No newline at end of file +rsource "ec11/Kconfig" +rsource "pmw3389/Kconfig" \ No newline at end of file diff --git a/app/drivers/sensor/pmw3389/Kconfig b/app/drivers/sensor/pmw3389/Kconfig new file mode 100644 index 00000000..219d8057 --- /dev/null +++ b/app/drivers/sensor/pmw3389/Kconfig @@ -0,0 +1,49 @@ +config PMW3389 + bool "PMW3389 Mouse Sensor" + depends on SPI + help + Enable mouse sensor + + The PMW3389 is a 16-bit optical mouse sensor + +if PMW3389 + +choice + prompt "Trigger mode" + default PMW3389_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config PMW3389_TRIGGER_NONE + bool "No trigger" + +config PMW3389_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select PMW3389_TRIGGER + +config PMW3389_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select PMW3389_TRIGGER + +endchoice + +config PMW3389_TRIGGER + bool + +config PMW3389_THREAD_PRIORITY + int "Thread priority" + depends on PMW3389_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config PMW3389_THREAD_STACK_SIZE + int "Thread stack size" + depends on PMW3389_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +endif # PMW3389 \ No newline at end of file diff --git a/app/drivers/sensor/pmw3389/pmw3389.c b/app/drivers/sensor/pmw3389/pmw3389.c index 32bcce63..914bc5b8 100644 --- a/app/drivers/sensor/pmw3389/pmw3389.c +++ b/app/drivers/sensor/pmw3389/pmw3389.c @@ -16,9 +16,7 @@ LOG_MODULE_REGISTER(PMW3389, CONFIG_SENSOR_LOG_LEVEL); -static int pmw3389_access(const struct device *dev, - uint8_t reg, uint8_t *value) -{ +static int pmw3389_access(const struct device *dev, uint8_t reg, uint8_t *value) { struct pmw3389_data *data = dev->data; const struct pmw3389_config *cfg = dev->config; const struct spi_config *spi_cfg = &cfg->bus_cfg.spi_cfg->spi_conf; @@ -38,8 +36,7 @@ static int pmw3389_access(const struct device *dev, .count = 2, }; struct spi_buf_set *rx; - if (reg & PMW3389_WR_MASK > 0) - { + if (reg & PMW3389_WR_MASK > 0) { rx = &(struct spi_buf_set){ .buffers = bufs, .count = 2, @@ -47,37 +44,32 @@ static int pmw3389_access(const struct device *dev, } return spi_transceive(data->bus, spi_cfg, &tx, rx); } -static int pmw3389_read_reg(const struct device *dev, const uint8_t reg, uint8_t *value) -{ +static int pmw3389_read_reg(const struct device *dev, const uint8_t reg, uint8_t *value) { return pmw3389_access(dev, reg, value); } -static int pmw3389_write_reg(const struct device *dev, const uint8_t reg, const uint8_t value) -{ +static int pmw3389_write_reg(const struct device *dev, const uint8_t reg, const uint8_t value) { return pmw3389_access(dev, reg & PMW3389_WR_MASK, &value); } // converts twos complement data to an int16 -static int16_t pmw3389_raw_to_int16(const uint8_t src[2]) -{ +static int16_t pmw3389_raw_to_int16(const uint8_t src[2]) { int16_t res = sys_get_be16(src[2]); if (res > BIT_MASK(15)) res -= BIT(16); return res; } -static int pmw3389_read_raw(const struct device *dev, const uint8_t reg_high, const uint8_t reg_low, int16_t *value) -{ +static int pmw3389_read_raw(const struct device *dev, const uint8_t reg_high, const uint8_t reg_low, + int16_t *value) { uint8_t raw[2] = {0x0, 0x0}; int err; err = pmw3389_read_reg(dev, reg_high, &raw[0]); - if (err) - { + if (err) { LOG_ERR("could not read high byte at %x", reg_high); return err; } err = pmw3389_read_reg(dev, reg_low, &raw[1]); - if (err) - { + if (err) { LOG_ERR("could not read low byte at %x", reg_low); return err; } @@ -85,48 +77,40 @@ static int pmw3389_read_raw(const struct device *dev, const uint8_t reg_high, co return 0; } -static bool pmw3389_spi_check_id(const struct device *dev) -{ +static bool pmw3389_spi_check_id(const struct device *dev) { int err; uint8_t val; err = pmw3389_read_reg(dev, &val, PMW3389_REG_PID); - if (err) - { + if (err) { LOG_ERR("could not read PID"); return false; } - if (val != PMW3389_PID) - { + if (val != PMW3389_PID) { LOG_ERR("invalid PID"); return false; } err = pmw3389_read_reg(dev, &val, PMW3389_REG_REV); - if (err) - { + if (err) { LOG_ERR("could not read REV"); return false; } - if (val != PMW3389_REV) - { + if (val != PMW3389_REV) { LOG_ERR("invalid REV"); return false; } return true; } -int pmw3389_spi_init(const struct device *dev) -{ +int pmw3389_spi_init(const struct device *dev) { struct pmw3389_data *data = dev->data; const struct pmw3389_config *cfg = dev->config; const struct pmw3389_spi_cfg *spi_cfg = cfg->bus_cfg.spi_cfg; - if (spi_cfg->cs_gpios_label != NULL) - { + if (spi_cfg->cs_gpios_label != NULL) { /* handle SPI CS thru GPIO if it is the case */ data->cs_ctrl.gpio_dev = device_get_binding(spi_cfg->cs_gpios_label); - if (!data->cs_ctrl.gpio_dev) - { + if (!data->cs_ctrl.gpio_dev) { LOG_ERR("Unable to get GPIO SPI CS device"); return -ENODEV; } @@ -135,32 +119,26 @@ int pmw3389_spi_init(const struct device *dev) return 0; } -static int pmw3389_sample_fetch(const struct device *dev, enum sensor_channel chan) -{ +static int pmw3389_sample_fetch(const struct device *dev, enum sensor_channel chan) { struct pmw3389_data *data = dev->data; const struct pmw3389_config *cfg = dev->config; uint16_t dx = 0, dy = 0; - if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_POS_DX && - chan != SENSOR_CHAN_POS_DY) + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_POS_DX && chan != SENSOR_CHAN_POS_DY) return -ENOTSUP; if (!pmw3389_spi_check_id(dev)) return -EINVAL; int err; - if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DX) - { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DX) { err = pmw3389_read_raw(dev, PMW3389_REG_DX_H, PMW3389_REG_DX_L, &dx); - if (err) - { + if (err) { LOG_DBG("could not read x motion"); return -EIO; } } - if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DY) - { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_POS_DY) { err = pmw3389_read_raw(dev, PMW3389_REG_DY_H, PMW3389_REG_DY_L, &dy); - if (err) - { + if (err) { LOG_DBG("could not read y motion"); return -EIO; } @@ -171,17 +149,15 @@ static int pmw3389_sample_fetch(const struct device *dev, enum sensor_channel ch } static int pmw3389_channel_get(const struct device *dev, enum sensor_channel chan, - struct sensor_value *val) -{ + struct sensor_value *val) { struct pmw3389_data *data = dev->data; const struct pmw3389_config *cfg = dev->config; - switch (chan) - { + switch (chan) { case SENSOR_CHAN_POS_DX: - return data->dx; + val->val1 = data->dx; case SENSOR_CHAN_POS_DY: - return data->dy; + val->val1 = data->dy; default: return -ENOTSUP; } @@ -197,35 +173,30 @@ static const struct sensor_driver_api pmw3389_driver_api = { .channel_get = pmw3389_channel_get, }; -static int pmw3389_init_chip(const struct device *dev) -{ +static int pmw3389_init_chip(const struct device *dev) { struct pmw3389_data *data = dev->data; return 0; } -static int pmw3389_init(const struct device *dev) -{ +static int pmw3389_init(const struct device *dev) { const struct pmw3389_config *const config = dev->config; struct pmw3389_data *data = dev->data; data->bus = device_get_binding(config->bus_name); - if (!data->bus) - { + if (!data->bus) { LOG_DBG("master not found: %s", log_strdup(config->bus_name)); return -EINVAL; } config->bus_init(dev); - if (pmw3389_init_chip(dev) < 0) - { + if (pmw3389_init_chip(dev) < 0) { LOG_DBG("failed to initialize chip"); return -EIO; } #ifdef CONFIG_PMW3389_TRIGGER - if (pmw3389_init_interrupt(dev) < 0) - { + if (pmw3389_init_interrupt(dev) < 0) { LOG_DBG("Failed to initialize interrupt!"); return -EIO; } @@ -236,55 +207,54 @@ static int pmw3389_init(const struct device *dev) #define PMW3389_HAS_CS(n) DT_INST_SPI_DEV_HAS_CS_GPIOS(n) -#define PMW3389_DATA_SPI_CS(n) \ - { \ - .cs_ctrl = { \ - .gpio_pin = DT_INST_SPI_DEV_CS_GPIOS_PIN(n), \ - .gpio_dt_flags = DT_INST_SPI_DEV_CS_GPIOS_FLAGS(n), \ - }, \ +#define PMW3389_DATA_SPI_CS(n) \ + { \ + .cs_ctrl = { \ + .gpio_pin = DT_INST_SPI_DEV_CS_GPIOS_PIN(n), \ + .gpio_dt_flags = DT_INST_SPI_DEV_CS_GPIOS_FLAGS(n), \ + }, \ } #define PMW3389_DATA_SPI(n) COND_CODE_1(PMW3389_HAS_CS(n), (PMW3389_DATA_SPI_CS(n)), ({})) #define PMW3389_SPI_CS_PTR(n) COND_CODE_1(PMW3389_HAS_CS(n), (&(pmw3389_data_##n.cs_ctrl)), (NULL)) -#define PMW3389_SPI_CS_LABEL(n) \ +#define PMW3389_SPI_CS_LABEL(n) \ COND_CODE_1(PMW3389_HAS_CS(n), (DT_INST_SPI_DEV_CS_GPIOS_LABEL(n)), (NULL)) -#define PMW3389_SPI_CFG(n) \ - (&(struct pmw3389_spi_cfg){ \ - .spi_conf = \ - { \ - .frequency = DT_INST_PROP(n, spi_max_frequency), \ - .operation = \ - (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA), \ - .slave = DT_INST_REG_ADDR(n), \ - .cs = PMW3389_SPI_CS_PTR(n), \ - }, \ - .cs_gpios_label = PMW3389_SPI_CS_LABEL(n), \ +#define PMW3389_SPI_CFG(n) \ + (&(struct pmw3389_spi_cfg){ \ + .spi_conf = \ + { \ + .frequency = DT_INST_PROP(n, spi_max_frequency), \ + .operation = \ + (SPI_WORD_SET(8) | SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA), \ + .slave = DT_INST_REG_ADDR(n), \ + .cs = PMW3389_SPI_CS_PTR(n), \ + }, \ + .cs_gpios_label = PMW3389_SPI_CS_LABEL(n), \ }) -#define PMW3389_GPIO_DT_SPEC_GET_BY_IDX(node_id, prop, idx) \ - { \ - .port = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx)), \ - .pin = DT_GPIO_PIN_BY_IDX(node_id, prop, idx), \ - .dt_flags = DT_GPIO_FLAGS_BY_IDX(node_id, prop, idx), \ +#define PMW3389_GPIO_DT_SPEC_GET_BY_IDX(node_id, prop, idx) \ + { \ + .port = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx)), \ + .pin = DT_GPIO_PIN_BY_IDX(node_id, prop, idx), \ + .dt_flags = DT_GPIO_FLAGS_BY_IDX(node_id, prop, idx), \ } -#define PMW3389_CONFIG_SPI(n) \ - { \ - .bus_name = DT_INST_BUS_LABEL(n), .bus_init = pmw3389_spi_init, \ - .bus_cfg = {.spi_cfg = PMW3389_SPI_CFG(n)}, \ - COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))) \ - COND_CODE_1(CONFIG_PMW3389_TRIGGER, \ - (, PMW3389_GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(n), motswk_gpios, 0), ), \ - ()) \ +#define PMW3389_CONFIG_SPI(n) \ + { \ + .bus_name = DT_INST_BUS_LABEL(n), .bus_init = pmw3389_spi_init, \ + .bus_cfg = {.spi_cfg = PMW3389_SPI_CFG(n)}, \ + COND_CODE_1(CONFIG_MA730_TRIGGER, \ + (, PMW3389_GPIO_DT_SPEC_GET_BY_IDX(DT_DRV_INST(n), motswk_gpios, 0)), ()) \ } -#define PMW3389_INST(n) \ - static struct pmw3389_data pmw3389_data_##n = PMW3389_DATA_SPI(n); \ - static const struct pmw3389_config pmw3389_cfg_##n = PMW3389_CONFIG_SPI(n); \ - DEVICE_DT_INST_DEFINE(n, pmw3389_init, device_pm_control_nop, &pmw3389_data_##n, &pmw3389_cfg_##n, \ - POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pmw3389_driver_api); +#define PMW3389_INST(n) \ + static struct pmw3389_data pmw3389_data_##n = PMW3389_DATA_SPI(n); \ + static const struct pmw3389_config pmw3389_cfg_##n = PMW3389_CONFIG_SPI(n); \ + DEVICE_DT_INST_DEFINE(n, pmw3389_init, device_pm_control_nop, &pmw3389_data_##n, \ + &pmw3389_cfg_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &pmw3389_driver_api); DT_INST_FOREACH_STATUS_OKAY(PMW3389_INST) \ No newline at end of file diff --git a/app/drivers/sensor/pmw3389/pmw3389.h b/app/drivers/sensor/pmw3389/pmw3389.h index ee000f30..0390b64a 100644 --- a/app/drivers/sensor/pmw3389/pmw3389.h +++ b/app/drivers/sensor/pmw3389/pmw3389.h @@ -40,9 +40,9 @@ struct pmw3389_config { int (*bus_init)(const struct device *dev); const union pmw3389_bus_cfg bus_cfg; int resolution; - struct pmw3389_gpio_dt_spec reset; + struct pmw3389_gpio_dt_spec reset_spec; #if CONFIG_PMW3389_TRIGGER - struct pmw3389_gpio_dt_spec motswk; + struct pmw3389_gpio_dt_spec motswk_spec; #endif // CONFIG_PMW3389_TRIGGER }; diff --git a/app/drivers/sensor/pmw3389/pmw3389_trigger.c b/app/drivers/sensor/pmw3389/pmw3389_trigger.c index 1ccd74f4..d60051b9 100644 --- a/app/drivers/sensor/pmw3389/pmw3389_trigger.c +++ b/app/drivers/sensor/pmw3389/pmw3389_trigger.c @@ -19,21 +19,18 @@ #include LOG_MODULE_DECLARE(PMW3389, CONFIG_SENSOR_LOG_LEVEL); -static inline void setup_int(const struct device *dev, bool enable) -{ +static inline void setup_int(const struct device *dev, bool enable) { struct pmw3389_data *data = dev->data; const struct pmw3389_config *cfg = dev->config; - if (gpio_pin_interrupt_configure(cfg->motswk.port, cfg->motswk.pin, - enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE)) - { + if (gpio_pin_interrupt_configure(cfg->motswk_spec.port, cfg->motswk_spec.pin, + enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE)) { LOG_WRN("Unable to set MOTSWK GPIO interrupt"); } } static void pmw3389_motswk_gpio_callback(const struct device *dev, struct gpio_callback *cb, - uint32_t pins) -{ + uint32_t pins) { struct pmw3389_data *drv_data = CONTAINER_OF(cb, struct pmw3389_data, motswk_gpio_cb); LOG_DBG(""); @@ -47,8 +44,7 @@ static void pmw3389_motswk_gpio_callback(const struct device *dev, struct gpio_c #endif } -static void pmw3389_thread_cb(const struct device *dev) -{ +static void pmw3389_thread_cb(const struct device *dev) { struct pmw3389_data *drv_data = dev->data; LOG_DBG("%p", drv_data->handler); @@ -59,15 +55,13 @@ static void pmw3389_thread_cb(const struct device *dev) } #ifdef CONFIG_PMW3389_TRIGGER_OWN_THREAD -static void pmw3389_thread(int dev_ptr, int unused) -{ +static void pmw3389_thread(int dev_ptr, int unused) { const struct device *dev = INT_TO_POINTER(dev_ptr); struct pmw3389_data *drv_data = dev->data; ARG_UNUSED(unused); - while (1) - { + while (1) { k_sem_take(&drv_data->gpio_sem, K_FOREVER); pmw3389_thread_cb(dev); } @@ -75,8 +69,7 @@ static void pmw3389_thread(int dev_ptr, int unused) #endif #ifdef CONFIG_PMW3389_TRIGGER_GLOBAL_THREAD -static void pmw3389_work_cb(struct k_work *work) -{ +static void pmw3389_work_cb(struct k_work *work) { struct pmw3389_data *drv_data = CONTAINER_OF(work, struct pmw3389_data, work); LOG_DBG(""); @@ -86,8 +79,7 @@ static void pmw3389_work_cb(struct k_work *work) #endif int pmw3389_trigger_set(const struct device *dev, const struct sensor_trigger *trig, - sensor_trigger_handler_t handler) -{ + sensor_trigger_handler_t handler) { struct pmw3389_data *drv_data = dev->data; setup_int(dev, false); @@ -102,18 +94,17 @@ int pmw3389_trigger_set(const struct device *dev, const struct sensor_trigger *t return 0; } -int pmw3389_init_interrupt(const struct device *dev) -{ +int pmw3389_init_interrupt(const struct device *dev) { struct pmw3389_data *drv_data = dev->data; const struct pmw3389_config *drv_cfg = dev->config; drv_data->dev = dev; /* setup gpio interrupt */ - gpio_init_callback(&drv_data->motswk_gpio_cb, pmw3389_motswk_gpio_callback, BIT(drv_cfg->motswk_spec.pin)); + gpio_init_callback(&drv_data->motswk_gpio_cb, pmw3389_motswk_gpio_callback, + BIT(drv_cfg->motswk_spec.pin)); - if (gpio_add_callback(drv_cfg->motswk_spec.port, &drv_data->motswk_gpio_cb) < 0) - { + if (gpio_add_callback(drv_cfg->motswk_spec.port, &drv_data->motswk_gpio_cb) < 0) { LOG_DBG("Failed to set MOTSWK callback!"); return -EIO; } diff --git a/app/drivers/zephyr/dts/bindings/sensor/pixart,pmw3389.yaml b/app/drivers/zephyr/dts/bindings/sensor/pixart,pmw3389.yaml new file mode 100644 index 00000000..1b9fc50e --- /dev/null +++ b/app/drivers/zephyr/dts/bindings/sensor/pixart,pmw3389.yaml @@ -0,0 +1,22 @@ +description: | + Sensor driver for the pixart PMW3389 optical mouse sensor +compatible: "pixart,pmw3389" + +include: spi-device.yaml + +properties: + label: + type: string + required: true + motswk-gpios: + type: phandle-array + required: false + description: interrupt pin for motion + reset-gpios: + type: phandle-array + required: false + description: A pin for the encoder + resolution: + type: int + description: mouse resolution + required: false \ No newline at end of file