diff --git a/arch/arm/src/sama5/sam_isi.c b/arch/arm/src/sama5/sam_isi.c index e013e72a9c2..124734a416c 100644 --- a/arch/arm/src/sama5/sam_isi.c +++ b/arch/arm/src/sama5/sam_isi.c @@ -159,7 +159,7 @@ int sam_isi_initialize(void) * 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", ISI_PCKID, CONFIG_ISI_MCKFREQ, g_isi.actual); diff --git a/arch/arm/src/sama5/sam_pck.c b/arch/arm/src/sama5/sam_pck.c index 55043fd4df2..e16ab855b46 100644 --- a/arch/arm/src/sama5/sam_pck.c +++ b/arch/arm/src/sama5/sam_pck.c @@ -1,7 +1,7 @@ /**************************************************************************** * 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 * * Redistribution and use in source and binary forms, with or without @@ -91,6 +91,8 @@ * * Input Parameters: * 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 * not be attainable. In this case, frequency is interpreted to be * 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 clkin; 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. */ - DEBUGASSERT(BOARD_MCK_FREQUENCY < BOARD_PLLA_FREQUENCY); - if (frequency <= BOARD_MCK_FREQUENCY || - frequency < BOARD_PLLA_FREQUENCY / 64) + if (clksrc == PCKSRC_SCK) { - regval = PMC_PCK_CSS_MCK; - clkin = BOARD_MCK_FREQUENCY; + /* Pick the slow clock */ + + regval = PMC_PCK_CSS_SLOW; + clkin = BOARD_SCK_FREQUENCY } else { - regval = PMC_PCK_CSS_PLLA; - clkin = BOARD_PLLA_FREQUENCY; + DEBUGASSERT(BOARD_MCK_FREQUENCY < 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 * frequency. */ - if (frequency > clkin) + if (frequency >= clkin) { regval |= PMC_PCK_PRES_DIV1; actual = clkin; } - else if (frequency > (clkin >> 1)) + else if (frequency >= (clkin >> 1)) { regval |= PMC_PCK_PRES_DIV2; actual = clkin >> 1; } - else if (frequency > (clkin >> 2)) + else if (frequency >= (clkin >> 2)) { regval |= PMC_PCK_PRES_DIV4; actual = clkin >> 2; } - else if (frequency > (clkin >> 3)) + else if (frequency >= (clkin >> 3)) { regval |= PMC_PCK_PRES_DIV8; actual = clkin >> 3; } - else if (frequency > (clkin >> 4)) + else if (frequency >= (clkin >> 4)) { regval |= PMC_PCK_PRES_DIV16; actual = clkin >> 4; } - else if (frequency > (clkin >> 5)) + else if (frequency >= (clkin >> 5)) { regval |= PMC_PCK_PRES_DIV32; actual = clkin >> 5; } - else if (frequency > (clkin >> 6)) + else if (frequency >= (clkin >> 6)) { regval |= PMC_PCK_PRES_DIV64; actual = clkin >> 6; diff --git a/arch/arm/src/sama5/sam_pck.h b/arch/arm/src/sama5/sam_pck.h index 8ea561dbe58..fb504069661 100644 --- a/arch/arm/src/sama5/sam_pck.h +++ b/arch/arm/src/sama5/sam_pck.h @@ -1,7 +1,7 @@ /************************************************************************************ * 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 * * Redistribution and use in source and binary forms, with or without @@ -61,6 +61,12 @@ enum pckid_e 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 ************************************************************************************/ @@ -87,6 +93,8 @@ extern "C" { * * Input Parameters: * 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 * not be attainable. In this case, frequency is interpreted to be * 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 diff --git a/configs/sama5d3x-ek/src/sam_ov2640.c b/configs/sama5d3x-ek/src/sam_ov2640.c index 4ed787c5dd1..876b60dd5d5 100644 --- a/configs/sama5d3x-ek/src/sam_ov2640.c +++ b/configs/sama5d3x-ek/src/sam_ov2640.c @@ -194,7 +194,7 @@ static inline int ov2640_camera_initialize(void) /* 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", (long)OV2640_FREQUENCY, (long)actual); diff --git a/configs/sama5d4-ek/src/sam_wm8904.c b/configs/sama5d4-ek/src/sam_wm8904.c index 78b169e042c..09ea542ffd8 100644 --- a/configs/sama5d4-ek/src/sam_wm8904.c +++ b/configs/sama5d4-ek/src/sam_wm8904.c @@ -280,7 +280,7 @@ int sam_wm8904_initialize(int minor) */ 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 */