1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2014 DENX Software Engineering
4  *     Heiko Schocher <hs@denx.de>
5  *
6  * Based on:
7  * Copyright (C) 2013 Atmel Corporation
8  *		      Bo Shen <voice.shen@atmel.com>
9  */
10 
11 #include <common.h>
12 #include <hang.h>
13 #include <init.h>
14 #include <log.h>
15 #include <asm/global_data.h>
16 #include <asm/io.h>
17 #include <asm/arch/at91_common.h>
18 #include <asm/arch/at91sam9_matrix.h>
19 #include <asm/arch/at91_pit.h>
20 #include <asm/arch/at91_rstc.h>
21 #include <asm/arch/at91_wdt.h>
22 #include <asm/arch/clk.h>
23 #include <spl.h>
24 
25 DECLARE_GLOBAL_DATA_PTR;
26 
enable_ext_reset(void)27 static void enable_ext_reset(void)
28 {
29 	struct at91_rstc *rstc = (struct at91_rstc *)ATMEL_BASE_RSTC;
30 
31 	writel(AT91_RSTC_KEY | AT91_RSTC_MR_URSTEN, &rstc->mr);
32 }
33 
lowlevel_clock_init(void)34 void lowlevel_clock_init(void)
35 {
36 	struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
37 
38 	if (!(readl(&pmc->sr) & AT91_PMC_MOSCS)) {
39 		/* Enable Main Oscillator */
40 		writel(AT91_PMC_MOSCS | (0x40 << 8), &pmc->mor);
41 
42 		/* Wait until Main Oscillator is stable */
43 		while (!(readl(&pmc->sr) & AT91_PMC_MOSCS))
44 			;
45 	}
46 
47 	/* After stabilization, switch to Main Oscillator */
48 	if ((readl(&pmc->mckr) & AT91_PMC_CSS) == AT91_PMC_CSS_SLOW) {
49 		unsigned long tmp;
50 
51 		tmp = readl(&pmc->mckr);
52 		tmp &= ~AT91_PMC_CSS;
53 		tmp |= AT91_PMC_CSS_MAIN;
54 		writel(tmp, &pmc->mckr);
55 		while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
56 			;
57 
58 		tmp &= ~AT91_PMC_PRES;
59 		tmp |= AT91_PMC_PRES_1;
60 		writel(tmp, &pmc->mckr);
61 		while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY))
62 			;
63 	}
64 
65 	return;
66 }
67 
matrix_init(void)68 void __weak matrix_init(void)
69 {
70 }
71 
at91_spl_board_init(void)72 void __weak at91_spl_board_init(void)
73 {
74 }
75 
spl_board_init(void)76 void __weak spl_board_init(void)
77 {
78 }
79 
board_init_f(ulong dummy)80 void board_init_f(ulong dummy)
81 {
82 #if CONFIG_IS_ENABLED(OF_CONTROL)
83 	int ret;
84 
85 	ret = spl_early_init();
86 	if (ret) {
87 		debug("spl_early_init() failed: %d\n", ret);
88 		hang();
89 	}
90 #endif
91 
92 	lowlevel_clock_init();
93 #if !defined(CONFIG_WDT_AT91)
94 	at91_disable_wdt();
95 #endif
96 
97 	/*
98 	 * At this stage the main oscillator is supposed to be enabled
99 	 * PCK = MCK = MOSC
100 	 */
101 	at91_pllicpr_init(0x00);
102 
103 	/* Configure PLLA = MOSC * (PLL_MULA + 1) / PLL_DIVA */
104 	at91_plla_init(CONFIG_SYS_AT91_PLLA);
105 
106 	/* PCK = PLLA = 2 * MCK */
107 	at91_mck_init(CONFIG_SYS_MCKR);
108 
109 	/* Switch MCK on PLLA output */
110 	at91_mck_init(CONFIG_SYS_MCKR_CSS);
111 
112 #if defined(CONFIG_SYS_AT91_PLLB)
113 	/* Configure PLLB */
114 	at91_pllb_init(CONFIG_SYS_AT91_PLLB);
115 #endif
116 
117 	/* Enable External Reset */
118 	enable_ext_reset();
119 
120 	/* Initialize matrix */
121 	matrix_init();
122 
123 	gd->arch.mck_rate_hz = CONFIG_SYS_MASTER_CLOCK;
124 	/*
125 	 * init timer long enough for using in spl.
126 	 */
127 	timer_init();
128 
129 	/* enable clocks for all PIOs */
130 #if defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAM9N12)
131 	at91_periph_clk_enable(ATMEL_ID_PIOAB);
132 	at91_periph_clk_enable(ATMEL_ID_PIOCD);
133 #else
134 	at91_periph_clk_enable(ATMEL_ID_PIOA);
135 	at91_periph_clk_enable(ATMEL_ID_PIOB);
136 	at91_periph_clk_enable(ATMEL_ID_PIOC);
137 #endif
138 
139 #if defined(CONFIG_SPL_SERIAL_SUPPORT)
140 	/* init console */
141 	at91_seriald_hw_init();
142 	preloader_console_init();
143 #endif
144 
145 	mem_init();
146 
147 	at91_spl_board_init();
148 }
149