ARM: atmel: switch to main crystal osc for SPL boot

If without switch to main crystal oscillator, the sama5d3 SoC will
use internal on chip RC oscillator.
In order to get better accuracy, switch to main crystal oscillator.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
Signed-off-by: Andreas Bießmann <andreas.devel@googlemail.com>
diff --git a/arch/arm/cpu/at91-common/spl.c b/arch/arm/cpu/at91-common/spl.c
index 7f4debb..cbb5a52 100644
--- a/arch/arm/cpu/at91-common/spl.c
+++ b/arch/arm/cpu/at91-common/spl.c
@@ -20,6 +20,43 @@
 	writel(AT91_WDT_MR_WDDIS, &wdt->mr);
 }
 
+static void switch_to_main_crystal_osc(void)
+{
+	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+	u32 tmp;
+
+	tmp = readl(&pmc->mor);
+	tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff);
+	tmp &= ~AT91_PMC_MOR_KEY(0xff);
+	tmp |= AT91_PMC_MOR_MOSCEN;
+	tmp |= AT91_PMC_MOR_OSCOUNT(8);
+	tmp |= AT91_PMC_MOR_KEY(0x37);
+	writel(tmp, &pmc->mor);
+	while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS))
+		;
+
+	tmp = readl(&pmc->mor);
+	tmp &= ~AT91_PMC_MOR_OSCBYPASS;
+	tmp &= ~AT91_PMC_MOR_KEY(0xff);
+	tmp |= AT91_PMC_MOR_KEY(0x37);
+	writel(tmp, &pmc->mor);
+
+	tmp = readl(&pmc->mor);
+	tmp |= AT91_PMC_MOR_MOSCSEL;
+	tmp &= ~AT91_PMC_MOR_KEY(0xff);
+	tmp |= AT91_PMC_MOR_KEY(0x37);
+	writel(tmp, &pmc->mor);
+
+	while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS))
+		;
+
+	tmp = readl(&pmc->mor);
+	tmp &= ~AT91_PMC_MOR_MOSCRCEN;
+	tmp &= ~AT91_PMC_MOR_KEY(0xff);
+	tmp |= AT91_PMC_MOR_KEY(0x37);
+	writel(tmp, &pmc->mor);
+}
+
 void at91_plla_init(u32 pllar)
 {
 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
@@ -76,6 +113,8 @@
 
 void s_init(void)
 {
+	switch_to_main_crystal_osc();
+
 	/* disable watchdog */
 	at91_disable_wdt();