diff options
author | Alexey Zaytsev <alexey.zaytsev@gmail.com> | 2010-12-11 08:18:49 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2010-12-12 09:26:50 +0100 |
commit | adcebd48f6a4387354a099a3c20daac560e635dd (patch) | |
tree | d18d53f0519b86ba8e040bf93b286d4c112cc596 /arch/arm/mach-versatile/core.c | |
parent | cebd35e4e89f35bd79409d68fdc92c53d6ea23e1 (diff) | |
download | barebox-adcebd48f6a4387354a099a3c20daac560e635dd.tar.gz barebox-adcebd48f6a4387354a099a3c20daac560e635dd.tar.xz |
Add basic support from ARM Versatile/PB
tested with qemu only
qemu-system-arm -M versatilepb -monitor null -kernel barebox -net nic -net user -tftp "<uImage-path>/" -serial stdio
add -nographic if you do not want the lcd via sdl
Signed-off-by: Alexey Zaytsev <alexey.zaytsev@gmail.com>
update:
- use default env
- move arm_timer.h as in the kernel
- add nor flash support
- udpate defconfig
- fix copyright copy from linux
- fix ARCH_TEXT_BASE
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/mach-versatile/core.c')
-rw-r--r-- | arch/arm/mach-versatile/core.c | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c new file mode 100644 index 0000000000..ee14f5f7b2 --- /dev/null +++ b/arch/arm/mach-versatile/core.c @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2010 B Labs Ltd, + * http://l4dev.org + * Author: Alexey Zaytsev <alexey.zaytsev@gmail.com> + * + * Based on mach-nomadik + * Copyright (C) 2009 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com> + * + * Copyright (C) 1999 - 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <init.h> +#include <clock.h> +#include <debug_ll.h> + +#include <linux/clkdev.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <asm/io.h> +#include <asm/hardware/arm_timer.h> +#include <asm/armlinux.h> + +#include <mach/platform.h> +#include <mach/init.h> + +static struct memory_platform_data ram_pdata = { + .name = "ram0", + .flags = DEVFS_RDWR, +}; + +static struct device_d sdram_dev = { + .id = -1, + .name = "mem", + .map_base = 0x00000000, + .platform_data = &ram_pdata, +}; + +void versatile_add_sdram(u32 size) +{ + sdram_dev.size = size; + register_device(&sdram_dev); + armlinux_add_dram(&sdram_dev); +} + +static struct device_d uart0_serial_device = { + .id = 0, + .name = "uart-pl011", + .map_base = VERSATILE_UART0_BASE, + .size = 4096, +}; + +static struct device_d uart1_serial_device = { + .id = 1, + .name = "uart-pl011", + .map_base = VERSATILE_UART1_BASE, + .size = 4096, +}; + +static struct device_d uart2_serial_device = { + .id = 2, + .name = "uart-pl011", + .map_base = VERSATILE_UART2_BASE, + .size = 4096, +}; + +static struct device_d uart3_serial_device = { + .id = 3, + .name = "uart-pl011", + .map_base = VERSATILE_UART3_BASE, + .size = 4096, +}; + +struct clk { + unsigned long rate; +}; + +static struct clk ref_clk_24 = { + .rate = 24000000, +}; + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +/* enable and disable do nothing */ +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +/* Create a clock structure with the given name */ +int vpb_clk_create(struct clk *clk, const char *dev_id) +{ + struct clk_lookup *clkdev; + + clkdev = clkdev_alloc(clk, NULL, dev_id); + if (!clkdev) + return -ENOMEM; + + clkdev_add(clkdev); + return 0; +} + +/* 1Mhz / 256 */ +#define TIMER_FREQ (1000000/256) + +#define TIMER0_BASE (VERSATILE_TIMER0_1_BASE) +#define TIMER1_BASE ((VERSATILE_TIMER0_1_BASE) + 0x20) +#define TIMER2_BASE (VERSATILE_TIMER2_3_BASE) +#define TIMER3_BASE ((VERSATILE_TIMER2_3_BASE) + 0x20) + +static uint64_t vpb_clocksource_read(void) +{ + return ~readl(TIMER0_BASE + TIMER_VALUE); +} + +static struct clocksource vpb_cs = { + .read = vpb_clocksource_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 10, +}; + +/* From Linux v2.6.35 + * arch/arm/mach-versatile/core.c */ +static void versatile_timer_init (void) +{ + u32 val; + + /* + * set clock frequency: + * VERSATILE_REFCLK is 32KHz + * VERSATILE_TIMCLK is 1MHz + */ + + val = readl(VERSATILE_SCTL_BASE); + val |= (VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel); + writel(val, VERSATILE_SCTL_BASE); + + /* + * Disable all timers, just to be sure. + */ + + writel(0, TIMER0_BASE + TIMER_CTRL); + writel(0, TIMER1_BASE + TIMER_CTRL); + writel(0, TIMER2_BASE + TIMER_CTRL); + writel(0, TIMER3_BASE + TIMER_CTRL); + + writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_DIV256, + TIMER0_BASE + TIMER_CTRL); +} + +static int vpb_clocksource_init(void) +{ + versatile_timer_init(); + vpb_cs.mult = clocksource_hz2mult(TIMER_FREQ, vpb_cs.shift); + + return init_clock(&vpb_cs); +} + +core_initcall(vpb_clocksource_init); + +void versatile_register_uart(unsigned id) +{ + switch (id) { + case 0: + vpb_clk_create(&ref_clk_24, dev_name(&uart0_serial_device)); + register_device(&uart0_serial_device); + break; + case 1: + vpb_clk_create(&ref_clk_24, dev_name(&uart1_serial_device)); + register_device(&uart1_serial_device); + break; + case 2: + vpb_clk_create(&ref_clk_24, dev_name(&uart2_serial_device)); + register_device(&uart2_serial_device); + break; + case 3: + vpb_clk_create(&ref_clk_24, dev_name(&uart3_serial_device)); + register_device(&uart3_serial_device); + break; + } +} + +void __noreturn reset_cpu (unsigned long ignored) +{ + u32 val; + + val = __raw_readl(VERSATILE_SYS_RESETCTL) & ~0x7; + val |= 0x105; + + __raw_writel(0xa05f, VERSATILE_SYS_LOCK); + __raw_writel(val, VERSATILE_SYS_RESETCTL); + __raw_writel(0, VERSATILE_SYS_LOCK); + + while(1); +} +EXPORT_SYMBOL(reset_cpu); |