SAMV7: Extend programmable clock support for queries about the PCK configuration

This commit is contained in:
Gregory Nutt 2015-12-03 14:11:39 -06:00
parent 8c4302f75d
commit 9d769f6056
4 changed files with 145 additions and 11 deletions

View File

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

View File

@ -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;
}

View File

@ -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 */

View File

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