xref: /openbmc/u-boot/board/armltd/vexpress/vexpress_common.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
29b58a3f6SRyan Harkin /*
39b58a3f6SRyan Harkin  * (C) Copyright 2002
49b58a3f6SRyan Harkin  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
59b58a3f6SRyan Harkin  * Marius Groeger <mgroeger@sysgo.de>
69b58a3f6SRyan Harkin  *
79b58a3f6SRyan Harkin  * (C) Copyright 2002
89b58a3f6SRyan Harkin  * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
99b58a3f6SRyan Harkin  *
109b58a3f6SRyan Harkin  * (C) Copyright 2003
119b58a3f6SRyan Harkin  * Texas Instruments, <www.ti.com>
129b58a3f6SRyan Harkin  * Kshitij Gupta <Kshitij@ti.com>
139b58a3f6SRyan Harkin  *
149b58a3f6SRyan Harkin  * (C) Copyright 2004
159b58a3f6SRyan Harkin  * ARM Ltd.
169b58a3f6SRyan Harkin  * Philippe Robin, <philippe.robin@arm.com>
179b58a3f6SRyan Harkin  */
189b58a3f6SRyan Harkin #include <common.h>
199b58a3f6SRyan Harkin #include <malloc.h>
209b58a3f6SRyan Harkin #include <errno.h>
219b58a3f6SRyan Harkin #include <netdev.h>
229b58a3f6SRyan Harkin #include <asm/io.h>
23c62db35dSSimon Glass #include <asm/mach-types.h>
249b58a3f6SRyan Harkin #include <asm/arch/systimer.h>
259b58a3f6SRyan Harkin #include <asm/arch/sysctrl.h>
269b58a3f6SRyan Harkin #include <asm/arch/wdt.h>
279b58a3f6SRyan Harkin #include "../drivers/mmc/arm_pl180_mmci.h"
289b58a3f6SRyan Harkin 
29cd4f46e1SRyan Harkin static struct systimer *systimer_base = (struct systimer *)V2M_TIMER01;
309b58a3f6SRyan Harkin static struct sysctrl *sysctrl_base = (struct sysctrl *)SCTL_BASE;
319b58a3f6SRyan Harkin 
329b58a3f6SRyan Harkin static void flash__init(void);
339b58a3f6SRyan Harkin static void vexpress_timer_init(void);
349b58a3f6SRyan Harkin DECLARE_GLOBAL_DATA_PTR;
359b58a3f6SRyan Harkin 
369b58a3f6SRyan Harkin #if defined(CONFIG_SHOW_BOOT_PROGRESS)
show_boot_progress(int progress)379b58a3f6SRyan Harkin void show_boot_progress(int progress)
389b58a3f6SRyan Harkin {
399b58a3f6SRyan Harkin 	printf("Boot reached stage %d\n", progress);
409b58a3f6SRyan Harkin }
419b58a3f6SRyan Harkin #endif
429b58a3f6SRyan Harkin 
delay(ulong loops)439b58a3f6SRyan Harkin static inline void delay(ulong loops)
449b58a3f6SRyan Harkin {
459b58a3f6SRyan Harkin 	__asm__ volatile ("1:\n"
469b58a3f6SRyan Harkin 		"subs %0, %1, #1\n"
479b58a3f6SRyan Harkin 		"bne 1b" : "=r" (loops) : "0" (loops));
489b58a3f6SRyan Harkin }
499b58a3f6SRyan Harkin 
board_init(void)509b58a3f6SRyan Harkin int board_init(void)
519b58a3f6SRyan Harkin {
529b58a3f6SRyan Harkin 	gd->bd->bi_boot_params = LINUX_BOOT_PARAM_ADDR;
539b58a3f6SRyan Harkin 	gd->bd->bi_arch_number = MACH_TYPE_VEXPRESS;
549b58a3f6SRyan Harkin 	gd->flags = 0;
559b58a3f6SRyan Harkin 
569b58a3f6SRyan Harkin 	icache_enable();
579b58a3f6SRyan Harkin 	flash__init();
589b58a3f6SRyan Harkin 	vexpress_timer_init();
599b58a3f6SRyan Harkin 
609b58a3f6SRyan Harkin 	return 0;
619b58a3f6SRyan Harkin }
629b58a3f6SRyan Harkin 
board_eth_init(bd_t * bis)639b58a3f6SRyan Harkin int board_eth_init(bd_t *bis)
649b58a3f6SRyan Harkin {
659b58a3f6SRyan Harkin 	int rc = 0;
669b58a3f6SRyan Harkin #ifdef CONFIG_SMC911X
679b58a3f6SRyan Harkin 	rc = smc911x_initialize(0, CONFIG_SMC911X_BASE);
689b58a3f6SRyan Harkin #endif
699b58a3f6SRyan Harkin 	return rc;
709b58a3f6SRyan Harkin }
719b58a3f6SRyan Harkin 
cpu_mmc_init(bd_t * bis)729b58a3f6SRyan Harkin int cpu_mmc_init(bd_t *bis)
739b58a3f6SRyan Harkin {
749b58a3f6SRyan Harkin 	int rc = 0;
759b58a3f6SRyan Harkin 	(void) bis;
769b58a3f6SRyan Harkin #ifdef CONFIG_ARM_PL180_MMCI
779b58a3f6SRyan Harkin 	struct pl180_mmc_host *host;
78cb0060e8SPatrice Chotard 	struct mmc *mmc;
799b58a3f6SRyan Harkin 
809b58a3f6SRyan Harkin 	host = malloc(sizeof(struct pl180_mmc_host));
819b58a3f6SRyan Harkin 	if (!host)
829b58a3f6SRyan Harkin 		return -ENOMEM;
839b58a3f6SRyan Harkin 	memset(host, 0, sizeof(*host));
849b58a3f6SRyan Harkin 
859b58a3f6SRyan Harkin 	strcpy(host->name, "MMC");
869b58a3f6SRyan Harkin 	host->base = (struct sdi_registers *)CONFIG_ARM_PL180_MMCI_BASE;
879b58a3f6SRyan Harkin 	host->pwr_init = INIT_PWR;
889b58a3f6SRyan Harkin 	host->clkdiv_init = SDI_CLKCR_CLKDIV_INIT_V1 | SDI_CLKCR_CLKEN;
899b58a3f6SRyan Harkin 	host->voltages = VOLTAGE_WINDOW_MMC;
909b58a3f6SRyan Harkin 	host->caps = 0;
919b58a3f6SRyan Harkin 	host->clock_in = ARM_MCLK;
929b58a3f6SRyan Harkin 	host->clock_min = ARM_MCLK / (2 * (SDI_CLKCR_CLKDIV_INIT_V1 + 1));
939b58a3f6SRyan Harkin 	host->clock_max = CONFIG_ARM_PL180_MMCI_CLOCK_FREQ;
94cb0060e8SPatrice Chotard 	rc = arm_pl180_mmci_init(host, &mmc);
959b58a3f6SRyan Harkin #endif
969b58a3f6SRyan Harkin 	return rc;
979b58a3f6SRyan Harkin }
989b58a3f6SRyan Harkin 
flash__init(void)999b58a3f6SRyan Harkin static void flash__init(void)
1009b58a3f6SRyan Harkin {
1019b58a3f6SRyan Harkin 	/* Setup the sytem control register to allow writing to flash */
1029b58a3f6SRyan Harkin 	writel(readl(&sysctrl_base->scflashctrl) | VEXPRESS_FLASHPROG_FLVPPEN,
1039b58a3f6SRyan Harkin 	       &sysctrl_base->scflashctrl);
1049b58a3f6SRyan Harkin }
1059b58a3f6SRyan Harkin 
dram_init(void)1069b58a3f6SRyan Harkin int dram_init(void)
1079b58a3f6SRyan Harkin {
1089b58a3f6SRyan Harkin 	gd->ram_size =
1099b58a3f6SRyan Harkin 		get_ram_size((long *)CONFIG_SYS_SDRAM_BASE, PHYS_SDRAM_1_SIZE);
1109b58a3f6SRyan Harkin 	return 0;
1119b58a3f6SRyan Harkin }
1129b58a3f6SRyan Harkin 
dram_init_banksize(void)11376b00acaSSimon Glass int dram_init_banksize(void)
1149b58a3f6SRyan Harkin {
1159b58a3f6SRyan Harkin 	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
1169b58a3f6SRyan Harkin 	gd->bd->bi_dram[0].size =
1179b58a3f6SRyan Harkin 			get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
1189b58a3f6SRyan Harkin 	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
1199b58a3f6SRyan Harkin 	gd->bd->bi_dram[1].size =
1209b58a3f6SRyan Harkin 			get_ram_size((long *)PHYS_SDRAM_2, PHYS_SDRAM_2_SIZE);
12176b00acaSSimon Glass 
12276b00acaSSimon Glass 	return 0;
1239b58a3f6SRyan Harkin }
1249b58a3f6SRyan Harkin 
1259b58a3f6SRyan Harkin /*
1269b58a3f6SRyan Harkin  * Start timer:
1279b58a3f6SRyan Harkin  *    Setup a 32 bit timer, running at 1KHz
1289b58a3f6SRyan Harkin  *    Versatile Express Motherboard provides 1 MHz timer
1299b58a3f6SRyan Harkin  */
vexpress_timer_init(void)1309b58a3f6SRyan Harkin static void vexpress_timer_init(void)
1319b58a3f6SRyan Harkin {
1329b58a3f6SRyan Harkin 	/*
1339b58a3f6SRyan Harkin 	 * Set clock frequency in system controller:
1349b58a3f6SRyan Harkin 	 *   VEXPRESS_REFCLK is 32KHz
1359b58a3f6SRyan Harkin 	 *   VEXPRESS_TIMCLK is 1MHz
1369b58a3f6SRyan Harkin 	 */
1379b58a3f6SRyan Harkin 	writel(SP810_TIMER0_ENSEL | SP810_TIMER1_ENSEL |
1389b58a3f6SRyan Harkin 	       SP810_TIMER2_ENSEL | SP810_TIMER3_ENSEL |
1399b58a3f6SRyan Harkin 	       readl(&sysctrl_base->scctrl), &sysctrl_base->scctrl);
1409b58a3f6SRyan Harkin 
1419b58a3f6SRyan Harkin 	/*
1429b58a3f6SRyan Harkin 	 * Set Timer0 to be:
1439b58a3f6SRyan Harkin 	 *   Enabled, free running, no interrupt, 32-bit, wrapping
1449b58a3f6SRyan Harkin 	 */
1459b58a3f6SRyan Harkin 	writel(SYSTIMER_RELOAD, &systimer_base->timer0load);
1469b58a3f6SRyan Harkin 	writel(SYSTIMER_RELOAD, &systimer_base->timer0value);
1479b58a3f6SRyan Harkin 	writel(SYSTIMER_EN | SYSTIMER_32BIT |
1489b58a3f6SRyan Harkin 	       readl(&systimer_base->timer0control),
1499b58a3f6SRyan Harkin 	       &systimer_base->timer0control);
1509b58a3f6SRyan Harkin }
1519b58a3f6SRyan Harkin 
v2m_cfg_write(u32 devfn,u32 data)152cd4f46e1SRyan Harkin int v2m_cfg_write(u32 devfn, u32 data)
153cd4f46e1SRyan Harkin {
154cd4f46e1SRyan Harkin 	/* Configuration interface broken? */
155cd4f46e1SRyan Harkin 	u32 val;
156cd4f46e1SRyan Harkin 
157cd4f46e1SRyan Harkin 	devfn |= SYS_CFG_START | SYS_CFG_WRITE;
158cd4f46e1SRyan Harkin 
159cd4f46e1SRyan Harkin 	val = readl(V2M_SYS_CFGSTAT);
160cd4f46e1SRyan Harkin 	writel(val & ~SYS_CFG_COMPLETE, V2M_SYS_CFGSTAT);
161cd4f46e1SRyan Harkin 
162cd4f46e1SRyan Harkin 	writel(data, V2M_SYS_CFGDATA);
163cd4f46e1SRyan Harkin 	writel(devfn, V2M_SYS_CFGCTRL);
164cd4f46e1SRyan Harkin 
165cd4f46e1SRyan Harkin 	do {
166cd4f46e1SRyan Harkin 		val = readl(V2M_SYS_CFGSTAT);
167cd4f46e1SRyan Harkin 	} while (val == 0);
168cd4f46e1SRyan Harkin 
169cd4f46e1SRyan Harkin 	return !!(val & SYS_CFG_ERR);
170cd4f46e1SRyan Harkin }
171cd4f46e1SRyan Harkin 
1729b58a3f6SRyan Harkin /* Use the ARM Watchdog System to cause reset */
reset_cpu(ulong addr)1739b58a3f6SRyan Harkin void reset_cpu(ulong addr)
1749b58a3f6SRyan Harkin {
175cd4f46e1SRyan Harkin 	if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0))
176cd4f46e1SRyan Harkin 		printf("Unable to reboot\n");
1779b58a3f6SRyan Harkin }
1789b58a3f6SRyan Harkin 
lowlevel_init(void)1799b58a3f6SRyan Harkin void lowlevel_init(void)
1809b58a3f6SRyan Harkin {
1819b58a3f6SRyan Harkin }
1829b58a3f6SRyan Harkin 
get_board_rev(void)1839b58a3f6SRyan Harkin ulong get_board_rev(void){
1849b58a3f6SRyan Harkin 	return readl((u32 *)SYS_ID);
1859b58a3f6SRyan Harkin }
1869b58a3f6SRyan Harkin 
187104d6fb6SJan Kiszka #ifdef CONFIG_ARMV7_NONSEC
188e261c83aSAndre Przywara /* Setting the address at which secondary cores start from.
189e261c83aSAndre Przywara  * Versatile Express uses one address for all cores, so ignore corenr
190e261c83aSAndre Przywara  */
smp_set_core_boot_addr(unsigned long addr,int corenr)191e261c83aSAndre Przywara void smp_set_core_boot_addr(unsigned long addr, int corenr)
192e261c83aSAndre Przywara {
193e261c83aSAndre Przywara 	/* The SYSFLAGS register on VExpress needs to be cleared first
194e261c83aSAndre Przywara 	 * by writing to the next address, since any writes to the address
195e261c83aSAndre Przywara 	 * at offset 0 will only be ORed in
196e261c83aSAndre Przywara 	 */
197e261c83aSAndre Przywara 	writel(~0, CONFIG_SYSFLAGS_ADDR + 4);
198e261c83aSAndre Przywara 	writel(addr, CONFIG_SYSFLAGS_ADDR);
199e261c83aSAndre Przywara }
200e261c83aSAndre Przywara #endif
201