diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 09:31:45 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 09:31:45 -0700 |
| commit | 97b1007a2924aaa9126398623f6755a8c3c6a616 (patch) | |
| tree | b65c6edb631256e64bb3c72f083fa1be048de097 /arch/arm/mach-at91/clock.c | |
| parent | dfab34aa61a0f8c14a67d7b4c1dae28e57ba592d (diff) | |
| parent | e0d20b69d3fa74a21ec363989612bddd58b930b8 (diff) | |
| download | olio-linux-3.10-97b1007a2924aaa9126398623f6755a8c3c6a616.tar.xz olio-linux-3.10-97b1007a2924aaa9126398623f6755a8c3c6a616.zip | |
Merge tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform updates from Olof Johansson:
"This branch contains part 1 of the platform updates for 3.10. Among
the highlights:
- Support for the new Atmel Cortex-A5 based platforms (SAMA5D3)
- New support for CSR SiRFatlas6 SoCs
- A handful of updates for NVidia T114 (a.k.a. Tegra 4)
- A bunch of updates for the shmobile platforms
- A handful of updates for davinci
- A few updates for Qualcomm MSM
- Plus a handful of other patches, defconfig updates, etc."
* tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (135 commits)
ARM: tegra: pm: fix build error w/o PM_SLEEP
ARM: davinci: ensure global variables are declared
ARM: davinci: sram.c: fix incorrect type in assignment
ARM: davinci: da8xx dt: make file local symbols static
ARM: davinci: da8xx: add remoteproc support
ARM: socfpga: Upgrade clk driver for socfpga to make use of dts clock entries
ARM: socfpga: Add clock entries into device tree
ARM: socfpga: Enable soft reset
ARM: EXYNOS: replace cpumask by the corresponding macro
ARM: EXYNOS: handle properly the return values
ARM: EXYNOS: factor out the idle states
ARM: OMAP4: Enable fix for Cortex-A9 erratas
ARM: OMAP2+: Export SoC information to userspace
ARM: OMAP2+: SoC name and revision unification
ARM: OMAP2+: Move common part of late init into common function
ARM: tegra: pm: remove duplicated include from pm.c
ARM: davinci: da850: override mmc DT node device name
ARM: davinci: da850: add mmc DT entries
mmc: davinci_mmc: add DT support
ARM: SAMSUNG: check processor type before cache restoration in resume
...
Diffstat (limited to 'arch/arm/mach-at91/clock.c')
| -rw-r--r-- | arch/arm/mach-at91/clock.c | 109 |
1 files changed, 84 insertions, 25 deletions
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 33361505c0c..da841885d01 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -54,7 +54,10 @@ EXPORT_SYMBOL_GPL(at91_pmc_base); */ #define cpu_has_utmi() ( cpu_is_at91sam9rl() \ || cpu_is_at91sam9g45() \ - || cpu_is_at91sam9x5()) + || cpu_is_at91sam9x5() \ + || cpu_is_sama5d3()) + +#define cpu_has_1056M_plla() (cpu_is_sama5d3()) #define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \ || cpu_is_at91sam9g45() \ @@ -75,7 +78,8 @@ EXPORT_SYMBOL_GPL(at91_pmc_base); || cpu_is_at91sam9n12())) #define cpu_has_upll() (cpu_is_at91sam9g45() \ - || cpu_is_at91sam9x5()) + || cpu_is_at91sam9x5() \ + || cpu_is_sama5d3()) /* USB host HS & FS */ #define cpu_has_uhp() (!cpu_is_at91sam9rl()) @@ -83,18 +87,22 @@ EXPORT_SYMBOL_GPL(at91_pmc_base); /* USB device FS only */ #define cpu_has_udpfs() (!(cpu_is_at91sam9rl() \ || cpu_is_at91sam9g45() \ - || cpu_is_at91sam9x5())) + || cpu_is_at91sam9x5() \ + || cpu_is_sama5d3())) #define cpu_has_plladiv2() (cpu_is_at91sam9g45() \ || cpu_is_at91sam9x5() \ - || cpu_is_at91sam9n12()) + || cpu_is_at91sam9n12() \ + || cpu_is_sama5d3()) #define cpu_has_mdiv3() (cpu_is_at91sam9g45() \ || cpu_is_at91sam9x5() \ - || cpu_is_at91sam9n12()) + || cpu_is_at91sam9n12() \ + || cpu_is_sama5d3()) #define cpu_has_alt_prescaler() (cpu_is_at91sam9x5() \ - || cpu_is_at91sam9n12()) + || cpu_is_at91sam9n12() \ + || cpu_is_sama5d3()) static LIST_HEAD(clocks); static DEFINE_SPINLOCK(clk_lock); @@ -210,10 +218,26 @@ struct clk mck = { static void pmc_periph_mode(struct clk *clk, int is_on) { - if (is_on) - at91_pmc_write(AT91_PMC_PCER, clk->pmc_mask); - else - at91_pmc_write(AT91_PMC_PCDR, clk->pmc_mask); + u32 regval = 0; + + /* + * With sama5d3 devices, we are managing clock division so we have to + * use the Peripheral Control Register introduced from at91sam9x5 + * devices. + */ + if (cpu_is_sama5d3()) { + regval |= AT91_PMC_PCR_CMD; /* write command */ + regval |= clk->pid & AT91_PMC_PCR_PID; /* peripheral selection */ + regval |= AT91_PMC_PCR_DIV(clk->div); + if (is_on) + regval |= AT91_PMC_PCR_EN; /* enable clock */ + at91_pmc_write(AT91_PMC_PCR, regval); + } else { + if (is_on) + at91_pmc_write(AT91_PMC_PCER, clk->pmc_mask); + else + at91_pmc_write(AT91_PMC_PCDR, clk->pmc_mask); + } } static struct clk __init *at91_css_to_clk(unsigned long css) @@ -443,14 +467,18 @@ static void __init init_programmable_clock(struct clk *clk) static int at91_clk_show(struct seq_file *s, void *unused) { - u32 scsr, pcsr, uckr = 0, sr; + u32 scsr, pcsr, pcsr1 = 0, uckr = 0, sr; struct clk *clk; scsr = at91_pmc_read(AT91_PMC_SCSR); pcsr = at91_pmc_read(AT91_PMC_PCSR); + if (cpu_is_sama5d3()) + pcsr1 = at91_pmc_read(AT91_PMC_PCSR1); sr = at91_pmc_read(AT91_PMC_SR); seq_printf(s, "SCSR = %8x\n", scsr); seq_printf(s, "PCSR = %8x\n", pcsr); + if (cpu_is_sama5d3()) + seq_printf(s, "PCSR1 = %8x\n", pcsr1); seq_printf(s, "MOR = %8x\n", at91_pmc_read(AT91_CKGR_MOR)); seq_printf(s, "MCFR = %8x\n", at91_pmc_read(AT91_CKGR_MCFR)); seq_printf(s, "PLLA = %8x\n", at91_pmc_read(AT91_CKGR_PLLAR)); @@ -470,20 +498,30 @@ static int at91_clk_show(struct seq_file *s, void *unused) list_for_each_entry(clk, &clocks, node) { char *state; - if (clk->mode == pmc_sys_mode) + if (clk->mode == pmc_sys_mode) { state = (scsr & clk->pmc_mask) ? "on" : "off"; - else if (clk->mode == pmc_periph_mode) - state = (pcsr & clk->pmc_mask) ? "on" : "off"; - else if (clk->mode == pmc_uckr_mode) + } else if (clk->mode == pmc_periph_mode) { + if (cpu_is_sama5d3()) { + u32 pmc_mask = 1 << (clk->pid % 32); + + if (clk->pid > 31) + state = (pcsr1 & pmc_mask) ? "on" : "off"; + else + state = (pcsr & pmc_mask) ? "on" : "off"; + } else { + state = (pcsr & clk->pmc_mask) ? "on" : "off"; + } + } else if (clk->mode == pmc_uckr_mode) { state = (uckr & clk->pmc_mask) ? "on" : "off"; - else if (clk->pmc_mask) + } else if (clk->pmc_mask) { state = (sr & clk->pmc_mask) ? "on" : "off"; - else if (clk == &clk32k || clk == &main_clk) + } else if (clk == &clk32k || clk == &main_clk) { state = "on"; - else + } else { state = ""; + } - seq_printf(s, "%-10s users=%2d %-3s %9ld Hz %s\n", + seq_printf(s, "%-10s users=%2d %-3s %9lu Hz %s\n", clk->name, clk->users, state, clk_get_rate(clk), clk->parent ? clk->parent->name : ""); } @@ -530,6 +568,9 @@ int __init clk_register(struct clk *clk) if (clk_is_peripheral(clk)) { if (!clk->parent) clk->parent = &mck; + if (cpu_is_sama5d3()) + clk->rate_hz = DIV_ROUND_UP(clk->parent->rate_hz, + 1 << clk->div); clk->mode = pmc_periph_mode; } else if (clk_is_sys(clk)) { @@ -555,7 +596,11 @@ static u32 __init at91_pll_rate(struct clk *pll, u32 freq, u32 reg) unsigned mul, div; div = reg & 0xff; - mul = (reg >> 16) & 0x7ff; + if (cpu_is_sama5d3()) + mul = AT91_PMC3_MUL_GET(reg); + else + mul = AT91_PMC_MUL_GET(reg); + if (div && mul) { freq /= div; freq *= mul + 1; @@ -706,12 +751,15 @@ static int __init at91_pmc_init(unsigned long main_clock) /* report if PLLA is more than mildly overclocked */ plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_pmc_read(AT91_CKGR_PLLAR)); - if (cpu_has_300M_plla()) { - if (plla.rate_hz > 300000000) + if (cpu_has_1056M_plla()) { + if (plla.rate_hz > 1056000000) pll_overclock = true; } else if (cpu_has_800M_plla()) { if (plla.rate_hz > 800000000) pll_overclock = true; + } else if (cpu_has_300M_plla()) { + if (plla.rate_hz > 300000000) + pll_overclock = true; } else if (cpu_has_240M_plla()) { if (plla.rate_hz > 240000000) pll_overclock = true; @@ -872,6 +920,7 @@ int __init at91_clock_init(unsigned long main_clock) static int __init at91_clock_reset(void) { unsigned long pcdr = 0; + unsigned long pcdr1 = 0; unsigned long scdr = 0; struct clk *clk; @@ -879,8 +928,17 @@ static int __init at91_clock_reset(void) if (clk->users > 0) continue; - if (clk->mode == pmc_periph_mode) - pcdr |= clk->pmc_mask; + if (clk->mode == pmc_periph_mode) { + if (cpu_is_sama5d3()) { + u32 pmc_mask = 1 << (clk->pid % 32); + + if (clk->pid > 31) + pcdr1 |= pmc_mask; + else + pcdr |= pmc_mask; + } else + pcdr |= clk->pmc_mask; + } if (clk->mode == pmc_sys_mode) scdr |= clk->pmc_mask; @@ -888,8 +946,9 @@ static int __init at91_clock_reset(void) pr_debug("Clocks: disable unused %s\n", clk->name); } - at91_pmc_write(AT91_PMC_PCDR, pcdr); at91_pmc_write(AT91_PMC_SCDR, scdr); + if (cpu_is_sama5d3()) + at91_pmc_write(AT91_PMC_PCDR1, pcdr1); return 0; } |