AT91: PMC definitions are plaform-depenent

Andrew Victor avictor.za at gmail.com
Mon May 2 12:16:29 EDT 2011


For supporting multiple AT91 processors in a single kernel image, the
base address of the PMC controller cannot be calculated at compile-time.
Changes required:
* calculate PMC base address in processor-dependent code and pass it
through to the clocks driver at initialization time.
* arch_idle() need to call into processor-dependent code to put the CPU
to sleep.  Added an 'at91_arch_idle' callback.
* Move at91_pm_verify_clocks() from pm.c to clocks.c
* Rename definitions of AT91_PMC to AT91xxx_PMC.


Signed-off-by: Andrew Victor <linux at maxim.org.za>


diff --git a/arch/arm/mach-at91/at572d940hf.c b/arch/arm/mach-at91/at572d940hf.c
index 461735c..040366f 100644
--- a/arch/arm/mach-at91/at572d940hf.c
+++ b/arch/arm/mach-at91/at572d940hf.c
@@ -24,6 +24,7 @@
 
 #include <linux/module.h>
 
+#include <asm/proc-fns.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -292,6 +293,18 @@ static struct at91_gpio_bank at572d940hf_gpio[] = {
 	}
 };
 
+static void at572d940hf_idle(void)
+{
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT572D940HF_PMC;
+
+	/*
+	 * Disable the processor clock, and set the processor (CP15)
+	 * into 'Wait for Interrupt' mode.
+	 */
+	__raw_writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+	cpu_do_idle();
+}
+
 static void at572d940hf_reset(void)
 {
 	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
@@ -304,15 +317,18 @@ static void at572d940hf_reset(void)
 
 void __init at572d940hf_initialize(unsigned long main_clock)
 {
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT572D940HF_PMC;
+
 	/* Map peripherals */
 	iotable_init(at572d940hf_io_desc, ARRAY_SIZE(at572d940hf_io_desc));
 
+	at91_arch_idle = at572d940hf_idle;
 	at91_arch_reset = at572d940hf_reset;
 	at91_extern_irq = (1 << AT572D940HF_ID_IRQ0) | (1 << AT572D940HF_ID_IRQ1)
 			| (1 << AT572D940HF_ID_IRQ2);
 
 	/* Init clock subsystem */
-	at91_clock_init(main_clock);
+	at91_clock_init(pmc, main_clock);
 
 	/* Register the processor-specific clocks */
 	at572d940hf_register_clocks();
diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
index ea2d820..077ed39 100644
--- a/arch/arm/mach-at91/at91cap9.c
+++ b/arch/arm/mach-at91/at91cap9.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 
+#include <asm/proc-fns.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -288,6 +289,18 @@ static struct at91_gpio_bank at91cap9_gpio[] = {
 	}
 };
 
+static void at91cap9_idle(void)
+{
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91CAP9_PMC;
+
+	/*
+	 * Disable the processor clock, and set the processor (CP15)
+	 * into 'Wait for Interrupt' mode.
+	 */
+	__raw_writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+	cpu_do_idle();
+}
+
 static void at91cap9_reset(void)
 {
 	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
@@ -305,15 +318,18 @@ static void at91cap9_poweroff(void)
 
 void __init at91cap9_initialize(unsigned long main_clock)
 {
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91CAP9_PMC;
+
 	/* Map peripherals */
 	iotable_init(at91cap9_io_desc, ARRAY_SIZE(at91cap9_io_desc));
 
+	at91_arch_idle = at91cap9_idle;
 	at91_arch_reset = at91cap9_reset;
 	pm_power_off = at91cap9_poweroff;
 	at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1);
 
 	/* Init clock subsystem */
-	at91_clock_init(main_clock);
+	at91_clock_init(pmc, main_clock);
 
 	/* Register the processor-specific clocks */
 	at91cap9_register_clocks();
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index efb081f..da2cc9a 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -257,6 +257,17 @@ static struct at91_gpio_bank at91rm9200_gpio[] = {
 	}
 };
 
+static void at91rm9200_idle(void)
+{
+	void __iomem *pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91RM9200_PMC;
+
+	/*
+	 * Disable the processor clock.  The processor will be automatically
+	 * re-enabled by an interrupt or by a reset.
+	 */
+	__raw_writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+}
+
 static void at91rm9200_reset(void)
 {
 	/*
@@ -272,9 +283,12 @@ static void at91rm9200_reset(void)
  * -------------------------------------------------------------------- */
 void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks)
 {
+	void __iomem *pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91RM9200_PMC;
+
 	/* Map peripherals */
 	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
 
+	at91_arch_idle = at91rm9200_idle;
 	at91_arch_reset = at91rm9200_reset;
 	at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1)
 			| (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3)
@@ -282,7 +296,7 @@ void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks
 			| (1 << AT91RM9200_ID_IRQ6);
 
 	/* Init clock subsystem */
-	at91_clock_init(main_clock);
+	at91_clock_init(pmc, main_clock);
 
 	/* Register the processor-specific clocks */
 	at91rm9200_register_clocks();
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 741a2b5..a9abb4b 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 
+#include <asm/proc-fns.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -279,6 +280,18 @@ static struct at91_gpio_bank at91sam9260_gpio[] = {
 	}
 };
 
+static void at91sam9260_idle(void)
+{
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9260_PMC;
+
+	/*
+	 * Disable the processor clock, and set the processor (CP15)
+	 * into 'Wait for Interrupt' mode.
+	 */
+	__raw_writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+	cpu_do_idle();
+}
+
 static void at91sam9260_poweroff(void)
 {
 	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -310,6 +323,8 @@ static void __init at91sam9xe_initialize(void)
 
 void __init at91sam9260_initialize(unsigned long main_clock)
 {
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9260_PMC;
+
 	/* Map peripherals */
 	iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc));
 
@@ -320,13 +335,14 @@ void __init at91sam9260_initialize(unsigned long main_clock)
 	else
 		iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
 
+	at91_arch_idle = at91sam9260_idle;
 	at91_arch_reset = at91sam9_alt_reset;
 	pm_power_off = at91sam9260_poweroff;
 	at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
 			| (1 << AT91SAM9260_ID_IRQ2);
 
 	/* Init clock subsystem */
-	at91_clock_init(main_clock);
+	at91_clock_init(pmc, main_clock);
 
 	/* Register the processor-specific clocks */
 	at91sam9260_register_clocks();
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index 192f983..3b66462 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 
+#include <asm/proc-fns.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -257,6 +258,18 @@ static struct at91_gpio_bank at91sam9261_gpio[] = {
 	}
 };
 
