SAMA5 PCK: Add support for the slow clock as the PCK clock source

This commit is contained in:
Gregory Nutt 2014-07-19 13:55:08 -06:00
parent c74531e014
commit d8f85d1caa
5 changed files with 47 additions and 22 deletions

View File

@ -159,7 +159,7 @@ int sam_isi_initialize(void)
* initialized? * initialized?
*/ */
g_isi.actual = sam_pck_configure(ISI_PCKID, CONFIG_ISI_MCKFREQ); g_isi.actual = sam_pck_configure(ISI_PCKID, PCKSRC_MCK, CONFIG_ISI_MCKFREQ);
gvdbg("PCK%d frequency=%d actual=%d\n", gvdbg("PCK%d frequency=%d actual=%d\n",
ISI_PCKID, CONFIG_ISI_MCKFREQ, g_isi.actual); ISI_PCKID, CONFIG_ISI_MCKFREQ, g_isi.actual);

View File

@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/sama5/sam_pck.c * arch/arm/src/sama5/sam_pck.c
* *
* Copyright (C) 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -91,6 +91,8 @@
* *
* Input Parameters: * Input Parameters:
* pckid - Identifies the programmable clock output (0, 1, or 2) * pckid - Identifies the programmable clock output (0, 1, or 2)
* clocksrc - MCK or SCK. If MCK is selected, the logic will automatically
* select the PLLACK clock if it seems like a better choice.
* frequency - Defines the desired frequency. The exact frequency may * frequency - Defines the desired frequency. The exact frequency may
* not be attainable. In this case, frequency is interpreted to be * not be attainable. In this case, frequency is interpreted to be
* a not-to-exceed frequency. * a not-to-exceed frequency.
@ -100,64 +102,78 @@
* *
****************************************************************************/ ****************************************************************************/
uint32_t sam_pck_configure(enum pckid_e pckid, uint32_t frequency) uint32_t sam_pck_configure(enum pckid_e pckid, enum pckid_clksrc_e clksrc,
uint32_t frequency)
{ {
uint32_t regval; uint32_t regval;
uint32_t clkin; uint32_t clkin;
uint32_t actual; uint32_t actual;
/* Pick a clock source. Several are possible but only MCK or PLLA is /* Pick a clock source. Several are possible but only MCK, PLLA, of SCK is
* chosen here. * chosen here.
*/ */
DEBUGASSERT(BOARD_MCK_FREQUENCY < BOARD_PLLA_FREQUENCY); if (clksrc == PCKSRC_SCK)
if (frequency <= BOARD_MCK_FREQUENCY ||
frequency < BOARD_PLLA_FREQUENCY / 64)
{ {
regval = PMC_PCK_CSS_MCK; /* Pick the slow clock */
clkin = BOARD_MCK_FREQUENCY;
regval = PMC_PCK_CSS_SLOW;
clkin = BOARD_SCK_FREQUENCY
} }
else else
{ {
regval = PMC_PCK_CSS_PLLA; DEBUGASSERT(BOARD_MCK_FREQUENCY < BOARD_PLLA_FREQUENCY);
clkin = BOARD_PLLA_FREQUENCY;
/* Pick the PLLACK if it seems like a better choice */
if (frequency <= BOARD_MCK_FREQUENCY ||
frequency < BOARD_PLLA_FREQUENCY / 64)
{
regval = PMC_PCK_CSS_MCK;
clkin = BOARD_MCK_FREQUENCY;
}
else
{
regval = PMC_PCK_CSS_PLLA;
clkin = BOARD_PLLA_FREQUENCY;
}
} }
/* The the larger smallest divisor that does not exceed the requested /* The the larger smallest divisor that does not exceed the requested
* frequency. * frequency.
*/ */
if (frequency > clkin) if (frequency >= clkin)
{ {
regval |= PMC_PCK_PRES_DIV1; regval |= PMC_PCK_PRES_DIV1;
actual = clkin; actual = clkin;
} }
else if (frequency > (clkin >> 1)) else if (frequency >= (clkin >> 1))
{ {
regval |= PMC_PCK_PRES_DIV2; regval |= PMC_PCK_PRES_DIV2;
actual = clkin >> 1; actual = clkin >> 1;
} }
else if (frequency > (clkin >> 2)) else if (frequency >= (clkin >> 2))
{ {
regval |= PMC_PCK_PRES_DIV4; regval |= PMC_PCK_PRES_DIV4;
actual = clkin >> 2; actual = clkin >> 2;
} }
else if (frequency > (clkin >> 3)) else if (frequency >= (clkin >> 3))
{ {
regval |= PMC_PCK_PRES_DIV8; regval |= PMC_PCK_PRES_DIV8;
actual = clkin >> 3; actual = clkin >> 3;
} }
else if (frequency > (clkin >> 4)) else if (frequency >= (clkin >> 4))
{ {
regval |= PMC_PCK_PRES_DIV16; regval |= PMC_PCK_PRES_DIV16;
actual = clkin >> 4; actual = clkin >> 4;
} }
else if (frequency > (clkin >> 5)) else if (frequency >= (clkin >> 5))
{ {
regval |= PMC_PCK_PRES_DIV32; regval |= PMC_PCK_PRES_DIV32;
actual = clkin >> 5; actual = clkin >> 5;
} }
else if (frequency > (clkin >> 6)) else if (frequency >= (clkin >> 6))
{ {
regval |= PMC_PCK_PRES_DIV64; regval |= PMC_PCK_PRES_DIV64;
actual = clkin >> 6; actual = clkin >> 6;

View File

@ -1,7 +1,7 @@
/************************************************************************************ /************************************************************************************
* arch/arm/src/sama5/sam_pck.h * arch/arm/src/sama5/sam_pck.h
* *
* Copyright (C) 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2013-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -61,6 +61,12 @@ enum pckid_e
PCK2 PCK2
}; };
enum pckid_clksrc_e
{
PCKSRC_MCK = 0, /* Source clock is the master clock (MCK) or PLLA output (PLLACK) */
PCKSRC_SCK /* Source clock is the slow clock (SCK) */
};
/************************************************************************************ /************************************************************************************
* Public Functions * Public Functions
************************************************************************************/ ************************************************************************************/
@ -87,6 +93,8 @@ extern "C" {
* *
* Input Parameters: * Input Parameters:
* pckid - Identifies the programmable clock output (0, 1, or 2) * pckid - Identifies the programmable clock output (0, 1, or 2)
* clocksrc - MCK or SCK. If MCK is selected, the logic will automatically
* select the PLLACK clock if it seems like a better choice.
* frequency - Defines the desired frequency. The exact frequency may * frequency - Defines the desired frequency. The exact frequency may
* not be attainable. In this case, frequency is interpreted to be * not be attainable. In this case, frequency is interpreted to be
* a not-to-exceed frequency. * a not-to-exceed frequency.
@ -96,7 +104,8 @@ extern "C" {
* *
****************************************************************************/ ****************************************************************************/
uint32_t sam_pck_configure(enum pckid_e pckid, uint32_t frequency); uint32_t sam_pck_configure(enum pckid_e pckid, enum pckid_clksrc_e clksrc,
uint32_t frequency);
/**************************************************************************** /****************************************************************************
* Function: sam_pck_enable * Function: sam_pck_enable

View File

@ -194,7 +194,7 @@ static inline int ov2640_camera_initialize(void)
/* Configure and enable the PCK1 output */ /* Configure and enable the PCK1 output */
actual = sam_pck_configure(PCK1, OV2640_FREQUENCY); actual = sam_pck_configure(PCK1, PCKSRC_MCK, OV2640_FREQUENCY);
gvdbg("Desired PCK1 frequency: %ld Actual: %ld\n", gvdbg("Desired PCK1 frequency: %ld Actual: %ld\n",
(long)OV2640_FREQUENCY, (long)actual); (long)OV2640_FREQUENCY, (long)actual);

View File

@ -280,7 +280,7 @@ int sam_wm8904_initialize(int minor)
*/ */
sam_sckc_enable(true); sam_sckc_enable(true);
(void)sam_pck_configure(PCK0, BOARD_SLOWCLK_FREQUENCY); (void)sam_pck_configure(PCK0, PCKSRC_SCK, BOARD_SLOWCLK_FREQUENCY);
/* Enable the DAC master clock */ /* Enable the DAC master clock */