@@ -24,3 +24,7 @@ obj-$(CONFIG_MACH_SPEAR320) += spear320.o
# spear320 boards files
obj-$(CONFIG_BOARD_SPEAR320_EVB) += spear320_evb.o
+
+# specific files
+obj-$(CONFIG_MACH_SPEAR310) += emi.o
+obj-$(CONFIG_MACH_SPEAR320) += emi.o
new file mode 100644
@@ -0,0 +1,101 @@
+/*
+ * arch/arm/mach-spear3xx/emi.c
+ *
+ * EMI (External Memory Interface) file
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Vipin Kumar<vipin.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <mach/emi.h>
+
+int __init emi_init(struct platform_device *pdev, unsigned long base,
+ u32 bank, u32 width)
+{
+ void __iomem *emi_reg_base;
+ struct clk *clk;
+ int ret;
+
+ if (bank > (EMI_MAX_BANKS - 1))
+ return -EINVAL;
+
+ emi_reg_base = ioremap(base, EMI_REG_SIZE);
+ if (!emi_reg_base)
+ return -ENOMEM;
+
+ clk = clk_get(NULL, "emi");
+ if (IS_ERR(clk)) {
+ iounmap(emi_reg_base);
+ return PTR_ERR(clk);
+ }
+
+ ret = clk_enable(clk);
+ if (ret) {
+ iounmap(emi_reg_base);
+ return ret;
+ }
+
+ /*
+ * Note: These are relaxed NOR device timings. Nor devices on spear
+ * eval machines are working fine with these timings. Specific board
+ * files can optimize these timings based on devices found on board.
+ */
+ writel(0x10, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TAP_REG);
+ writel(0x05, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TSDP_REG);
+ writel(0x0a, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TDPW_REG);
+ writel(0x0a, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TDPR_REG);
+ writel(0x05, emi_reg_base + (EMI_BANK_REG_SIZE * bank) + TDCS_REG);
+
+ switch (width) {
+ case EMI_FLASH_WIDTH8:
+ width = EMI_CNTL_WIDTH8;
+ break;
+
+ case EMI_FLASH_WIDTH16:
+ width = EMI_CNTL_WIDTH16;
+ break;
+
+ case EMI_FLASH_WIDTH32:
+ width = EMI_CNTL_WIDTH32;
+ break;
+ default:
+ width = EMI_CNTL_WIDTH8;
+ break;
+ }
+ /* set the data width */
+ writel(width | EMI_CNTL_ENBBYTERW,
+ emi_reg_base + (EMI_BANK_REG_SIZE * bank) + CTRL_REG);
+
+ /* disable all the acks */
+ writel(0x3f, emi_reg_base + ack_reg);
+
+ iounmap(emi_reg_base);
+
+ return 0;
+}
+
+void __init
+emi_init_board_info(struct platform_device *pdev, struct resource *resources,
+ int res_num, struct mtd_partition *partitions,
+ unsigned int nr_partitions, unsigned int width)
+{
+ struct physmap_flash_data *emi_plat_data = dev_get_platdata(&pdev->dev);
+
+ pdev->resource = resources;
+ pdev->num_resources = res_num;
+
+ if (partitions) {
+ emi_plat_data->parts = partitions;
+ emi_plat_data->nr_parts = nr_partitions;
+ }
+
+ emi_plat_data->width = width;
+}
new file mode 100644
@@ -0,0 +1,64 @@
+/*
+ * arch/arm/mach-spear3xx/include/mach/emi.h
+ *
+ * EMI macros for SPEAr platform
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Vipin Kumar <vipin.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_EMI_H
+#define __MACH_EMI_H
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+
+#define EMI_FLASH_WIDTH8 1
+#define EMI_FLASH_WIDTH16 2
+#define EMI_FLASH_WIDTH32 4
+
+#define EMI_REG_SIZE 0x100
+#define EMI_BANK_REG_SIZE 0x18
+
+#define TAP_REG (0x0)
+#define TSDP_REG (0x4)
+#define TDPW_REG (0x8)
+#define TDPR_REG (0xC)
+#define TDCS_REG (0x10)
+#define CTRL_REG (0x14)
+
+#if defined(CONFIG_MACH_SPEAR310)
+#define TIMEOUT_REG (0x90)
+#define ACK_REG (0x94)
+#define IRQ_REG (0x98)
+
+#define EMI_MAX_BANKS 6
+
+#elif defined(CONFIG_MACH_SPEAR320)
+#define TIMEOUT_REG (0x60)
+#define ACK_REG (0x64)
+#define IRQ_REG (0x68)
+
+#define EMI_MAX_BANKS 4
+
+#endif
+
+/* Control register definitions */
+#define EMI_CNTL_WIDTH8 (0 << 0)
+#define EMI_CNTL_WIDTH16 (1 << 0)
+#define EMI_CNTL_WIDTH32 (2 << 0)
+#define EMI_CNTL_ENBBYTEW (1 << 2)
+#define EMI_CNTL_ENBBYTER (1 << 3)
+#define EMI_CNTL_ENBBYTERW (EMI_CNTL_ENBBYTER | EMI_CNTL_ENBBYTEW)
+
+extern int __init emi_init(struct platform_device *pdev, unsigned long base,
+ u32 bank, u32 width);
+extern void __init emi_init_board_info(struct platform_device *pdev,
+ struct resource *resources, int res_num, struct mtd_partition
+ *partitions, unsigned int nr_partitions, unsigned int width);
+#endif
@@ -166,6 +166,7 @@ extern struct amba_device uart2_device;
extern struct amba_device uart3_device;
extern struct amba_device uart4_device;
extern struct amba_device uart5_device;
+extern struct platform_device emi_nor_device;
extern struct platform_device plgpio_device;
extern struct platform_device nand_device;
@@ -191,6 +192,7 @@ extern struct amba_device uart1_device;
extern struct amba_device uart2_device;
extern struct platform_device can0_device;
extern struct platform_device can1_device;
+extern struct platform_device emi_nor_device;
extern struct platform_device i2c1_device;
extern struct platform_device nand_device;
extern struct platform_device plgpio_device;
@@ -18,6 +18,15 @@
#define SPEAR310_NAND_BASE UL(0x40000000)
#define SPEAR310_FSMC_BASE UL(0x44000000)
+#define SPEAR310_EMI_REG_BASE UL(0x4F000000)
+#define SPEAR310_EMI_MEM_0_BASE UL(0x50000000)
+#define SPEAR310_EMI_MEM_1_BASE UL(0x60000000)
+#define SPEAR310_EMI_MEM_2_BASE UL(0x70000000)
+#define SPEAR310_EMI_MEM_3_BASE UL(0x80000000)
+#define SPEAR310_EMI_MEM_4_BASE UL(0x90000000)
+#define SPEAR310_EMI_MEM_5_BASE UL(0xA0000000)
+#define SPEAR310_EMI_MEM_SIZE UL(0x10000000)
+
#define SPEAR310_UART1_BASE UL(0xB2000000)
#define SPEAR310_UART2_BASE UL(0xB2080000)
#define SPEAR310_UART3_BASE UL(0xB2100000)
@@ -17,6 +17,12 @@
#define __MACH_SPEAR320_H
#define SPEAR320_EMI_CTRL_BASE UL(0x40000000)
+#define SPEAR320_EMI_MEM_0_BASE UL(0x44000000)
+#define SPEAR320_EMI_MEM_1_BASE UL(0x45000000)
+#define SPEAR320_EMI_MEM_2_BASE UL(0x46000000)
+#define SPEAR320_EMI_MEM_3_BASE UL(0x47000000)
+#define SPEAR320_EMI_MEM_SIZE UL(0x01000000)
+
#define SPEAR320_FSMC_BASE UL(0x4C000000)
#define SPEAR320_NAND_BASE UL(0x50000000)
#define SPEAR320_I2S_BASE UL(0x60000000)
@@ -11,6 +11,7 @@
* warranty of any kind, whether express or implied.
*/
+#include <linux/mtd/physmap.h>
#include <linux/ptrace.h>
#include <mtd/fsmc.h>
#include <asm/irq.h>
@@ -268,6 +269,14 @@ int spear300_o2p(int offset)
return offset + 2;
}
+/* emi nor flash device registeration */
+static struct physmap_flash_data emi_norflash_data;
+struct platform_device emi_nor_device = {
+ .name = "physmap-flash",
+ .id = -1,
+ .dev.platform_data = &emi_norflash_data,
+};
+
static struct plgpio_platform_data plgpio_plat_data = {
.gpio_base = 8,
.irq_base = SPEAR_PLGPIO_INT_BASE,
@@ -17,6 +17,7 @@
#include <asm/mach-types.h>
#include <linux/spi/flash.h>
#include <linux/spi/spi.h>
+#include <mach/emi.h>
#include <mach/generic.h>
#include <mach/gpio.h>
#include <mach/spear.h>
@@ -24,6 +25,24 @@
#include <plat/smi.h>
#include <plat/spi.h>
+#define PARTITION(n, off, sz) {.name = n, .offset = off, .size = sz}
+
+static struct mtd_partition partition_info[] = {
+ PARTITION("X-loader", 0, 1 * 0x20000),
+ PARTITION("U-Boot", 0x20000, 3 * 0x20000),
+ PARTITION("Kernel", 0x80000, 24 * 0x20000),
+ PARTITION("Root File System", 0x380000, 84 * 0x20000),
+};
+
+/* emi nor flash resources registeration */
+static struct resource emi_nor_resources[] = {
+ {
+ .start = SPEAR310_EMI_MEM_0_BASE,
+ .end = SPEAR310_EMI_MEM_0_BASE + SPEAR310_EMI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
/* padmux devices to enable */
static struct pmx_dev *pmx_devs[] = {
/* spear3xx specific devices */
@@ -61,6 +80,7 @@ static struct amba_device *amba_devs[] __initdata = {
static struct platform_device *plat_devs[] __initdata = {
/* spear3xx specific devices */
&ehci_device,
+ &emi_nor_device,
&i2c_device,
&nand_device,
&ohci0_device,
@@ -129,6 +149,11 @@ static void __init spear310_evb_init(void)
/* initialize serial nor related data in smi plat data */
smi_init_board_info(&smi_device);
+ /* initialize emi related data in emi plat data */
+ emi_init_board_info(&emi_nor_device, emi_nor_resources,
+ ARRAY_SIZE(emi_nor_resources), partition_info,
+ ARRAY_SIZE(partition_info), EMI_FLASH_WIDTH32);
+
/* Add Platform Devices */
platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
@@ -136,6 +161,9 @@ static void __init spear310_evb_init(void)
for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
amba_device_register(amba_devs[i], &iomem_resource);
+ /* Initialize emi regiters */
+ emi_init(&emi_nor_device, SPEAR310_EMI_REG_BASE, 0, EMI_FLASH_WIDTH32);
+
spi_init();
}
@@ -12,6 +12,7 @@
*/
#include <linux/amba/pl022.h>
+#include <linux/mtd/physmap.h>
#include <linux/ptrace.h>
#include <linux/types.h>
#include <linux/mmc/sdhci-spear.h>
@@ -473,6 +474,14 @@ struct amba_device uart2_device = {
.irq = {VIRQ_UART2, NO_IRQ},
};
+/* emi nor flash device registeration */
+static struct physmap_flash_data emi_norflash_data;
+struct platform_device emi_nor_device = {
+ .name = "physmap-flash",
+ .id = -1,
+ .dev.platform_data = &emi_norflash_data,
+};
+
/* plgpio device registeration */
static struct plgpio_platform_data plgpio_plat_data = {
.gpio_base = 8,
@@ -18,6 +18,7 @@
#include <linux/spi/flash.h>
#include <linux/mmc/sdhci-spear.h>
#include <linux/spi/spi.h>
+#include <mach/emi.h>
#include <mach/generic.h>
#include <mach/gpio.h>
#include <mach/spear.h>
@@ -25,6 +26,24 @@
#include <plat/smi.h>
#include <plat/spi.h>
+#define PARTITION(n, off, sz) {.name = n, .offset = off, .size = sz}
+
+static struct mtd_partition partition_info[] = {
+ PARTITION("X-loader", 0, 1 * 0x20000),
+ PARTITION("U-Boot", 0x20000, 3 * 0x20000),
+ PARTITION("Kernel", 0x80000, 24 * 0x20000),
+ PARTITION("Root File System", 0x380000, 84 * 0x20000),
+};
+
+/* emi nor flash resources registeration */
+static struct resource emi_nor_resources[] = {
+ {
+ .start = SPEAR310_EMI_MEM_0_BASE,
+ .end = SPEAR310_EMI_MEM_0_BASE + SPEAR310_EMI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
/* padmux devices to enable */
static struct pmx_dev *pmx_devs[] = {
/* spear3xx specific devices */
@@ -116,6 +135,11 @@ static void __init spear320_evb_init(void)
/* Register slave devices on the I2C buses */
i2c_register_board_devices();
+ /* initialize emi related data in emi plat data */
+ emi_init_board_info(&emi_nor_device, emi_nor_resources,
+ ARRAY_SIZE(emi_nor_resources), partition_info,
+ ARRAY_SIZE(partition_info), EMI_FLASH_WIDTH16);
+
/* Add Platform Devices */
platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
@@ -123,6 +147,9 @@ static void __init spear320_evb_init(void)
for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
amba_device_register(amba_devs[i], &iomem_resource);
+ /* Initialize emi regiters */
+ emi_init(&emi_nor_device, SPEAR320_EMI_CTRL_BASE, 0, EMI_FLASH_WIDTH16);
+
spi_init();
}