+static void at91sam9261_idle(void)
+{
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9261_PMC;
+
+	/*
+	 * Disable the processor clock, and set the processor (CP15)
+	 * into 'Wait for Interrupt' mode.
+	 */
+	__raw_writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+	cpu_do_idle();
+}
+
 static void at91sam9261_poweroff(void)
 {
 	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -269,6 +282,8 @@ static void at91sam9261_poweroff(void)
 
 void __init at91sam9261_initialize(unsigned long main_clock)
 {
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9261_PMC;
+
 	/* Map peripherals */
 	iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
 
@@ -277,14 +292,14 @@ void __init at91sam9261_initialize(unsigned long main_clock)
 	else
 		iotable_init(at91sam9261_sram_desc, ARRAY_SIZE(at91sam9261_sram_desc));
 
-
+	at91_arch_idle = at91sam9261_idle;
 	at91_arch_reset = at91sam9_alt_reset;
 	pm_power_off = at91sam9261_poweroff;
 	at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
 			| (1 << AT91SAM9261_ID_IRQ2);
 
 	/* Init clock subsystem */
-	at91_clock_init(main_clock);
+	at91_clock_init(pmc, main_clock);
 
 	/* Register the processor-specific clocks */
 	at91sam9261_register_clocks();
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index a9b3687..a6c72a6 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 
+#include <asm/proc-fns.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -269,6 +270,18 @@ static struct at91_gpio_bank at91sam9263_gpio[] = {
 	}
 };
 
+static void at91sam9263_idle(void)
+{
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9263_PMC;
+
+	/*
+	 * Disable the processor clock, and set the processor (CP15)
+	 * into 'Wait for Interrupt' mode.
+	 */
+	__raw_writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+	cpu_do_idle();
+}
+
 static void at91sam9263_poweroff(void)
 {
 	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -281,15 +294,18 @@ static void at91sam9263_poweroff(void)
 
 void __init at91sam9263_initialize(unsigned long main_clock)
 {
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9263_PMC;
+
 	/* Map peripherals */
 	iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
 
+	at91_arch_idle = at91sam9263_idle;
 	at91_arch_reset = at91sam9_alt_reset;
 	pm_power_off = at91sam9263_poweroff;
 	at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
 
 	/* Init clock subsystem */
-	at91_clock_init(main_clock);
+	at91_clock_init(pmc, main_clock);
 
 	/* Register the processor-specific clocks */
 	at91sam9263_register_clocks();
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 7342c9b..180dd26 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 
+#include <asm/proc-fns.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -291,6 +292,18 @@ static struct at91_gpio_bank at91sam9g45_gpio[] = {
 	}
 };
 
+static void at91sam9g45_idle(void)
+{
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9G45_PMC;
+
+	/*
+	 * Disable the processor clock, and set the processor (CP15)
+	 * into 'Wait for Interrupt' mode.
+	 */
+	__raw_writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+	cpu_do_idle();
+}
+
 static void at91sam9g45_reset(void)
 {
 	at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
@@ -308,15 +321,18 @@ static void at91sam9g45_poweroff(void)
 
 void __init at91sam9g45_initialize(unsigned long main_clock)
 {
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9G45_PMC;
+
 	/* Map peripherals */
 	iotable_init(at91sam9g45_io_desc, ARRAY_SIZE(at91sam9g45_io_desc));
 
+	at91_arch_idle = at91sam9g45_idle;
 	at91_arch_reset = at91sam9g45_reset;
 	pm_power_off = at91sam9g45_poweroff;
 	at91_extern_irq = (1 << AT91SAM9G45_ID_IRQ0);
 
 	/* Init clock subsystem */
-	at91_clock_init(main_clock);
+	at91_clock_init(pmc, main_clock);
 
 	/* Register the processor-specific clocks */
 	at91sam9g45_register_clocks();
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index cdd3eab..2c0029e 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 
+#include <asm/proc-fns.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -242,6 +243,18 @@ static struct at91_gpio_bank at91sam9rl_gpio[] = {
 	}
 };
 
+static void at91sam9rl_idle(void)
+{
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9RL_PMC;
+
+	/*
+	 * Disable the processor clock, and set the processor (CP15)
+	 * into 'Wait for Interrupt' mode.
+	 */
+	__raw_writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+	cpu_do_idle();
+}
+
 static void at91sam9rl_poweroff(void)
 {
 	at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -254,6 +267,7 @@ static void at91sam9rl_poweroff(void)
 
 void __init at91sam9rl_initialize(unsigned long main_clock)
 {
+	void __iomem* pmc = (void __iomem *)AT91_VA_BASE_SYS + AT91SAM9RL_PMC;
 	unsigned long sram_size;
 
 	/* Map peripherals */
@@ -274,12 +288,13 @@ void __init at91sam9rl_initialize(unsigned long main_clock)
 	/* Map SRAM */
 	iotable_init(at91sam9rl_sram_desc, ARRAY_SIZE(at91sam9rl_sram_desc));
 
+	at91_arch_idle = at91sam9rl_idle;
 	at91_arch_reset = at91sam9_alt_reset;
 	pm_power_off = at91sam9rl_poweroff;
 	at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0);
 
 	/* Init clock subsystem */
-	at91_clock_init(main_clock);
+	at91_clock_init(pmc, main_clock);
 
 	/* Register the processor-specific clocks */
 	at91sam9rl_register_clocks();
diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c
index 4cf8444..330bd0e 100644
--- a/arch/arm/mach-at91/at91x40.c
+++ b/arch/arm/mach-at91/at91x40.c
@@ -42,8 +42,20 @@ struct clk *clk_get(struct device *dev, const char *id)
 	return NULL;
 }
 
+static void at91x40_idle(void)
+{
+	void __iomem *ps = (void __iomem *)AT91_VA_BASE_SYS + AT91X40_PS;
+
+	/*
+	 * Disable the processor clock.  The processor will be automatically
+	 * re-enabled by an interrupt or by a reset.
+	 */
+	__raw_writel(AT91_PS_CR_CPU, ps + AT91_PS_CR);
+}
+
 void __init at91x40_initialize(unsigned long main_clock)
 {
+	at91_arch_idle = at91x40_idle;
 	at91_extern_irq = (1 << AT91X40_ID_IRQ0) | (1 << AT91X40_ID_IRQ1)
 			| (1 << AT91X40_ID_IRQ2);
 }
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index 9113da6..a624a23 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -68,6 +68,12 @@
 #define cpu_has_udpfs()		(!(cpu_is_at91sam9rl() \
 				|| cpu_is_at91sam9g45()))
 
+/* Base IO address of PMC */
+void __iomem *at91_pmc_base_addr __read_mostly;
+
+#define pmc_readl(reg)		__raw_readl(at91_pmc_base_addr + (reg))
+#define pmc_writel(reg, val)	__raw_writel((val), at91_pmc_base_addr + (reg))
+
 static LIST_HEAD(clocks);
 static DEFINE_SPINLOCK(clk_lock);
 
@@ -111,11 +117,11 @@ static void pllb_mode(struct clk *clk, int is_on)
 		value = 0;
 
 	// REVISIT: Add work-around for AT91RM9200 Errata #26 ?
