Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2013 Atmel Corporation * Bo Shen <voice.shen@atmel.com> */ #include <config.h> #include <hang.h> #include <init.h> #include <log.h> #include <asm/io.h> #include <asm/arch/at91_common.h> #include <asm/arch/at91_pit.h> #include <asm/arch/at91_pmc.h> #include <asm/arch/at91_rstc.h> #include <asm/arch/at91_wdt.h> #include <asm/arch/clk.h> #include <spl.h> static void switch_to_main_crystal_osc(void) { struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; u32 tmp; tmp = readl(&pmc->mor); tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff); tmp &= ~AT91_PMC_MOR_KEY(0xff); tmp |= AT91_PMC_MOR_MOSCEN; tmp |= AT91_PMC_MOR_OSCOUNT(8); tmp |= AT91_PMC_MOR_KEY(0x37); writel(tmp, &pmc->mor); while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS)) ; #if defined(CONFIG_SAMA5D2) /* Enable a measurement of the external oscillator */ tmp = readl(&pmc->mcfr); tmp |= AT91_PMC_MCFR_CCSS_XTAL_OSC; tmp |= AT91_PMC_MCFR_RCMEAS; writel(tmp, &pmc->mcfr); while (!(readl(&pmc->mcfr) & AT91_PMC_MCFR_MAINRDY)) ; if (!(readl(&pmc->mcfr) & AT91_PMC_MCFR_MAINF_MASK)) hang(); #endif tmp = readl(&pmc->mor); /* * some boards have an external oscillator with driving. * in this case we need to disable the internal SoC driving (bypass mode) */ #if defined(CONFIG_SPL_AT91_MCK_BYPASS) tmp |= AT91_PMC_MOR_OSCBYPASS; #else tmp &= ~AT91_PMC_MOR_OSCBYPASS; #endif tmp &= ~AT91_PMC_MOR_KEY(0xff); tmp |= AT91_PMC_MOR_KEY(0x37); writel(tmp, &pmc->mor); tmp = readl(&pmc->mor); tmp |= AT91_PMC_MOR_MOSCSEL; tmp &= ~AT91_PMC_MOR_KEY(0xff); tmp |= AT91_PMC_MOR_KEY(0x37); writel(tmp, &pmc->mor); while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCSELS)) ; #if !defined(CONFIG_SAMA5D2) /* Wait until MAINRDY field is set to make sure main clock is stable */ while (!(readl(&pmc->mcfr) & AT91_PMC_MAINRDY)) ; #endif #if !defined(CONFIG_SAMA5D4) && !defined(CONFIG_SAMA5D2) tmp = readl(&pmc->mor); tmp &= ~AT91_PMC_MOR_MOSCRCEN; tmp &= ~AT91_PMC_MOR_KEY(0xff); tmp |= AT91_PMC_MOR_KEY(0x37); writel(tmp, &pmc->mor); #endif } __weak void matrix_init(void) { /* This only be used for sama5d4 soc now */ } __weak void redirect_int_from_saic_to_aic(void) { /* This only be used for sama5d4 soc now */ } /* empty stub to satisfy current lowlevel_init, can be removed any time */ void s_init(void) { } void board_init_f(ulong dummy) { int ret; if (IS_ENABLED(CONFIG_OF_CONTROL)) { ret = spl_early_init(); if (ret) { debug("spl_early_init() failed: %d\n", ret); hang(); } } switch_to_main_crystal_osc(); #ifdef CONFIG_SAMA5D2 configure_2nd_sram_as_l2_cache(); #endif #if !defined(CONFIG_WDT_AT91) /* disable watchdog */ at91_disable_wdt(); #endif /* PMC configuration */ at91_pmc_init(); at91_clock_init(CFG_SYS_AT91_MAIN_CLOCK); matrix_init(); redirect_int_from_saic_to_aic(); timer_init(); board_early_init_f(); at91_mem_init(); ret = spl_init(); if (ret) { debug("spl_init() failed: %d\n", ret); hang(); } preloader_console_init(); } |