driver: sensor: npcx: add tachometer sensor support.
In NPCX7 series, it contains two tachometer (TACH) modules that contains two Independent timers (counter 1 and 2). They are used to capture a counter value when an event is detected via the external pads (TA or TB). The CL also includes: — Add npcx tachometer device tree declarations. — Zephyr sensor api implementation for tachometer. — Enable "tach1" device in npcx7m6fb.dts for testing. Signed-off-by: Mulin Chao <mlchao@nuvoton.com>
This commit is contained in:
parent
377456c5af
commit
7c9d3f44f0
|
@ -79,3 +79,11 @@
|
|||
status = "okay";
|
||||
clock-frequency = <I2C_BITRATE_FAST>;
|
||||
};
|
||||
|
||||
&tach1 {
|
||||
status = "okay";
|
||||
pinctrl-0 = <&alt3_ta1_sl1>; /* Use TA1_SL1 (PIN40) as input pin */
|
||||
port = <NPCX_TACH_PORT_A>; /* port-A is selected */
|
||||
sample_clk = <NPCX_TACH_FREQ_LFCLK>; /* Use LFCLK as sampling clock */
|
||||
pulses_per_round = <1>; /* number of pulses per round of encoder */
|
||||
};
|
||||
|
|
|
@ -79,6 +79,7 @@ add_subdirectory_ifdef(CONFIG_TEMP_KINETIS nxp_kinetis_temp)
|
|||
add_subdirectory_ifdef(CONFIG_TACH_XEC mchp_tach_xec)
|
||||
add_subdirectory_ifdef(CONFIG_ITDS wsen_itds)
|
||||
add_subdirectory_ifdef(CONFIG_MCUX_ACMP mcux_acmp)
|
||||
add_subdirectory_ifdef(CONFIG_TACH_NPCX nuvoton_tach_npcx)
|
||||
|
||||
zephyr_sources_ifdef(CONFIG_USERSPACE sensor_handlers.c)
|
||||
zephyr_sources_ifdef(CONFIG_SENSOR_SHELL sensor_shell.c)
|
||||
|
|
|
@ -196,4 +196,6 @@ source "drivers/sensor/wsen_itds/Kconfig"
|
|||
|
||||
source "drivers/sensor/mcux_acmp/Kconfig"
|
||||
|
||||
source "drivers/sensor/nuvoton_tach_npcx/Kconfig"
|
||||
|
||||
endif # SENSOR
|
||||
|
|
5
drivers/sensor/nuvoton_tach_npcx/CMakeLists.txt
Normal file
5
drivers/sensor/nuvoton_tach_npcx/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_TACH_NPCX tach_nuvoton_npcx.c)
|
10
drivers/sensor/nuvoton_tach_npcx/Kconfig
Normal file
10
drivers/sensor/nuvoton_tach_npcx/Kconfig
Normal file
|
@ -0,0 +1,10 @@
|
|||
# NPCX tachometer sensor configuration options
|
||||
|
||||
# Copyright (c) 2021 Nuvoton Technology Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config TACH_NPCX
|
||||
bool "Nuvoton NPCX Tachometer sensor"
|
||||
depends on SOC_FAMILY_NPCX
|
||||
help
|
||||
Enable the "Nuvoton NPCX tachometer sensor.
|
390
drivers/sensor/nuvoton_tach_npcx/tach_nuvoton_npcx.c
Normal file
390
drivers/sensor/nuvoton_tach_npcx/tach_nuvoton_npcx.c
Normal file
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nuvoton Technology Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT nuvoton_npcx_tach
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Nuvoton NPCX tachometer sensor module driver
|
||||
*
|
||||
* This file contains a driver for the tachometer sensor module which contains
|
||||
* two independent timers (counter 1 and 2). They are used to capture a counter
|
||||
* value when the signals via external pins match the condition. The following
|
||||
* is block diagram of this module when it set to mode 5.
|
||||
*
|
||||
* | Capture A
|
||||
* | | +-----------+ TA Pin
|
||||
* +-----------+ | +-----+-----+ | _ _ | |
|
||||
* APB_CLK-->| Prescaler |--->|---+--->| Counter 1 |<--| _| |_| |_ |<--+
|
||||
* +-----------+ | | +-----------+ +-----------+
|
||||
* | CLK_SEL Edge Detection
|
||||
* | Capture B
|
||||
* LFCLK--------------------->| | +-----------+ TB Pin
|
||||
* | +-----+-----+ | _ _ | |
|
||||
* |---+--->| Counter 2 |<--| _| |_| |_ |<--+
|
||||
* | | +-----------+ +-----------+
|
||||
* | CLK_SEL Edge Detection
|
||||
* |
|
||||
* | TACH_CLK
|
||||
* +----------
|
||||
* (NPCX Tachometer Mode 5, Dual-Independent Input Capture)
|
||||
*
|
||||
* This mode is used to measure either the frequency of two external clocks
|
||||
* (via TA or TB pins) that are slower than TACH_CLK. A transition event (rising
|
||||
* or falling edge) received on TAn/TBn pin causes a transfer of timer 1/2
|
||||
* contents to Capture register and reload counter. Based on this value, we can
|
||||
* compute the current RPM of external signal from encoders.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <device.h>
|
||||
#include <drivers/clock_control.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <dt-bindings/sensor/npcx_tach.h>
|
||||
#include <soc.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(tach_npcx, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
/* Device config */
|
||||
struct tach_npcx_config {
|
||||
/* tachometer controller base address */
|
||||
uintptr_t base;
|
||||
/* clock configuration */
|
||||
struct npcx_clk_cfg clk_cfg;
|
||||
/* pinmux configuration */
|
||||
const uint8_t alts_size;
|
||||
const struct npcx_alt *alts_list;
|
||||
/* sampling clock frequency of tachometer */
|
||||
uint32_t sample_clk;
|
||||
/* selected port of tachometer */
|
||||
int port;
|
||||
/* number of pulses (holes) per round of tachometer's input (encoder) */
|
||||
int pulses_per_round;
|
||||
};
|
||||
|
||||
/* Driver data */
|
||||
struct tach_npcx_data {
|
||||
/* Input clock for tachometers */
|
||||
uint32_t input_clk;
|
||||
/* Captured counts of tachometer */
|
||||
uint32_t capture;
|
||||
};
|
||||
|
||||
/* Driver convenience defines */
|
||||
#define DRV_CONFIG(dev) ((const struct tach_npcx_config *)(dev)->config)
|
||||
|
||||
#define DRV_DATA(dev) ((struct tach_npcx_data *)(dev)->data)
|
||||
|
||||
#define HAL_INSTANCE(dev) (struct tach_reg *)(DRV_CONFIG(dev)->base)
|
||||
|
||||
/* Maximum count of prescaler */
|
||||
#define NPCX_TACHO_PRSC_MAX 0xff
|
||||
/* Maximum count of counter */
|
||||
#define NPCX_TACHO_CNT_MAX 0xffff
|
||||
/* Operation mode used for tachometer */
|
||||
#define NPCX_TACH_MDSEL 4
|
||||
/* Clock selection for tachometer */
|
||||
#define NPCX_CLKSEL_APBCLK 1
|
||||
#define NPCX_CLKSEL_LFCLK 4
|
||||
|
||||
/* TACH inline local functions */
|
||||
static inline void tach_npcx_start_port_a(const struct device *dev)
|
||||
{
|
||||
struct tach_npcx_data *const data = DRV_DATA(dev);
|
||||
struct tach_reg *const inst = HAL_INSTANCE(dev);
|
||||
|
||||
/* Set the default value of counter and capture register of timer 1. */
|
||||
inst->TCNT1 = NPCX_TACHO_CNT_MAX;
|
||||
inst->TCRA = NPCX_TACHO_CNT_MAX;
|
||||
|
||||
/*
|
||||
* Set the edge detection polarity of port A to falling (high-to-low
|
||||
* transition) and enable the functionality to capture TCNT1 into TCRA
|
||||
* and preset TCNT1 when event is triggered.
|
||||
*/
|
||||
inst->TMCTRL |= BIT(NPCX_TMCTRL_TAEN);
|
||||
|
||||
/* Enable input debounce logic into TA pin. */
|
||||
inst->TCFG |= BIT(NPCX_TCFG_TADBEN);
|
||||
|
||||
/* Select clock source of timer 1 from no clock and start to count. */
|
||||
SET_FIELD(inst->TCKC, NPCX_TCKC_C1CSEL_FIELD, data->input_clk == LFCLK
|
||||
? NPCX_CLKSEL_LFCLK : NPCX_CLKSEL_APBCLK);
|
||||
}
|
||||
|
||||
static inline void tach_npcx_start_port_b(const struct device *dev)
|
||||
{
|
||||
struct tach_reg *const inst = HAL_INSTANCE(dev);
|
||||
struct tach_npcx_data *const data = DRV_DATA(dev);
|
||||
|
||||
/* Set the default value of counter and capture register of timer 2. */
|
||||
inst->TCNT2 = NPCX_TACHO_CNT_MAX;
|
||||
inst->TCRB = NPCX_TACHO_CNT_MAX;
|
||||
|
||||
/*
|
||||
* Set the edge detection polarity of port B to falling (high-to-low
|
||||
* transition) and enable the functionality to capture TCNT2 into TCRB
|
||||
* and preset TCNT2 when event is triggered.
|
||||
*/
|
||||
inst->TMCTRL |= BIT(NPCX_TMCTRL_TBEN);
|
||||
|
||||
/* Enable input debounce logic into TB pin. */
|
||||
inst->TCFG |= BIT(NPCX_TCFG_TBDBEN);
|
||||
|
||||
/* Select clock source of timer 2 from no clock and start to count. */
|
||||
SET_FIELD(inst->TCKC, NPCX_TCKC_C2CSEL_FIELD, data->input_clk == LFCLK
|
||||
? NPCX_CLKSEL_LFCLK : NPCX_CLKSEL_APBCLK);
|
||||
}
|
||||
|
||||
static inline bool tach_npcx_is_underflow(const struct device *dev)
|
||||
{
|
||||
const struct tach_npcx_config *const config = DRV_CONFIG(dev);
|
||||
struct tach_reg *const inst = HAL_INSTANCE(dev);
|
||||
|
||||
LOG_DBG("port A is underflow %d, port b is underflow %d",
|
||||
IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TCPND),
|
||||
IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TDPND));
|
||||
|
||||
/*
|
||||
* In mode 5, the flag TCPND or TDPND indicates the TCNT1 or TCNT2
|
||||
* is under underflow situation. (No edges are detected.)
|
||||
*/
|
||||
if (config->port == NPCX_TACH_PORT_A) {
|
||||
return IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TCPND);
|
||||
} else {
|
||||
return IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TDPND);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tach_npcx_clear_underflow_flag(const struct device *dev)
|
||||
{
|
||||
const struct tach_npcx_config *const config = DRV_CONFIG(dev);
|
||||
struct tach_reg *const inst = HAL_INSTANCE(dev);
|
||||
|
||||
if (config->port == NPCX_TACH_PORT_A) {
|
||||
inst->TECLR = BIT(NPCX_TECLR_TCCLR);
|
||||
} else {
|
||||
inst->TECLR = BIT(NPCX_TECLR_TDCLR);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool tach_npcx_is_captured(const struct device *dev)
|
||||
{
|
||||
const struct tach_npcx_config *const config = DRV_CONFIG(dev);
|
||||
struct tach_reg *const inst = HAL_INSTANCE(dev);
|
||||
|
||||
LOG_DBG("port A is captured %d, port b is captured %d",
|
||||
IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TAPND),
|
||||
IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TAPND));
|
||||
|
||||
/*
|
||||
* In mode 5, the flag TAPND or TBPND indicates a input captured on
|
||||
* TAn or TBn transition.
|
||||
*/
|
||||
if (config->port == NPCX_TACH_PORT_A) {
|
||||
return IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TAPND);
|
||||
} else {
|
||||
return IS_BIT_SET(inst->TECTRL, NPCX_TECTRL_TBPND);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tach_npcx_clear_captured_flag(const struct device *dev)
|
||||
{
|
||||
const struct tach_npcx_config *const config = DRV_CONFIG(dev);
|
||||
struct tach_reg *const inst = HAL_INSTANCE(dev);
|
||||
|
||||
if (config->port == NPCX_TACH_PORT_A) {
|
||||
inst->TECLR = BIT(NPCX_TECLR_TACLR);
|
||||
} else {
|
||||
inst->TECLR = BIT(NPCX_TECLR_TBCLR);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint16_t tach_npcx_get_captured_count(const struct device *dev)
|
||||
{
|
||||
const struct tach_npcx_config *const config = DRV_CONFIG(dev);
|
||||
struct tach_reg *const inst = HAL_INSTANCE(dev);
|
||||
|
||||
if (config->port == NPCX_TACH_PORT_A) {
|
||||
return inst->TCRA;
|
||||
} else {
|
||||
return inst->TCRB;
|
||||
}
|
||||
}
|
||||
|
||||
/* TACH local functions */
|
||||
static int tach_npcx_configure(const struct device *dev)
|
||||
{
|
||||
const struct tach_npcx_config *const config = DRV_CONFIG(dev);
|
||||
struct tach_npcx_data *const data = DRV_DATA(dev);
|
||||
struct tach_reg *const inst = HAL_INSTANCE(dev);
|
||||
|
||||
/* Set mode 5 to tachometer module */
|
||||
SET_FIELD(inst->TMCTRL, NPCX_TMCTRL_MDSEL_FIELD, NPCX_TACH_MDSEL);
|
||||
|
||||
/* Configure clock module and its frequency of tachometer */
|
||||
if (config->sample_clk == 0) {
|
||||
return -EINVAL;
|
||||
} else if (data->input_clk == LFCLK) {
|
||||
/* Enable low power mode */
|
||||
inst->TCKC |= BIT(NPCX_TCKC_LOW_PWR);
|
||||
if (config->sample_clk != data->input_clk) {
|
||||
LOG_ERR("%s operate freq is %d not fixed to 32kHz",
|
||||
dev->name, data->input_clk);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
/* Configure sampling freq by setting prescaler of APB1 */
|
||||
uint16_t prescaler = data->input_clk / config->sample_clk;
|
||||
|
||||
if (data->input_clk > config->sample_clk) {
|
||||
LOG_ERR("%s operate freq exceeds APB1 clock",
|
||||
dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
inst->TPRSC = MIN(NPCX_TACHO_PRSC_MAX, MAX(prescaler, 1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TACH api functions */
|
||||
int tach_npcx_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
ARG_UNUSED(chan);
|
||||
struct tach_npcx_data *const data = DRV_DATA(dev);
|
||||
|
||||
/* Check whether underflow flag of tachometer is occurred */
|
||||
if (tach_npcx_is_underflow(dev)) {
|
||||
/* Clear pending flags */
|
||||
tach_npcx_clear_underflow_flag(dev);
|
||||
|
||||
LOG_INF("%s is underflow!", dev->name);
|
||||
data->capture = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check whether capture flag of tachometer is set */
|
||||
if (tach_npcx_is_captured(dev)) {
|
||||
/* Clear pending flags */
|
||||
tach_npcx_clear_captured_flag(dev);
|
||||
/* Save captured count */
|
||||
data->capture = NPCX_TACHO_CNT_MAX -
|
||||
tach_npcx_get_captured_count(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tach_npcx_channel_get(const struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
const struct tach_npcx_config *const config = DRV_CONFIG(dev);
|
||||
struct tach_npcx_data *const data = DRV_DATA(dev);
|
||||
|
||||
if (chan != SENSOR_CHAN_RPM) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (data->capture > 0) {
|
||||
/*
|
||||
* RPM = (f * 60) / (n * TACH)
|
||||
* n = Pulses per round
|
||||
* f = Tachometer operation freqency (Hz)
|
||||
* TACH = Captured counts of tachometer
|
||||
*/
|
||||
val->val1 = (config->sample_clk * 60) /
|
||||
(config->pulses_per_round * data->capture);
|
||||
} else {
|
||||
val->val1 = 0U;
|
||||
}
|
||||
|
||||
val->val2 = 0U;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* TACH driver registration */
|
||||
static int tach_npcx_init(const struct device *dev)
|
||||
{
|
||||
const struct tach_npcx_config *const config = DRV_CONFIG(dev);
|
||||
struct tach_npcx_data *const data = DRV_DATA(dev);
|
||||
const struct device *const clk_dev =
|
||||
device_get_binding(NPCX_CLK_CTRL_NAME);
|
||||
int ret;
|
||||
|
||||
/* Turn on device clock first and get source clock freq. */
|
||||
ret = clock_control_on(clk_dev, (clock_control_subsys_t *)
|
||||
&config->clk_cfg);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Turn on tachometer clock fail %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clock_control_get_rate(clk_dev, (clock_control_subsys_t *)
|
||||
&config->clk_cfg, &data->input_clk);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Get tachometer clock rate error %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure pin-mux for tachometer device */
|
||||
npcx_pinctrl_mux_configure(config->alts_list, config->alts_size, 1);
|
||||
|
||||
/* Configure tachometer and its operate freq. */
|
||||
ret = tach_npcx_configure(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Config tachometer port %d failed", config->port);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Start tachometer sensor */
|
||||
if (config->port == NPCX_TACH_PORT_A) {
|
||||
tach_npcx_start_port_a(dev);
|
||||
} else if (config->port == NPCX_TACH_PORT_B) {
|
||||
tach_npcx_start_port_b(dev);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api tach_npcx_driver_api = {
|
||||
.sample_fetch = tach_npcx_sample_fetch,
|
||||
.channel_get = tach_npcx_channel_get,
|
||||
};
|
||||
|
||||
#define NPCX_TACH_INIT(inst) \
|
||||
static const struct npcx_alt tach_alts##inst[] = \
|
||||
NPCX_DT_ALT_ITEMS_LIST(inst); \
|
||||
\
|
||||
static const struct tach_npcx_config tach_cfg_##inst = { \
|
||||
.base = DT_INST_REG_ADDR(inst), \
|
||||
.clk_cfg = NPCX_DT_CLK_CFG_ITEM(inst), \
|
||||
.alts_size = ARRAY_SIZE(tach_alts##inst), \
|
||||
.alts_list = tach_alts##inst, \
|
||||
.sample_clk = DT_INST_PROP(inst, sample_clk), \
|
||||
.port = DT_INST_PROP(inst, port), \
|
||||
.pulses_per_round = DT_INST_PROP(inst, pulses_per_round), \
|
||||
}; \
|
||||
\
|
||||
static struct tach_npcx_data tach_data_##inst; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(inst, \
|
||||
tach_npcx_init, \
|
||||
device_pm_control_nop, \
|
||||
&tach_data_##inst, \
|
||||
&tach_cfg_##inst, \
|
||||
POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, \
|
||||
&tach_npcx_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(NPCX_TACH_INIT)
|
|
@ -11,6 +11,7 @@
|
|||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/i2c/i2c.h>
|
||||
#include <dt-bindings/pwm/pwm.h>
|
||||
#include <dt-bindings/sensor/npcx_tach.h>
|
||||
|
||||
/* NPCX7 series pinmux mapping table */
|
||||
#include "npcx/npcx7-alts-map.dtsi"
|
||||
|
@ -700,6 +701,22 @@
|
|||
label = "I2C_7_PORT_0";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
tach1: tach@400e1000 {
|
||||
compatible = "nuvoton,npcx-tach";
|
||||
reg = <0x400e1000 0x2000>;
|
||||
clocks = <&pcc NPCX_CLOCK_BUS_LFCLK NPCX_PWDWN_CTL1 5>;
|
||||
label = "TACH_1";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
tach2: tach@400e3000 {
|
||||
compatible = "nuvoton,npcx-tach";
|
||||
reg = <0x400e3000 0x2000>;
|
||||
clocks = <&pcc NPCX_CLOCK_BUS_LFCLK NPCX_PWDWN_CTL1 6>;
|
||||
label = "TACH_2";
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
32
dts/bindings/tach/nuvoton,npcx-tach.yaml
Normal file
32
dts/bindings/tach/nuvoton,npcx-tach.yaml
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Copyright (c) 2021 Nuvoton Technology Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Nuvoton, NPCX-Tachometer node
|
||||
|
||||
compatible: "nuvoton,npcx-tach"
|
||||
|
||||
include: tach.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
clocks:
|
||||
required: true
|
||||
pinctrl-0:
|
||||
type: phandles
|
||||
required: false
|
||||
description: configurations of pinmux controllers in tachometers
|
||||
sample_clk:
|
||||
type: int
|
||||
required: false
|
||||
description: |
|
||||
sampling clock frequency of tachometer. Please notice that it must be
|
||||
fixed to 32768 if bus in clocks property is NPCX_CLOCK_BUS_LFCLK.
|
||||
port:
|
||||
type: int
|
||||
required: false
|
||||
description: selected port of tachometer (port-A is 0 and port-B is 1)
|
||||
pulses_per_round:
|
||||
type: int
|
||||
required: false
|
||||
description: number of pulses (holes) per round of tachometer's input (encoder)
|
16
include/dt-bindings/sensor/npcx_tach.h
Normal file
16
include/dt-bindings/sensor/npcx_tach.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nuvoton Technology Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_NPCX_TACH_H_
|
||||
#define ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_NPCX_TACH_H_
|
||||
|
||||
/* NPCX tachometer port type */
|
||||
#define NPCX_TACH_PORT_A 0
|
||||
#define NPCX_TACH_PORT_B 1
|
||||
|
||||
/* NPCX tachometer specific operate frequency */
|
||||
#define NPCX_TACH_FREQ_LFCLK 32768
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_SENSOR_NPCX_TACH_H_ */
|
|
@ -1173,4 +1173,78 @@ struct itim64_reg {
|
|||
#define NPCX_ITCTSXX_CKSEL 4
|
||||
#define NPCX_ITCTSXX_ITEN 7
|
||||
|
||||
/*
|
||||
* Tachometer (TACH) Sensor device registers
|
||||
*/
|
||||
struct tach_reg {
|
||||
/* 0x000: Timer/Counter 1 */
|
||||
volatile uint16_t TCNT1;
|
||||
/* 0x002: Reload/Capture A */
|
||||
volatile uint16_t TCRA;
|
||||
/* 0x004: Reload/Capture B */
|
||||
volatile uint16_t TCRB;
|
||||
/* 0x006: Timer/Counter 2 */
|
||||
volatile uint16_t TCNT2;
|
||||
/* 0x008: Clock Prescaler */
|
||||
volatile uint8_t TPRSC;
|
||||
volatile uint8_t reserved1;
|
||||
/* 0x00A: Clock Unit Control */
|
||||
volatile uint8_t TCKC;
|
||||
volatile uint8_t reserved2;
|
||||
/* 0x00C: Timer Mode Control */
|
||||
volatile uint8_t TMCTRL;
|
||||
volatile uint8_t reserved3;
|
||||
/* 0x00E: Timer Event Control */
|
||||
volatile uint8_t TECTRL;
|
||||
volatile uint8_t reserved4;
|
||||
/* 0x010: Timer Event Clear */
|
||||
volatile uint8_t TECLR;
|
||||
volatile uint8_t reserved5;
|
||||
/* 0x012: Timer Interrupt Enable */
|
||||
volatile uint8_t TIEN;
|
||||
volatile uint8_t reserved6;
|
||||
/* 0x014: Compare A */
|
||||
volatile uint16_t TCPA;
|
||||
/* 0x016: Compare B */
|
||||
volatile uint16_t TCPB;
|
||||
/* 0x018: Compare Configuration */
|
||||
volatile uint8_t TCPCFG;
|
||||
volatile uint8_t reserved7;
|
||||
/* 0x01A: Timer Wake-Up Enablen */
|
||||
volatile uint8_t TWUEN;
|
||||
volatile uint8_t reserved8;
|
||||
/* 0x01C: Timer Configuration */
|
||||
volatile uint8_t TCFG;
|
||||
volatile uint8_t reserved9;
|
||||
};
|
||||
|
||||
/* TACH register fields */
|
||||
#define NPCX_TCKC_LOW_PWR 7
|
||||
#define NPCX_TCKC_PLS_ACC_CLK 6
|
||||
#define NPCX_TCKC_C1CSEL_FIELD FIELD(0, 3)
|
||||
#define NPCX_TCKC_C2CSEL_FIELD FIELD(3, 3)
|
||||
#define NPCX_TMCTRL_MDSEL_FIELD FIELD(0, 3)
|
||||
#define NPCX_TMCTRL_TAEN 5
|
||||
#define NPCX_TMCTRL_TBEN 6
|
||||
#define NPCX_TMCTRL_TAEDG 3
|
||||
#define NPCX_TMCTRL_TBEDG 4
|
||||
#define NPCX_TCFG_TADBEN 6
|
||||
#define NPCX_TCFG_TBDBEN 7
|
||||
#define NPCX_TECTRL_TAPND 0
|
||||
#define NPCX_TECTRL_TBPND 1
|
||||
#define NPCX_TECTRL_TCPND 2
|
||||
#define NPCX_TECTRL_TDPND 3
|
||||
#define NPCX_TECLR_TACLR 0
|
||||
#define NPCX_TECLR_TBCLR 1
|
||||
#define NPCX_TECLR_TCCLR 2
|
||||
#define NPCX_TECLR_TDCLR 3
|
||||
#define NPCX_TIEN_TAIEN 0
|
||||
#define NPCX_TIEN_TBIEN 1
|
||||
#define NPCX_TIEN_TCIEN 2
|
||||
#define NPCX_TIEN_TDIEN 3
|
||||
#define NPCX_TWUEN_TAWEN 0
|
||||
#define NPCX_TWUEN_TBWEN 1
|
||||
#define NPCX_TWUEN_TCWEN 2
|
||||
#define NPCX_TWUEN_TDWEN 3
|
||||
|
||||
#endif /* _NUVOTON_NPCX_REG_DEF_H */
|
||||
|
|
|
@ -88,6 +88,15 @@ config I2C_NPCX
|
|||
both Intel SMBus and Philips I2C physical layer. There are 8 SMBus
|
||||
modules and 10 buses in NPCX7 series.
|
||||
|
||||
config TACH_NPCX
|
||||
default y
|
||||
depends on SENSOR
|
||||
help
|
||||
Enable support for NPCX tachometer sensor driver. The NPCX7 series
|
||||
contains two tachometer (TACH) modules that contains two counters
|
||||
(counter A and B). They are used to capture/compare a counter value
|
||||
when an event is generated on comparison of signals match.
|
||||
|
||||
if SOC_POWER_MANAGEMENT
|
||||
|
||||
config PM
|
||||
|
|
|
@ -149,3 +149,11 @@ NPCX_REG_OFFSET_CHECK(itim64_reg, ITPRE64, 0x001);
|
|||
NPCX_REG_OFFSET_CHECK(itim64_reg, ITCTS64, 0x004);
|
||||
NPCX_REG_OFFSET_CHECK(itim64_reg, ITCNT64L, 0x008);
|
||||
NPCX_REG_OFFSET_CHECK(itim64_reg, ITCNT64H, 0x00c);
|
||||
|
||||
/* TACH register structure check */
|
||||
NPCX_REG_SIZE_CHECK(tach_reg, 0x01e);
|
||||
NPCX_REG_OFFSET_CHECK(tach_reg, TPRSC, 0x008);
|
||||
NPCX_REG_OFFSET_CHECK(tach_reg, TECLR, 0x010);
|
||||
NPCX_REG_OFFSET_CHECK(tach_reg, TCPA, 0x014);
|
||||
NPCX_REG_OFFSET_CHECK(tach_reg, TCPCFG, 0x018);
|
||||
NPCX_REG_OFFSET_CHECK(tach_reg, TCFG, 0x01c);
|
||||
|
|
|
@ -37,6 +37,7 @@ CONFIG_SI7055=y
|
|||
CONFIG_SI7060=y
|
||||
CONFIG_SM351LT=y
|
||||
CONFIG_SX9500=y
|
||||
CONFIG_TACH_NPCX=y
|
||||
CONFIG_TEMP_NRF5=y
|
||||
CONFIG_TH02=y
|
||||
CONFIG_TI_HDC=y
|
||||
|
|
Loading…
Reference in a new issue