-	at91_sys_write(AT91_CKGR_PLLBR, value);
+	pmc_writel(AT91_CKGR_PLLBR, value);
 
 	do {
 		cpu_relax();
-	} while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKB) != is_on);
+	} while ((pmc_readl(AT91_PMC_SR) & AT91_PMC_LOCKB) != is_on);
 }
 
 static struct clk pllb = {
@@ -130,14 +136,14 @@ static struct clk pllb = {
 static void pmc_sys_mode(struct clk *clk, int is_on)
 {
 	if (is_on)
-		at91_sys_write(AT91_PMC_SCER, clk->pmc_mask);
+		pmc_writel(AT91_PMC_SCER, clk->pmc_mask);
 	else
-		at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
+		pmc_writel(AT91_PMC_SCDR, clk->pmc_mask);
 }
 
 static void pmc_uckr_mode(struct clk *clk, int is_on)
 {
-	unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
+	unsigned int uckr = pmc_readl(AT91_CKGR_UCKR);
 
 	if (cpu_is_at91sam9g45()) {
 		if (is_on)
@@ -148,13 +154,13 @@ static void pmc_uckr_mode(struct clk *clk, int is_on)
 
 	if (is_on) {
 		is_on = AT91_PMC_LOCKU;
-		at91_sys_write(AT91_CKGR_UCKR, uckr | clk->pmc_mask);
+		pmc_writel(AT91_CKGR_UCKR, uckr | clk->pmc_mask);
 	} else
-		at91_sys_write(AT91_CKGR_UCKR, uckr & ~(clk->pmc_mask));
+		pmc_writel(AT91_CKGR_UCKR, uckr & ~(clk->pmc_mask));
 
 	do {
 		cpu_relax();
-	} while ((at91_sys_read(AT91_PMC_SR) & AT91_PMC_LOCKU) != is_on);
+	} while ((pmc_readl(AT91_PMC_SR) & AT91_PMC_LOCKU) != is_on);
 }
 
 /* USB function clocks (PLLB must be 48 MHz) */
@@ -190,9 +196,9 @@ static struct clk mck = {
 static void pmc_periph_mode(struct clk *clk, int is_on)
 {
 	if (is_on)
-		at91_sys_write(AT91_PMC_PCER, clk->pmc_mask);
+		pmc_writel(AT91_PMC_PCER, clk->pmc_mask);
 	else
-		at91_sys_write(AT91_PMC_PCDR, clk->pmc_mask);
+		pmc_writel(AT91_PMC_PCDR, clk->pmc_mask);
 }
 
 static struct clk __init *at91_css_to_clk(unsigned long css)
@@ -366,10 +372,10 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 		if (actual && actual <= rate) {
 			u32	pckr;
 
-			pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+			pckr = pmc_readl(AT91_PMC_PCKR(clk->id));
 			pckr &= AT91_PMC_CSS;	/* clock selection */
 			pckr |= prescale << 2;
-			at91_sys_write(AT91_PMC_PCKR(clk->id), pckr);
+			pmc_writel(AT91_PMC_PCKR(clk->id), pckr);
 			clk->rate_hz = actual;
 			break;
 		}
@@ -403,7 +409,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 
 	clk->rate_hz = parent->rate_hz;
 	clk->parent = parent;
-	at91_sys_write(AT91_PMC_PCKR(clk->id), parent->id);
+	pmc_writel(AT91_PMC_PCKR(clk->id), parent->id);
 
 	spin_unlock_irqrestore(&clk_lock, flags);
 	return 0;
@@ -416,7 +422,7 @@ static void __init init_programmable_clock(struct clk *clk)
 	struct clk	*parent;
 	u32		pckr;
 
-	pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
+	pckr = pmc_readl(AT91_PMC_PCKR(clk->id));
 	parent = at91_css_to_clk(pckr & AT91_PMC_CSS);
 	clk->parent = parent;
 	clk->rate_hz = parent->rate_hz / (1 << ((pckr & AT91_PMC_PRES) >> 2));
@@ -433,19 +439,19 @@ static int at91_clk_show(struct seq_file *s, void *unused)
 	u32		scsr, pcsr, uckr = 0, sr;
 	struct clk	*clk;
 
-	seq_printf(s, "SCSR = %8x\n", scsr = at91_sys_read(AT91_PMC_SCSR));
-	seq_printf(s, "PCSR = %8x\n", pcsr = at91_sys_read(AT91_PMC_PCSR));
-	seq_printf(s, "MOR  = %8x\n", at91_sys_read(AT91_CKGR_MOR));
-	seq_printf(s, "MCFR = %8x\n", at91_sys_read(AT91_CKGR_MCFR));
-	seq_printf(s, "PLLA = %8x\n", at91_sys_read(AT91_CKGR_PLLAR));
+	seq_printf(s, "SCSR = %8x\n", scsr = pmc_readl(AT91_PMC_SCSR));
+	seq_printf(s, "PCSR = %8x\n", pcsr = pmc_readl(AT91_PMC_PCSR));
+	seq_printf(s, "MOR  = %8x\n", pmc_readl(AT91_CKGR_MOR));
+	seq_printf(s, "MCFR = %8x\n", pmc_readl(AT91_CKGR_MCFR));
+	seq_printf(s, "PLLA = %8x\n", pmc_readl(AT91_CKGR_PLLAR));
 	if (cpu_has_pllb())
-		seq_printf(s, "PLLB = %8x\n", at91_sys_read(AT91_CKGR_PLLBR));
+		seq_printf(s, "PLLB = %8x\n", pmc_readl(AT91_CKGR_PLLBR));
 	if (cpu_has_utmi())
-		seq_printf(s, "UCKR = %8x\n", uckr = at91_sys_read(AT91_CKGR_UCKR));
-	seq_printf(s, "MCKR = %8x\n", at91_sys_read(AT91_PMC_MCKR));
+		seq_printf(s, "UCKR = %8x\n", uckr = pmc_readl(AT91_CKGR_UCKR));
+	seq_printf(s, "MCKR = %8x\n", pmc_readl(AT91_PMC_MCKR));
 	if (cpu_has_upll())
-		seq_printf(s, "USB  = %8x\n", at91_sys_read(AT91_PMC_USB));
-	seq_printf(s, "SR   = %8x\n", sr = at91_sys_read(AT91_PMC_SR));
+		seq_printf(s, "USB  = %8x\n", pmc_readl(AT91_PMC_USB));
+	seq_printf(s, "SR   = %8x\n", sr = pmc_readl(AT91_PMC_SR));
 
 	seq_printf(s, "\n");
 
@@ -495,6 +501,59 @@ postcore_initcall(at91_clk_debugfs_init);
 
 #endif
 
+
+/*------------------------------------------------------------------------*/
+
+/*
+ * Verify that all the clocks are correct before entering
+ * slow-clock mode.
+ */
+int at91_clocks_valid_for_suspend(void)
+{
+	unsigned long scsr;
+	int i;
+
+	scsr = pmc_readl(AT91_PMC_SCSR);
+
+	/* USB must not be using PLLB */
+	if (cpu_is_at91rm9200()) {
+		if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) {
+			pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
+			return 0;
+		}
+	} else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()
+			|| cpu_is_at91sam9g20() || cpu_is_at91sam9g10()) {
+		if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) {
+			pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
+			return 0;
+		}
+	} else if (cpu_is_at91cap9()) {
+		if ((scsr & AT91CAP9_PMC_UHP) != 0) {
+			pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
+			return 0;
+		}
+	}
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+	/* PCK0..PCK3 must be disabled, or configured to use clk32k */
+	for (i = 0; i < 4; i++) {
+		u32 css;
+
+		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
+			continue;
+
+		css = pmc_readl(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
+		if (css != AT91_PMC_CSS_SLOW) {
+			pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
+			return 0;
+		}
+	}
+#endif
+
+	return 1;
+}
+
+
 /*------------------------------------------------------------------------*/
 
 /* Register a new clock */
@@ -627,7 +686,7 @@ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock)
 	if (cpu_is_at91rm9200()) {
 		uhpck.pmc_mask = AT91RM9200_PMC_UHP;
 		udpck.pmc_mask = AT91RM9200_PMC_UDP;
-		at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
+		pmc_writel(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP);
 	} else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() ||
 		   cpu_is_at91sam9263() || cpu_is_at91sam9g20() ||
 		   cpu_is_at91sam9g10() || cpu_is_at572d940hf()) {
@@ -636,7 +695,7 @@ static void __init at91_pllb_usbfs_clock_init(unsigned long main_clock)
 	} else if (cpu_is_at91cap9()) {
 		uhpck.pmc_mask = AT91CAP9_PMC_UHP;
 	}
