1 /* 2 * Copyright (C) 2013 Atmel Corporation 3 * Bo Shen <voice.shen@atmel.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #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 18 DECLARE_GLOBAL_DATA_PTR; 19 20 static 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 tmp &= ~AT91_PMC_MOR_OSCBYPASS; 51 tmp &= ~AT91_PMC_MOR_KEY(0xff); 52 tmp |= AT91_PMC_MOR_KEY(0x37); 53 writel(tmp, &pmc->mor); 54 55 tmp = readl(&pmc->mor); 56 tmp |= AT91_PMC_MOR_MOSCSEL; 57 tmp &= ~AT91_PMC_MOR_KEY(0xff); 58 tmp |= AT91_PMC_MOR_KEY(0x37); 59 writel(tmp, &pmc->mor); 60 61 while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS)) 62 ; 63 64 #if !defined(CONFIG_SAMA5D2) 65 /* Wait until MAINRDY field is set to make sure main clock is stable */ 66 while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY)) 67 ; 68 #endif 69 70 #if !defined(CONFIG_SAMA5D4) && !defined(CONFIG_SAMA5D2) 71 tmp = readl(&pmc->mor); 72 tmp &= ~AT91_PMC_MOR_MOSCRCEN; 73 tmp &= ~AT91_PMC_MOR_KEY(0xff); 74 tmp |= AT91_PMC_MOR_KEY(0x37); 75 writel(tmp, &pmc->mor); 76 #endif 77 } 78 79 __weak void matrix_init(void) 80 { 81 /* This only be used for sama5d4 soc now */ 82 } 83 84 __weak void redirect_int_from_saic_to_aic(void) 85 { 86 /* This only be used for sama5d4 soc now */ 87 } 88 89 /* empty stub to satisfy current lowlevel_init, can be removed any time */ 90 void s_init(void) 91 { 92 } 93 94 void board_init_f(ulong dummy) 95 { 96 int ret; 97 98 switch_to_main_crystal_osc(); 99 100 #ifdef CONFIG_SAMA5D2 101 configure_2nd_sram_as_l2_cache(); 102 #endif 103 104 /* disable watchdog */ 105 at91_disable_wdt(); 106 107 /* PMC configuration */ 108 at91_pmc_init(); 109 110 at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); 111 112 matrix_init(); 113 114 redirect_int_from_saic_to_aic(); 115 116 timer_init(); 117 118 board_early_init_f(); 119 120 mem_init(); 121 122 ret = spl_init(); 123 if (ret) { 124 debug("spl_init() failed: %d\n", ret); 125 hang(); 126 } 127 128 preloader_console_init(); 129 130 } 131