From 0245a27bc54c9ca1f1c4dff440754f9070ce4a25 Mon Sep 17 00:00:00 2001 From: Mulin Chao Date: Thu, 2 Jul 2020 15:44:38 +0800 Subject: [PATCH] driver: clock: Add clock controller support in NPCX series. Add clock controller support for Nuvoton NPCX series. This CL includes: 1. Add clock controller device tree declarations. 2. Introduce clock-cells in yaml file clock tree to get module's source clock and turn off/on the its clock 3. Clock controller driver implementation. Signed-off-by: Mulin Chao --- CODEOWNERS | 1 + drivers/clock_control/CMakeLists.txt | 1 + drivers/clock_control/Kconfig | 2 + drivers/clock_control/Kconfig.npcx | 43 +++++ drivers/clock_control/clock_control_npcx.c | 162 ++++++++++++++++++ dts/arm/nuvoton/npcx7m6fb.dtsi | 16 ++ dts/bindings/clock/nuvoton,npcx-pcc.yaml | 17 ++ include/dt-bindings/clock/npcx_clock.h | 32 ++++ soc/arm/nuvoton_npcx/common/reg/reg_def.h | 111 ++++++++++++ soc/arm/nuvoton_npcx/common/soc_clock.h | 127 ++++++++++++++ soc/arm/nuvoton_npcx/common/soc_dt.h | 21 +++ .../npcx7/Kconfig.defconfig.series | 6 + soc/arm/nuvoton_npcx/npcx7/soc.c | 14 ++ soc/arm/nuvoton_npcx/npcx7/soc.h | 2 + 14 files changed, 555 insertions(+) create mode 100644 drivers/clock_control/Kconfig.npcx create mode 100644 drivers/clock_control/clock_control_npcx.c create mode 100644 dts/bindings/clock/nuvoton,npcx-pcc.yaml create mode 100644 include/dt-bindings/clock/npcx_clock.h create mode 100644 soc/arm/nuvoton_npcx/common/soc_clock.h create mode 100644 soc/arm/nuvoton_npcx/common/soc_dt.h diff --git a/CODEOWNERS b/CODEOWNERS index 7b64cdf5ff8..ef5f8a01c2c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -150,6 +150,7 @@ /drivers/can/*mcp2515* @karstenkoenig /drivers/clock_control/*nrf* @nordic-krch /drivers/clock_control/*esp32* @extremegtx +/drivers/clock_control/*npcx* @MulinChao /drivers/counter/ @nordic-krch /drivers/console/semihost_console.c @luozhongyao /drivers/counter/counter_cmos.c @andrewboie diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 6ac012741f4..a4426a350a2 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -7,6 +7,7 @@ zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_MCUX_MCG clock_control_mcux zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_MCUX_PCC clock_control_mcux_pcc.c) zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_MCUX_SCG clock_control_mcux_scg.c) zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_MCUX_SIM clock_control_mcux_sim.c) +zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_NPCX clock_control_npcx.c) zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF nrf_power_clock.c) zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION nrf_clock_calibration.c) zephyr_sources_ifdef(CONFIG_CLOCK_CONTROL_RV32M1_PCC clock_control_rv32m1_pcc.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index 0234d89613c..92275f1d5bb 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -38,6 +38,8 @@ source "drivers/clock_control/Kconfig.mcux_scg" source "drivers/clock_control/Kconfig.mcux_sim" +source "drivers/clock_control/Kconfig.npcx" + source "drivers/clock_control/Kconfig.rv32m1" source "drivers/clock_control/Kconfig.esp32" diff --git a/drivers/clock_control/Kconfig.npcx b/drivers/clock_control/Kconfig.npcx new file mode 100644 index 00000000000..53f88fbb9c1 --- /dev/null +++ b/drivers/clock_control/Kconfig.npcx @@ -0,0 +1,43 @@ +# NPCX Clock controller driver configuration options + +# Copyright (c) 2020 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_NPCX + bool "NPCX clock controller driver" + depends on SOC_FAMILY_NPCX + help + Enable support for NPCX clock controller driver. + +config CLOCK_NPCX_OSC_CYCLES_PER_SEC + int "CDCG PLL frequency" + default 48000000 + range 10000000 100000000 + depends on SOC_FAMILY_NPCX + help + Core Domain Clock Generator PLL frequency, + allowed values: From 10Mhz to 100Mhz. + +config CLOCK_NPCX_APB1_PRESCALER + int "APB1 prescaler" + default 4 + range 1 10 + depends on SOC_FAMILY_NPCX + help + APB1 prescaler, allowed values: From 1 to 10. + +config CLOCK_NPCX_APB2_PRESCALER + int "APB1 prescaler" + default 8 + range 1 10 + depends on SOC_FAMILY_NPCX + help + APB2 prescaler, allowed values: From 1 to 10. + +config CLOCK_NPCX_APB3_PRESCALER + int "APB3 prescaler" + default 2 + range 1 10 + depends on SOC_FAMILY_NPCX + help + APB3 prescaler, allowed values: From 1 to 10. diff --git a/drivers/clock_control/clock_control_npcx.c b/drivers/clock_control/clock_control_npcx.c new file mode 100644 index 00000000000..e5f442bae21 --- /dev/null +++ b/drivers/clock_control/clock_control_npcx.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2020 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_npcx_pcc + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(clock_control_npcx, LOG_LEVEL_ERR); + +/* Driver config */ +struct npcx_pcc_config { + /* cdcg device base address */ + uint32_t base_cdcg; + /* pmc device base address */ + uint32_t base_pmc; +}; + +/* Driver convenience defines */ +#define DRV_CONFIG(dev) \ + ((const struct npcx_pcc_config *)(dev)->config) + +#define HAL_CDCG_INST(dev) \ + (struct cdcg_reg_t *)(DRV_CONFIG(dev)->base_cdcg) + +#define HAL_PMC_INST(dev) \ + (struct pmc_reg_t *)(DRV_CONFIG(dev)->base_pmc) + +/* Clock controller local functions */ +static inline int npcx_clock_control_on(struct device *dev, + clock_control_subsys_t sub_system) +{ + ARG_UNUSED(dev); + struct npcx_clk_cfg *clk_cfg = (struct npcx_clk_cfg *)(sub_system); + uint32_t pmc_base = DRV_CONFIG(dev)->base_pmc; + + /* Clear related PD (Power-Down) bit of module to turn on clock */ + NPCX_PWDWN_CTL(pmc_base, clk_cfg->ctrl) &= ~(BIT(clk_cfg->bit)); + return 0; +} + +static inline int npcx_clock_control_off(struct device *dev, + clock_control_subsys_t sub_system) +{ + ARG_UNUSED(dev); + struct npcx_clk_cfg *clk_cfg = (struct npcx_clk_cfg *)(sub_system); + uint32_t pmc_base = DRV_CONFIG(dev)->base_pmc; + + /* Set related PD (Power-Down) bit of module to turn off clock */ + NPCX_PWDWN_CTL(pmc_base, clk_cfg->ctrl) |= BIT(clk_cfg->bit); + return 0; +} + +static int npcx_clock_control_get_subsys_rate(struct device *dev, + clock_control_subsys_t sub_system, + uint32_t *rate) +{ + ARG_UNUSED(dev); + struct npcx_clk_cfg *clk_cfg = (struct npcx_clk_cfg *)(sub_system); + + switch (clk_cfg->bus) { + case NPCX_CLOCK_BUS_APB1: + *rate = NPCX_APB_CLOCK(1); + break; + case NPCX_CLOCK_BUS_APB2: + *rate = NPCX_APB_CLOCK(2); + break; + case NPCX_CLOCK_BUS_APB3: + *rate = NPCX_APB_CLOCK(3); + break; + case NPCX_CLOCK_BUS_AHB6: + *rate = CORE_CLK/(AHB6DIV_VAL + 1); + break; + case NPCX_CLOCK_BUS_FIU: + *rate = CORE_CLK/(FIUDIV_VAL + 1); + break; + case NPCX_CLOCK_BUS_CORE: + *rate = CORE_CLK; + break; + case NPCX_CLOCK_BUS_LFCLK: + *rate = LFCLK; + break; + default: + *rate = 0U; + /* Invalid parameters */ + return -EINVAL; + }; + + return 0; +} + +/* Clock controller driver registration */ +static struct clock_control_driver_api npcx_clock_control_api = { + .on = npcx_clock_control_on, + .off = npcx_clock_control_off, + .get_rate = npcx_clock_control_get_subsys_rate, +}; + +static int npcx_clock_control_init(struct device *dev) +{ + struct cdcg_reg_t *inst_cdcg = HAL_CDCG_INST(dev); + uint32_t pmc_base = DRV_CONFIG(dev)->base_pmc; + + /* + * Resetting the OSC_CLK (even to the same value) will make the clock + * unstable for a little which can affect peripheral communication like + * eSPI. Skip this if not needed. + */ + if (inst_cdcg->HFCGN != HFCGN_VAL || inst_cdcg->HFCGML != HFCGML_VAL + || inst_cdcg->HFCGMH != HFCGMH_VAL) { + /* + * Configure frequency multiplier M/N values according to + * the requested OSC_CLK (Unit:Hz). + */ + inst_cdcg->HFCGN = HFCGN_VAL; + inst_cdcg->HFCGML = HFCGML_VAL; + inst_cdcg->HFCGMH = HFCGMH_VAL; + + /* Load M and N values into the frequency multiplier */ + inst_cdcg->HFCGCTRL |= BIT(NPCX_HFCGCTRL_LOAD); + /* Wait for stable */ + while (IS_BIT_SET(inst_cdcg->HFCGCTRL, NPCX_HFCGCTRL_CLK_CHNG)) + ; + } + + /* Set all clock prescalers of core and peripherals. */ + inst_cdcg->HFCGP = ((FPRED_VAL << 4) | AHB6DIV_VAL); + inst_cdcg->HFCBCD = (FIUDIV_VAL << 4); + inst_cdcg->HFCBCD1 = (APB1DIV_VAL | (APB2DIV_VAL << 4)); + inst_cdcg->HFCBCD2 = APB3DIV_VAL; + + /* + * Power-down (turn off clock) the modules initially for better + * power consumption. + */ + NPCX_PWDWN_CTL(pmc_base, NPCX_PWDWN_CTL1) = 0xF9; /* No SDP_PD/FIU_PD */ + NPCX_PWDWN_CTL(pmc_base, NPCX_PWDWN_CTL2) = 0xFF; + NPCX_PWDWN_CTL(pmc_base, NPCX_PWDWN_CTL3) = 0x1F; /* No GDMA_PD */ + NPCX_PWDWN_CTL(pmc_base, NPCX_PWDWN_CTL4) = 0xFF; + NPCX_PWDWN_CTL(pmc_base, NPCX_PWDWN_CTL5) = 0xFA; + NPCX_PWDWN_CTL(pmc_base, NPCX_PWDWN_CTL6) = 0xFF; + NPCX_PWDWN_CTL(pmc_base, NPCX_PWDWN_CTL7) = 0xE7; + + return 0; +} + +const struct npcx_pcc_config pcc_config = { + .base_cdcg = DT_INST_REG_ADDR_BY_NAME(0, cdcg), + .base_pmc = DT_INST_REG_ADDR_BY_NAME(0, pmc), +}; + +DEVICE_AND_API_INIT(npcx_cdcg, NPCX_CLOCK_CONTROL_NAME, + &npcx_clock_control_init, + NULL, &pcc_config, + PRE_KERNEL_1, + CONFIG_KERNEL_INIT_PRIORITY_OBJECTS, + &npcx_clock_control_api); diff --git a/dts/arm/nuvoton/npcx7m6fb.dtsi b/dts/arm/nuvoton/npcx7m6fb.dtsi index ca4bdad821c..0b0c0ec3666 100644 --- a/dts/arm/nuvoton/npcx7m6fb.dtsi +++ b/dts/arm/nuvoton/npcx7m6fb.dtsi @@ -5,6 +5,8 @@ */ #include +/* Macros for device tree declarations */ +#include / { cpus { @@ -26,6 +28,20 @@ compatible = "mmio-sram"; reg = <0x200C0000 0x10000>; }; + + soc { + pcc: clock-controller@4000d000 { + compatible = "nuvoton,npcx-pcc"; + /* Cells for bus type, clock control reg and bit */ + #clock-cells = <3>; + /* First reg region is Power Management Controller */ + /* Second reg region is Core Domain Clock Generator */ + reg = <0x4000d000 0x2000 + 0x400b5000 0x2000>; + reg-names = "pmc", "cdcg"; + label = "PMC_CDCG"; + }; + }; }; &nvic { diff --git a/dts/bindings/clock/nuvoton,npcx-pcc.yaml b/dts/bindings/clock/nuvoton,npcx-pcc.yaml new file mode 100644 index 00000000000..25d56b64202 --- /dev/null +++ b/dts/bindings/clock/nuvoton,npcx-pcc.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2020 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, NPCX PCC (Power and Clock Controller) node + +compatible: "nuvoton,npcx-pcc" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + +clock-cells: + - bus + - ctl + - bit diff --git a/include/dt-bindings/clock/npcx_clock.h b/include/dt-bindings/clock/npcx_clock.h new file mode 100644 index 00000000000..6f63c7ff8f8 --- /dev/null +++ b/include/dt-bindings/clock/npcx_clock.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NPCX_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NPCX_CLOCK_H_ + +/* clock bus references */ +#define NPCX_CLOCK_BUS_FREERUN 0 +#define NPCX_CLOCK_BUS_LFCLK 1 +#define NPCX_CLOCK_BUS_OSC 2 +#define NPCX_CLOCK_BUS_FIU 3 +#define NPCX_CLOCK_BUS_CORE 4 +#define NPCX_CLOCK_BUS_APB1 5 +#define NPCX_CLOCK_BUS_APB2 6 +#define NPCX_CLOCK_BUS_APB3 7 +#define NPCX_CLOCK_BUS_APB4 8 +#define NPCX_CLOCK_BUS_AHB6 9 + +/* clock enable/disable references */ +#define NPCX_PWDWN_CTL1 0 +#define NPCX_PWDWN_CTL2 1 +#define NPCX_PWDWN_CTL3 2 +#define NPCX_PWDWN_CTL4 3 +#define NPCX_PWDWN_CTL5 4 +#define NPCX_PWDWN_CTL6 5 +#define NPCX_PWDWN_CTL7 6 +#define NPCX_PWDWN_CTL8 7 +#define NPCX_PWDWN_CTL_NONE 8 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NPCX_CLOCK_H_ */ diff --git a/soc/arm/nuvoton_npcx/common/reg/reg_def.h b/soc/arm/nuvoton_npcx/common/reg/reg_def.h index 759f6b69f5e..4a8b0f51785 100644 --- a/soc/arm/nuvoton_npcx/common/reg/reg_def.h +++ b/soc/arm/nuvoton_npcx/common/reg/reg_def.h @@ -7,6 +7,117 @@ #ifndef _NUVOTON_NPCX_REG_DEF_H #define _NUVOTON_NPCX_REG_DEF_H +/* + * NPCX register structure size/offset checking macro function to mitigate + * the risk of unexpected compiling results. All addresses of NPCX registers + * must meet the alignment requirement of cortex-m4. + * DO NOT use 'packed' attribute if module contains different length ie. + * 8/16/32 bits registers. + */ +#define NPCX_REG_SIZE_CHECK(reg_def, size) \ + BUILD_ASSERT(sizeof(struct reg_def) == size, \ + "Failed in size check of register structure!") +#define NPCX_REG_OFFSET_CHECK(reg_def, member, offset) \ + BUILD_ASSERT(offsetof(struct reg_def, member) == offset, \ + "Failed in offset check of register structure member!") + +/* + * Core Domain Clock Generator (CDCG) device registers + */ +struct cdcg_reg_t { + /* High Frequency Clock Generator (HFCG) registers */ + /* 0x000: HFCG Control */ + volatile uint8_t HFCGCTRL; + volatile uint8_t reserved1; + /* 0x002: HFCG M Low Byte Value */ + volatile uint8_t HFCGML; + volatile uint8_t reserved2; + /* 0x004: HFCG M High Byte Value */ + volatile uint8_t HFCGMH; + volatile uint8_t reserved3; + /* 0x006: HFCG N Value */ + volatile uint8_t HFCGN; + volatile uint8_t reserved4; + /* 0x008: HFCG Prescaler */ + volatile uint8_t HFCGP; + volatile uint8_t reserved5[7]; + /* 0x010: HFCG Bus Clock Dividers */ + volatile uint8_t HFCBCD; + volatile uint8_t reserved6; + /* 0x012: HFCG Bus Clock Dividers */ + volatile uint8_t HFCBCD1; + volatile uint8_t reserved7; + /* 0x014: HFCG Bus Clock Dividers */ + volatile uint8_t HFCBCD2; + volatile uint8_t reserved8[235]; + + /* Low Frequency Clock Generator (LFCG) registers */ + /* 0x100: LFCG Control */ + volatile uint8_t LFCGCTL; + volatile uint8_t reserved9; + /* 0x102: High-Frequency Reference Divisor I */ + volatile uint16_t HFRDI; + /* 0x104: High-Frequency Reference Divisor F */ + volatile uint16_t HFRDF; + /* 0x106: FRCLK Clock Divisor */ + volatile uint16_t FRCDIV; + /* 0x108: Divisor Correction Value 1 */ + volatile uint16_t DIVCOR1; + /* 0x10A: Divisor Correction Value 2 */ + volatile uint16_t DIVCOR2; + volatile uint8_t reserved10[8]; + /* 0x114: LFCG Control 2 */ + volatile uint8_t LFCGCTL2; + volatile uint8_t reserved11; +}; + +/* CDCG register fields */ +#define NPCX_HFCGCTRL_LOAD 0 +#define NPCX_HFCGCTRL_LOCK 2 +#define NPCX_HFCGCTRL_CLK_CHNG 7 + +/* + * Power Management Controller (PMC) device registers + */ +struct pmc_reg_t { + /* 0x000: Power Management Controller */ + volatile uint8_t PMCSR; + volatile uint8_t reserved1[2]; + /* 0x003: Enable in Sleep Control */ + volatile uint8_t ENIDL_CTL; + /* 0x004: Disable in Idle Control */ + volatile uint8_t DISIDL_CTL; + /* 0x005: Disable in Idle Control 1 */ + volatile uint8_t DISIDL_CTL1; + volatile uint8_t reserved2[2]; + /* 0x008 - 0D: Power-Down Control 1 - 6 */ + volatile uint8_t PWDWN_CTL1[6]; + volatile uint8_t reserved3[18]; + /* 0x020 - 21: Power-Down Control 1 - 2 */ + volatile uint8_t RAM_PD[2]; + volatile uint8_t reserved4[2]; + /* 0x024: Power-Down Control 7 */ + volatile uint8_t PWDWN_CTL7[1]; +}; + +/* PMC multi-registers */ +#define NPCX_PWDWN_CTL_OFFSET(n) (((n) < 6) ? (0x008 + n) : (0x024 + (n - 6))) +#define NPCX_PWDWN_CTL(base, n) (*(volatile uint8_t *)(base + \ + NPCX_PWDWN_CTL_OFFSET(n))) + +/* PMC register fields */ +#define NPCX_PMCSR_DI_INSTW 0 +#define NPCX_PMCSR_DHF 1 +#define NPCX_PMCSR_IDLE 2 +#define NPCX_PMCSR_NWBI 3 +#define NPCX_PMCSR_OHFC 6 +#define NPCX_PMCSR_OLFC 7 +#define NPCX_DISIDL_CTL_RAM_DID 5 +#define NPCX_ENIDL_CTL_ADC_LFSL 7 +#define NPCX_ENIDL_CTL_LP_WK_CTL 6 +#define NPCX_ENIDL_CTL_PECI_ENI 2 +#define NPCX_ENIDL_CTL_ADC_ACC_DIS 1 + #endif /* _NUVOTON_NPCX_REG_DEF_H */ diff --git a/soc/arm/nuvoton_npcx/common/soc_clock.h b/soc/arm/nuvoton_npcx/common/soc_clock.h new file mode 100644 index 00000000000..eae92ddd9d1 --- /dev/null +++ b/soc/arm/nuvoton_npcx/common/soc_clock.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2020 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _NUVOTON_NPCX_SOC_CLOCK_H_ +#define _NUVOTON_NPCX_SOC_CLOCK_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Common clock control device name for all NPCX series */ +#define NPCX_CLOCK_CONTROL_NAME "npcx-cc" + +/** + * @brief NPCX clock configuration structure + * + * Used to indicate the device's clock bus type and corresponding PWDWN_CTL + * register/bit to turn on/off its source clock. + */ +struct npcx_clk_cfg { + uint16_t bus:8; + uint16_t ctrl:5; + uint16_t bit:3; +}; + +/* + * NPCX7 and later series clock tree macros: + * (Please refer Figure 58. for more information.) + * + * Suggestion: + * - OSC_CLK >= 80MHz, XF_RANGE should be 1, else 0. + * - CORE_CLK > 66MHz, AHB6DIV should be 1, else 0. + * - CORE_CLK > 50MHz, FIUDIV should be 1, else 0. + */ + +/* Target OSC_CLK freq */ +#define OSC_CLK CONFIG_CLOCK_NPCX_OSC_CYCLES_PER_SEC +/* Core domain clock */ +#define CORE_CLK CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC +/* Low Frequency clock */ +#define LFCLK 32768 +/* Core clock prescaler */ +#define FPRED_VAL ((OSC_CLK / CORE_CLK) - 1) + +/* FMUL clock */ +#if (OSC_CLK >= 80000000) +#define FMCLK (OSC_CLK / 2) /* FMUL clock = OSC_CLK/2 if OSC_CLK >= 80MHz */ +#else +#define FMCLK OSC_CLK /* FMUL clock = OSC_CLK */ +#endif + +/* APBs source clock */ +#define APBSRC_CLK OSC_CLK +/* APB1 clock divider, default value (APB1 clock = OSC_CLK/6) */ +#define APB1DIV_VAL (CONFIG_CLOCK_NPCX_APB1_PRESCALER - 1) +/* APB2 clock divider, default value (APB2 clock = OSC_CLK/6) */ +#define APB2DIV_VAL (CONFIG_CLOCK_NPCX_APB2_PRESCALER - 1) +/* APB3 clock divider, default value (APB3 clock = OSC_CLK/6) */ +#define APB3DIV_VAL (CONFIG_CLOCK_NPCX_APB3_PRESCALER - 1) + +/* AHB6 clock */ +#if (CORE_CLK > 66000000) +#define AHB6DIV_VAL 1 /* AHB6_CLK = CORE_CLK/2 if CORE_CLK > 66MHz */ +#else +#define AHB6DIV_VAL 0 /* AHB6_CLK = CORE_CLK */ +#endif +/* FIU clock divider */ +#if (CORE_CLK > 50000000) +#define FIUDIV_VAL 1 /* FIU_CLK = CORE_CLK/2 */ +#else +#define FIUDIV_VAL 0 /* FIU_CLK = CORE_CLK */ +#endif + +/* Get APB clock freq */ +#define NPCX_APB_CLOCK(no) (APBSRC_CLK / (APB##no##DIV_VAL + 1)) + +/* + * Frequency multiplier M/N value definitions according to the requested + * OSC_CLK (Unit:Hz). + */ +#if (OSC_CLK > 80000000) +#define HFCGN_VAL 0x82 /* Set XF_RANGE as 1 if OSC_CLK >= 80MHz */ +#else +#define HFCGN_VAL 0x02 +#endif +#if (OSC_CLK == 100000000) +#define HFCGMH_VAL 0x0B +#define HFCGML_VAL 0xEC +#elif (OSC_CLK == 90000000) +#define HFCGMH_VAL 0x0A +#define HFCGML_VAL 0xBA +#elif (OSC_CLK == 80000000) +#define HFCGMH_VAL 0x09 +#define HFCGML_VAL 0x89 +#elif (OSC_CLK == 66000000) +#define HFCGMH_VAL 0x0F +#define HFCGML_VAL 0xBC +#elif (OSC_CLK == 50000000) +#define HFCGMH_VAL 0x0B +#define HFCGML_VAL 0xEC +#elif (OSC_CLK == 48000000) +#define HFCGMH_VAL 0x0B +#define HFCGML_VAL 0x72 +#elif (OSC_CLK == 40000000) +#define HFCGMH_VAL 0x09 +#define HFCGML_VAL 0x89 +#elif (OSC_CLK == 33000000) +#define HFCGMH_VAL 0x07 +#define HFCGML_VAL 0xDE +#elif (OSC_CLK == 30000000) +#define HFCGMH_VAL 0x07 +#define HFCGML_VAL 0x27 +#elif (OSC_CLK == 26000000) +#define HFCGMH_VAL 0x06 +#define HFCGML_VAL 0x33 +#else +#error "Unsupported OSC_CLK Frequency" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _NUVOTON_NPCX_SOC_CLOCK_H_ */ diff --git a/soc/arm/nuvoton_npcx/common/soc_dt.h b/soc/arm/nuvoton_npcx/common/soc_dt.h new file mode 100644 index 00000000000..8724327bd4b --- /dev/null +++ b/soc/arm/nuvoton_npcx/common/soc_dt.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _NUVOTON_NPCX_SOC_DT_H_ +#define _NUVOTON_NPCX_SOC_DT_H_ + +/* + * Construct a npcx_clk_cfg item from clocks prop which type is 'phandle-array' + * to handle "clock-cells" in current driver device + */ +#define DT_NPCX_CLK_CFG_ITEM(inst) \ + { \ + .bus = DT_PHA(DT_DRV_INST(inst), clocks, bus), \ + .ctrl = DT_PHA(DT_DRV_INST(inst), clocks, ctl), \ + .bit = DT_PHA(DT_DRV_INST(inst), clocks, bit), \ + } + +#endif /* _NUVOTON_NPCX_SOC_DT_H_ */ diff --git a/soc/arm/nuvoton_npcx/npcx7/Kconfig.defconfig.series b/soc/arm/nuvoton_npcx/npcx7/Kconfig.defconfig.series index 29fad34fdb6..39a077fcb87 100644 --- a/soc/arm/nuvoton_npcx/npcx7/Kconfig.defconfig.series +++ b/soc/arm/nuvoton_npcx/npcx7/Kconfig.defconfig.series @@ -10,6 +10,12 @@ config SOC_SERIES config NUM_IRQS default 64 + +config CLOCK_CONTROL_NPCX + default y + depends on CLOCK_CONTROL + help + Enable support for NPCX clock controller driver. source "soc/arm/nuvoton_npcx/npcx7/Kconfig.defconfig.npcx7*" diff --git a/soc/arm/nuvoton_npcx/npcx7/soc.c b/soc/arm/nuvoton_npcx/npcx7/soc.c index 0a031cac8f8..f69d77b68cf 100644 --- a/soc/arm/nuvoton_npcx/npcx7/soc.c +++ b/soc/arm/nuvoton_npcx/npcx7/soc.c @@ -17,3 +17,17 @@ static int soc_init(struct device *dev) } SYS_INIT(soc_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); + +/* CDCG register structure check */ +NPCX_REG_SIZE_CHECK(cdcg_reg_t, 0x116); +NPCX_REG_OFFSET_CHECK(cdcg_reg_t, HFCBCD, 0x010); +NPCX_REG_OFFSET_CHECK(cdcg_reg_t, HFCBCD2, 0x014); +NPCX_REG_OFFSET_CHECK(cdcg_reg_t, LFCGCTL, 0x100); +NPCX_REG_OFFSET_CHECK(cdcg_reg_t, LFCGCTL2, 0x114); + +/* PMC register structure check */ +NPCX_REG_SIZE_CHECK(pmc_reg_t, 0x025); +NPCX_REG_OFFSET_CHECK(pmc_reg_t, ENIDL_CTL, 0x003); +NPCX_REG_OFFSET_CHECK(pmc_reg_t, PWDWN_CTL1, 0x008); +NPCX_REG_OFFSET_CHECK(pmc_reg_t, PWDWN_CTL7, 0x024); + diff --git a/soc/arm/nuvoton_npcx/npcx7/soc.h b/soc/arm/nuvoton_npcx/npcx7/soc.h index 09cfd27f3e9..4353f579246 100644 --- a/soc/arm/nuvoton_npcx/npcx7/soc.h +++ b/soc/arm/nuvoton_npcx/npcx7/soc.h @@ -16,5 +16,7 @@ #include #include +#include +#include #endif /* _NUVOTON_NPCX_SOC_H_ */