-	at91_sys_write(AT91_CKGR_PLLBR, 0);
+	pmc_writel(AT91_CKGR_PLLBR, 0);
 
 	udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
 	uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init);
@@ -653,21 +712,24 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
 	/* Setup divider by 10 to reach 48 MHz */
 	usbr |= ((10 - 1) << 8) & AT91_PMC_OHCIUSBDIV;
 
-	at91_sys_write(AT91_PMC_USB, usbr);
+	pmc_writel(AT91_PMC_USB, usbr);
 
 	/* Now set uhpck values */
 	uhpck.parent = &utmi_clk;
 	uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
 	uhpck.rate_hz = utmi_clk.rate_hz;
-	uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
+	uhpck.rate_hz /= 1 + ((pmc_readl(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
 }
 
-int __init at91_clock_init(unsigned long main_clock)
+int __init at91_clock_init(void __iomem *regbase, unsigned long main_clock)
 {
 	unsigned tmp, freq, mckr;
 	int i;
 	int pll_overclock = false;
 
+	/* Store base-address */
+	at91_pmc_base_addr = regbase;
+
 	/*
 	 * When the bootloader initialized the main oscillator correctly,
 	 * there's no problem using the cycle counter.  But if it didn't,
@@ -676,14 +738,14 @@ int __init at91_clock_init(unsigned long main_clock)
 	 */
 	if (!main_clock) {
 		do {
-			tmp = at91_sys_read(AT91_CKGR_MCFR);
+			tmp = pmc_readl(AT91_CKGR_MCFR);
 		} while (!(tmp & AT91_PMC_MAINRDY));
 		main_clock = (tmp & AT91_PMC_MAINF) * (AT91_SLOW_CLOCK / 16);
 	}
 	main_clk.rate_hz = 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));
+	plla.rate_hz = at91_pll_rate(&plla, main_clock, pmc_readl(AT91_CKGR_PLLAR));
 	if (cpu_has_300M_plla()) {
 		if (plla.rate_hz > 300000000)
 			pll_overclock = true;
@@ -698,7 +760,7 @@ int __init at91_clock_init(unsigned long main_clock)
 		pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000);
 
 	if (cpu_is_at91sam9g45()) {
-		mckr = at91_sys_read(AT91_PMC_MCKR);
+		mckr = pmc_readl(AT91_PMC_MCKR);
 		plla.rate_hz /= (1 << ((mckr & AT91_PMC_PLLADIV2) >> 12));	/* plla divisor by 2 */
 	}
 
@@ -709,7 +771,6 @@ int __init at91_clock_init(unsigned long main_clock)
 		utmi_clk.id = 3;
 	}
 
-
 	/*
 	 * USB HS clock init
 	 */
@@ -734,7 +795,7 @@ int __init at91_clock_init(unsigned long main_clock)
 	 * MCK and CPU derive from one of those primary clocks.
 	 * For now, assume this parentage won't change.
 	 */
-	mckr = at91_sys_read(AT91_PMC_MCKR);
+	mckr = pmc_readl(AT91_PMC_MCKR);
 	mck.parent = at91_css_to_clk(mckr & AT91_PMC_CSS);
 	freq = mck.parent->rate_hz;
 	freq /= (1 << ((mckr & AT91_PMC_PRES) >> 2));				/* prescale */
@@ -801,8 +862,8 @@ static int __init at91_clock_reset(void)
 		pr_debug("Clocks: disable unused %s\n", clk->name);
 	}
 
-	at91_sys_write(AT91_PMC_PCDR, pcdr);
-	at91_sys_write(AT91_PMC_SCDR, scdr);
+	pmc_writel(AT91_PMC_PCDR, pcdr);
+	pmc_writel(AT91_PMC_SCDR, scdr);
 
 	return 0;
 }
diff --git a/arch/arm/mach-at91/clock.h b/arch/arm/mach-at91/clock.h
index 6cf4b78..e929ffc 100644
--- a/arch/arm/mach-at91/clock.h
+++ b/arch/arm/mach-at91/clock.h
@@ -29,3 +29,4 @@ struct clk {
 
 
 extern int __init clk_register(struct clk *clk);
+extern int at91_clocks_valid_for_suspend(void);
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index f00ad37..2bd94d8 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -38,7 +38,7 @@ extern struct sys_timer at91sam926x_timer;
 extern struct sys_timer at91x40_timer;
 
  /* Clocks */
-extern int __init at91_clock_init(unsigned long main_clock);
+extern int __init at91_clock_init(void __iomem* regbase, unsigned long main_clock);
 struct device;
 extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func);
 
@@ -61,5 +61,6 @@ struct at91_gpio_bank {
 extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks);
 extern void __init at91_gpio_irq_setup(void);
 
+extern void (*at91_arch_idle)(void);
 extern void (*at91_arch_reset)(void);
 extern int at91_extern_irq;
