arm: at91: clock: Add the generated clock support
PATCH v3 1/1 arm: at91: clock: Add the generated clock support
Some peripherals may need a second clock source that may be different from the system clock. This second clock is the generated clock (GCK) and is managed by the PMC via PMC_PCR.
For simplicity, the clock source of the GCK is fixed to PLLA_CLK.
---
Changes in v3:
1./ add arguments for at91_enable_periph_generated_clk(). 2./ add return value for at91_enable_periph_generated_clk().
Changes in v2:
1./ add timeout to wait for GCK ready.
2./ add warning for timeout to wait for GCK ready.
3./ add printout when the improper GCK clock source is selected. 4./ rework AT91_PMC_PCR_GCKDIV_(x) macro to make sure x is right.
arch/arm/mach-at91/armv7/clock.c | 95 ++++++++++++++++++++++++++++ arch/arm/mach-at91/include/mach/at91_pmc.h | 13 ++++ arch/arm/mach-at91/include/mach/clk.h | 10 +++ 3 files changed, 118 insertions(+)
arch/arm/mach-at91/armv7/clock.c +95 -0
@@ -5,11 +5,13 @@* Copyright (C) 2005 Ivan Kokshaysky * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <[email protected]> * Copyright (C) 2013 Bo Shen <[email protected]> +* Copyright (C) 2015 Wenyou Yang <[email protected]> * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> +#include <asm/errno.h> #include <asm/io.h> #include <asm/arch/hardware.h> #include <asm/arch/at91_pmc.h>
@@ -173,3 +175,96 @@ void at91_periph_clk_disable(int id)writel (regval, &pmc->pcr); } + +int at91_enable_periph_generated_clk (u32 id,u32 clk_source,u32 div) +{ +struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC ; +u32 regval, status; +u32 timeout =1000 ; + +if (id >AT91_PMC_PCR_PID_MASK ) +return -EINVAL ; + +if (div >0xff ) +return -EINVAL ; + +writel (id, &pmc->pcr); + regval =readl (&pmc->pcr); + regval &= ~AT91_PMC_PCR_GCKCSS ; + regval &= ~AT91_PMC_PCR_GCKDIV ; + +switch (clk_source) { +case GCK_CSS_SLOW_CLK : + regval |=AT91_PMC_PCR_GCKCSS_SLOW_CLK ; +break ; +case GCK_CSS_MAIN_CLK : + regval |=AT91_PMC_PCR_GCKCSS_MAIN_CLK ; +break ; +case GCK_CSS_PLLA_CLK : + regval |=AT91_PMC_PCR_GCKCSS_PLLA_CLK ; +break ; +case GCK_CSS_UPLL_CLK : + regval |=AT91_PMC_PCR_GCKCSS_UPLL_CLK ; +break ; +case GCK_CSS_MCK_CLK : + regval |=AT91_PMC_PCR_GCKCSS_MCK_CLK ; +break ; +case GCK_CSS_AUDIO_CLK : + regval |=AT91_PMC_PCR_GCKCSS_AUDIO_CLK ; +break ; +default : +printf ("Error GCK clock source selection!\n" ); +return -EINVAL ; + } + + regval |=AT91_PMC_PCR_CMD_WRITE | +AT91_PMC_PCR_GCKDIV_ (div) | +AT91_PMC_PCR_GCKEN ; + +writel (regval, &pmc->pcr); + +do { +udelay (1 ); + status =readl (&pmc->sr); + }while ((!!(--timeout)) && (!(status &AT91_PMC_GCKRDY ))); + +if (!timeout) +printf ("Timeout waiting for GCK ready!\n" ); + +return 0 ; +} + +u32 at91_get_periph_generated_clk (u32 id) +{ +struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC ; +u32 regval, clk_source, div; +u32 freq; + +if (id >AT91_PMC_PCR_PID_MASK ) +return 0 ; + +writel (id, &pmc->pcr); + regval =readl (&pmc->pcr); + + clk_source = regval &AT91_PMC_PCR_GCKCSS ; +switch (clk_source) { +case AT91_PMC_PCR_GCKCSS_SLOW_CLK : + freq =CONFIG_SYS_AT91_SLOW_CLOCK ; +break ; +case AT91_PMC_PCR_GCKCSS_MAIN_CLK : + freq = gd->arch.main_clk_rate_hz; +break ; +case AT91_PMC_PCR_GCKCSS_PLLA_CLK : + freq = gd->arch.plla_rate_hz; +break ; +default : +printf ("Improper GCK clock source selection!\n" ); + freq =0 ; +break ; + } + + div = ((regval &AT91_PMC_PCR_GCKDIV ) >>AT91_PMC_PCR_GCKDIV_OFFSET ); + div +=1 ; + +return freq / div; +}
arch/arm/mach-at91/include/mach/at91_pmc.h +13 -0
@@ -153,8 +153,20 @@ typedef struct at91_pmc {#define AT91_PMC_IXR_MOSCSELS 0x00010000#define AT91_PMC_PCR_PID_MASK (0x3f) +#define AT91_PMC_PCR_GCKCSS (0x7 << 8) +#define AT91_PMC_PCR_GCKCSS_SLOW_CLK (0x0 << 8) +#define AT91_PMC_PCR_GCKCSS_MAIN_CLK (0x1 << 8) +#define AT91_PMC_PCR_GCKCSS_PLLA_CLK (0x2 << 8) +#define AT91_PMC_PCR_GCKCSS_UPLL_CLK (0x3 << 8) +#define AT91_PMC_PCR_GCKCSS_MCK_CLK (0x4 << 8) +#define AT91_PMC_PCR_GCKCSS_AUDIO_CLK (0x5 << 8)#define AT91_PMC_PCR_CMD_WRITE (0x1 << 12) +#define AT91_PMC_PCR_DIV (0x3 << 16) +#define AT91_PMC_PCR_GCKDIV (0xff << 20) +#define AT91_PMC_PCR_GCKDIV_ (x) ((x & 0xff) << 20) +#define AT91_PMC_PCR_GCKDIV_OFFSET 20#define AT91_PMC_PCR_EN (0x1 << 28) +#define AT91_PMC_PCR_GCKEN (0x1 << 29)#define AT91_PMC_PCK (1 << 0)/* Processor Clock */ #define AT91RM9200_PMC_UDP (1 << 1)/* USB Devcice Port Clock [AT91RM9200 only] */
@@ -236,6 +248,7 @@ typedef struct at91_pmc {#define AT91_PMC_PCK1RDY (1 << 9)/* Programmable Clock 1 */ #define AT91_PMC_PCK2RDY (1 << 10)/* Programmable Clock 2 */ #define AT91_PMC_PCK3RDY (1 << 11)/* Programmable Clock 3 */ +#define AT91_PMC_GCKRDY (1 << 24)#define AT91_PMC_PROTKEY 0x504d4301/* Activation Code */ #endif
arch/arm/mach-at91/include/mach/clk.h +10 -0
@@ -13,6 +13,13 @@#include <asm/arch/at91_pmc.h> #include <asm/global_data.h> +#define GCK_CSS_SLOW_CLK 0 +#define GCK_CSS_MAIN_CLK 1 +#define GCK_CSS_PLLA_CLK 2 +#define GCK_CSS_UPLL_CLK 3 +#define GCK_CSS_MCK_CLK 4 +#define GCK_CSS_AUDIO_CLK 5 +static inline unsigned long get_cpu_clk_rate (void ) {DECLARE_GLOBAL_DATA_PTR ;
@@ -119,4 +126,7 @@ static inline unsigned long get_pit_clk_rate(void)int at91_clock_init (unsigned long main_clock);void at91_periph_clk_enable (int id);void at91_periph_clk_disable (int id); +int at91_enable_periph_generated_clk (u32 id,u32 clk_source,u32 div); +u32 at91_get_periph_generated_clk (u32 id); +#endif /* __ASM_ARM_ARCH_CLK_H__ */
Signature · 1 line
1.7.9.5
PATCH v3 1/1 arm: at91: clock: Add the generated clock support
Dear Wenyou Yang,
Quoted 20 lines · Wenyou Yang
Some peripherals may need a second clock source that may be different from the system clock. This second clock is the generated clock (GCK) and is managed by the PMC via
PMC_PCR.For simplicity, the clock source of the GCK is fixed to
PLLA_CLK.Signed-off-by Wenyou Yang <[email protected]>Reviewed-by Andreas Bie?mann <[email protected]>---
Changes in v3:
1./ add arguments forat91_enable_periph_generated_clk(). 2./ add return value forat91_enable_periph_generated_clk().Changes in v2:
1./ add timeout to wait for GCK ready.
2./ add warning for timeout to wait for GCK ready.
3./ add printout when the improper GCK clock source is selected. 4./ reworkAT91_PMC_PCR_GCKDIV_(x)macro to make sure x is right.
Quoted 4 lines
arch/arm/mach-at91/armv7/clock.c | 95 ++++++++++++++++++++++++++++ arch/arm/mach-at91/include/mach/at91_pmc.h | 13 ++++ arch/arm/mach-at91/include/mach/clk.h | 10 +++ 3 files changed, 118 insertions(+)
applied to u-boot-atmel/master, thanks!
Best regards,
Andreas Bie?mann