summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-at91/clock.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 17:48:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 17:48:14 -0700
commit2ca7d674d7ab2220707b2ada0b690c0e7c95e7ac (patch)
tree9c0927ed1d540e5fd704c1f82689870786514655 /arch/arm/mach-at91/clock.c
parent2195d2818c37bdf263865f1e9effccdd9fc5f9d4 (diff)
parent87d721ad7a37b7650dd710c88dd5c6a5bf9fe996 (diff)
downloadop-kernel-dev-2ca7d674d7ab2220707b2ada0b690c0e7c95e7ac.zip
op-kernel-dev-2ca7d674d7ab2220707b2ada0b690c0e7c95e7ac.tar.gz
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (257 commits) [ARM] Update mach-types ARM: 5636/1: Move vendor enum to AMBA include ARM: Fix pfn_valid() for sparse memory [ARM] orion5x: Add LaCie NAS 2Big Network support [ARM] pxa/sharpsl_pm: zaurus c3000 aka spitz: fix resume ARM: 5686/1: at91: Correct AC97 reset line in at91sam9263ek board ARM: 5640/1: This patch modifies the support of AC97 on the at91sam9263 ek board ARM: 5689/1: Update default config of HP Jornada 700-series machines ARM: 5691/1: fix cache aliasing issues between kmap() and kmap_atomic() with highmem ARM: 5688/1: ks8695_serial: disable_irq() lockup ARM: 5687/1: fix an oops with highmem ARM: 5684/1: Add nuc960 platform to w90x900 ARM: 5683/1: Add nuc950 platform to w90x900 ARM: 5682/1: Add cpu.c and dev.c and modify some files of w90p910 platform ARM: 5626/1: add suspend/resume functions to amba-pl011 serial driver ARM: 5625/1: fix hard coded 4K resource size in amba bus detection MMC: MMCI: convert realview MMC to use gpiolib ARM: 5685/1: Make MMCI driver compile without gpiolib ARM: implement highpte ARM: Show FIQ in /proc/interrupts on CONFIG_FIQ ... Fix up trivial conflict in arch/arm/kernel/signal.c. It was due to the TIF_NOTIFY_RESUME addition in commit d0420c83f ("KEYS: Extend TIF_NOTIFY_RESUME to (almost) all architectures") and follow-ups.
Diffstat (limited to 'arch/arm/mach-at91/clock.c')
-rw-r--r--arch/arm/mach-at91/clock.c66
1 files changed, 55 insertions, 11 deletions
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index bac578f..c042dcf 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -47,20 +47,25 @@
* Chips have some kind of clocks : group them by functionality
*/
#define cpu_has_utmi() ( cpu_is_at91cap9() \
- || cpu_is_at91sam9rl())
+ || cpu_is_at91sam9rl() \
+ || cpu_is_at91sam9g45())
-#define cpu_has_800M_plla() (cpu_is_at91sam9g20())
+#define cpu_has_800M_plla() ( cpu_is_at91sam9g20() \
+ || cpu_is_at91sam9g45())
-#define cpu_has_pllb() (!cpu_is_at91sam9rl())
+#define cpu_has_300M_plla() (cpu_is_at91sam9g10())
-#define cpu_has_upll() (0)
+#define cpu_has_pllb() (!(cpu_is_at91sam9rl() \
+ || cpu_is_at91sam9g45()))
+
+#define cpu_has_upll() (cpu_is_at91sam9g45())
/* USB host HS & FS */
#define cpu_has_uhp() (!cpu_is_at91sam9rl())
/* USB device FS only */
-#define cpu_has_udpfs() (!cpu_is_at91sam9rl())
-
+#define cpu_has_udpfs() (!(cpu_is_at91sam9rl() \
+ || cpu_is_at91sam9g45()))
static LIST_HEAD(clocks);
static DEFINE_SPINLOCK(clk_lock);
@@ -133,6 +138,13 @@ static void pmc_uckr_mode(struct clk *clk, int is_on)
{
unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
+ if (cpu_is_at91sam9g45()) {
+ if (is_on)
+ uckr |= AT91_PMC_BIASEN;
+ else
+ uckr &= ~AT91_PMC_BIASEN;
+ }
+
if (is_on) {
is_on = AT91_PMC_LOCKU;
at91_sys_write(AT91_CKGR_UCKR, uckr | clk->pmc_mask);
@@ -310,6 +322,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
unsigned long flags;
unsigned prescale;
unsigned long actual;
+ unsigned long prev = ULONG_MAX;
if (!clk_is_programmable(clk))
return -EINVAL;
@@ -317,8 +330,16 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
actual = clk->parent->rate_hz;
for (prescale = 0; prescale < 7; prescale++) {
- if (actual && actual <= rate)
+ if (actual > rate)
+ prev = actual;
+
+ if (actual && actual <= rate) {
+ if ((prev - rate) < (rate - actual)) {
+ actual = prev;
+ prescale--;
+ }
break;
+ }
actual >>= 1;
}
@@ -373,6 +394,10 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
return -EBUSY;
if (!clk_is_primary(parent) || !clk_is_programmable(clk))
return -EINVAL;
+
+ if (cpu_is_at91sam9rl() && parent->id == AT91_PMC_CSS_PLLB)
+ return -EINVAL;
+
spin_lock_irqsave(&clk_lock, flags);
clk->rate_hz = parent->rate_hz;
@@ -601,7 +626,9 @@ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock)
uhpck.pmc_mask = AT91RM9200_PMC_UHP;
udpck.pmc_mask = AT91RM9200_PMC_UDP;
at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
- } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
+ } else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() ||
+ cpu_is_at91sam9263() || cpu_is_at91sam9g20() ||
+ cpu_is_at91sam9g10()) {
uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
udpck.pmc_mask = AT91SAM926x_PMC_UDP;
} else if (cpu_is_at91cap9()) {
@@ -637,6 +664,7 @@ int __init at91_clock_init(unsigned long main_clock)
{
unsigned tmp, freq, mckr;
int i;
+ int pll_overclock = false;
/*
* When the bootloader initialized the main oscillator correctly,
@@ -654,12 +682,25 @@ int __init at91_clock_init(unsigned long main_clock)
/* report if PLLA is more than mildly overclocked */
plla.rate_hz = at91_pll_rate(&plla, main_clock, at91_sys_read(AT91_CKGR_PLLAR));
- if ((!cpu_has_800M_plla() && plla.rate_hz > 209000000)
- || (cpu_has_800M_plla() && plla.rate_hz > 800000000))
+ if (cpu_has_300M_plla()) {
+ if (plla.rate_hz > 300000000)
+ pll_overclock = true;
+ } else if (cpu_has_800M_plla()) {
+ if (plla.rate_hz > 800000000)
+ pll_overclock = true;
+ } else {
+ if (plla.rate_hz > 209000000)
+ pll_overclock = true;
+ }
+ if (pll_overclock)
pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
+ if (cpu_is_at91sam9g45()) {
+ mckr = at91_sys_read(AT91_PMC_MCKR);
+ plla.rate_hz /= (1 << ((mckr & AT91_PMC_PLLADIV2) >> 12)); /* plla divisor by 2 */
+ }
- if (cpu_has_upll() && !cpu_has_pllb()) {
+ if (!cpu_has_pllb() && cpu_has_upll()) {
/* setup UTMI clock as the fourth primary clock
* (instead of pllb) */
utmi_clk.type |= CLK_TYPE_PRIMARY;
@@ -701,6 +742,9 @@ int __init at91_clock_init(unsigned long main_clock)
freq / ((mckr & AT91_PMC_MDIV) >> 7) : freq; /* mdiv ; (x >> 7) = ((x >> 8) * 2) */
if (mckr & AT91_PMC_PDIV)
freq /= 2; /* processor clock division */
+ } else if (cpu_is_at91sam9g45()) {
+ mck.rate_hz = (mckr & AT91_PMC_MDIV) == AT91SAM9_PMC_MDIV_3 ?
+ freq / 3 : freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
} else {
mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */
}
OpenPOWER on IntegriCloud