diff --git a/arch/arm/mach-at91/include/mach/at572d940hf.h b/arch/arm/mach-at91/include/mach/at572d940hf.h
index c258e4d..c31a8e2 100644
--- a/arch/arm/mach-at91/include/mach/at572d940hf.h
+++ b/arch/arm/mach-at91/include/mach/at572d940hf.h
@@ -97,7 +97,7 @@
 #define AT572D940HF_PIOA	(0xfffff400 - AT91_BASE_SYS)
 #define AT572D940HF_PIOB	(0xfffff600 - AT91_BASE_SYS)
 #define AT572D940HF_PIOC	(0xfffff800 - AT91_BASE_SYS)
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT572D940HF_PMC		(0xfffffc00 - AT91_BASE_SYS)
 #define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
 #define AT572D940HF_RTT		(0xfffffd20 - AT91_BASE_SYS)
 #define AT91_PIT	(0xfffffd30 - AT91_BASE_SYS)
diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h
index ba429f7..7d5926e 100644
--- a/arch/arm/mach-at91/include/mach/at91_pmc.h
+++ b/arch/arm/mach-at91/include/mach/at91_pmc.h
@@ -16,10 +16,10 @@
 #ifndef AT91_PMC_H
 #define AT91_PMC_H
 
-#define	AT91_PMC_SCER		(AT91_PMC + 0x00)	/* System Clock Enable Register */
-#define	AT91_PMC_SCDR		(AT91_PMC + 0x04)	/* System Clock Disable Register */
+#define	AT91_PMC_SCER		0x00			/* System Clock Enable Register */
+#define	AT91_PMC_SCDR		0x04			/* System Clock Disable Register */
 
-#define	AT91_PMC_SCSR		(AT91_PMC + 0x08)	/* System Clock Status Register */
+#define	AT91_PMC_SCSR		0x08			/* System Clock Status Register */
 #define		AT91_PMC_PCK		(1 <<  0)		/* Processor Clock */
 #define		AT91RM9200_PMC_UDP	(1 <<  1)		/* USB Devcice Port Clock [AT91RM9200 only] */
 #define		AT91RM9200_PMC_MCKUDP	(1 <<  2)		/* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
@@ -36,27 +36,27 @@
 #define		AT91_PMC_HCK0		(1 << 16)		/* AHB Clock (USB host) [AT91SAM9261 only] */
 #define		AT91_PMC_HCK1		(1 << 17)		/* AHB Clock (LCD) [AT91SAM9261 only] */
 
-#define	AT91_PMC_PCER		(AT91_PMC + 0x10)	/* Peripheral Clock Enable Register */
-#define	AT91_PMC_PCDR		(AT91_PMC + 0x14)	/* Peripheral Clock Disable Register */
-#define	AT91_PMC_PCSR		(AT91_PMC + 0x18)	/* Peripheral Clock Status Register */
+#define	AT91_PMC_PCER		0x10			/* Peripheral Clock Enable Register */
+#define	AT91_PMC_PCDR		0x14			/* Peripheral Clock Disable Register */
+#define	AT91_PMC_PCSR		0x18			/* Peripheral Clock Status Register */
 
-#define	AT91_CKGR_UCKR		(AT91_PMC + 0x1C)	/* UTMI Clock Register [some SAM9, CAP9] */
+#define	AT91_CKGR_UCKR		0x1C			/* UTMI Clock Register [some SAM9, CAP9] */
 #define		AT91_PMC_UPLLEN		(1   << 16)		/* UTMI PLL Enable */
 #define		AT91_PMC_UPLLCOUNT	(0xf << 20)		/* UTMI PLL Start-up Time */
 #define		AT91_PMC_BIASEN		(1   << 24)		/* UTMI BIAS Enable */
 #define		AT91_PMC_BIASCOUNT	(0xf << 28)		/* UTMI BIAS Start-up Time */
 
-#define	AT91_CKGR_MOR		(AT91_PMC + 0x20)	/* Main Oscillator Register [not on SAM9RL] */
+#define	AT91_CKGR_MOR		0x20			/* Main Oscillator Register [not on SAM9RL] */
 #define		AT91_PMC_MOSCEN		(1    << 0)		/* Main Oscillator Enable */
 #define		AT91_PMC_OSCBYPASS	(1    << 1)		/* Oscillator Bypass [SAM9x, CAP9] */
 #define		AT91_PMC_OSCOUNT	(0xff << 8)		/* Main Oscillator Start-up Time */
 
-#define	AT91_CKGR_MCFR		(AT91_PMC + 0x24)	/* Main Clock Frequency Register */
+#define	AT91_CKGR_MCFR		0x24			/* Main Clock Frequency Register */
 #define		AT91_PMC_MAINF		(0xffff <<  0)		/* Main Clock Frequency */
 #define		AT91_PMC_MAINRDY	(1	<< 16)		/* Main Clock Ready */
 
-#define	AT91_CKGR_PLLAR		(AT91_PMC + 0x28)	/* PLL A Register */
-#define	AT91_CKGR_PLLBR		(AT91_PMC + 0x2c)	/* PLL B Register */
+#define	AT91_CKGR_PLLAR		0x28			/* PLL A Register */
+#define	AT91_CKGR_PLLBR		0x2c			/* PLL B Register */
 #define		AT91_PMC_DIV		(0xff  <<  0)		/* Divider */
 #define		AT91_PMC_PLLCOUNT	(0x3f  <<  8)		/* PLL Counter */
 #define		AT91_PMC_OUT		(3     << 14)		/* PLL Clock Frequency Range */
@@ -67,7 +67,7 @@
 #define			AT91_PMC_USBDIV_4		(2 << 28)
 #define		AT91_PMC_USB96M		(1     << 28)		/* Divider by 2 Enable (PLLB only) */
 
-#define	AT91_PMC_MCKR		(AT91_PMC + 0x30)	/* Master Clock Register */
+#define	AT91_PMC_MCKR		0x30			/* Master Clock Register */
 #define		AT91_PMC_CSS		(3 <<  0)		/* Master Clock Selection */
 #define			AT91_PMC_CSS_SLOW		(0 << 0)
 #define			AT91_PMC_CSS_MAIN		(1 << 0)
@@ -99,20 +99,20 @@
 #define			AT91_PMC_PLLADIV2_OFF		(0 << 12)
 #define			AT91_PMC_PLLADIV2_ON		(1 << 12)
 
-#define	AT91_PMC_USB		(AT91_PMC + 0x38)	/* USB Clock Register [some SAM9 only] */
+#define	AT91_PMC_USB		0x38			/* USB Clock Register [some SAM9 only] */
 #define		AT91_PMC_USBS		(0x1 <<  0)		/* USB OHCI Input clock selection */
 #define			AT91_PMC_USBS_PLLA		(0 << 0)
 #define			AT91_PMC_USBS_UPLL		(1 << 0)
 #define		AT91_PMC_OHCIUSBDIV	(0xF <<  8)		/* Divider for USB OHCI Clock */
 
-#define	AT91_PMC_PCKR(n)	(AT91_PMC + 0x40 + ((n) * 4))	/* Programmable Clock 0-N Registers */
+#define	AT91_PMC_PCKR(n)	(0x40 + ((n) * 4))	/* Programmable Clock 0-N Registers */
 #define		AT91_PMC_CSSMCK		(0x1 <<  8)		/* CSS or Master Clock Selection */
 #define			AT91_PMC_CSSMCK_CSS		(0 << 8)
 #define			AT91_PMC_CSSMCK_MCK		(1 << 8)
 
