From 9d769f60560118a20d6bbf992e7c1591a97a4863 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 3 Dec 2015 14:11:39 -0600 Subject: [PATCH] SAMV7: Extend programmable clock support for queries about the PCK configuration --- arch/arm/src/samv7/sam_freerun.c | 2 +- arch/arm/src/samv7/sam_pck.c | 95 +++++++++++++++++++++++++++++++- arch/arm/src/samv7/sam_pck.h | 42 +++++++++++++- arch/arm/src/samv7/sam_tc.c | 17 ++++-- 4 files changed, 145 insertions(+), 11 deletions(-) diff --git a/arch/arm/src/samv7/sam_freerun.c b/arch/arm/src/samv7/sam_freerun.c index c31472f8947..e30f94555c9 100644 --- a/arch/arm/src/samv7/sam_freerun.c +++ b/arch/arm/src/samv7/sam_freerun.c @@ -146,7 +146,7 @@ int sam_freerun_initialize(struct sam_freerun_s *freerun, int chan, /* Allocate the timer/counter and select its mode of operation * - * CMR_TCCLKS - Returned by sam_tc_divisor + * TC_CMR_TCCLKS - Returned by sam_tc_divisor * TC_CMR_CLKI=0 - Not inverted * TC_CMR_BURST_NONE - Not gated by an external signal * TC_CMR_CPCSTOP=0 - Don't stop the clock on an RC compare event diff --git a/arch/arm/src/samv7/sam_pck.c b/arch/arm/src/samv7/sam_pck.c index 0af5a713e16..c72ee139682 100644 --- a/arch/arm/src/samv7/sam_pck.c +++ b/arch/arm/src/samv7/sam_pck.c @@ -218,6 +218,70 @@ uint32_t sam_pck_configure(enum pckid_e pckid, enum pckid_clksrc_e clksrc, return actual; } +/**************************************************************************** + * Function: sam_pck_frequency + * + * Description: + * Return the frequency if the programmable clock + * + * Input Parameters: + * pckid - Identifies the programmable clock output (0, 1, .., 6) + * + * Returned Value: + * The frequency of the programmable clock (which may or may not be + * enabled). + * + ****************************************************************************/ + +uint32_t sam_pck_frequency(enum pckid_e pckid) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t clkin; + uint32_t presc; + + /* Get the programmable clock configuration */ + + regaddr = SAM_PMC_PCK((int)pckid); + regval = getreg32(regaddr); + + /* Get the frequency of the clock source */ + + switch (regval & PMC_PCK_CSS_MASK) + { + case PMC_PCK_CSS_SLOW: /* Slow Clock */ + clkin = BOARD_SLOWCLK_FREQUENCY; + break; + + case PMC_PCK_CSS_MAIN: /* Main Clock */ + clkin = BOARD_MAINOSC_FREQUENCY; + break; + + case PMC_PCK_CSS_PLLA: /* PLLA Clock */ + clkin = BOARD_PLLA_FREQUENCY; + break; + +#ifdef BOARD_UPLL_FREQUENCY + case PMC_PCK_CSS_UPLL: /* Divided UPLL Clock */ + clkin = BOARD_UPLL_FREQUENCY; + break; +#endif + + case PMC_PCK_CSS_MCK: /* Master Clock */ + clkin = BOARD_MCK_FREQUENCY; + break; + + default: + dbg("ERROR: Unknown clock source\n"); + return 0; + } + + /* Get the prescaler value */ + + presc = (regval & PMC_PCK_PRES_MASK) >> PMC_PCK_PRES_SHIFT; + return clkin / (presc + 1); +} + /**************************************************************************** * Function: sam_pck_enable * @@ -225,7 +289,7 @@ uint32_t sam_pck_configure(enum pckid_e pckid, enum pckid_clksrc_e clksrc, * Enable or disable a programmable clock output. * * Input Parameters: - * pckid - Identifies the programmable clock output (0, 1, or 2) + * pckid - Identifies the programmable clock output (0, 1, .., 6) * enable - True: enable the clock output, False: disable the clock output * * Returned Value: @@ -248,7 +312,34 @@ void sam_pck_enable(enum pckid_e pckid, bool enable) regaddr = enable ? SAM_PMC_SCER : SAM_PMC_SCDR; - /* And do the deead */ + /* And do the deed */ putreg32(regval, regaddr); } + +/**************************************************************************** + * Function: sam_pck_isenabled + * + * Description: + * Return true if the programmable clock is enabled. + * + * Input Parameters: + * pckid - Identifies the programmable clock output (0, 1, .., 6) + * + * Returned Value: + * True if the specified programmable clock is enabled + * + ****************************************************************************/ + +bool sam_pck_isenabled(enum pckid_e pckid) +{ + uint32_t mask; + + /* Select the bit in the PMC_SCSR corresponding to the programmable clock. */ + + mask = PMC_PCK(pckid); + + /* Return true if the bit is set */ + + return (getreg32(SAM_PMC_SCSR) & mask) != 0; +} diff --git a/arch/arm/src/samv7/sam_pck.h b/arch/arm/src/samv7/sam_pck.h index 511b4eade2f..173fc0c53f5 100644 --- a/arch/arm/src/samv7/sam_pck.h +++ b/arch/arm/src/samv7/sam_pck.h @@ -58,7 +58,11 @@ enum pckid_e { PCK0 = 0, PCK1, - PCK2 + PCK2, + PCK3, + PCK4, + PCK5, + PCK6, }; enum pckid_clksrc_e @@ -109,6 +113,23 @@ extern "C" uint32_t sam_pck_configure(enum pckid_e pckid, enum pckid_clksrc_e clksrc, uint32_t frequency); +/**************************************************************************** + * Function: sam_pck_frequency + * + * Description: + * Return the frequency if the programmable clock + * + * Input Parameters: + * pckid - Identifies the programmable clock output (0, 1, .., 6) + * + * Returned Value: + * The frequency of the programmable clock (which may or may not be + * enabled). + * + ****************************************************************************/ + +uint32_t sam_pck_frequency(enum pckid_e pckid); + /**************************************************************************** * Function: sam_pck_enable * @@ -116,7 +137,7 @@ uint32_t sam_pck_configure(enum pckid_e pckid, enum pckid_clksrc_e clksrc, * Enable or disable a programmable clock output. * * Input Parameters: - * pckid - Identifies the programmable clock output (0, 1, or 2) + * pckid - Identifies the programmable clock output (0, 1, .., 6) * enable - True: enable the clock output, False: disable the clock output * * Returned Value: @@ -126,6 +147,22 @@ uint32_t sam_pck_configure(enum pckid_e pckid, enum pckid_clksrc_e clksrc, void sam_pck_enable(enum pckid_e pckid, bool enable); +/**************************************************************************** + * Function: sam_pck_isenabled + * + * Description: + * Return true if the programmable clock is enabled. + * + * Input Parameters: + * pckid - Identifies the programmable clock output (0, 1, .., 6) + * + * Returned Value: + * True if the specified programmable clock is enabled + * + ****************************************************************************/ + +bool sam_pck_isenabled(enum pckid_e pckid); + #undef EXTERN #if defined(__cplusplus) } @@ -133,4 +170,3 @@ void sam_pck_enable(enum pckid_e pckid, bool enable); #endif /* __ASSEMBLY__ */ #endif /* __ARCH_ARM_SRC_SAMV7_SAM_PCK_H */ - diff --git a/arch/arm/src/samv7/sam_tc.c b/arch/arm/src/samv7/sam_tc.c index 43dc8fbb59c..72ef965144d 100644 --- a/arch/arm/src/samv7/sam_tc.c +++ b/arch/arm/src/samv7/sam_tc.c @@ -553,10 +553,10 @@ static struct sam_tc_s g_tc901; static const uint8_t g_log2divider[TC_NDIVIDERS] = { - 1, /* TIMER_CLOCK1 -> div2 */ - 3, /* TIMER_CLOCK2 -> div8 */ - 5, /* TIMER_CLOCK3 -> div32 */ - 7 /* TIMER_CLOCK4 -> div128 */ + 1, /* TIMER_CLOCK1 -> PCK6 REVISIT! Was MCK/2 */ + 3, /* TIMER_CLOCK2 -> MCK/8 */ + 5, /* TIMER_CLOCK3 -> MCK/32 */ + 7 /* TIMER_CLOCK4 -> MCK/128 */ }; /* TC register lookup used by sam_tc_setregister */ @@ -1548,7 +1548,7 @@ uint32_t sam_tc_divfreq(TC_HANDLE handle) * Finds the best MCK divisor given the timer frequency and MCK. The * result is guaranteed to satisfy the following equation: * - * (Ftcin / (div * 65536)) <= freq <= (Ftcin / dev) + * (Ftcin / (div * 65536)) <= freq <= (Ftcin / div) * * where: * freq - the desired frequency @@ -1572,6 +1572,13 @@ int sam_tc_divisor(uint32_t frequency, uint32_t *div, uint32_t *tcclks) tcvdbg("frequency=%d\n", frequency); + /* On other chips, TCCLCKS==0 corresponded to MCK/2. But for the SAMV7, + * this is PCK6. That will need to be handled differently. + */ + +#warning REVISIT: PCK6 clock source not yet supported + ndx++; + /* Satisfy lower bound. That is, the value of the divider such that: * * frequency >= (tc_input_frequency * 65536) / divider.