diff options
Diffstat (limited to 'roms/u-boot/arch/arm/cpu/arm920t/ep93xx')
-rw-r--r-- | roms/u-boot/arch/arm/cpu/arm920t/ep93xx/Makefile | 21 | ||||
-rw-r--r-- | roms/u-boot/arch/arm/cpu/arm920t/ep93xx/cpu.c | 37 | ||||
-rw-r--r-- | roms/u-boot/arch/arm/cpu/arm920t/ep93xx/led.c | 85 | ||||
-rw-r--r-- | roms/u-boot/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S | 49 | ||||
-rw-r--r-- | roms/u-boot/arch/arm/cpu/arm920t/ep93xx/speed.c | 96 | ||||
-rw-r--r-- | roms/u-boot/arch/arm/cpu/arm920t/ep93xx/timer.c | 120 | ||||
-rw-r--r-- | roms/u-boot/arch/arm/cpu/arm920t/ep93xx/u-boot.lds | 57 |
7 files changed, 465 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/Makefile b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/Makefile new file mode 100644 index 00000000..638333a4 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/Makefile @@ -0,0 +1,21 @@ +# +# Cirrus Logic EP93xx CPU-specific Makefile +# +# Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> +# +# Copyright (C) 2004, 2005 +# Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> +# +# Copyright (C) 2006 +# Dominic Rath <Dominic.Rath@gmx.de> +# +# Based on an original Makefile, which is +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o led.o speed.o timer.o +obj-y += lowlevel_init.o diff --git a/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/cpu.c b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/cpu.c new file mode 100644 index 00000000..bb5ffd29 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/cpu.c @@ -0,0 +1,37 @@ +/* + * Cirrus Logic EP93xx CPU-specific support. + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * Copyright (C) 2004, 2005 + * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/ep93xx.h> +#include <asm/io.h> + +/* We reset the CPU by generating a 1-->0 transition on DeviceCfg bit 31. */ +extern void reset_cpu(ulong addr) +{ + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + uint32_t value; + + /* Unlock DeviceCfg and set SWRST */ + writel(0xAA, &syscon->sysswlock); + value = readl(&syscon->devicecfg); + value |= SYSCON_DEVICECFG_SWRST; + writel(value, &syscon->devicecfg); + + /* Unlock DeviceCfg and clear SWRST */ + writel(0xAA, &syscon->sysswlock); + value = readl(&syscon->devicecfg); + value &= ~SYSCON_DEVICECFG_SWRST; + writel(value, &syscon->devicecfg); + + /* Dying... */ + while (1) + ; /* noop */ +} diff --git a/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/led.c b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/led.c new file mode 100644 index 00000000..61447291 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/led.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2010, 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/io.h> +#include <asm/arch/ep93xx.h> +#include <config.h> +#include <status_led.h> + +static uint8_t saved_state[2] = {STATUS_LED_OFF, STATUS_LED_OFF}; +static uint32_t gpio_pin[2] = {1 << STATUS_LED_GREEN, + 1 << STATUS_LED_RED}; + +inline void switch_LED_on(uint8_t led) +{ + register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE; + + writel(readl(&gpio->pedr) | gpio_pin[led], &gpio->pedr); + saved_state[led] = STATUS_LED_ON; +} + +inline void switch_LED_off(uint8_t led) +{ + register struct gpio_regs *gpio = (struct gpio_regs *)GPIO_BASE; + + writel(readl(&gpio->pedr) & ~gpio_pin[led], &gpio->pedr); + saved_state[led] = STATUS_LED_OFF; +} + +void red_led_on(void) +{ + switch_LED_on(STATUS_LED_RED); +} + +void red_led_off(void) +{ + switch_LED_off(STATUS_LED_RED); +} + +void green_led_on(void) +{ + switch_LED_on(STATUS_LED_GREEN); +} + +void green_led_off(void) +{ + switch_LED_off(STATUS_LED_GREEN); +} + +void __led_init(led_id_t mask, int state) +{ + __led_set(mask, state); +} + +void __led_toggle(led_id_t mask) +{ + if (STATUS_LED_RED == mask) { + if (STATUS_LED_ON == saved_state[STATUS_LED_RED]) + red_led_off(); + else + red_led_on(); + } else if (STATUS_LED_GREEN == mask) { + if (STATUS_LED_ON == saved_state[STATUS_LED_GREEN]) + green_led_off(); + else + green_led_on(); + } +} + +void __led_set(led_id_t mask, int state) +{ + if (STATUS_LED_RED == mask) { + if (STATUS_LED_ON == state) + red_led_on(); + else + red_led_off(); + } else if (STATUS_LED_GREEN == mask) { + if (STATUS_LED_ON == state) + green_led_on(); + else + green_led_off(); + } +} diff --git a/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S new file mode 100644 index 00000000..bf2fa2ac --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/lowlevel_init.S @@ -0,0 +1,49 @@ +/* + * Low-level initialization for EP93xx + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * Copyright (C) 2006 Dominic Rath <Dominic.Rath@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <version.h> +#include <asm/arch/ep93xx.h> + +.globl lowlevel_init +lowlevel_init: + /* backup return address */ + ldr r1, =SYSCON_SCRATCH0 + str lr, [r1] + + /* Turn on both LEDs */ + bl red_led_on + bl green_led_on + + /* Configure flash wait states before we switch to the PLL */ + bl flash_cfg + + /* Set up PLL */ + bl pll_cfg + + /* Turn off the Green LED and leave the Red LED on */ + bl green_led_off + + /* Setup SDRAM */ + bl sdram_cfg + + /* Turn on Green LED, Turn off the Red LED */ + bl green_led_on + bl red_led_off + + /* FIXME: we use async mode for now */ + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0xc0000000 + mcr p15, 0, r0, c1, c0, 0 + + /* restore return address */ + ldr r1, =SYSCON_SCRATCH0 + ldr lr, [r1] + + mov pc, lr diff --git a/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/speed.c b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/speed.c new file mode 100644 index 00000000..9dc60b6f --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/speed.c @@ -0,0 +1,96 @@ +/* + * Cirrus Logic EP93xx PLL support. + * + * Copyright (C) 2009 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/arch/ep93xx.h> +#include <asm/io.h> +#include <div64.h> + +/* + * CONFIG_SYS_CLK_FREQ should be defined as the input frequency of the PLL. + * + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ + +/* + * return the PLL output frequency + * + * PLL rate = CONFIG_SYS_CLK_FREQ * (X1FBD + 1) * (X2FBD + 1) + * / (X2IPD + 1) / 2^PS + */ +static ulong get_PLLCLK(uint32_t *pllreg) +{ + uint8_t i; + const uint32_t clkset = readl(pllreg); + uint64_t rate = CONFIG_SYS_CLK_FREQ; + rate *= ((clkset >> SYSCON_CLKSET_PLL_X1FBD1_SHIFT) & 0x1f) + 1; + rate *= ((clkset >> SYSCON_CLKSET_PLL_X2FBD2_SHIFT) & 0x3f) + 1; + do_div(rate, (clkset & 0x1f) + 1); /* X2IPD */ + for (i = 0; i < ((clkset >> SYSCON_CLKSET_PLL_PS_SHIFT) & 3); i++) + rate >>= 1; + + return (ulong)rate; +} + +/* return FCLK frequency */ +ulong get_FCLK() +{ + const uint8_t fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + + const uint32_t clkset1 = readl(&syscon->clkset1); + const uint8_t fclk_div = + fclk_divisors[(clkset1 >> SYSCON_CLKSET1_FCLK_DIV_SHIFT) & 7]; + const ulong fclk_rate = get_PLLCLK(&syscon->clkset1) / fclk_div; + + return fclk_rate; +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + const uint8_t hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + + const uint32_t clkset1 = readl(&syscon->clkset1); + const uint8_t hclk_div = + hclk_divisors[(clkset1 >> SYSCON_CLKSET1_HCLK_DIV_SHIFT) & 7]; + const ulong hclk_rate = get_PLLCLK(&syscon->clkset1) / hclk_div; + + return hclk_rate; +} + +/* return PCLK frequency */ +ulong get_PCLK(void) +{ + const uint8_t pclk_divisors[] = { 1, 2, 4, 8 }; + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + + const uint32_t clkset1 = readl(&syscon->clkset1); + const uint8_t pclk_div = + pclk_divisors[(clkset1 >> SYSCON_CLKSET1_PCLK_DIV_SHIFT) & 3]; + const ulong pclk_rate = get_HCLK() / pclk_div; + + return pclk_rate; +} + +/* return UCLK frequency */ +ulong get_UCLK(void) +{ + struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; + ulong uclk_rate; + + const uint32_t value = readl(&syscon->pwrcnt); + if (value & SYSCON_PWRCNT_UART_BAUD) + uclk_rate = CONFIG_SYS_CLK_FREQ; + else + uclk_rate = CONFIG_SYS_CLK_FREQ / 2; + + return uclk_rate; +} diff --git a/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/timer.c b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/timer.c new file mode 100644 index 00000000..c2f239aa --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/timer.c @@ -0,0 +1,120 @@ +/* + * Cirrus Logic EP93xx timer support. + * + * Copyright (C) 2009, 2010 Matthias Kaehlcke <matthias@kaehlcke.net> + * + * Copyright (C) 2004, 2005 + * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com> + * + * Based on the original intr.c Cirrus Logic EP93xx Rev D. interrupt support, + * author unknown. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <linux/types.h> +#include <asm/arch/ep93xx.h> +#include <asm/io.h> +#include <div64.h> + +#define TIMER_CLKSEL (1 << 3) +#define TIMER_ENABLE (1 << 7) + +#define TIMER_FREQ 508469 /* ticks / second */ +#define TIMER_MAX_VAL 0xFFFFFFFF + +static struct ep93xx_timer +{ + unsigned long long ticks; + unsigned long last_read; +} timer; + +static inline unsigned long long usecs_to_ticks(unsigned long usecs) +{ + unsigned long long ticks = (unsigned long long)usecs * TIMER_FREQ; + do_div(ticks, 1000 * 1000); + + return ticks; +} + +static inline void read_timer(void) +{ + struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE; + const unsigned long now = TIMER_MAX_VAL - readl(&timer_regs->timer3.value); + + if (now >= timer.last_read) + timer.ticks += now - timer.last_read; + else + /* an overflow occurred */ + timer.ticks += TIMER_MAX_VAL - timer.last_read + now; + + timer.last_read = now; +} + +/* + * Get the number of ticks (in CONFIG_SYS_HZ resolution) + */ +unsigned long long get_ticks(void) +{ + unsigned long long sys_ticks; + + read_timer(); + + sys_ticks = timer.ticks * CONFIG_SYS_HZ; + do_div(sys_ticks, TIMER_FREQ); + + return sys_ticks; +} + +unsigned long get_timer_masked(void) +{ + return get_ticks(); +} + +unsigned long get_timer(unsigned long base) +{ + return get_timer_masked() - base; +} + +void __udelay(unsigned long usec) +{ + unsigned long long target; + + read_timer(); + + target = timer.ticks + usecs_to_ticks(usec); + + while (timer.ticks < target) + read_timer(); +} + +int timer_init(void) +{ + struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE; + + /* use timer 3 with 508KHz and free running, not enabled now */ + writel(TIMER_CLKSEL, &timer_regs->timer3.control); + + /* set initial timer value */ + writel(TIMER_MAX_VAL, &timer_regs->timer3.load); + + /* Enable the timer */ + writel(TIMER_ENABLE | TIMER_CLKSEL, + &timer_regs->timer3.control); + + /* Reset the timer */ + read_timer(); + timer.ticks = 0; + + return 0; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +unsigned long get_tbclk(void) +{ + return CONFIG_SYS_HZ; +} diff --git a/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/u-boot.lds b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/u-boot.lds new file mode 100644 index 00000000..96994043 --- /dev/null +++ b/roms/u-boot/arch/arm/cpu/arm920t/ep93xx/u-boot.lds @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.__image_copy_start) + arch/arm/cpu/arm920t/start.o (.text*) + /* the EP93xx expects to find the pattern 'CRUS' at 0x1000 */ + . = 0x1000; + LONG(0x53555243) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(.rodata*) } + + . = ALIGN(4); + .data : { *(.data*) } + + . = ALIGN(4); + .got : { *(.got) } + + . = .; + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + + .image_copy_end : + { + *(.__image_copy_end) + } + + __bss_start = .; + .bss : { *(.bss*) } + __bss_end = .; + + .end : + { + *(.__end) + } +} |