-#define	AT91_PMC_IER		(AT91_PMC + 0x60)	/* Interrupt Enable Register */
-#define	AT91_PMC_IDR		(AT91_PMC + 0x64)	/* Interrupt Disable Register */
-#define	AT91_PMC_SR		(AT91_PMC + 0x68)	/* Status Register */
+#define	AT91_PMC_IER		0x60			/* Interrupt Enable Register */
+#define	AT91_PMC_IDR		0x64			/* Interrupt Disable Register */
+#define	AT91_PMC_SR		0x68			/* Status Register */
 #define		AT91_PMC_MOSCS		(1 <<  0)		/* MOSCS Flag */
 #define		AT91_PMC_LOCKA		(1 <<  1)		/* PLLA Lock */
 #define		AT91_PMC_LOCKB		(1 <<  2)		/* PLLB Lock */
@@ -123,11 +123,11 @@
 #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_IMR		(AT91_PMC + 0x6c)	/* Interrupt Mask Register */
+#define	AT91_PMC_IMR		0x6c			/* Interrupt Mask Register */
 
-#define AT91_PMC_PROT		(AT91_PMC + 0xe4)	/* Protect Register [AT91CAP9 revC only] */
+#define AT91_PMC_PROT		0xe4			/* Protect Register [AT91CAP9 revC only] */
 #define		AT91_PMC_PROTKEY	0x504d4301		/* Activation Code */
 
-#define AT91_PMC_VER		(AT91_PMC + 0xfc)	/* PMC Module Version [AT91CAP9 only] */
+#define AT91_PMC_VER		0xfc			/* PMC Module Version [AT91CAP9 only] */
 
 #endif
diff --git a/arch/arm/mach-at91/include/mach/at91cap9.h b/arch/arm/mach-at91/include/mach/at91cap9.h
index 3f9b00c..1128dcf 100644
--- a/arch/arm/mach-at91/include/mach/at91cap9.h
+++ b/arch/arm/mach-at91/include/mach/at91cap9.h
@@ -95,7 +95,7 @@
 #define AT91CAP9_PIOB	(0xfffff400 - AT91_BASE_SYS)
 #define AT91CAP9_PIOC	(0xfffff600 - AT91_BASE_SYS)
 #define AT91CAP9_PIOD	(0xfffff800 - AT91_BASE_SYS)
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT91CAP9_PMC	(0xfffffc00 - AT91_BASE_SYS)
 #define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
 #define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
 #define AT91CAP9_RTT	(0xfffffd20 - AT91_BASE_SYS)
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200.h b/arch/arm/mach-at91/include/mach/at91rm9200.h
index 0da806f..ef01000 100644
--- a/arch/arm/mach-at91/include/mach/at91rm9200.h
+++ b/arch/arm/mach-at91/include/mach/at91rm9200.h
@@ -88,7 +88,7 @@
 #define AT91RM9200_PIOB	(0xfffff600 - AT91_BASE_SYS)	/* PIO Controller B */
 #define AT91RM9200_PIOC	(0xfffff800 - AT91_BASE_SYS)	/* PIO Controller C */
 #define AT91RM9200_PIOD	(0xfffffa00 - AT91_BASE_SYS)	/* PIO Controller D */
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)	/* Power Management Controller */
+#define AT91RM9200_PMC	(0xfffffc00 - AT91_BASE_SYS)	/* Power Management Controller */
 #define AT91_ST		(0xfffffd00 - AT91_BASE_SYS)	/* System Timer */
 #define AT91RM9200_RTC	(0xfffffe00 - AT91_BASE_SYS)	/* Real-Time Clock */
 #define AT91_MC		(0xffffff00 - AT91_BASE_SYS)	/* Memory Controllers */
diff --git a/arch/arm/mach-at91/include/mach/at91sam9260.h b/arch/arm/mach-at91/include/mach/at91sam9260.h
index c37b67e..65cd119 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9260.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9260.h
@@ -93,7 +93,7 @@
 #define AT91SAM9260_PIOA	(0xfffff400 - AT91_BASE_SYS)
 #define AT91SAM9260_PIOB	(0xfffff600 - AT91_BASE_SYS)
 #define AT91SAM9260_PIOC	(0xfffff800 - AT91_BASE_SYS)
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT91SAM9260_PMC		(0xfffffc00 - AT91_BASE_SYS)
 #define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
 #define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
 #define AT91SAM9260_RTT		(0xfffffd20 - AT91_BASE_SYS)
diff --git a/arch/arm/mach-at91/include/mach/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h
index aebd964..5807d0e 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9261.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9261.h
@@ -76,7 +76,7 @@
 #define AT91SAM9261_PIOA	(0xfffff400 - AT91_BASE_SYS)
 #define AT91SAM9261_PIOB	(0xfffff600 - AT91_BASE_SYS)
 #define AT91SAM9261_PIOC	(0xfffff800 - AT91_BASE_SYS)
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT91SAM9261_PMC		(0xfffffc00 - AT91_BASE_SYS)
 #define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
 #define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
 #define AT91SAM9261_RTT		(0xfffffd20 - AT91_BASE_SYS)
diff --git a/arch/arm/mach-at91/include/mach/at91sam9263.h b/arch/arm/mach-at91/include/mach/at91sam9263.h
index df10b7e..9d5ed94 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9263.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9263.h
@@ -92,7 +92,7 @@
 #define AT91SAM9263_PIOC	(0xfffff600 - AT91_BASE_SYS)
 #define AT91SAM9263_PIOD	(0xfffff800 - AT91_BASE_SYS)
 #define AT91SAM9263_PIOE	(0xfffffa00 - AT91_BASE_SYS)
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT91SAM9263_PMC		(0xfffffc00 - AT91_BASE_SYS)
 #define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
 #define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
 #define AT91SAM9263_RTT0	(0xfffffd20 - AT91_BASE_SYS)
diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
index 22fb598..10c492c 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9g45.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h
@@ -102,7 +102,7 @@
 #define AT91SAM9G45_PIOC	(0xfffff600 - AT91_BASE_SYS)
 #define AT91SAM9G45_PIOD	(0xfffff800 - AT91_BASE_SYS)
 #define AT91SAM9G45_PIOE	(0xfffffa00 - AT91_BASE_SYS)
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT91SAM9G45_PMC		(0xfffffc00 - AT91_BASE_SYS)
 #define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
 #define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
 #define AT91SAM9G45_RTT		(0xfffffd20 - AT91_BASE_SYS)
