drivers: sensors: Add tachometer driver for MEC family

Introduce the tach driver for the microchip XEC SoCs.

Signed-off-by: Francisco Munoz <francisco.munoz.ruiz@intel.com>
This commit is contained in:
Francisco Munoz 2020-02-03 18:08:13 -08:00 committed by Maureen Helm
commit 7357ae974f
5 changed files with 163 additions and 0 deletions

View file

@ -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)

View file

@ -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"

View file

@ -0,0 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_TACH_XEC tach_mchp_xec.c)

View file

@ -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.

View file

@ -0,0 +1,145 @@
/*
* Copyright (c) 2020 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <device.h>
#include <drivers/sensor.h>
#include <soc.h>
#include <logging/log.h>
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