diff options
author | Bo Shen <voice.shen@atmel.com> | 2013-05-12 22:40:54 +0000 |
---|---|---|
committer | Andreas Bießmann <andreas.devel@googlemail.com> | 2013-05-21 11:54:16 +0200 |
commit | 3225f34e5c704a9caf3c69527ee1f822aee15108 (patch) | |
tree | 9ae7edc8f5e9d02616c4c5e625736a7922fc762e /arch/arm/cpu/armv7/at91/clock.c | |
parent | e5e8bb05a4cc31624306dbbcc89f99795ff8f462 (diff) |
ARM: atmel: add sama5d3xek support
Add sama5d3xek support with following feature
- boot from NAND flash, PMECC support, 4bit ECC @ 512 bytes sector
- boot from SPI flash support
- boot from SD card support
- LCD support
- EMAC support
- USB OHCI support
Signed-off-by: Bo Shen <voice.shen@atmel.com>
Signed-off-by: Andreas Bießmann <andreas.devel@googlemail.com>
Diffstat (limited to 'arch/arm/cpu/armv7/at91/clock.c')
-rw-r--r-- | arch/arm/cpu/armv7/at91/clock.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/at91/clock.c b/arch/arm/cpu/armv7/at91/clock.c new file mode 100644 index 0000000000..624b52cc31 --- /dev/null +++ b/arch/arm/cpu/armv7/at91/clock.c @@ -0,0 +1,125 @@ +/* + * [origin: Linux kernel linux/arch/arm/mach-at91/clock.c] + * + * Copyright (C) 2005 David Brownell + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * Copyright (C) 2013 Bo Shen <voice.shen@atmel.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/clk.h> + +#if !defined(CONFIG_AT91FAMILY) +# error You need to define CONFIG_AT91FAMILY in your board config! +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static unsigned long at91_css_to_rate(unsigned long css) +{ + switch (css) { + case AT91_PMC_MCKR_CSS_SLOW: + return CONFIG_SYS_AT91_SLOW_CLOCK; + case AT91_PMC_MCKR_CSS_MAIN: + return gd->arch.main_clk_rate_hz; + case AT91_PMC_MCKR_CSS_PLLA: + return gd->arch.plla_rate_hz; + } + + return 0; +} + +static u32 at91_pll_rate(u32 freq, u32 reg) +{ + unsigned mul, div; + + div = reg & 0xff; + mul = (reg >> 18) & 0x7f; + if (div && mul) { + freq /= div; + freq *= mul + 1; + } else { + freq = 0; + } + + return freq; +} + +int at91_clock_init(unsigned long main_clock) +{ + unsigned freq, mckr; + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; +#ifndef CONFIG_SYS_AT91_MAIN_CLOCK + unsigned tmp; + /* + * When the bootloader initialized the main oscillator correctly, + * there's no problem using the cycle counter. But if it didn't, + * or when using oscillator bypass mode, we must be told the speed + * of the main clock. + */ + if (!main_clock) { + do { + tmp = readl(&pmc->mcfr); + } while (!(tmp & AT91_PMC_MCFR_MAINRDY)); + tmp &= AT91_PMC_MCFR_MAINF_MASK; + main_clock = tmp * (CONFIG_SYS_AT91_SLOW_CLOCK / 16); + } +#endif + gd->arch.main_clk_rate_hz = main_clock; + + /* report if PLLA is more than mildly overclocked */ + gd->arch.plla_rate_hz = at91_pll_rate(main_clock, readl(&pmc->pllar)); + + /* + * MCK and CPU derive from one of those primary clocks. + * For now, assume this parentage won't change. + */ + mckr = readl(&pmc->mckr); + + /* plla divisor by 2 */ + if (mckr & (1 << 12)) + gd->arch.plla_rate_hz >>= 1; + + gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); + freq = gd->arch.mck_rate_hz; + + /* prescale */ + freq >>= mckr & AT91_PMC_MCKR_PRES_MASK; + + switch (mckr & AT91_PMC_MCKR_MDIV_MASK) { + case AT91_PMC_MCKR_MDIV_2: + gd->arch.mck_rate_hz = freq / 2; + break; + case AT91_PMC_MCKR_MDIV_3: + gd->arch.mck_rate_hz = freq / 3; + break; + case AT91_PMC_MCKR_MDIV_4: + gd->arch.mck_rate_hz = freq / 4; + break; + default: + break; + } + + gd->arch.cpu_clk_rate_hz = freq; + + return 0; +} + +void at91_periph_clk_enable(int id) +{ + struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + + if (id > 31) + writel(1 << (id - 32), &pmc->pcer1); + else + writel(1 << id, &pmc->pcer); +} |