#include <asm/arch/usb.h>
#include <asm/arch/board.h>
#include <asm/arch/common.h>
+#include <asm/arch/gpmc.h>
#include "prcm-regs.h"
/* LED & Switch macros */
#define SW_UP_GPIO17 17
#define SW_DOWN_GPIO58 58
+#define APOLLON_FLASH_CS 0
+#define APOLLON_ETH_CS 1
+
static struct mtd_partition apollon_partitions[] = {
{
.name = "X-Loader + U-Boot",
.nr_parts = ARRAY_SIZE(apollon_partitions),
};
-static struct resource apollon_flash_resource = {
- .start = APOLLON_CS0_BASE,
- .end = APOLLON_CS0_BASE + SZ_128K,
- .flags = IORESOURCE_MEM,
+static struct resource apollon_flash_resource[] = {
+ [0] = {
+ .flags = IORESOURCE_MEM,
+ },
};
static struct platform_device apollon_onenand_device = {
.dev = {
.platform_data = &apollon_flash_data,
},
- .num_resources = ARRAY_SIZE(&apollon_flash_resource),
- .resource = &apollon_flash_resource,
+ .num_resources = ARRAY_SIZE(apollon_flash_resource),
+ .resource = apollon_flash_resource,
};
+static void __init apollon_flash_init(void)
+{
+ unsigned long base;
+
+ if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, &base) < 0) {
+ printk(KERN_ERR "Cannot request OneNAND GPMC CS\n");
+ return;
+ }
+ apollon_flash_resource[0].start = base;
+ apollon_flash_resource[0].end = base + SZ_128K - 1;
+}
+
static struct resource apollon_smc91x_resources[] = {
[0] = {
- .start = APOLLON_ETHR_START, /* Physical */
- .end = APOLLON_ETHR_START + 0xf,
.flags = IORESOURCE_MEM,
},
[1] = {
static inline void __init apollon_init_smc91x(void)
{
+ unsigned long base;
+
/* Make sure CS1 timings are correct */
GPMC_CONFIG1_1 = 0x00011203;
GPMC_CONFIG2_1 = 0x001f1f01;
GPMC_CONFIG4_1 = 0x1c091c09;
GPMC_CONFIG5_1 = 0x041f1f1f;
GPMC_CONFIG6_1 = 0x000004c4;
- GPMC_CONFIG7_1 = 0x00000f40 | (APOLLON_CS1_BASE >> 24);
+
+ if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) {
+ printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
+ return;
+ }
+ apollon_smc91x_resources[0].start = base + 0x300;
+ apollon_smc91x_resources[1].end = base + 0x30f;
udelay(100);
omap_cfg_reg(W4__24XX_GPIO74);
if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) {
printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
APOLLON_ETHR_GPIO_IRQ);
+ gpmc_cs_free(APOLLON_ETH_CS);
return;
}
omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1);
{
apollon_led_init();
apollon_sw_init();
+ apollon_flash_init();
/* REVISIT: where's the correct place */
omap_cfg_reg(W19_24XX_SYS_NIRQ);
#include <asm/io.h>
#include <asm/delay.h>
+#define H4_FLASH_CS 0
+#define H4_SMC91X_CS 1
+
static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
};
static struct resource h4_flash_resource = {
- .start = H4_CS0_BASE,
- .end = H4_CS0_BASE + SZ_64M - 1,
.flags = IORESOURCE_MEM,
};
return 0;
}
-#define SMC91X_CS 1
-
static inline void __init h4_init_smc91x(void)
{
int eth_cs;
+ unsigned long cs_mem_base;
unsigned int muxed, rate;
struct clk *l3ck;
- eth_cs = SMC91X_CS;
+ eth_cs = H4_SMC91X_CS;
l3ck = clk_get(NULL, "core_l3_ck");
if (IS_ERR(l3ck))
gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
}
- gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG7,
- 0x00000f40 | (0x08000000 >> 24));
+ if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
+ printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
+ return;
+ }
+ h4_smc91x_resources[0].start = cs_mem_base + 0x300;
+ h4_smc91x_resources[0].end = cs_mem_base + 0x30f;
udelay(100);
omap_cfg_reg(M15_24XX_GPIO92);
if (omap_request_gpio(OMAP24XX_ETHR_GPIO_IRQ) < 0) {
printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
OMAP24XX_ETHR_GPIO_IRQ);
+ gpmc_cs_free(eth_cs);
return;
}
omap_set_gpio_direction(OMAP24XX_ETHR_GPIO_IRQ, 1);
- h4_smc91x_resources[0].start = gpmc_cs_get_base_addr(1) + 0x300;
- h4_smc91x_resources[0].end = h4_smc91x_resources[0].start + 0xf;
+}
+
+static void __init h4_init_flash(void)
+{
+ unsigned long base;
+
+ if (gpmc_cs_request(H4_FLASH_CS, SZ_64M, &base) < 0) {
+ printk("Can't request GPMC CS for flash\n");
+ return;
+ }
+ h4_flash_resource.start = base;
+ h4_flash_resource.end = base + SZ_64M - 1;
}
static void __init omap_h4_init_irq(void)
omap_init_irq();
omap_gpio_init();
h4_init_smc91x();
+ h4_init_flash();
}
static struct omap_uart_config h4_uart_config __initdata = {
#include <linux/init.h>
#include <linux/err.h>
#include <linux/clk.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/arch/gpmc.h>
#define GPMC_CS0 0x60
#define GPMC_CS_SIZE 0x30
+#define GPMC_CS_NUM 8
+#define GPMC_MEM_START 0x00000000
+#define GPMC_MEM_END 0x3FFFFFFF
+#define BOOT_ROM_SPACE 0x100000 /* 1MB */
+
+#define GPMC_CHUNK_SHIFT 24 /* 16 MB */
+#define GPMC_SECTION_SHIFT 28 /* 128 MB */
+
+static struct resource gpmc_mem_root;
+static struct resource gpmc_cs_mem[GPMC_CS_NUM];
+static spinlock_t gpmc_mem_lock = SPIN_LOCK_UNLOCKED;
+static unsigned gpmc_cs_map;
+
static void __iomem *gpmc_base =
(void __iomem *) IO_ADDRESS(GPMC_BASE);
static void __iomem *gpmc_cs_base =
return 0;
}
-unsigned long gpmc_cs_get_base_addr(int cs)
+static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
+{
+ u32 l;
+ u32 mask;
+
+ mask = (1 << GPMC_SECTION_SHIFT) - size;
+ l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+ l &= ~0x3f;
+ l = (base >> GPMC_CHUNK_SHIFT) & 0x3f;
+ l &= ~(0x0f << 8);
+ l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
+ l |= 1 << 6; /* CSVALID */
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_disable_mem(int cs)
+{
+ u32 l;
+
+ l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+ l &= ~(1 << 6); /* CSVALID */
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
+{
+ u32 l;
+ u32 mask;
+
+ l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+ *base = (l & 0x3f) << GPMC_CHUNK_SHIFT;
+ mask = (l >> 8) & 0x0f;
+ *size = (1 << GPMC_SECTION_SHIFT) - (mask << GPMC_CHUNK_SHIFT);
+}
+
+static int gpmc_cs_mem_enabled(int cs)
+{
+ u32 l;
+
+ l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+ return l & (1 << 6);
+}
+
+static void gpmc_cs_set_reserved(int cs, int reserved)
{
- return (gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7) & 0x1f) << 24;
+ gpmc_cs_map &= ~(1 << cs);
+ gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+}
+
+static int gpmc_cs_reserved(int cs)
+{
+ return gpmc_cs_map & (1 << cs);
+}
+
+static unsigned long gpmc_mem_align(unsigned long size)
+{
+ int order;
+
+ size = (size - 1) >> (GPMC_CHUNK_SHIFT - 1);
+ order = GPMC_CHUNK_SHIFT - 1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ size = 1 << order;
+ return size;
+}
+
+static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
+{
+ struct resource *res = &gpmc_cs_mem[cs];
+ int r;
+
+ size = gpmc_mem_align(size);
+ spin_lock(&gpmc_mem_lock);
+ res->start = base;
+ res->end = base + size - 1;
+ r = request_resource(&gpmc_mem_root, res);
+ spin_unlock(&gpmc_mem_lock);
+
+ return r;
+}
+
+int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
+{
+ struct resource *res = &gpmc_cs_mem[cs];
+ int r = -1;
+
+ if (cs > GPMC_CS_NUM)
+ return -ENODEV;
+
+ size = gpmc_mem_align(size);
+ if (size > (1 << GPMC_SECTION_SHIFT))
+ return -ENOMEM;
+
+ spin_lock(&gpmc_mem_lock);
+ if (gpmc_cs_reserved(cs)) {
+ r = -EBUSY;
+ goto out;
+ }
+ if (gpmc_cs_mem_enabled(cs))
+ r = adjust_resource(res, res->start & ~(size - 1), size);
+ if (r < 0)
+ r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
+ size, NULL, NULL);
+ if (r < 0)
+ goto out;
+
+ gpmc_cs_enable_mem(cs, res->start, res->end - res->start + 1);
+ *base = res->start;
+ gpmc_cs_set_reserved(cs, 1);
+out:
+ spin_unlock(&gpmc_mem_lock);
+ return r;
+}
+
+void gpmc_cs_free(int cs)
+{
+ spin_lock(&gpmc_mem_lock);
+ if (cs >= GPMC_CS_NUM || !gpmc_cs_reserved(cs)) {
+ printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
+ BUG();
+ spin_unlock(&gpmc_mem_lock);
+ return;
+ }
+ gpmc_cs_disable_mem(cs);
+ release_resource(&gpmc_cs_mem[cs]);
+ gpmc_cs_set_reserved(cs, 0);
+ spin_unlock(&gpmc_mem_lock);
+}
+
+void __init gpmc_mem_init(void)
+{
+ int cs;
+ unsigned long boot_rom_space = 0;
+
+ if (cpu_is_omap242x()) {
+ u32 l;
+ l = omap_readl(OMAP242X_CONTROL_STATUS);
+ /* In case of internal boot the 1st MB is redirected to the
+ * boot ROM memory space.
+ */
+ if (l & (1 << 3))
+ boot_rom_space = BOOT_ROM_SPACE;
+ } else
+ /* We assume internal boot if the mode can't be
+ * determined.
+ */
+ boot_rom_space = BOOT_ROM_SPACE;
+ gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
+ gpmc_mem_root.end = GPMC_MEM_END;
+
+ /* Reserve all regions that has been set up by bootloader */
+ for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+ u32 base, size;
+
+ if (!gpmc_cs_mem_enabled(cs))
+ continue;
+ gpmc_cs_get_memconf(cs, &base, &size);
+ if (gpmc_cs_insert_mem(cs, base, size) < 0)
+ BUG();
+ }
}
void __init gpmc_init(void)
l &= 0x03 << 3;
l |= (0x02 << 3) | (1 << 0);
gpmc_write_reg(GPMC_SYSCONFIG, l);
+
+ gpmc_mem_init();
}
#define __ASM_ARCH_OMAP_APOLLON_H
/* Placeholder for APOLLON specific defines */
-/* GPMC CS0 */
-#define APOLLON_CS0_BASE 0x00000000
-/* GPMC CS1 */
-#define APOLLON_CS1_BASE 0x08000000
-#define APOLLON_ETHR_START (APOLLON_CS1_BASE + 0x300)
#define APOLLON_ETHR_GPIO_IRQ 74
-/* GPMC CS2 - reserved for OneNAND */
-#define APOLLON_CS2_BASE 0x10000000
-/* GPMC CS3 - reserved for NOR or NAND */
-#define APOLLON_CS3_BASE 0x18000000
#endif /* __ASM_ARCH_OMAP_APOLLON_H */
/* Placeholder for H4 specific defines */
#define OMAP24XX_ETHR_GPIO_IRQ 92
-#define H4_CS0_BASE 0x04000000
#endif /* __ASM_ARCH_OMAP_H4_H */
extern u32 gpmc_cs_read_reg(int cs, int idx);
extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk);
extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
-extern unsigned long gpmc_cs_get_base_addr(int cs);
-
+extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
+extern void gpmc_cs_free(int cs);
#endif