blob: 6ee0e1c24cfbc6fa4715ae2ffcf9753a9a9800f6 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Heiko Schocher5abc00d2014-10-31 08:31:04 +01002/*
3 * Copyright (C) 2013 Atmel Corporation
4 * Bo Shen <voice.shen@atmel.com>
Heiko Schocher5abc00d2014-10-31 08:31:04 +01005 */
6
7#include <common.h>
Simon Glassdb41d652019-12-28 10:45:07 -07008#include <hang.h>
Heiko Schocher5abc00d2014-10-31 08:31:04 +01009#include <asm/io.h>
10#include <asm/arch/at91_common.h>
11#include <asm/arch/at91_pit.h>
12#include <asm/arch/at91_pmc.h>
13#include <asm/arch/at91_rstc.h>
14#include <asm/arch/at91_wdt.h>
15#include <asm/arch/clk.h>
16#include <spl.h>
17
Heiko Schocher5abc00d2014-10-31 08:31:04 +010018static void switch_to_main_crystal_osc(void)
19{
20 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
21 u32 tmp;
22
23 tmp = readl(&pmc->mor);
24 tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff);
25 tmp &= ~AT91_PMC_MOR_KEY(0xff);
26 tmp |= AT91_PMC_MOR_MOSCEN;
27 tmp |= AT91_PMC_MOR_OSCOUNT(8);
28 tmp |= AT91_PMC_MOR_KEY(0x37);
29 writel(tmp, &pmc->mor);
30 while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS))
31 ;
32
Wenyou Yang3ceb5112017-09-13 14:58:48 +080033#if defined(CONFIG_SAMA5D2)
34 /* Enable a measurement of the external oscillator */
35 tmp = readl(&pmc->mcfr);
36 tmp |= AT91_PMC_MCFR_CCSS_XTAL_OSC;
37 tmp |= AT91_PMC_MCFR_RCMEAS;
38 writel(tmp, &pmc->mcfr);
39
40 while (!(readl(&pmc->mcfr) & AT91_PMC_MCFR_MAINRDY))
41 ;
42
43 if (!(readl(&pmc->mcfr) & AT91_PMC_MCFR_MAINF_MASK))
44 hang();
45#endif
46
Heiko Schocher5abc00d2014-10-31 08:31:04 +010047 tmp = readl(&pmc->mor);
Eugen Hristev0be07872019-05-24 09:38:10 +030048/*
49 * some boards have an external oscillator with driving.
50 * in this case we need to disable the internal SoC driving (bypass mode)
51 */
52#if defined(CONFIG_SPL_AT91_MCK_BYPASS)
53 tmp |= AT91_PMC_MOR_OSCBYPASS;
54#else
Heiko Schocher5abc00d2014-10-31 08:31:04 +010055 tmp &= ~AT91_PMC_MOR_OSCBYPASS;
Eugen Hristev0be07872019-05-24 09:38:10 +030056#endif
Heiko Schocher5abc00d2014-10-31 08:31:04 +010057 tmp &= ~AT91_PMC_MOR_KEY(0xff);
58 tmp |= AT91_PMC_MOR_KEY(0x37);
59 writel(tmp, &pmc->mor);
60
61 tmp = readl(&pmc->mor);
62 tmp |= AT91_PMC_MOR_MOSCSEL;
63 tmp &= ~AT91_PMC_MOR_KEY(0xff);
64 tmp |= AT91_PMC_MOR_KEY(0x37);
65 writel(tmp, &pmc->mor);
66
67 while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS))
68 ;
69
Wenyou Yang3ceb5112017-09-13 14:58:48 +080070#if !defined(CONFIG_SAMA5D2)
Heiko Schocher5abc00d2014-10-31 08:31:04 +010071 /* Wait until MAINRDY field is set to make sure main clock is stable */
72 while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY))
73 ;
Wenyou Yang3ceb5112017-09-13 14:58:48 +080074#endif
Heiko Schocher5abc00d2014-10-31 08:31:04 +010075
Wenyou Yang3ceb5112017-09-13 14:58:48 +080076#if !defined(CONFIG_SAMA5D4) && !defined(CONFIG_SAMA5D2)
Heiko Schocher5abc00d2014-10-31 08:31:04 +010077 tmp = readl(&pmc->mor);
78 tmp &= ~AT91_PMC_MOR_MOSCRCEN;
79 tmp &= ~AT91_PMC_MOR_KEY(0xff);
80 tmp |= AT91_PMC_MOR_KEY(0x37);
81 writel(tmp, &pmc->mor);
Bo Shen0246b7c2014-12-15 13:24:32 +080082#endif
Heiko Schocher5abc00d2014-10-31 08:31:04 +010083}
84
Bo Shen433be902014-12-15 13:24:30 +080085__weak void matrix_init(void)
86{
87 /* This only be used for sama5d4 soc now */
88}
89
Bo Shen4514b5f2014-12-15 13:24:31 +080090__weak void redirect_int_from_saic_to_aic(void)
91{
92 /* This only be used for sama5d4 soc now */
93}
94
Tom Rinie755d542015-02-10 19:07:22 -050095/* empty stub to satisfy current lowlevel_init, can be removed any time */
Heiko Schocher5abc00d2014-10-31 08:31:04 +010096void s_init(void)
97{
Tom Rinie755d542015-02-10 19:07:22 -050098}
99
100void board_init_f(ulong dummy)
101{
Wenyou Yang730a7b42017-03-24 11:34:04 +0800102 int ret;
103
Heiko Schocher5abc00d2014-10-31 08:31:04 +0100104 switch_to_main_crystal_osc();
105
Samuel Mescofff7cf2912016-02-16 09:45:06 +0100106#ifdef CONFIG_SAMA5D2
107 configure_2nd_sram_as_l2_cache();
108#endif
109
Prasanthi Chellakumar1473f6a2018-10-09 11:46:40 -0700110#if !defined(CONFIG_WDT_AT91)
Heiko Schocher5abc00d2014-10-31 08:31:04 +0100111 /* disable watchdog */
112 at91_disable_wdt();
Tom Rinif58e9462018-05-10 07:15:52 -0400113#endif
Heiko Schocher5abc00d2014-10-31 08:31:04 +0100114
115 /* PMC configuration */
116 at91_pmc_init();
117
118 at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK);
119
Bo Shen433be902014-12-15 13:24:30 +0800120 matrix_init();
121
Bo Shen4514b5f2014-12-15 13:24:31 +0800122 redirect_int_from_saic_to_aic();
123
Heiko Schocher5abc00d2014-10-31 08:31:04 +0100124 timer_init();
125
126 board_early_init_f();
127
Wenyou Yang5bede732017-03-24 11:34:05 +0800128 mem_init();
129
Wenyou Yang730a7b42017-03-24 11:34:04 +0800130 ret = spl_init();
131 if (ret) {
132 debug("spl_init() failed: %d\n", ret);
133 hang();
134 }
135
Heiko Schocher5abc00d2014-10-31 08:31:04 +0100136 preloader_console_init();
137
Heiko Schocher5abc00d2014-10-31 08:31:04 +0100138}