diff --git a/arch/arm/mach-at91/include/mach/at91sam9rl.h b/arch/arm/mach-at91/include/mach/at91sam9rl.h
index 7920d96..337a84a 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9rl.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9rl.h
@@ -84,7 +84,7 @@
 #define AT91SAM9RL_PIOB		(0xfffff600 - AT91_BASE_SYS)
 #define AT91SAM9RL_PIOC		(0xfffff800 - AT91_BASE_SYS)
 #define AT91SAM9RL_PIOD		(0xfffffa00 - AT91_BASE_SYS)
-#define AT91_PMC	(0xfffffc00 - AT91_BASE_SYS)
+#define AT91SAM9RL_PMC		(0xfffffc00 - AT91_BASE_SYS)
 #define AT91_RSTC	(0xfffffd00 - AT91_BASE_SYS)
 #define AT91_SHDWC	(0xfffffd10 - AT91_BASE_SYS)
 #define AT91SAM9RL_RTT		(0xfffffd20 - AT91_BASE_SYS)
diff --git a/arch/arm/mach-at91/include/mach/at91x40.h b/arch/arm/mach-at91/include/mach/at91x40.h
index 07e4f6e..92cbb6b 100644
--- a/arch/arm/mach-at91/include/mach/at91x40.h
+++ b/arch/arm/mach-at91/include/mach/at91x40.h
@@ -36,14 +36,17 @@
 
 #define AT91_EBI	(0xffe00000 - AT91_BASE_SYS)	/* External Bus Interface */
 #define AT91X40_SF	(0xfff00000 - AT91_BASE_SYS)	/* Special Function */
-#define AT91_USART1	(0xfffcc000 - AT91_BASE_SYS)	/* USART 1 */
-#define AT91_USART0	(0xfffd0000 - AT91_BASE_SYS)	/* USART 0 */
+#define AT91X40_USART1	(0xfffcc000 - AT91_BASE_SYS)	/* USART 1 */
+#define AT91X40_USART0	(0xfffd0000 - AT91_BASE_SYS)	/* USART 0 */
 #define AT91_TC		(0xfffe0000 - AT91_BASE_SYS)	/* Timer Counter */
 #define AT91X40_PIOA	(0xffff0000 - AT91_BASE_SYS)	/* PIO Controller A */
 #define AT91X40_PS	(0xffff4000 - AT91_BASE_SYS)	/* Power Save */
 #define AT91X40_WD	(0xffff8000 - AT91_BASE_SYS)	/* Watchdog Timer */
 #define AT91X40_AIC	(0xfffff000 - AT91_BASE_SYS)	/* Advanced Interrupt Controller */
 
+#define AT91_USART0	AT91X40_USART0
+#define AT91_USART1	AT91X40_USART1
+
 /*
  * The AT91x40 series doesn't have a debug unit like the other AT91 parts.
  * But it does have a chip identify register and extension ID, so define at
@@ -56,7 +59,7 @@
 /*
  * Support defines for the simple Power Controller module.
  */
-#define	AT91_PS_CR	(AT91X40_PS + 0)	/* PS Control register */
+#define	AT91_PS_CR	(0x00)			/* PS Control register */
 #define	AT91_PS_CR_CPU		(1 << 0)		/* CPU clock disable bit */
 
 #endif /* AT91X40_H */
diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h
index 521d8ed..90bba33 100644
--- a/arch/arm/mach-at91/include/mach/cpu.h
+++ b/arch/arm/mach-at91/include/mach/cpu.h
@@ -83,7 +83,7 @@ static inline unsigned long at91_sram_size(void)
 
 static inline unsigned long at91cap9_rev_identify(void)
 {
-	return (at91_sys_read(AT91_PMC_VER));
+	return (at91_sys_read(AT91CAP9_PMC + AT91_PMC_VER));
 }
 #endif
 
diff --git a/arch/arm/mach-at91/include/mach/system.h b/arch/arm/mach-at91/include/mach/system.h
index 44dc3f7..3acd2d2 100644
--- a/arch/arm/mach-at91/include/mach/system.h
+++ b/arch/arm/mach-at91/include/mach/system.h
@@ -22,29 +22,14 @@
 #define __ASM_ARCH_SYSTEM_H
 
 #include <mach/hardware.h>
-#include <mach/at91_st.h>
-#include <mach/at91_dbgu.h>
-#include <mach/at91_pmc.h>
+
+void (*at91_arch_idle)(void);
 
 static inline void arch_idle(void)
 {
-	/*
-	 * Disable the processor clock.  The processor will be automatically
-	 * re-enabled by an interrupt or by a reset.
-	 */
-#ifdef AT91X40_PS
-	at91_sys_write(AT91X40_PS_CR, AT91_PS_CR_CPU);
-#else
-	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK);
-#endif
-#ifndef CONFIG_CPU_ARM920T
-	/*
-	 * Set the processor (CP15) into 'Wait for Interrupt' mode.
-	 * Post-RM9200 processors need this in conjunction with the above
-	 * to save power when idle.
-	 */
-	cpu_do_idle();
-#endif
+	/* call the CPU-specific idle function */
+	if (at91_arch_idle)
+		(at91_arch_idle)();
 }
 
 void (*at91_arch_reset)(void);
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 852c417..544a18f 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -29,6 +29,7 @@
 #include <mach/cpu.h>
 
 #include "generic.h"
+#include "clock.h"
 #include "pm.h"
 
 /*
@@ -130,55 +131,6 @@ static int at91_pm_begin(suspend_state_t state)
 }
 
 /*
- * Verify that all the clocks are correct before entering
- * slow-clock mode.
- */
-static int at91_pm_verify_clocks(void)
-{
-	unsigned long scsr;
-	int i;
-
-	scsr = at91_sys_read(AT91_PMC_SCSR);
-
-	/* USB must not be using PLLB */
-	if (cpu_is_at91rm9200()) {
-		if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) {
-			pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
-			return 0;
-		}
-	} else if (cpu_is_at91sam9260() || cpu_is_at91sam9261() || cpu_is_at91sam9263()
-			|| cpu_is_at91sam9g20() || cpu_is_at91sam9g10()) {
-		if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) {
-			pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
-			return 0;
-		}
-	} else if (cpu_is_at91cap9()) {
-		if ((scsr & AT91CAP9_PMC_UHP) != 0) {
-			pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
-			return 0;
-		}
-	}
-
-#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
-	/* PCK0..PCK3 must be disabled, or configured to use clk32k */
-	for (i = 0; i < 4; i++) {
-		u32 css;
-
-		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
-			continue;
-
-		css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
-		if (css != AT91_PMC_CSS_SLOW) {
-			pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
-			return 0;
-		}
-	}
-#endif
-
-	return 1;
-}
-
-/*
  * Call this from platform driver suspend() to see how deeply to suspend.
  * For example, some controllers (like OHCI) need one of the PLL clocks
  * in order to act as a wakeup source, and those are not available when
@@ -228,7 +180,7 @@ static int at91_pm_enter(suspend_state_t state)
 			/*
 			 * Ensure that clocks are in a valid state.
 			 */
