From 7357ae974fdf590045398bd545b50646cb824997 Mon Sep 17 00:00:00 2001 From: Francisco Munoz Date: Mon, 3 Feb 2020 18:08:13 -0800 Subject: [PATCH] drivers: sensors: Add tachometer driver for MEC family Introduce the tach driver for the microchip XEC SoCs. Signed-off-by: Francisco Munoz --- drivers/sensor/CMakeLists.txt | 1 + drivers/sensor/Kconfig | 2 + drivers/sensor/mchp_tach_xec/CMakeLists.txt | 5 + drivers/sensor/mchp_tach_xec/Kconfig | 10 ++ drivers/sensor/mchp_tach_xec/tach_mchp_xec.c | 145 +++++++++++++++++++ 5 files changed, 163 insertions(+) create mode 100644 drivers/sensor/mchp_tach_xec/CMakeLists.txt create mode 100644 drivers/sensor/mchp_tach_xec/Kconfig create mode 100644 drivers/sensor/mchp_tach_xec/tach_mchp_xec.c diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 6421729f5db..594de34a7c5 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -61,6 +61,7 @@ add_subdirectory_ifdef(CONFIG_TMP112 tmp112) add_subdirectory_ifdef(CONFIG_TMP116 tmp116) add_subdirectory_ifdef(CONFIG_VL53L0X vl53l0x) add_subdirectory_ifdef(CONFIG_TEMP_KINETIS nxp_kinetis_temp) +add_subdirectory_ifdef(CONFIG_TACH_XEC mchp_tach_xec) zephyr_sources_ifdef(CONFIG_USERSPACE sensor_handlers.c) zephyr_sources_ifdef(CONFIG_SENSOR_SHELL sensor_shell.c) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 543dcb755c5..bf8897934fe 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -113,6 +113,8 @@ source "drivers/sensor/max30101/Kconfig" source "drivers/sensor/max44009/Kconfig" +source "drivers/sensor/mchp_tach_xec/Kconfig" + source "drivers/sensor/mcp9808/Kconfig" source "drivers/sensor/mpu6050/Kconfig" diff --git a/drivers/sensor/mchp_tach_xec/CMakeLists.txt b/drivers/sensor/mchp_tach_xec/CMakeLists.txt new file mode 100644 index 00000000000..9658421e10f --- /dev/null +++ b/drivers/sensor/mchp_tach_xec/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_TACH_XEC tach_mchp_xec.c) diff --git a/drivers/sensor/mchp_tach_xec/Kconfig b/drivers/sensor/mchp_tach_xec/Kconfig new file mode 100644 index 00000000000..45045a9b925 --- /dev/null +++ b/drivers/sensor/mchp_tach_xec/Kconfig @@ -0,0 +1,10 @@ +# Mcrochip mec150x tachometer sensor configuration options + +# Copyright (c) 2020 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config TACH_XEC + bool "XEC Tachometer sensor" + depends on SOC_FAMILY_MEC + help + Enable the Microchip XEC tachometer sensor. diff --git a/drivers/sensor/mchp_tach_xec/tach_mchp_xec.c b/drivers/sensor/mchp_tach_xec/tach_mchp_xec.c new file mode 100644 index 00000000000..f6c8e5b64c7 --- /dev/null +++ b/drivers/sensor/mchp_tach_xec/tach_mchp_xec.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(tach_xec, CONFIG_SENSOR_LOG_LEVEL); + +struct tach_xec_config { + u32_t base_address; +}; + +struct tach_xec_data { + u16_t count; +}; + +#define FAN_STOPPED 0xFFFFU +#define COUNT_100KHZ_SEC 100000U +#define SEC_TO_MINUTE 60U +#define PIN_STS_TIMEOUT 20U + +#define TACH_XEC_REG_BASE(_dev) \ + ((TACH_Type *) \ + ((const struct tach_xec_config * const) \ + _dev->config->config_info)->base_address) + +#define TACH_XEC_CONFIG(_dev) \ + (((const struct counter_xec_config * const) \ + _dev->config->config_info)) + +#define TACH_XEC_DATA(_dev) \ + ((struct tach_xec_data *)dev->driver_data) + + +int tach_xec_sample_fetch(struct device *dev, enum sensor_channel chan) +{ + ARG_UNUSED(chan); + + TACH_Type *tach = TACH_XEC_REG_BASE(dev); + struct tach_xec_data *data = TACH_XEC_DATA(dev); + u8_t poll_count = 0; + + while (poll_count < PIN_STS_TIMEOUT) { + /* See whether internal counter is already latched */ + if (tach->STATUS & MCHP_TACH_STS_CNT_RDY) { + data->count = + tach->CONTROL >> MCHP_TACH_CTRL_COUNTER_POS; + break; + } + + poll_count++; + + /* Allow other threads to run while we sleep */ + k_usleep(USEC_PER_MSEC); + } + + if (poll_count == PIN_STS_TIMEOUT) { + return -EINVAL; + } + + /* We interprept a fan stopped or jammed as 0 */ + if (data->count == FAN_STOPPED) { + data->count = 0U; + } + + return 0; +} + +static int tach_xec_channel_get(struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct tach_xec_data *data = TACH_XEC_DATA(dev); + + if (chan != SENSOR_CHAN_RPM) { + return -ENOTSUP; + } + + /* Convert the count per 100khz cycles to rpm */ + if (data->count != FAN_STOPPED && data->count != 0U) { + val->val1 = (SEC_TO_MINUTE * COUNT_100KHZ_SEC)/data->count; + val->val2 = 0U; + } else { + val->val1 = 0U; + } + + val->val2 = 0U; + + return 0; +} + +static int tach_xec_init(struct device *dev) +{ + TACH_Type *tach = TACH_XEC_REG_BASE(dev); + + tach->CONTROL = MCHP_TACH_CTRL_READ_MODE_100K_CLOCK | + MCHP_TACH_CTRL_EDGES_5 | + MCHP_TACH_CTRL_FILTER_EN | + MCHP_TACH_CTRL_EN; + + return 0; +} + +static const struct sensor_driver_api tach_xec_driver_api = { + .sample_fetch = tach_xec_sample_fetch, + .channel_get = tach_xec_channel_get, +}; + +#define TACH_XEC_DEVICE(id) \ + static const struct tach_xec_config tach_xec_dev_config##id = { \ + .base_address = \ + DT_INST_##id##_MICROCHIP_XEC_TACH_BASE_ADDRESS, \ + }; \ + \ + static struct tach_xec_data tach_xec_dev_data##id; \ + \ + DEVICE_AND_API_INIT(tach##id, \ + DT_INST_##id##_MICROCHIP_XEC_TACH_LABEL, \ + tach_xec_init, \ + &tach_xec_dev_data##id, \ + &tach_xec_dev_config##id, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &tach_xec_driver_api) \ + +#ifdef DT_INST_0_MICROCHIP_XEC_TACH +TACH_XEC_DEVICE(0); +#endif + +#ifdef DT_INST_1_MICROCHIP_XEC_TACH +TACH_XEC_DEVICE(1); +#endif + +#ifdef DT_INST_2_MICROCHIP_XEC_TACH +TACH_XEC_DEVICE(2); +#endif + +#ifdef DT_INST_3_MICROCHIP_XEC_TACH +TACH_XEC_DEVICE(3); +#endif