diff options
| author | fishsoupisgood <github@madingley.org> | 2019-04-29 01:17:54 +0100 | 
|---|---|---|
| committer | fishsoupisgood <github@madingley.org> | 2019-05-27 03:43:43 +0100 | 
| commit | 3f2546b2ef55b661fd8dd69682b38992225e86f6 (patch) | |
| tree | 65ca85f13617aee1dce474596800950f266a456c /roms/u-boot/arch/arm/cpu/arm926ejs/pantheon | |
| download | qemu-master.tar.gz qemu-master.tar.bz2 qemu-master.zip  | |
Diffstat (limited to 'roms/u-boot/arch/arm/cpu/arm926ejs/pantheon')
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/Makefile | 9 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/cpu.c | 85 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/dram.c | 117 | ||||
| -rw-r--r-- | roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/timer.c | 201 | 
4 files changed, 412 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/Makefile b/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/Makefile new file mode 100644 index 00000000..988341f8 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2011 +# Marvell Semiconductor <www.marvell.com> +# Written-by: Lei Wen <leiwen@marvell.com> +# +# SPDX-License-Identifier:	GPL-2.0+ +# + +obj-y	= cpu.o timer.o dram.o diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/cpu.c b/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/cpu.c new file mode 100644 index 00000000..4e2a177c --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/cpu.c @@ -0,0 +1,85 @@ +/* + * (C) Copyright 2011 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Lei Wen <leiwen@marvell.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/pantheon.h> + +#define UARTCLK14745KHZ	(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(1)) +#define SET_MRVL_ID	(1<<8) +#define L2C_RAM_SEL	(1<<4) + +int arch_cpu_init(void) +{ +	u32 val; +	struct panthcpu_registers *cpuregs = +		(struct panthcpu_registers*) PANTHEON_CPU_BASE; + +	struct panthapb_registers *apbclkres = +		(struct panthapb_registers*) PANTHEON_APBC_BASE; + +	struct panthmpmu_registers *mpmu = +		(struct panthmpmu_registers*) PANTHEON_MPMU_BASE; + +	struct panthapmu_registers *apmu = +		(struct panthapmu_registers *) PANTHEON_APMU_BASE; + +	/* set SEL_MRVL_ID bit in PANTHEON_CPU_CONF register */ +	val = readl(&cpuregs->cpu_conf); +	val = val | SET_MRVL_ID; +	writel(val, &cpuregs->cpu_conf); + +	/* Turn on clock gating (PMUM_CCGR) */ +	writel(0xFFFFFFFF, &mpmu->ccgr); + +	/* Turn on clock gating (PMUM_ACGR) */ +	writel(0xFFFFFFFF, &mpmu->acgr); + +	/* Turn on uart2 clock */ +	writel(UARTCLK14745KHZ, &apbclkres->uart0); + +	/* Enable GPIO clock */ +	writel(APBC_APBCLK, &apbclkres->gpio); + +#ifdef CONFIG_I2C_MV +	/* Enable I2C clock */ +	writel(APBC_RST | APBC_FNCLK | APBC_APBCLK, &apbclkres->twsi); +	writel(APBC_FNCLK | APBC_APBCLK, &apbclkres->twsi); +#endif + +#ifdef CONFIG_MV_SDHCI +	/* Enable mmc clock */ +	writel(APMU_PERI_CLK | APMU_AXI_CLK | APMU_PERI_RST | APMU_AXI_RST, +			&apmu->sd1); +	writel(APMU_PERI_CLK | APMU_AXI_CLK | APMU_PERI_RST | APMU_AXI_RST, +			&apmu->sd3); +#endif + +	icache_enable(); + +	return 0; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ +	u32 id; +	struct panthcpu_registers *cpuregs = +		(struct panthcpu_registers*) PANTHEON_CPU_BASE; + +	id = readl(&cpuregs->chip_id); +	printf("SoC:   PANTHEON 88AP%X-%X\n", (id & 0xFFF), (id >> 0x10)); +	return 0; +} +#endif + +#ifdef CONFIG_I2C_MV +void i2c_clk_enable(void) +{ +} +#endif diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/dram.c b/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/dram.c new file mode 100644 index 00000000..f77e3d0a --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/dram.c @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2011 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Lei Wen <leiwen@marvell.com>, + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pantheon.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Pantheon DRAM controller supports upto 8 banks + * for chip select 0 and 1 + */ + +/* + * DDR Memory Control Registers + * Refer Datasheet 4.4 + */ +struct panthddr_map_registers { +	u32	cs;	/* Memory Address Map Register -CS */ +	u32	pad[3]; +}; + +struct panthddr_registers { +	u8	pad[0x100 - 0x000]; +	struct panthddr_map_registers mmap[2]; +}; + +/* + * panth_sdram_base - reads SDRAM Base Address Register + */ +u32 panth_sdram_base(int chip_sel) +{ +	struct panthddr_registers *ddr_regs = +		(struct panthddr_registers *)PANTHEON_DRAM_BASE; +	u32 result = 0; +	u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); + +	if (!CS_valid) +		return 0; + +	result = readl(&ddr_regs->mmap[chip_sel].cs) & 0xFF800000; +	return result; +} + +/* + * panth_sdram_size - reads SDRAM size + */ +u32 panth_sdram_size(int chip_sel) +{ +	struct panthddr_registers *ddr_regs = +		(struct panthddr_registers *)PANTHEON_DRAM_BASE; +	u32 result = 0; +	u32 CS_valid = 0x01 & readl(&ddr_regs->mmap[chip_sel].cs); + +	if (!CS_valid) +		return 0; + +	result = readl(&ddr_regs->mmap[chip_sel].cs); +	result = (result >> 16) & 0xF; +	if (result < 0x7) { +		printf("Unknown DRAM Size\n"); +		return -1; +	} else { +		return ((0x8 << (result - 0x7)) * 1024 * 1024); +	} +} + +#ifndef CONFIG_SYS_BOARD_DRAM_INIT +int dram_init(void) +{ +	int i; + +	gd->ram_size = 0; +	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { +		gd->bd->bi_dram[i].start = panth_sdram_base(i); +		gd->bd->bi_dram[i].size = panth_sdram_size(i); +		/* +		 * It is assumed that all memory banks are consecutive +		 * and without gaps. +		 * If the gap is found, ram_size will be reported for +		 * consecutive memory only +		 */ +		if (gd->bd->bi_dram[i].start != gd->ram_size) +			break; + +		gd->ram_size += gd->bd->bi_dram[i].size; + +	} + +	for (; i < CONFIG_NR_DRAM_BANKS; i++) { +		/* +		 * If above loop terminated prematurely, we need to set +		 * remaining banks' start address & size as 0. Otherwise other +		 * u-boot functions and Linux kernel gets wrong values which +		 * could result in crash +		 */ +		gd->bd->bi_dram[i].start = 0; +		gd->bd->bi_dram[i].size = 0; +	} +	return 0; +} + +/* + * If this function is not defined here, + * board.c alters dram bank zero configuration defined above. + */ +void dram_init_banksize(void) +{ +	dram_init(); +} +#endif /* CONFIG_SYS_BOARD_DRAM_INIT */ diff --git a/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/timer.c b/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/timer.c new file mode 100644 index 00000000..6382d3b0 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm926ejs/pantheon/timer.c @@ -0,0 +1,201 @@ +/* + * (C) Copyright 2011 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Lei Wen <leiwen@marvell.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/cpu.h> +#include <asm/arch/pantheon.h> + +/* + * Timer registers + * Refer 6.2.9 in Datasheet + */ +struct panthtmr_registers { +	u32 clk_ctrl;	/* Timer clk control reg */ +	u32 match[9];	/* Timer match registers */ +	u32 count[3];	/* Timer count registers */ +	u32 status[3]; +	u32 ie[3]; +	u32 preload[3];	/* Timer preload value */ +	u32 preload_ctrl[3]; +	u32 wdt_match_en; +	u32 wdt_match_r; +	u32 wdt_val; +	u32 wdt_sts; +	u32 icr[3]; +	u32 wdt_icr; +	u32 cer;	/* Timer count enable reg */ +	u32 cmr; +	u32 ilr[3]; +	u32 wcr; +	u32 wfar; +	u32 wsar; +	u32 cvwr[3]; +}; + +#define TIMER			0	/* Use TIMER 0 */ +/* Each timer has 3 match registers */ +#define MATCH_CMP(x)		((3 * TIMER) + x) +#define TIMER_LOAD_VAL 		0xffffffff +#define	COUNT_RD_REQ		0x1 + +DECLARE_GLOBAL_DATA_PTR; +/* Using gd->arch.tbu from timestamp and gd->arch.tbl for lastdec */ + +/* + * For preventing risk of instability in reading counter value, + * first set read request to register cvwr and then read same + * register after it captures counter value. + */ +ulong read_timer(void) +{ +	struct panthtmr_registers *panthtimers = +		(struct panthtmr_registers *) PANTHEON_TIMER_BASE; +	volatile int loop=100; +	ulong val; + +	writel(COUNT_RD_REQ, &panthtimers->cvwr); +	while (loop--) +		val = readl(&panthtimers->cvwr); + +	/* +	 * This stop gcc complain and prevent loop mistake init to 0 +	 */ +	val = readl(&panthtimers->cvwr); + +	return val; +} + +ulong get_timer_masked(void) +{ +	ulong now = read_timer(); + +	if (now >= gd->arch.tbl) { +		/* normal mode */ +		gd->arch.tbu += now - gd->arch.tbl; +	} else { +		/* we have an overflow ... */ +		gd->arch.tbu += now + TIMER_LOAD_VAL - gd->arch.tbl; +	} +	gd->arch.tbl = now; + +	return gd->arch.tbu; +} + +ulong get_timer(ulong base) +{ +	return ((get_timer_masked() / (CONFIG_SYS_HZ_CLOCK / 1000)) - +		base); +} + +void __udelay(unsigned long usec) +{ +	ulong delayticks; +	ulong endtime; + +	delayticks = (usec * (CONFIG_SYS_HZ_CLOCK / 1000000)); +	endtime = get_timer_masked() + delayticks; + +	while (get_timer_masked() < endtime) +		; +} + +/* + * init the Timer + */ +int timer_init(void) +{ +	struct panthapb_registers *apb1clkres = +		(struct panthapb_registers *) PANTHEON_APBC_BASE; +	struct panthtmr_registers *panthtimers = +		(struct panthtmr_registers *) PANTHEON_TIMER_BASE; + +	/* Enable Timer clock at 3.25 MHZ */ +	writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), &apb1clkres->timers); + +	/* load value into timer */ +	writel(0x0, &panthtimers->clk_ctrl); +	/* Use Timer 0 Match Resiger 0 */ +	writel(TIMER_LOAD_VAL, &panthtimers->match[MATCH_CMP(0)]); +	/* Preload value is 0 */ +	writel(0x0, &panthtimers->preload[TIMER]); +	/* Enable match comparator 0 for Timer 0 */ +	writel(0x1, &panthtimers->preload_ctrl[TIMER]); + +	/* Enable timer 0 */ +	writel(0x1, &panthtimers->cer); +	/* init the gd->arch.tbu and gd->arch.tbl value */ +	gd->arch.tbl = read_timer(); +	gd->arch.tbu = 0; + +	return 0; +} + +#define MPMU_APRR_WDTR	(1<<4) +#define TMR_WFAR	0xbaba	/* WDT Register First key */ +#define TMP_WSAR	0xeb10	/* WDT Register Second key */ + +/* + * This function uses internal Watchdog Timer + * based reset mechanism. + * Steps to write watchdog registers (protected access) + * 1. Write key value to TMR_WFAR reg. + * 2. Write key value to TMP_WSAR reg. + * 3. Perform write operation. + */ +void reset_cpu (unsigned long ignored) +{ +	struct panthmpmu_registers *mpmu = +		(struct panthmpmu_registers *) PANTHEON_MPMU_BASE; +	struct panthtmr_registers *panthtimers = +		(struct panthtmr_registers *) PANTHEON_WD_TIMER_BASE; +	u32 val; + +	/* negate hardware reset to the WDT after system reset */ +	val = readl(&mpmu->aprr); +	val = val | MPMU_APRR_WDTR; +	writel(val, &mpmu->aprr); + +	/* reset/enable WDT clock */ +	writel(APBC_APBCLK, &mpmu->wdtpcr); + +	/* clear previous WDT status */ +	writel(TMR_WFAR, &panthtimers->wfar); +	writel(TMP_WSAR, &panthtimers->wsar); +	writel(0, &panthtimers->wdt_sts); + +	/* set match counter */ +	writel(TMR_WFAR, &panthtimers->wfar); +	writel(TMP_WSAR, &panthtimers->wsar); +	writel(0xf, &panthtimers->wdt_match_r); + +	/* enable WDT reset */ +	writel(TMR_WFAR, &panthtimers->wfar); +	writel(TMP_WSAR, &panthtimers->wsar); +	writel(0x3, &panthtimers->wdt_match_en); + +	/*enable functional WDT clock */ +	writel(APBC_APBCLK | APBC_FNCLK, &mpmu->wdtpcr); +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ +	return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ +	return (ulong)CONFIG_SYS_HZ; +}  | 
