From 7bb7b33a87e277cb2e60cbd3f1b790d095c7150e Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 14 Feb 2008 12:06:40 +0900 Subject: [PATCH] ARM: OMAP: Register external NOR flash at apollon Yes, memory configuration is done by bootloader. But some users don't want to update their bootloader. So it set at kernel. Signed-off-by: Kyungmin Park Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-apollon.c | 151 +++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 2ee24a8cf33..6c2bfdb6ec4 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/mach-omap2/board-apollon.c * - * Copyright (C) 2005,2006 Samsung Electronics + * Copyright (C) 2005-2008 Samsung Electronics * Author: Kyungmin Park * * Modified from mach-omap2/board-h4.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -53,6 +54,10 @@ #define APOLLON_FLASH_CS 0 #define APOLLON_ETH_CS 1 +#define APOLLON_NOR_CS 3 + +#define APOLLON_ONENAND_CS2_ADDRESS (0x00000e40 | (0x10000000 >> 24)) +#define APOLLON_EXT_CS3_ADDRESS (0x00000c40 | (0x18000000 >> 24)) static struct mtd_partition apollon_partitions[] = { { @@ -109,6 +114,63 @@ static struct platform_device apollon_onenand_device = { .resource = apollon_flash_resource, }; +static struct mtd_partition apollon_nor_partitions[] = { + { + .name = "U-Boot", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE, + }, + { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + }, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = SZ_4M - SZ_256K, + }, + { + .name = "application", + .offset = MTDPART_OFS_APPEND, + .size = SZ_8M + SZ_2M, + }, + { + .name = "reserved", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct flash_platform_data apollon_nor_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = apollon_nor_partitions, + .nr_parts = ARRAY_SIZE(apollon_nor_partitions), +}; + +static struct resource apollon_nor_resource[] = { + [0] = { + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device apollon_nor_device = { + .name = "omapflash", + .id = -1, + .dev = { + .platform_data = &apollon_nor_data, + }, + .num_resources = ARRAY_SIZE(apollon_nor_resource), + .resource = apollon_nor_resource, +}; + static void __init apollon_flash_init(void) { unsigned long base; @@ -119,6 +181,13 @@ static void __init apollon_flash_init(void) } apollon_flash_resource[0].start = base; apollon_flash_resource[0].end = base + SZ_128K - 1; + + if (gpmc_cs_request(APOLLON_NOR_CS, SZ_32M, &base) < 0) { + printk(KERN_ERR "Cannot request NOR GPMC CS\n"); + return; + } + apollon_nor_resource[0].start = base; + apollon_nor_resource[0].end = base + SZ_32M - 1; } static struct resource apollon_smc91x_resources[] = { @@ -194,6 +263,7 @@ static struct platform_device apollon_led_device = { static struct platform_device *apollon_devices[] __initdata = { &apollon_onenand_device, + &apollon_nor_device, &apollon_smc91x_device, &apollon_lcd_device, &apollon_led_device, @@ -366,8 +436,87 @@ static void __init apollon_tsc_init(void) omap_cfg_reg(W14_24XX_SYS_CLKOUT); /* mclk */ } +static void __init apollon_cs_init(void) +{ + unsigned long base; + unsigned int rate; + struct clk *l3ck; + u32 value; + int cs, sync = 0; + + l3ck = clk_get(NULL, "core_l3_ck"); + if (IS_ERR(l3ck)) + rate = 100000000; + else + rate = clk_get_rate(l3ck); + + /* CS2: OneNAND */ + cs = 2; + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG1); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG2); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG3); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG4); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG5); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, value); + value = gpmc_cs_read_reg(0, GPMC_CS_CONFIG6); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, value); + + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, APOLLON_ONENAND_CS2_ADDRESS); + + /* CS3: External NOR */ + cs = APOLLON_NOR_CS; + if (rate >= 160000000) { + sync = 1; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0xe5011211); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00090b01); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00020201); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x09030b03); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x010a0a0c); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000); + } else if (rate >= 130000000) { + /* Not yet know ... Use the async values */ + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0x00021201); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00121601); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00040401); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x12061605); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x01151317); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000); + } else {/* rate = 100000000 */ + sync = 1; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, 0xe1001202); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, 0x00151501); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, 0x00050501); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, 0x0e070e07); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG5, 0x01131F1F); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, 0x00000000); + } + + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, APOLLON_EXT_CS3_ADDRESS); + + if (gpmc_cs_request(cs, SZ_32M, &base) < 0) { + printk(KERN_ERR "Failed to request GPMC CS for external\n"); + return; + } + + /* Synchronous mode */ + if (sync) { + void __iomem *addr = ioremap(base, SZ_32M); + writew(0xaa, addr + 0xaaa); + writew(0x55, addr + 0x554); + writew(0xc0, addr + 0x24aaa); + iounmap(addr); + } + + gpmc_cs_free(cs); +} + static void __init omap_apollon_init(void) { + apollon_cs_init(); apollon_led_init(); apollon_flash_init(); apollon_usb_init(); -- 2.41.1