1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2014 DENX Software Engineering 4 * Heiko Schocher <hs@denx.de> 5 * 6 * Based on: 7 * Copyright (C) 2013 Atmel Corporation 8 * Bo Shen <voice.shen@atmel.com> 9 */ 10 11#include <common.h> 12#include <hang.h> 13#include <init.h> 14#include <log.h> 15#include <asm/global_data.h> 16#include <asm/io.h> 17#include <asm/arch/at91_common.h> 18#include <asm/arch/at91sam9_matrix.h> 19#include <asm/arch/at91_pit.h> 20#include <asm/arch/at91_rstc.h> 21#include <asm/arch/at91_wdt.h> 22#include <asm/arch/clk.h> 23#include <spl.h> 24 25DECLARE_GLOBAL_DATA_PTR; 26 27static void enable_ext_reset(void) 28{ 29 struct at91_rstc *rstc = (struct at91_rstc *)ATMEL_BASE_RSTC; 30 31 writel(AT91_RSTC_KEY | AT91_RSTC_MR_URSTEN, &rstc->mr); 32} 33 34void lowlevel_clock_init(void) 35{ 36 struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; 37 38 if (!(readl(&pmc->sr) & AT91_PMC_MOSCS)) { 39 /* Enable Main Oscillator */ 40 writel(AT91_PMC_MOSCS | (0x40 << 8), &pmc->mor); 41 42 /* Wait until Main Oscillator is stable */ 43 while (!(readl(&pmc->sr) & AT91_PMC_MOSCS)) 44 ; 45 } 46 47 /* After stabilization, switch to Main Oscillator */ 48 if ((readl(&pmc->mckr) & AT91_PMC_CSS) == AT91_PMC_CSS_SLOW) { 49 unsigned long tmp; 50 51 tmp = readl(&pmc->mckr); 52 tmp &= ~AT91_PMC_CSS; 53 tmp |= AT91_PMC_CSS_MAIN; 54 writel(tmp, &pmc->mckr); 55 while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) 56 ; 57 58 tmp &= ~AT91_PMC_PRES; 59 tmp |= AT91_PMC_PRES_1; 60 writel(tmp, &pmc->mckr); 61 while (!(readl(&pmc->sr) & AT91_PMC_MCKRDY)) 62 ; 63 } 64 65 return; 66} 67 68void __weak matrix_init(void) 69{ 70} 71 72void __weak at91_spl_board_init(void) 73{ 74} 75 76void __weak spl_board_init(void) 77{ 78} 79 80void board_init_f(ulong dummy) 81{ 82#if CONFIG_IS_ENABLED(OF_CONTROL) 83 int ret; 84 85 ret = spl_early_init(); 86 if (ret) { 87 debug("spl_early_init() failed: %d\n", ret); 88 hang(); 89 } 90#endif 91 92 lowlevel_clock_init(); 93#if !defined(CONFIG_WDT_AT91) 94 at91_disable_wdt(); 95#endif 96 97 /* 98 * At this stage the main oscillator is supposed to be enabled 99 * PCK = MCK = MOSC 100 */ 101 at91_pllicpr_init(0x00); 102 103 /* Configure PLLA = MOSC * (PLL_MULA + 1) / PLL_DIVA */ 104 at91_plla_init(CONFIG_SYS_AT91_PLLA); 105 106 /* PCK = PLLA = 2 * MCK */ 107 at91_mck_init(CONFIG_SYS_MCKR); 108 109 /* Switch MCK on PLLA output */ 110 at91_mck_init(CONFIG_SYS_MCKR_CSS); 111 112#if defined(CONFIG_SYS_AT91_PLLB) 113 /* Configure PLLB */ 114 at91_pllb_init(CONFIG_SYS_AT91_PLLB); 115#endif 116 117 /* Enable External Reset */ 118 enable_ext_reset(); 119 120 /* Initialize matrix */ 121 matrix_init(); 122 123 gd->arch.mck_rate_hz = CONFIG_SYS_MASTER_CLOCK; 124 /* 125 * init timer long enough for using in spl. 126 */ 127 timer_init(); 128 129 /* enable clocks for all PIOs */ 130#if defined(CONFIG_AT91SAM9X5) || defined(CONFIG_AT91SAM9N12) 131 at91_periph_clk_enable(ATMEL_ID_PIOAB); 132 at91_periph_clk_enable(ATMEL_ID_PIOCD); 133#else 134 at91_periph_clk_enable(ATMEL_ID_PIOA); 135 at91_periph_clk_enable(ATMEL_ID_PIOB); 136 at91_periph_clk_enable(ATMEL_ID_PIOC); 137#endif 138 139#if defined(CONFIG_SPL_SERIAL) 140 /* init console */ 141 at91_seriald_hw_init(); 142 preloader_console_init(); 143#endif 144 145 mem_init(); 146 147 at91_spl_board_init(); 148} 149