-			if (!at91_pm_verify_clocks())
+			if (!at91_clocks_valid_for_suspend())
 				goto error;
 
 			/*
diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S
index f7922a4..467ae53 100644
--- a/arch/arm/mach-at91/pm_slowclock.S
+++ b/arch/arm/mach-at91/pm_slowclock.S
@@ -57,7 +57,7 @@
 1:	sub	r4, r4, #1
 	cmp	r4, #0
 	beq	2f
-	ldr	r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
+	ldr	r3, [r1, #(AT91_PMC_SR)]
 	tst	r3, #AT91_PMC_MCKRDY
 	beq	1b
 2:
@@ -71,7 +71,7 @@
 1:	sub	r4, r4, #1
 	cmp	r4, #0
 	beq	2f
-	ldr	r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
+	ldr	r3, [r1, #(AT91_PMC_SR)]
 	tst	r3, #AT91_PMC_MOSCS
 	beq	1b
 2:
@@ -85,7 +85,7 @@
 1:	sub	r4, r4, #1
 	cmp	r4, #0
 	beq	2f
-	ldr	r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
+	ldr	r3, [r1, #(AT91_PMC_SR)]
 	tst	r3, #AT91_PMC_LOCKA
 	beq	1b
 2:
@@ -99,7 +99,7 @@
 1:	sub	r4, r4, #1
 	cmp	r4, #0
 	beq	2f
-	ldr	r3, [r1, #(AT91_PMC_SR - AT91_PMC)]
+	ldr	r3, [r1, #(AT91_PMC_SR)]
 	tst	r3, #AT91_PMC_LOCKB
 	beq	1b
 2:
@@ -119,7 +119,8 @@ ENTRY(at91_slow_clock)
 	 *  R4 = temporary register
 	 *  R5 = Base address of second RAM Controller or 0 if not present
 	 */
-	ldr	r1, .at91_va_base_pmc
+	ldr	r1, =at91_pmc_base_addr
+	ldr	r1, [r1]
 	ldr	r2, .at91_va_base_sdramc
 	ldr	r5, .at91_va_base_ramc1
 
@@ -161,14 +162,14 @@ ENTRY(at91_slow_clock)
 #endif
 
 	/* Save Master clock setting */
-	ldr	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
+	ldr	r3, [r1, #(AT91_PMC_MCKR)]
 	str	r3, .saved_mckr
 
 	/*
 	 * Set the Master clock source to slow clock
 	 */
 	bic	r3, r3, #AT91_PMC_CSS
-	str	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
+	str	r3, [r1, #(AT91_PMC_MCKR)]
 
 	wait_mckrdy
 
@@ -179,44 +180,44 @@ ENTRY(at91_slow_clock)
 	 * See AT91RM9200 errata #27 and #28 for details.
 	 */
 	mov	r3, #0
-	str	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
+	str	r3, [r1, #(AT91_PMC_MCKR)]
 
 	wait_mckrdy
 #endif
 
 	/* Save PLLA setting and disable it */
-	ldr	r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
+	ldr	r3, [r1, #(AT91_CKGR_PLLAR)]
 	str	r3, .saved_pllar
 
 	mov	r3, #AT91_PMC_PLLCOUNT
 	orr	r3, r3, #(1 << 29)		/* bit 29 always set */
-	str	r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
+	str	r3, [r1, #(AT91_CKGR_PLLAR)]
 
 	/* Save PLLB setting and disable it */
-	ldr	r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
+	ldr	r3, [r1, #(AT91_CKGR_PLLBR)]
 	str	r3, .saved_pllbr
 
 	mov	r3, #AT91_PMC_PLLCOUNT
-	str	r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
+	str	r3, [r1, #(AT91_CKGR_PLLBR)]
 
 	/* Turn off the main oscillator */
-	ldr	r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
+	ldr	r3, [r1, #(AT91_CKGR_MOR)]
 	bic	r3, r3, #AT91_PMC_MOSCEN
-	str	r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
+	str	r3, [r1, #(AT91_CKGR_MOR)]
 
 	/* Wait for interrupt */
 	mcr	p15, 0, r0, c7, c0, 4
 
 	/* Turn on the main oscillator */
-	ldr	r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
+	ldr	r3, [r1, #(AT91_CKGR_MOR)]
 	orr	r3, r3, #AT91_PMC_MOSCEN
-	str	r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
+	str	r3, [r1, #(AT91_CKGR_MOR)]
 
 	wait_moscrdy
 
 	/* Restore PLLB setting */
 	ldr	r3, .saved_pllbr
-	str	r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
+	str	r3, [r1, #(AT91_CKGR_PLLBR)]
 
 	tst	r3, #(AT91_PMC_MUL &  0xff0000)
 	bne	1f
@@ -228,7 +229,7 @@ ENTRY(at91_slow_clock)
 
 	/* Restore PLLA setting */
 	ldr	r3, .saved_pllar
-	str	r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
+	str	r3, [r1, #(AT91_CKGR_PLLAR)]
 
 	tst	r3, #(AT91_PMC_MUL &  0xff0000)
 	bne	3f
@@ -249,7 +250,7 @@ ENTRY(at91_slow_clock)
 	tst	r3, #AT91_PMC_PRES
 	beq	2f
 	and	r3, r3, #AT91_PMC_PRES
-	str	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
+	str	r3, [r1, #(AT91_PMC_MCKR)]
 
 	wait_mckrdy
 #endif
@@ -258,7 +259,7 @@ ENTRY(at91_slow_clock)
 	 * Restore master clock setting
 	 */
 2:	ldr	r3, .saved_mckr
-	str	r3, [r1, #(AT91_PMC_MCKR - AT91_PMC)]
+	str	r3, [r1, #(AT91_PMC_MCKR)]
 
 	wait_mckrdy
 
@@ -300,9 +301,6 @@ ENTRY(at91_slow_clock)
 .saved_sam9_lpr1:
 	.word 0
 
-.at91_va_base_pmc:
-	.word AT91_VA_BASE_SYS + AT91_PMC
-
 #ifdef CONFIG_ARCH_AT91RM9200
 .at91_va_base_sdramc:
 	.word AT91_VA_BASE_SYS
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index e7c65a4..c137b99 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -332,12 +332,12 @@ static int vbus_is_present(struct usba_udc *udc)
 
 static void toggle_bias(int is_on)
 {
-	unsigned int uckr = at91_sys_read(AT91_CKGR_UCKR);
+	unsigned int uckr = at91_sys_read(AT91SAM9RL_PMC + AT91_CKGR_UCKR);
 
 	if (is_on)
-		at91_sys_write(AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
+		at91_sys_write(AT91SAM9RL_PMC + AT91_CKGR_UCKR, uckr | AT91_PMC_BIASEN);
 	else
-		at91_sys_write(AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
+		at91_sys_write(AT91SAM9RL_PMC + AT91_CKGR_UCKR, uckr & ~(AT91_PMC_BIASEN));
 }
 
 #else





More information about the linux-arm-kernel mailing list