1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2013 Atmel Corporation 4 * Bo Shen <voice.shen@atmel.com> 5 */ 6 7 #include <common.h> 8 #include <hang.h> 9 #include <init.h> 10 #include <log.h> 11 #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 switch_to_main_crystal_osc(void)20static 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 35 #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 49 tmp = readl(&pmc->mor); 50 /* 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 57 tmp &= ~AT91_PMC_MOR_OSCBYPASS; 58 #endif 59 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 72 #if !defined(CONFIG_SAMA5D2) 73 /* Wait until MAINRDY field is set to make sure main clock is stable */ 74 while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY)) 75 ; 76 #endif 77 78 #if !defined(CONFIG_SAMA5D4) && !defined(CONFIG_SAMA5D2) 79 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); 84 #endif 85 } 86 matrix_init(void)87__weak void matrix_init(void) 88 { 89 /* This only be used for sama5d4 soc now */ 90 } 91 redirect_int_from_saic_to_aic(void)92__weak void redirect_int_from_saic_to_aic(void) 93 { 94 /* This only be used for sama5d4 soc now */ 95 } 96 97 /* empty stub to satisfy current lowlevel_init, can be removed any time */ s_init(void)98void s_init(void) 99 { 100 } 101 board_init_f(ulong dummy)102void board_init_f(ulong dummy) 103 { 104 int ret; 105 106 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 } 113 switch_to_main_crystal_osc(); 114 115 #ifdef CONFIG_SAMA5D2 116 configure_2nd_sram_as_l2_cache(); 117 #endif 118 119 #if !defined(CONFIG_WDT_AT91) 120 /* disable watchdog */ 121 at91_disable_wdt(); 122 #endif 123 124 /* PMC configuration */ 125 at91_pmc_init(); 126 127 at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); 128 129 matrix_init(); 130 131 redirect_int_from_saic_to_aic(); 132 133 timer_init(); 134 135 board_early_init_f(); 136 137 mem_init(); 138 139 ret = spl_init(); 140 if (ret) { 141 debug("spl_init() failed: %d\n", ret); 142 hang(); 143 } 144 145 preloader_console_init(); 146 147 } 148