blob: 7bfbadf0483ea9ada3bbf8ffae480e6a71d5b70a [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +01002/*
3 * Copyright (C) 2013 Atmel Corporation
4 * Bo Shen <voice.shen@atmel.com>
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +01005 */
6
Tom Rinidec7ea02024-05-20 13:35:03 -06007#include <config.h>
Simon Glassf11478f2019-12-28 10:45:07 -07008#include <hang.h>
Simon Glass97589732020-05-10 11:40:02 -06009#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010011#include <asm/io.h>
12#include <asm/arch/at91_common.h>
13#include <asm/arch/at91_pit.h>
14#include <asm/arch/at91_pmc.h>
15#include <asm/arch/at91_rstc.h>
16#include <asm/arch/at91_wdt.h>
17#include <asm/arch/clk.h>
18#include <spl.h>
19
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010020static void switch_to_main_crystal_osc(void)
21{
22 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
23 u32 tmp;
24
25 tmp = readl(&pmc->mor);
26 tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff);
27 tmp &= ~AT91_PMC_MOR_KEY(0xff);
28 tmp |= AT91_PMC_MOR_MOSCEN;
29 tmp |= AT91_PMC_MOR_OSCOUNT(8);
30 tmp |= AT91_PMC_MOR_KEY(0x37);
31 writel(tmp, &pmc->mor);
32 while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS))
33 ;
34
Wenyou Yangf5fb5452017-09-13 14:58:48 +080035#if defined(CONFIG_SAMA5D2)
36 /* Enable a measurement of the external oscillator */
37 tmp = readl(&pmc->mcfr);
38 tmp |= AT91_PMC_MCFR_CCSS_XTAL_OSC;
39 tmp |= AT91_PMC_MCFR_RCMEAS;
40 writel(tmp, &pmc->mcfr);
41
42 while (!(readl(&pmc->mcfr) & AT91_PMC_MCFR_MAINRDY))
43 ;
44
45 if (!(readl(&pmc->mcfr) & AT91_PMC_MCFR_MAINF_MASK))
46 hang();
47#endif
48
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010049 tmp = readl(&pmc->mor);
Eugen Hristevfdd833e2019-05-24 09:38:10 +030050/*
51 * some boards have an external oscillator with driving.
52 * in this case we need to disable the internal SoC driving (bypass mode)
53 */
54#if defined(CONFIG_SPL_AT91_MCK_BYPASS)
55 tmp |= AT91_PMC_MOR_OSCBYPASS;
56#else
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010057 tmp &= ~AT91_PMC_MOR_OSCBYPASS;
Eugen Hristevfdd833e2019-05-24 09:38:10 +030058#endif
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010059 tmp &= ~AT91_PMC_MOR_KEY(0xff);
60 tmp |= AT91_PMC_MOR_KEY(0x37);
61 writel(tmp, &pmc->mor);
62
63 tmp = readl(&pmc->mor);
64 tmp |= AT91_PMC_MOR_MOSCSEL;
65 tmp &= ~AT91_PMC_MOR_KEY(0xff);
66 tmp |= AT91_PMC_MOR_KEY(0x37);
67 writel(tmp, &pmc->mor);
68
69 while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS))
70 ;
71
Wenyou Yangf5fb5452017-09-13 14:58:48 +080072#if !defined(CONFIG_SAMA5D2)
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010073 /* Wait until MAINRDY field is set to make sure main clock is stable */
74 while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY))
75 ;
Wenyou Yangf5fb5452017-09-13 14:58:48 +080076#endif
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010077
Wenyou Yangf5fb5452017-09-13 14:58:48 +080078#if !defined(CONFIG_SAMA5D4) && !defined(CONFIG_SAMA5D2)
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010079 tmp = readl(&pmc->mor);
80 tmp &= ~AT91_PMC_MOR_MOSCRCEN;
81 tmp &= ~AT91_PMC_MOR_KEY(0xff);
82 tmp |= AT91_PMC_MOR_KEY(0x37);
83 writel(tmp, &pmc->mor);
Bo Shen73864b12014-12-15 13:24:32 +080084#endif
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010085}
86
Bo Shen7dc2dbd2014-12-15 13:24:30 +080087__weak void matrix_init(void)
88{
89 /* This only be used for sama5d4 soc now */
90}
91
Bo Shen0a910282014-12-15 13:24:31 +080092__weak void redirect_int_from_saic_to_aic(void)
93{
94 /* This only be used for sama5d4 soc now */
95}
96
Tom Rinid9eae552015-02-10 19:07:22 -050097/* empty stub to satisfy current lowlevel_init, can be removed any time */
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +010098void s_init(void)
99{
Tom Rinid9eae552015-02-10 19:07:22 -0500100}
101
102void board_init_f(ulong dummy)
103{
Wenyou Yangf13d0ff2017-03-24 11:34:04 +0800104 int ret;
105
Greg Gallagher6a9390f2021-01-21 11:55:36 -0500106 if (IS_ENABLED(CONFIG_OF_CONTROL)) {
107 ret = spl_early_init();
108 if (ret) {
109 debug("spl_early_init() failed: %d\n", ret);
110 hang();
111 }
112 }
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +0100113 switch_to_main_crystal_osc();
114
Samuel Mescoffc3156fc2016-02-16 09:45:06 +0100115#ifdef CONFIG_SAMA5D2
116 configure_2nd_sram_as_l2_cache();
117#endif
118
Prasanthi Chellakumar0509c4e2018-10-09 11:46:40 -0700119#if !defined(CONFIG_WDT_AT91)
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +0100120 /* disable watchdog */
121 at91_disable_wdt();
Tom Rini4a2b61b2018-05-10 07:15:52 -0400122#endif
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +0100123
124 /* PMC configuration */
125 at91_pmc_init();
126
Tom Rini6a5dccc2022-11-16 13:10:41 -0500127 at91_clock_init(CFG_SYS_AT91_MAIN_CLOCK);
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +0100128
Bo Shen7dc2dbd2014-12-15 13:24:30 +0800129 matrix_init();
130
Bo Shen0a910282014-12-15 13:24:31 +0800131 redirect_int_from_saic_to_aic();
132
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +0100133 timer_init();
134
135 board_early_init_f();
136
Jerome Forissierab4e2532024-09-11 11:58:16 +0200137 at91_mem_init();
Wenyou Yangac8af4c2017-03-24 11:34:05 +0800138
Wenyou Yangf13d0ff2017-03-24 11:34:04 +0800139 ret = spl_init();
140 if (ret) {
141 debug("spl_init() failed: %d\n", ret);
142 hang();
143 }
144
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +0100145 preloader_console_init();
146
Heiko Schocherf1e3a8c2014-10-31 08:31:04 +0100147}