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