driver: clock: npcx: Add valid clock checking
NPCX clock has some limitations about the frequency range & synchronization between core clock & other clocks. Add build assert to check whether NPCX clock setting correct. This also fixed soc_clock.h to consist with datasheet. Signed-off-by: Wealian Liao <WHLIAO@nuvoton.com>
This commit is contained in:
parent
8d48b919c6
commit
42aeaccb3e
3 changed files with 73 additions and 24 deletions
|
@ -15,7 +15,7 @@ config CLOCK_NPCX_OSC_CYCLES_PER_SEC
|
|||
range 10000000 100000000
|
||||
depends on SOC_FAMILY_NPCX
|
||||
help
|
||||
Core Domain Clock Generator PLL frequency,
|
||||
Core Domain Clock (OSC_CLK) Generator PLL frequency,
|
||||
allowed values: From 10Mhz to 100Mhz.
|
||||
|
||||
config CLOCK_NPCX_APB1_PRESCALER
|
||||
|
@ -24,15 +24,33 @@ config CLOCK_NPCX_APB1_PRESCALER
|
|||
range 1 10
|
||||
depends on SOC_FAMILY_NPCX
|
||||
help
|
||||
APB1 prescaler, allowed values: From 1 to 10.
|
||||
This sets the APB1 prescaler which changes the frequency of APB1_CLK.
|
||||
APB1_CLK frequency = OSC_CLK / APB1_PRE. The APB1 prescaler allowed
|
||||
value is from 1 to 10.
|
||||
|
||||
The generated frequency of APB1_CLK should comply with the following
|
||||
requirements:
|
||||
- The frequency of APB1_CLK must be set to:
|
||||
4MHz <= APB1_CLK <= 50MHz.
|
||||
- The frequency of APB1_CLK must be an integer division (including 1)
|
||||
of the frequency of the Core clock.
|
||||
|
||||
config CLOCK_NPCX_APB2_PRESCALER
|
||||
int "APB1 prescaler"
|
||||
int "APB2 prescaler"
|
||||
default 8
|
||||
range 1 10
|
||||
depends on SOC_FAMILY_NPCX
|
||||
help
|
||||
APB2 prescaler, allowed values: From 1 to 10.
|
||||
This sets the APB2 prescaler which changes the frequency of APB2_CLK.
|
||||
APB2_CLK frequency = OSC_CLK / APB2_PRE. The APB2 prescaler allowed
|
||||
value is from 1 to 10.
|
||||
|
||||
The generated frequency of APB2_CLK should comply with the following
|
||||
requirements:
|
||||
- The frequency of APB2_CLK must be set to:
|
||||
8MHz <= APB2_CLK <= 50MHz.
|
||||
- The frequency of APB2_CLK must be an integer division (including 1)
|
||||
of the frequency of the Core clock.
|
||||
|
||||
config CLOCK_NPCX_APB3_PRESCALER
|
||||
int "APB3 prescaler"
|
||||
|
@ -40,4 +58,13 @@ config CLOCK_NPCX_APB3_PRESCALER
|
|||
range 1 10
|
||||
depends on SOC_FAMILY_NPCX
|
||||
help
|
||||
APB3 prescaler, allowed values: From 1 to 10.
|
||||
This sets the APB3 prescaler which changes the frequency of APB3_CLK.
|
||||
APB3_CLK frequency = OSC_CLK / APB3_PRE. The APB3 prescaler allowed
|
||||
value is from 1 to 10.
|
||||
|
||||
The generated frequency of APB3_CLK should comply with the following
|
||||
requirements:
|
||||
- The frequency of APB3_CLK must be set to:
|
||||
12.5MHz <= APB3_CLK <= 50MHz.
|
||||
- The frequency of APB3_CLK must be an integer division (including 1)
|
||||
of the frequency of the Core clock.
|
||||
|
|
|
@ -138,6 +138,31 @@ static struct clock_control_driver_api npcx_clock_control_api = {
|
|||
.get_rate = npcx_clock_control_get_subsys_rate,
|
||||
};
|
||||
|
||||
/* valid clock frequency check */
|
||||
BUILD_ASSERT(CORE_CLK <= 100000000 &&
|
||||
CORE_CLK >= 4000000 &&
|
||||
OSC_CLK % CORE_CLK == 0 &&
|
||||
OSC_CLK / CORE_CLK <= 10,
|
||||
"Invalid CORE_CLK setting");
|
||||
BUILD_ASSERT(CORE_CLK / (FIUDIV_VAL + 1) <= 50000000 &&
|
||||
CORE_CLK / (FIUDIV_VAL + 1) >= 4000000,
|
||||
"Invalid FIUCLK setting");
|
||||
BUILD_ASSERT(CORE_CLK / (AHB6DIV_VAL + 1) <= 50000000 &&
|
||||
CORE_CLK / (AHB6DIV_VAL + 1) >= 4000000,
|
||||
"Invalid AHB6_CLK setting");
|
||||
BUILD_ASSERT(APBSRC_CLK / (APB1DIV_VAL + 1) <= 50000000 &&
|
||||
APBSRC_CLK / (APB1DIV_VAL + 1) >= 4000000 &&
|
||||
(APB1DIV_VAL + 1) % (FPRED_VAL + 1) == 0,
|
||||
"Invalid APB1_CLK setting");
|
||||
BUILD_ASSERT(APBSRC_CLK / (APB2DIV_VAL + 1) <= 50000000 &&
|
||||
APBSRC_CLK / (APB2DIV_VAL + 1) >= 8000000 &&
|
||||
(APB2DIV_VAL + 1) % (FPRED_VAL + 1) == 0,
|
||||
"Invalid APB2_CLK setting");
|
||||
BUILD_ASSERT(APBSRC_CLK / (APB3DIV_VAL + 1) <= 50000000 &&
|
||||
APBSRC_CLK / (APB3DIV_VAL + 1) >= 12500000 &&
|
||||
(APB3DIV_VAL + 1) % (FPRED_VAL + 1) == 0,
|
||||
"Invalid APB3_CLK setting");
|
||||
|
||||
static int npcx_clock_control_init(const struct device *dev)
|
||||
{
|
||||
struct cdcg_reg *const inst_cdcg = HAL_CDCG_INST(dev);
|
||||
|
|
|
@ -31,8 +31,8 @@ struct npcx_clk_cfg {
|
|||
* (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.
|
||||
* - OSC_CLK > 50MHz, XF_RANGE should be 1, else 0.
|
||||
* - CORE_CLK > 50MHz, AHB6DIV should be 1, else 0.
|
||||
* - CORE_CLK > 50MHz, FIUDIV should be 1, else 0.
|
||||
*/
|
||||
|
||||
|
@ -46,24 +46,24 @@ struct npcx_clk_cfg {
|
|||
#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 */
|
||||
#if (OSC_CLK > 50000000)
|
||||
#define FMCLK (OSC_CLK / 2) /* FMUL clock = OSC_CLK/2 if OSC_CLK > 50MHz */
|
||||
#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) */
|
||||
/* APB1 clock divider, default value (APB1 clock = OSC_CLK/4) */
|
||||
#define APB1DIV_VAL (CONFIG_CLOCK_NPCX_APB1_PRESCALER - 1)
|
||||
/* APB2 clock divider, default value (APB2 clock = OSC_CLK/6) */
|
||||
/* APB2 clock divider, default value (APB2 clock = OSC_CLK/8) */
|
||||
#define APB2DIV_VAL (CONFIG_CLOCK_NPCX_APB2_PRESCALER - 1)
|
||||
/* APB3 clock divider, default value (APB3 clock = OSC_CLK/6) */
|
||||
/* APB3 clock divider, default value (APB3 clock = OSC_CLK/2) */
|
||||
#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 */
|
||||
#if (CORE_CLK > 50000000)
|
||||
#define AHB6DIV_VAL 1 /* AHB6_CLK = CORE_CLK/2 if CORE_CLK > 50MHz */
|
||||
#else
|
||||
#define AHB6DIV_VAL 0 /* AHB6_CLK = CORE_CLK */
|
||||
#endif
|
||||
|
@ -81,14 +81,17 @@ struct npcx_clk_cfg {
|
|||
* 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 */
|
||||
#if (OSC_CLK > 50000000)
|
||||
#define HFCGN_VAL 0x82 /* Set XF_RANGE as 1 if OSC_CLK > 50MHz */
|
||||
#else
|
||||
#define HFCGN_VAL 0x02
|
||||
#endif
|
||||
#if (OSC_CLK == 100000000)
|
||||
#define HFCGMH_VAL 0x0B
|
||||
#define HFCGML_VAL 0xEC
|
||||
#elif (OSC_CLK == 96000000)
|
||||
#define HFCGMH_VAL 0x0B
|
||||
#define HFCGML_VAL 0x72
|
||||
#elif (OSC_CLK == 90000000)
|
||||
#define HFCGMH_VAL 0x0A
|
||||
#define HFCGML_VAL 0xBA
|
||||
|
@ -96,8 +99,8 @@ struct npcx_clk_cfg {
|
|||
#define HFCGMH_VAL 0x09
|
||||
#define HFCGML_VAL 0x89
|
||||
#elif (OSC_CLK == 66000000)
|
||||
#define HFCGMH_VAL 0x0F
|
||||
#define HFCGML_VAL 0xBC
|
||||
#define HFCGMH_VAL 0x07
|
||||
#define HFCGML_VAL 0xDE
|
||||
#elif (OSC_CLK == 50000000)
|
||||
#define HFCGMH_VAL 0x0B
|
||||
#define HFCGML_VAL 0xEC
|
||||
|
@ -110,12 +113,6 @@ struct npcx_clk_cfg {
|
|||
#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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue