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 <asm/io.h> 9 #include <asm/arch/at91_common.h> 10 #include <asm/arch/at91_pit.h> 11 #include <asm/arch/at91_pmc.h> 12 #include <asm/arch/at91_rstc.h> 13 #include <asm/arch/at91_wdt.h> 14 #include <asm/arch/clk.h> 15 #include <spl.h> 16 17 static void switch_to_main_crystal_osc(void) 18 { 19 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 20 u32 tmp; 21 22 tmp = readl(&pmc->mor); 23 tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff); 24 tmp &= ~AT91_PMC_MOR_KEY(0xff); 25 tmp |= AT91_PMC_MOR_MOSCEN; 26 tmp |= AT91_PMC_MOR_OSCOUNT(8); 27 tmp |= AT91_PMC_MOR_KEY(0x37); 28 writel(tmp, &pmc->mor); 29 while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS)) 30 ; 31 32 #if defined(CONFIG_SAMA5D2) 33 /* Enable a measurement of the external oscillator */ 34 tmp = readl(&pmc->mcfr); 35 tmp |= AT91_PMC_MCFR_CCSS_XTAL_OSC; 36 tmp |= AT91_PMC_MCFR_RCMEAS; 37 writel(tmp, &pmc->mcfr); 38 39 while (!(readl(&pmc->mcfr) & AT91_PMC_MCFR_MAINRDY)) 40 ; 41 42 if (!(readl(&pmc->mcfr) & AT91_PMC_MCFR_MAINF_MASK)) 43 hang(); 44 #endif 45 46 tmp = readl(&pmc->mor); 47 tmp &= ~AT91_PMC_MOR_OSCBYPASS; 48 tmp &= ~AT91_PMC_MOR_KEY(0xff); 49 tmp |= AT91_PMC_MOR_KEY(0x37); 50 writel(tmp, &pmc->mor); 51 52 tmp = readl(&pmc->mor); 53 tmp |= AT91_PMC_MOR_MOSCSEL; 54 tmp &= ~AT91_PMC_MOR_KEY(0xff); 55 tmp |= AT91_PMC_MOR_KEY(0x37); 56 writel(tmp, &pmc->mor); 57 58 while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS)) 59 ; 60 61 #if !defined(CONFIG_SAMA5D2) 62 /* Wait until MAINRDY field is set to make sure main clock is stable */ 63 while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY)) 64 ; 65 #endif 66 67 #if !defined(CONFIG_SAMA5D4) && !defined(CONFIG_SAMA5D2) 68 tmp = readl(&pmc->mor); 69 tmp &= ~AT91_PMC_MOR_MOSCRCEN; 70 tmp &= ~AT91_PMC_MOR_KEY(0xff); 71 tmp |= AT91_PMC_MOR_KEY(0x37); 72 writel(tmp, &pmc->mor); 73 #endif 74 } 75 76 __weak void matrix_init(void) 77 { 78 /* This only be used for sama5d4 soc now */ 79 } 80 81 __weak void redirect_int_from_saic_to_aic(void) 82 { 83 /* This only be used for sama5d4 soc now */ 84 } 85 86 /* empty stub to satisfy current lowlevel_init, can be removed any time */ 87 void s_init(void) 88 { 89 } 90 91 void board_init_f(ulong dummy) 92 { 93 int ret; 94 95 switch_to_main_crystal_osc(); 96 97 #ifdef CONFIG_SAMA5D2 98 configure_2nd_sram_as_l2_cache(); 99 #endif 100 101 #if !defined(CONFIG_WDT_AT91) 102 /* disable watchdog */ 103 at91_disable_wdt(); 104 #endif 105 106 /* PMC configuration */ 107 at91_pmc_init(); 108 109 at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); 110 111 matrix_init(); 112 113 redirect_int_from_saic_to_aic(); 114 115 timer_init(); 116 117 board_early_init_f(); 118 119 mem_init(); 120 121 ret = spl_init(); 122 if (ret) { 123 debug("spl_init() failed: %d\n", ret); 124 hang(); 125 } 126 127 preloader_console_init(); 128 129 } 130