Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V6 08/17] ST SPEAr3xx: EMI (External Memory Interface) controller driver
From: Viresh Kumar @ 2011-03-01 11:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar@st.com>

Two SPEAr platform SoCs(spear310 and spear320) support an External Memory
Interface controller. This controller is used to interface with
Parallel NOR Flash devices.

This patch adds just the platform code needed for EMI (mainly EMI
initialization). The driver being used is driver/mtd/maps/physmap.c

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/mach-spear3xx/Makefile                |    4 +
 arch/arm/mach-spear3xx/emi.c                   |   98 ++++++++++++++++++++++++
 arch/arm/mach-spear3xx/include/mach/emi.h      |   61 +++++++++++++++
 arch/arm/mach-spear3xx/include/mach/spear310.h |    9 ++
 arch/arm/mach-spear3xx/include/mach/spear320.h |    6 ++
 arch/arm/mach-spear3xx/spear310_evb.c          |   35 +++++++++
 arch/arm/mach-spear3xx/spear320_evb.c          |   35 +++++++++
 7 files changed, 248 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-spear3xx/emi.c
 create mode 100644 arch/arm/mach-spear3xx/include/mach/emi.h

diff --git a/arch/arm/mach-spear3xx/Makefile b/arch/arm/mach-spear3xx/Makefile
index b248624..d38ae47 100644
--- a/arch/arm/mach-spear3xx/Makefile
+++ b/arch/arm/mach-spear3xx/Makefile
@@ -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
diff --git a/arch/arm/mach-spear3xx/emi.c b/arch/arm/mach-spear3xx/emi.c
new file mode 100644
index 0000000..4d01322
--- /dev/null
+++ b/arch/arm/mach-spear3xx/emi.c
@@ -0,0 +1,98 @@
+/*
+ * 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 <asm/mach-types.h>
+#include <mach/emi.h>
+
+int __init emi_init(unsigned long base, u32 bank, u32 width)
+{
+	void __iomem *emi_reg_base;
+	struct clk *clk;
+	int ret;
+	u32 ack_reg, max_banks;
+	/* u32 timeout_reg, irq_reg; */
+
+	/* fixing machine dependent values */
+	if (machine_is_spear310()) {
+		ack_reg = SPEAR310_ACK_REG;
+		max_banks = SPEAR310_EMI_MAX_BANKS;
+		/* timeout_reg = SPEAR310_TIMEOUT_REG; */
+		/* irq_reg = SPEAR310_IRQ_REG; */
+	} else {
+		ack_reg = SPEAR320_ACK_REG;
+		max_banks = SPEAR320_EMI_MAX_BANKS;
+		/* timeout_reg = SPEAR320_TIMEOUT_REG; */
+		/* irq_reg = SPEAR320_IRQ_REG; */
+	}
+
+	if (bank > (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;
+}
diff --git a/arch/arm/mach-spear3xx/include/mach/emi.h b/arch/arm/mach-spear3xx/include/mach/emi.h
new file mode 100644
index 0000000..c15b12e
--- /dev/null
+++ b/arch/arm/mach-spear3xx/include/mach/emi.h
@@ -0,0 +1,61 @@
+/*
+ * 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 SPEAR310_TIMEOUT_REG	(0x90)
+#define SPEAR310_ACK_REG	(0x94)
+#define SPEAR310_IRQ_REG	(0x98)
+
+#define SPEAR310_EMI_MAX_BANKS	6
+#endif
+
+#if defined(CONFIG_MACH_SPEAR320)
+#define SPEAR320_TIMEOUT_REG	(0x60)
+#define SPEAR320_ACK_REG	(0x64)
+#define SPEAR320_IRQ_REG	(0x68)
+
+#define SPEAR320_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(unsigned long base, u32 bank, u32 width);
+#endif
diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h
index 1567d0da..0780c47 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear310.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear310.h
@@ -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)
diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h
index 8cfa83f..30ea941 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear320.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear320.h
@@ -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)
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 36fb611..8d5becb 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -13,9 +13,40 @@
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <mach/emi.h>
 #include <mach/generic.h>
 #include <mach/hardware.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,
+	},
+};
+
+static struct physmap_flash_data emi_norflash_data = {
+	.parts = partition_info,
+	.nr_parts = ARRAY_SIZE(partition_info),
+	.width = 4,
+};
+static struct platform_device spear310_emi_nor_device = {
+	.name	= "physmap-flash",
+	.id	= -1,
+	.dev.platform_data = &emi_norflash_data,
+	.resource = emi_nor_resources,
+	.num_resources = ARRAY_SIZE(emi_nor_resources),
+};
+
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
 	/* spear3xx specific devices */
@@ -58,6 +89,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
 
 	/* spear310 specific devices */
+	&spear310_emi_nor_device,
 	&spear310_plgpio_device,
 };
 
@@ -68,6 +100,9 @@ static void __init spear310_evb_init(void)
 	/* call spear310 machine init function */
 	spear310_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
+	/* Initialize emi regiters */
+	emi_init(SPEAR310_EMI_REG_BASE, 0, EMI_FLASH_WIDTH32);
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index f2c3cd3..8addd5f 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -13,9 +13,40 @@
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <mach/emi.h>
 #include <mach/generic.h>
 #include <mach/hardware.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	= SPEAR320_EMI_MEM_0_BASE,
+		.end	= SPEAR320_EMI_MEM_0_BASE + SPEAR320_EMI_MEM_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct physmap_flash_data emi_norflash_data = {
+	.parts = partition_info,
+	.nr_parts = ARRAY_SIZE(partition_info),
+	.width = 2,
+};
+static struct platform_device spear320_emi_nor_device = {
+	.name	= "physmap-flash",
+	.id	= -1,
+	.dev.platform_data = &emi_norflash_data,
+	.resource = emi_nor_resources,
+	.num_resources = ARRAY_SIZE(emi_nor_resources),
+};
+
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
 	/* spear3xx specific devices */
@@ -54,6 +85,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	/* spear320 specific devices */
 	&spear320_can0_device,
 	&spear320_can1_device,
+	&spear320_emi_nor_device,
 	&spear320_plgpio_device,
 	&spear320_pwm_device,
 };
@@ -66,6 +98,9 @@ static void __init spear320_evb_init(void)
 	spear320_init(&spear320_auto_net_mii_mode, pmx_devs,
 			ARRAY_SIZE(pmx_devs));
 
+	/* Initialize emi regiters */
+	emi_init(SPEAR320_EMI_CTRL_BASE, 0, EMI_FLASH_WIDTH16);
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 09/17] ST SPEAr: Adding machine support for rtc-spear
From: Viresh Kumar @ 2011-03-01 11:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

From: Rajeev Kumar <rajeev-dlh.kumar@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |    1 +
 arch/arm/mach-spear13xx/spear1310_evb.c        |    1 +
 arch/arm/mach-spear13xx/spear13xx.c            |   19 +++++++++++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    1 +
 arch/arm/mach-spear3xx/spear300_evb.c          |    1 +
 arch/arm/mach-spear3xx/spear310_evb.c          |    1 +
 arch/arm/mach-spear3xx/spear320_evb.c          |    1 +
 arch/arm/mach-spear3xx/spear3xx.c              |   19 +++++++++++++++++++
 arch/arm/mach-spear6xx/include/mach/generic.h  |    1 +
 arch/arm/mach-spear6xx/spear600_evb.c          |    1 +
 arch/arm/mach-spear6xx/spear6xx.c              |   19 +++++++++++++++++++
 12 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index de9de17..b598236 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -223,6 +223,7 @@ extern struct pmx_dev pmx_uart1_modem;
 /* Add spear13xx family device structure declarations here */
 extern struct amba_device spear13xx_gpio_device[];
 extern struct amba_device spear13xx_uart_device;
+extern struct platform_device spear13xx_rtc_device;
 extern struct sys_timer spear13xx_timer;
 
 /* Add spear13xx family function declarations here */
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 4799ae1..796d04c 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -44,6 +44,7 @@ static struct amba_device *amba_devs[] __initdata = {
 };
 
 static struct platform_device *plat_devs[] __initdata = {
+	&spear13xx_rtc_device,
 };
 
 #ifdef CONFIG_PCIEPORTBUS
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index 2e74879..1eea995 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -59,6 +59,7 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear13xx specific devices */
+	&spear13xx_rtc_device,
 
 	/* spear1310 specific devices */
 	&spear1310_can0_device,
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 6c2525a..e9ba888 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -76,6 +76,25 @@ struct amba_device spear13xx_uart_device = {
 	.irq = {IRQ_UART, NO_IRQ},
 };
 
+/* rtc device registration */
+static struct resource rtc_resources[] = {
+	{
+		.start = SPEAR13XX_RTC_BASE,
+		.end = SPEAR13XX_RTC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_RTC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear13xx_rtc_device = {
+	.name = "rtc-spear",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(rtc_resources),
+	.resource = rtc_resources,
+};
+
 #ifdef CONFIG_PCIEPORTBUS
 /* PCIE0 clock always needs to be enabled if any of the three PCIE port
  * have to be used. So call this function from the board initilization
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index e8dfbb5..73f3f3b 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -34,6 +34,7 @@
 extern struct amba_device spear3xx_gpio_device;
 extern struct amba_device spear3xx_uart_device;
 extern struct amba_device spear3xx_wdt_device;
+extern struct platform_device spear3xx_rtc_device;
 extern struct sys_timer spear3xx_timer;
 
 /* Add spear3xx family function declarations here */
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index f4fd6db..e4a9a4f 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -44,6 +44,7 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
+	&spear3xx_rtc_device,
 
 	/* spear300 specific devices */
 };
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 8d5becb..97c9551 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -87,6 +87,7 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
+	&spear3xx_rtc_device,
 
 	/* spear310 specific devices */
 	&spear310_emi_nor_device,
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 8addd5f..17248f4 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -81,6 +81,7 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
+	&spear3xx_rtc_device,
 
 	/* spear320 specific devices */
 	&spear320_can0_device,
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index b07c659..6e8bcd0 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -66,6 +66,25 @@ struct amba_device spear3xx_wdt_device = {
 	},
 };
 
+/* rtc device registration */
+static struct resource rtc_resources[] = {
+	{
+		.start = SPEAR3XX_ICM3_RTC_BASE,
+		.end = SPEAR3XX_ICM3_RTC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = SPEAR3XX_IRQ_BASIC_RTC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear3xx_rtc_device = {
+	.name = "rtc-spear",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(rtc_resources),
+	.resource = rtc_resources,
+};
+
 /* Do spear3xx familiy common initialization part here */
 void __init spear3xx_init(void)
 {
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index 0d17e65..9b7a758 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -32,6 +32,7 @@
 extern struct amba_device gpio_device[];
 extern struct amba_device uart_device[];
 extern struct amba_device wdt_device;
+extern struct platform_device rtc_device;
 extern struct sys_timer spear6xx_timer;
 
 /* Add spear6xx family function declarations here */
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index 6730868..2b8cd87 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -26,6 +26,7 @@ static struct amba_device *amba_devs[] __initdata = {
 };
 
 static struct platform_device *plat_devs[] __initdata = {
+	&rtc_device,
 };
 
 static void __init spear600_evb_init(void)
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index 3842545..f976377 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -111,6 +111,25 @@ struct amba_device wdt_device = {
 	},
 };
 
+/* rtc device registration */
+static struct resource rtc_resources[] = {
+	{
+		.start = SPEAR6XX_ICM3_RTC_BASE,
+		.end = SPEAR6XX_ICM3_RTC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_BASIC_RTC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device rtc_device = {
+	.name = "rtc-spear",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(rtc_resources),
+	.resource = rtc_resources,
+};
+
 /* This will add devices, and do machine specific tasks */
 void __init spear6xx_init(void)
 {
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 0/3] Clock Framework & CPU Freq Updates
From: Viresh Kumar @ 2011-03-01 11:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset contains following updates:
- Adding support for DDR
- Adding support for PLL frequency change
- Adding support for CPU Freq framework

Note: These patches were earlier sent as part of a larger patchset:
"Updating SPEAr Support"

Now it is divided into smaller patchsets. In order to apply these patches
cleanly following order of patchsets must be maintained.
- SPEAr3xx & SPEAr6xx Fixes
- SPEAr3xx & SPEAr6xx: Single Image solution and padmux updates
- Adding SPEAr13xx support
- Adding devices support for all spear machines
- Clock Framework & CPU Freq Updates

Deepak Sikri (2):
  ST SPEAr Clock Framework: Adding support for PLL frequency change
  ST SPEAr CPU freq: Adding support for CPU Freq framework

Viresh Kumar (1):
  ST SPEAr Clock Framework: Adding support for DDR

 arch/arm/Kconfig                                |    1 +
 arch/arm/mach-spear13xx/clock.c                 |   68 +++++++--
 arch/arm/mach-spear3xx/clock.c                  |  100 ++++++++++--
 arch/arm/mach-spear3xx/include/mach/misc_regs.h |    7 +
 arch/arm/mach-spear3xx/spear3xx.c               |    5 +
 arch/arm/mach-spear6xx/clock.c                  |  100 ++++++++++--
 arch/arm/mach-spear6xx/include/mach/misc_regs.h |    7 +
 arch/arm/mach-spear6xx/spear6xx.c               |    5 +
 arch/arm/plat-spear/Makefile                    |    4 +-
 arch/arm/plat-spear/clock.c                     |  124 +++++++++++++---
 arch/arm/plat-spear/cpufreq.c                   |  164 ++++++++++++++++++++
 arch/arm/plat-spear/include/plat/clock.h        |   44 ++++--
 arch/arm/plat-spear/pll_clk.S                   |  187 +++++++++++++++++++++++
 13 files changed, 731 insertions(+), 85 deletions(-)
 create mode 100644 arch/arm/plat-spear/cpufreq.c
 create mode 100644 arch/arm/plat-spear/pll_clk.S

-- 
1.7.2.2

^ permalink raw reply

* [PATCH V6 1/3] ST SPEAr Clock Framework: Adding support for DDR
From: Viresh Kumar @ 2011-03-01 11:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977735.git.viresh.kumar@st.com>

Changing rate of clk, which is ancestor of DDR requires to put DDR in refresh
mode before changing parents rate. For this DDR support is added in clock
framework. Now at boot time all ancestors of DDR is marked specially and
changing their rate must be first acked by ddr (i.e. ddr will run on that
clock). This patch adds support for this.

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: shiraz hashim <shiraz.hashim@st.com>
---
 arch/arm/mach-spear13xx/clock.c                 |   61 +++++++++---
 arch/arm/mach-spear3xx/clock.c                  |   97 +++++++++++++++---
 arch/arm/mach-spear3xx/include/mach/misc_regs.h |    7 ++
 arch/arm/mach-spear6xx/clock.c                  |   97 +++++++++++++++---
 arch/arm/mach-spear6xx/include/mach/misc_regs.h |    7 ++
 arch/arm/plat-spear/clock.c                     |  124 +++++++++++++++++++----
 arch/arm/plat-spear/include/plat/clock.h        |   43 ++++++--
 7 files changed, 359 insertions(+), 77 deletions(-)

diff --git a/arch/arm/mach-spear13xx/clock.c b/arch/arm/mach-spear13xx/clock.c
index 008749a..8aba6cf 100644
--- a/arch/arm/mach-spear13xx/clock.c
+++ b/arch/arm/mach-spear13xx/clock.c
@@ -23,19 +23,19 @@
 /* root clks */
 /* 24 MHz oscillator clock */
 static struct clk osc1_24m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 24000000,
 };
 
 /* 32 KHz oscillator clock */
 static struct clk osc2_32k_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 32000,
 };
 
 /* 25 MHz MIPHY oscillator clock */
 static struct clk osc3_25m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 25000000,
 };
 
@@ -99,7 +99,7 @@ struct pll_rate_tbl pll_rtbl[] = {
 
 /* pll1 clock */
 static struct clk pll1_clk = {
-	.flags = ENABLED_ON_INIT,
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
 	.pclk_sel = &pll_pclk_sel,
 	.pclk_sel_shift = PLL1_CLK_SHIFT,
 	.en_reg = PLL1_CTR,
@@ -113,7 +113,7 @@ static struct clk pll1_clk = {
 
 /* pll1div2 clock */
 static struct clk pll1div2_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 2,
 	.recalc = &follow_parent,
@@ -121,7 +121,7 @@ static struct clk pll1div2_clk = {
 
 /* pll1div4 clock */
 static struct clk pll1div4_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 4,
 	.recalc = &follow_parent,
@@ -136,6 +136,7 @@ static struct pll_clk_config pll2_config = {
 
 /* pll2 clock */
 static struct clk pll2_clk = {
+	.flags = SYSTEM_CLK,
 	.pclk_sel = &pll_pclk_sel,
 	.pclk_sel_shift = PLL2_CLK_SHIFT,
 	.en_reg = PLL2_CTR,
@@ -156,6 +157,7 @@ static struct pll_clk_config pll3_config = {
 
 /* pll3 clock */
 static struct clk pll3_clk = {
+	.flags = SYSTEM_CLK,
 	.pclk_sel = &pll_pclk_sel,
 	.pclk_sel_shift = PLL3_CLK_SHIFT,
 	.en_reg = PLL3_CTR,
@@ -184,7 +186,7 @@ struct pll_rate_tbl pll4_rtbl[] = {
 
 /* pll4 (DDR) clock */
 static struct clk pll4_clk = {
-	.flags = ENABLED_ON_INIT,
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
 	.pclk = &osc1_24m_clk,
 	.en_reg = PLL4_CTR,
 	.en_reg_bit = PLL_ENABLE,
@@ -197,22 +199,54 @@ static struct clk pll4_clk = {
 
 /* pll5 USB 48 MHz clock */
 static struct clk pll5_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &osc1_24m_clk,
 	.rate = 48000000,
 };
 
 /* pll6 (MIPHY) clock */
 static struct clk pll6_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &osc3_25m_clk,
 	.rate = 25000000,
 };
 
 /* clocks derived from pll1 clk */
+/* ddr clock */
+struct ddr_rate_tbl ddr_rate_tbl = {
+	.minrate = 332000000,
+	.maxrate = 500000000,
+};
+
+static struct pclk_info ddr_pclk_info[] = {
+	{
+		.pclk = &pll1_clk,
+		.pclk_val = MCTR_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll4_clk,
+		.pclk_val = MCTR_CLK_PLL4_VAL,
+	},
+};
+
+/* ddr parent select structure */
+static struct pclk_sel ddr_pclk_sel = {
+	.pclk_info = ddr_pclk_info,
+	.pclk_count = ARRAY_SIZE(ddr_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = MCTR_CLK_MASK,
+};
+
+static struct clk ddr_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.recalc = &follow_parent,
+	.pclk_sel = &ddr_pclk_sel,
+	.pclk_sel_shift = MCTR_CLK_SHIFT,
+	.private_data = &ddr_rate_tbl,
+};
+
 /* cpu clock */
 static struct clk cpu_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 2,
 	.recalc = &follow_parent,
@@ -220,7 +254,7 @@ static struct clk cpu_clk = {
 
 /* ahb clock */
 static struct clk ahb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 6,
 	.recalc = &follow_parent,
@@ -228,7 +262,7 @@ static struct clk ahb_clk = {
 
 /* apb clock */
 static struct clk apb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.div_factor = 12,
 	.recalc = &follow_parent,
@@ -1048,6 +1082,7 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{.con_id = "pll6_clk",		.clk = &pll6_clk},
 
 	/* clock derived from pll1 clk */
+	{.con_id = "ddr_clk",		.clk = &ddr_clk},
 	{.con_id = "cpu_clk",		.clk = &cpu_clk},
 	{.con_id = "ahb_clk",		.clk = &ahb_clk},
 	{.con_id = "apb_clk",		.clk = &apb_clk},
@@ -1163,5 +1198,5 @@ void __init spear13xx_clk_init(void)
 	for (i = 0; i < cnt; i++)
 		clk_register(&lookups[i]);
 
-	clk_init();
+	clk_init(&ddr_clk);
 }
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index f67860c..2392cd6 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c
@@ -20,13 +20,13 @@
 /* root clks */
 /* 32 KHz oscillator clock */
 static struct clk osc_32k_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 32000,
 };
 
 /* 24 MHz oscillator clock */
 static struct clk osc_24m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 24000000,
 };
 
@@ -41,7 +41,7 @@ static struct clk rtc_clk = {
 
 /* clock derived from 24 MHz osc clk */
 /* pll masks structure */
-static struct pll_clk_masks pll1_masks = {
+static struct pll_clk_masks pll_masks = {
 	.mode_mask = PLL_MODE_MASK,
 	.mode_shift = PLL_MODE_SHIFT,
 	.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
@@ -54,22 +54,22 @@ static struct pll_clk_masks pll1_masks = {
 	.div_n_shift = PLL_DIV_N_SHIFT,
 };
 
-/* pll1 configuration structure */
-static struct pll_clk_config pll1_config = {
-	.mode_reg = PLL1_CTR,
-	.cfg_reg = PLL1_FRQ,
-	.masks = &pll1_masks,
-};
-
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
 	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
 
+/* pll1 configuration structure */
+static struct pll_clk_config pll1_config = {
+	.mode_reg = PLL1_CTR,
+	.cfg_reg = PLL1_FRQ,
+	.masks = &pll_masks,
+};
+
 /* PLL1 clock */
 static struct clk pll1_clk = {
-	.flags = ENABLED_ON_INIT,
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
 	.pclk = &osc_24m_clk,
 	.en_reg = PLL1_CTR,
 	.en_reg_bit = PLL_ENABLE,
@@ -80,9 +80,29 @@ static struct clk pll1_clk = {
 	.private_data = &pll1_config,
 };
 
+/* pll2 configuration structure */
+static struct pll_clk_config pll2_config = {
+	.mode_reg = PLL2_CTR,
+	.cfg_reg = PLL2_FRQ,
+	.masks = &pll_masks,
+};
+
+/* PLL2 clock */
+static struct clk pll2_clk = {
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
+	.pclk = &osc_24m_clk,
+	.en_reg = PLL2_CTR,
+	.en_reg_bit = PLL_ENABLE,
+	.calc_rate = &pll_calc_rate,
+	.recalc = &pll_clk_recalc,
+	.set_rate = &pll_clk_set_rate,
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
+	.private_data = &pll2_config,
+};
+
 /* PLL3 48 MHz clock */
 static struct clk pll3_48m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &osc_24m_clk,
 	.rate = 48000000,
 };
@@ -97,7 +117,7 @@ static struct clk wdt_clk = {
 /* clock derived from pll1 clk */
 /* cpu clock */
 static struct clk cpu_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.recalc = &follow_parent,
 };
@@ -124,7 +144,7 @@ struct bus_rate_tbl bus_rtbl[] = {
 
 /* ahb clock */
 static struct clk ahb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
@@ -411,6 +431,48 @@ static struct clk usbd_clk = {
 };
 
 /* clock derived from ahb clk */
+/* ahb multiplied by 2 clock */
+static struct clk ahbmult2_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.pclk = &ahb_clk,
+	.recalc = &ahbmult2_clk_recalc,
+};
+
+/* ddr clock */
+struct ddr_rate_tbl ddr_rate_tbl = {
+	.minrate = 166000000,
+	.maxrate = 332000000,
+};
+
+static struct pclk_info ddr_pclk_info[] = {
+	{
+		.pclk = &ahb_clk,
+		.pclk_val = MCTR_CLK_HCLK_VAL,
+	}, {
+		.pclk = &ahbmult2_clk,
+		.pclk_val = MCTR_CLK_2HCLK_VAL,
+	}, {
+		.pclk = &pll2_clk,
+		.pclk_val = MCTR_CLK_PLL2_VAL,
+	},
+};
+
+/* ddr parent select structure */
+static struct pclk_sel ddr_pclk_sel = {
+	.pclk_info = ddr_pclk_info,
+	.pclk_count = ARRAY_SIZE(ddr_pclk_info),
+	.pclk_sel_reg = PLL_CLK_CFG,
+	.pclk_sel_mask = MCTR_CLK_MASK,
+};
+
+static struct clk ddr_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.recalc = &follow_parent,
+	.pclk_sel = &ddr_pclk_sel,
+	.pclk_sel_shift = MCTR_CLK_SHIFT,
+	.private_data = &ddr_rate_tbl,
+};
+
 /* apb masks structure */
 static struct bus_clk_masks apb_masks = {
 	.mask = HCLK_PCLK_RATIO_MASK,
@@ -425,7 +487,7 @@ static struct bus_clk_config apb_config = {
 
 /* apb clock */
 static struct clk apb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &ahb_clk,
 	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
@@ -659,6 +721,7 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "rtc-spear",	.clk = &rtc_clk},
 	/* clock derived from 24 MHz osc clk */
 	{ .con_id = "pll1_clk",		.clk = &pll1_clk},
+	{ .con_id = "pll2_clk",		.clk = &pll2_clk},
 	{ .con_id = "pll3_48m_clk",	.clk = &pll3_48m_clk},
 	{ .dev_id = "wdt",		.clk = &wdt_clk},
 	/* clock derived from pll1 clk */
@@ -678,6 +741,8 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "designware_udc",   .clk = &usbd_clk},
 	{ .con_id = "usbh_clk",		.clk = &usbh_clk},
 	/* clock derived from ahb clk */
+	{ .con_id = "ahbmult2_clk",	.clk = &ahbmult2_clk},
+	{ .con_id = "ddr_clk",		.clk = &ddr_clk},
 	{ .con_id = "apb_clk",		.clk = &apb_clk},
 	{ .dev_id = "i2c_designware.0",	.clk = &i2c_clk},
 	{ .dev_id = "dma",		.clk = &dma_clk},
@@ -755,5 +820,5 @@ void __init spear3xx_clk_init(void)
 	for (i = 0; i < cnt; i++)
 		clk_register(&lookups[i]);
 
-	clk_init();
+	clk_init(&ddr_clk);
 }
diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
index 5bd8cd8..934e5c5 100644
--- a/arch/arm/mach-spear3xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
@@ -46,6 +46,13 @@
 
 #define PLL2_MOD		(MISC_BASE + 0x01C)
 #define PLL_CLK_CFG		(MISC_BASE + 0x020)
+/* PLL_CLK_CFG register masks */
+#define MCTR_CLK_SHIFT		28
+#define MCTR_CLK_MASK		0x7
+#define MCTR_CLK_HCLK_VAL	0x0
+#define MCTR_CLK_2HCLK_VAL	0x1
+#define MCTR_CLK_PLL2_VAL	0x3
+
 #define CORE_CLK_CFG		(MISC_BASE + 0x024)
 /* CORE CLK CFG register masks */
 #define PLL_HCLK_RATIO_SHIFT	10
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index ac70e0d..6eb0daf 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c
@@ -19,13 +19,13 @@
 /* root clks */
 /* 32 KHz oscillator clock */
 static struct clk osc_32k_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 32000,
 };
 
 /* 30 MHz oscillator clock */
 static struct clk osc_30m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.rate = 30000000,
 };
 
@@ -40,7 +40,7 @@ static struct clk rtc_clk = {
 
 /* clock derived from 30 MHz osc clk */
 /* pll masks structure */
-static struct pll_clk_masks pll1_masks = {
+static struct pll_clk_masks pll_masks = {
 	.mode_mask = PLL_MODE_MASK,
 	.mode_shift = PLL_MODE_SHIFT,
 	.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
@@ -53,22 +53,22 @@ static struct pll_clk_masks pll1_masks = {
 	.div_n_shift = PLL_DIV_N_SHIFT,
 };
 
-/* pll1 configuration structure */
-static struct pll_clk_config pll1_config = {
-	.mode_reg = PLL1_CTR,
-	.cfg_reg = PLL1_FRQ,
-	.masks = &pll1_masks,
-};
-
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
 	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
 
+/* pll1 configuration structure */
+static struct pll_clk_config pll1_config = {
+	.mode_reg = PLL1_CTR,
+	.cfg_reg = PLL1_FRQ,
+	.masks = &pll_masks,
+};
+
 /* PLL1 clock */
 static struct clk pll1_clk = {
-	.flags = ENABLED_ON_INIT,
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
 	.pclk = &osc_30m_clk,
 	.en_reg = PLL1_CTR,
 	.en_reg_bit = PLL_ENABLE,
@@ -79,9 +79,29 @@ static struct clk pll1_clk = {
 	.private_data = &pll1_config,
 };
 
+/* pll2 configuration structure */
+static struct pll_clk_config pll2_config = {
+	.mode_reg = PLL2_CTR,
+	.cfg_reg = PLL2_FRQ,
+	.masks = &pll_masks,
+};
+
+/* PLL2 clock */
+static struct clk pll2_clk = {
+	.flags = ENABLED_ON_INIT | SYSTEM_CLK,
+	.pclk = &osc_30m_clk,
+	.en_reg = PLL2_CTR,
+	.en_reg_bit = PLL_ENABLE,
+	.calc_rate = &pll_calc_rate,
+	.recalc = &pll_clk_recalc,
+	.set_rate = &pll_clk_set_rate,
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
+	.private_data = &pll2_config,
+};
+
 /* PLL3 48 MHz clock */
 static struct clk pll3_48m_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &osc_30m_clk,
 	.rate = 48000000,
 };
@@ -96,7 +116,7 @@ static struct clk wdt_clk = {
 /* clock derived from pll1 clk */
 /* cpu clock */
 static struct clk cpu_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.recalc = &follow_parent,
 };
@@ -123,7 +143,7 @@ struct bus_rate_tbl bus_rtbl[] = {
 
 /* ahb clock */
 static struct clk ahb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &pll1_clk,
 	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
@@ -491,6 +511,48 @@ static struct clk usbd_clk = {
 };
 
 /* clock derived from ahb clk */
+/* ahb multiplied by 2 clock */
+static struct clk ahbmult2_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.pclk = &ahb_clk,
+	.recalc = &ahbmult2_clk_recalc,
+};
+
+/* ddr clock */
+struct ddr_rate_tbl ddr_rate_tbl = {
+	.minrate = 166000000,
+	.maxrate = 332000000,
+};
+
+static struct pclk_info ddr_pclk_info[] = {
+	{
+		.pclk = &ahb_clk,
+		.pclk_val = MCTR_CLK_HCLK_VAL,
+	}, {
+		.pclk = &ahbmult2_clk,
+		.pclk_val = MCTR_CLK_2HCLK_VAL,
+	}, {
+		.pclk = &pll2_clk,
+		.pclk_val = MCTR_CLK_PLL2_VAL,
+	},
+};
+
+/* ddr parent select structure */
+static struct pclk_sel ddr_pclk_sel = {
+	.pclk_info = ddr_pclk_info,
+	.pclk_count = ARRAY_SIZE(ddr_pclk_info),
+	.pclk_sel_reg = PLL_CLK_CFG,
+	.pclk_sel_mask = MCTR_CLK_MASK,
+};
+
+static struct clk ddr_clk = {
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
+	.recalc = &follow_parent,
+	.pclk_sel = &ddr_pclk_sel,
+	.pclk_sel_shift = MCTR_CLK_SHIFT,
+	.private_data = &ddr_rate_tbl,
+};
+
 /* apb masks structure */
 static struct bus_clk_masks apb_masks = {
 	.mask = HCLK_PCLK_RATIO_MASK,
@@ -505,7 +567,7 @@ static struct bus_clk_config apb_config = {
 
 /* apb clock */
 static struct clk apb_clk = {
-	.flags = ALWAYS_ENABLED,
+	.flags = ALWAYS_ENABLED | SYSTEM_CLK,
 	.pclk = &ahb_clk,
 	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
@@ -630,6 +692,7 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "rtc-spear",	.clk = &rtc_clk},
 	/* clock derived from 30 MHz os		 clk */
 	{ .con_id = "pll1_clk",		.clk = &pll1_clk},
+	{ .con_id = "pll2_clk",		.clk = &pll2_clk},
 	{ .con_id = "pll3_48m_clk",	.clk = &pll3_48m_clk},
 	{ .dev_id = "wdt",		.clk = &wdt_clk},
 	/* clock derived from pll1 clk */
@@ -654,6 +717,8 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .con_id = "usbh.0_clk",	.clk = &usbh0_clk},
 	{ .con_id = "usbh.1_clk",	.clk = &usbh1_clk},
 	/* clock derived from ahb clk */
+	{ .con_id = "ahbmult2_clk",	.clk = &ahbmult2_clk},
+	{ .con_id = "ddr_clk",		.clk = &ddr_clk},
 	{ .con_id = "apb_clk",		.clk = &apb_clk},
 	{ .dev_id = "i2c_designware.0",	.clk = &i2c_clk},
 	{ .dev_id = "dma",		.clk = &dma_clk},
@@ -678,5 +743,5 @@ void __init spear6xx_clk_init(void)
 	for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
 		clk_register(&spear_clk_lookups[i]);
 
-	clk_init();
+	clk_init(&ddr_clk);
 }
diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
index 68c20a0..7b4537c 100644
--- a/arch/arm/mach-spear6xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
@@ -47,6 +47,13 @@
 #define PLL2_MOD		(MISC_BASE + 0x01C)
 #define PLL_CLK_CFG		(MISC_BASE + 0x020)
 #define CORE_CLK_CFG		(MISC_BASE + 0x024)
+/* PLL_CLK_CFG register masks */
+#define MCTR_CLK_SHIFT		28
+#define MCTR_CLK_MASK		0x7
+#define MCTR_CLK_HCLK_VAL	0x0
+#define MCTR_CLK_2HCLK_VAL	0x1
+#define MCTR_CLK_PLL2_VAL	0x3
+
 /* CORE CLK CFG register masks */
 #define PLL_HCLK_RATIO_SHIFT	10
 #define PLL_HCLK_RATIO_MASK	0x3
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index 6fa474c..75aff7c 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -21,6 +21,8 @@
 #include <linux/spinlock.h>
 #include <plat/clock.h>
 
+/* pointer to ddr clock structure */
+static struct clk *ddr_clk;
 static DEFINE_SPINLOCK(clocks_lock);
 static LIST_HEAD(root_clks);
 #ifdef CONFIG_DEBUG_FS
@@ -160,7 +162,7 @@ static int do_clk_enable(struct clk *clk)
 		 * time please reclac
 		 */
 		if (clk->recalc) {
-			ret = clk->recalc(clk);
+			ret = clk->recalc(clk, &clk->rate, clk->pclk->rate);
 			if (ret)
 				goto err;
 		}
@@ -298,7 +300,16 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 			propagate_rate(clk, 0);
 		spin_unlock_irqrestore(&clocks_lock, flags);
 	} else if (clk->pclk) {
-		u32 mult = clk->div_factor ? clk->div_factor : 1;
+		u32 mult;
+		/*
+		 * if pclk is SYSTEM_CLK and clk is not SYSTEM_CLK then return
+		 * error
+		 */
+		if (clk->pclk->flags & SYSTEM_CLK)
+			if (!(clk->flags & SYSTEM_CLK))
+				return -EPERM;
+
+		mult = clk->div_factor ? clk->div_factor : 1;
 		ret = clk_set_rate(clk->pclk, mult * rate);
 	}
 
@@ -371,7 +382,7 @@ void propagate_rate(struct clk *pclk, int on_init)
 
 	list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) {
 		if (clk->recalc) {
-			ret = clk->recalc(clk);
+			ret = clk->recalc(clk, &clk->rate, clk->pclk->rate);
 			/*
 			 * recalc will return error if clk out is not programmed
 			 * In this case configure default rate.
@@ -390,6 +401,47 @@ void propagate_rate(struct clk *pclk, int on_init)
 	}
 }
 
+/* updates "rate" pointer with current_clk's output for input "rate" */
+static void rate_calc(struct clk *current_clk, struct clk *ancestor_clk,
+		unsigned long *rate)
+{
+	if (current_clk->pclk != ancestor_clk)
+		rate_calc(current_clk->pclk, ancestor_clk, rate);
+
+	if (current_clk->recalc)
+		current_clk->recalc(current_clk, rate, *rate);
+}
+
+/*
+ * Check if ancestor clk rate is acceptable to ddr or not.
+ * This will call recursive rate_calc function, starting from ddr upto ancestor
+ * clk mentioned. This will calculate divisions / multiplications by all
+ * intermediate ancestor clocks and return the final rate of ddr if ancestor clk
+ * sets its rate to "rate", value passed in function.
+ */
+static int ddr_rate_acceptable(struct clk *aclk, unsigned long rate)
+{
+	struct ddr_rate_tbl *tbl = ddr_clk->private_data;
+
+	rate_calc(ddr_clk, aclk, &rate);
+	if ((rate >= tbl->minrate) && (rate <= tbl->maxrate))
+		return true;
+
+	return false;
+}
+
+/* mark all ddr ancestors with DDR_ANCESTOR flag */
+static void mark_ddr_ancestors(struct clk *dclk)
+{
+	struct clk *clk = dclk->pclk;
+
+	/* mark all ancestors of DDR */
+	while (clk != NULL) {
+		clk->flags |= DDR_ANCESTOR;
+		clk = clk->pclk;
+	}
+}
+
 /**
  * round_rate_index - return closest programmable rate index in rate_config tbl
  * @clk: ptr to clock structure
@@ -505,7 +557,7 @@ unsigned long pll_calc_rate(struct clk *clk, int index)
  * In Dithered mode
  * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
  */
-int pll_clk_recalc(struct clk *clk)
+int pll_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct pll_clk_config *config = clk->private_data;
 	unsigned int num = 2, den = 0, val, mode = 0;
@@ -534,7 +586,7 @@ int pll_clk_recalc(struct clk *clk)
 	if (!den)
 		return -EINVAL;
 
-	clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
+	*rate = (((prate/10000) * num) / den) * 10000;
 	return 0;
 }
 
@@ -552,6 +604,25 @@ int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
 	if (i < 0)
 		return i;
 
+	/* if clk is ddrs ancestor, check if rate is acceptable to ddr */
+	if (ddr_clk && (clk->flags & DDR_ANCESTOR)) {
+		int ret;
+
+		ret = ddr_rate_acceptable(clk, rate);
+		if (ret == false)
+			return -EPERM;
+		else {
+			/*
+			 * call routine to put ddr in refresh mode, and
+			 * configure pll.
+			 */
+			/* TBD */
+			clk->rate = rate;
+		}
+
+		return ret;
+	}
+
 	val = readl(config->mode_reg) &
 		~(config->masks->mode_mask << config->masks->mode_shift);
 	val |= (tbls[i].mode & config->masks->mode_mask) <<
@@ -593,7 +664,7 @@ unsigned long bus_calc_rate(struct clk *clk, int index)
 }
 
 /* calculates current programmed rate of ahb or apb bus */
-int bus_clk_recalc(struct clk *clk)
+int bus_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct bus_clk_config *config = clk->private_data;
 	unsigned int div;
@@ -604,7 +675,7 @@ int bus_clk_recalc(struct clk *clk)
 	if (!div)
 		return -EINVAL;
 
-	clk->rate = (unsigned long)clk->pclk->rate / div;
+	*rate = prate / div;
 	return 0;
 }
 
@@ -630,6 +701,14 @@ int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate)
 	return 0;
 }
 
+/* calculates current programmed rate of ahbmult2 */
+int
+ahbmult2_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
+{
+	*rate = prate * 2;
+	return 0;
+}
+
 /*
  * gives rate for different values of eq, x and y
  *
@@ -657,7 +736,7 @@ unsigned long aux_calc_rate(struct clk *clk, int index)
  *
  * Selection of eqn 1 or 2 is programmed in register
  */
-int aux_clk_recalc(struct clk *clk)
+int aux_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct aux_clk_config *config = clk->private_data;
 	unsigned int num = 1, den = 1, val, eqn;
@@ -680,7 +759,7 @@ int aux_clk_recalc(struct clk *clk)
 	if (!den)
 		return -EINVAL;
 
-	clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
+	*rate = (((prate / 10000) * num) / den) * 10000;
 	return 0;
 }
 
@@ -734,7 +813,7 @@ unsigned long gpt_calc_rate(struct clk *clk, int index)
  * Fout from synthesizer can be given from below equations:
  * Fout= Fin/((2 ^ (N+1)) * (M+1))
  */
-int gpt_clk_recalc(struct clk *clk)
+int gpt_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct gpt_clk_config *config = clk->private_data;
 	unsigned int div = 1, val;
@@ -748,7 +827,7 @@ int gpt_clk_recalc(struct clk *clk)
 	if (!div)
 		return -EINVAL;
 
-	clk->rate = (unsigned long)clk->pclk->rate / div;
+	*rate = prate / div;
 	return 0;
 }
 
@@ -816,11 +895,10 @@ unsigned long clcd_calc_rate(struct clk *clk, int index)
  * complete div (including fractional part) and then right shift the
  * result by 14 places.
  */
-int clcd_clk_recalc(struct clk *clk)
+int clcd_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	struct clcd_clk_config *config = clk->private_data;
 	unsigned int div = 1;
-	unsigned long prate;
 	unsigned int val;
 
 	val = readl(config->synth_reg);
@@ -830,10 +908,10 @@ int clcd_clk_recalc(struct clk *clk)
 	if (!div)
 		return -EINVAL;
 
-	prate = clk->pclk->rate / 1000; /* first level division, make it KHz */
+	prate = prate / 1000; /* first level division, make it KHz */
 
-	clk->rate = (((unsigned long)prate << 12) / (2 * div)) >> 12;
-	clk->rate *= 1000;
+	*rate = (((unsigned long)prate << 12) / (2 * div)) >> 12;
+	*rate *= 1000;
 	return 0;
 }
 
@@ -864,11 +942,11 @@ int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate)
  * Used for clocks that always have value as the parent clock divided by a
  * fixed divisor
  */
-int follow_parent(struct clk *clk)
+int follow_parent(struct clk *clk, unsigned long *rate, unsigned long prate)
 {
 	unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor;
 
-	clk->rate = clk->pclk->rate/div_factor;
+	*rate = prate / div_factor;
 	return 0;
 }
 
@@ -887,7 +965,7 @@ void recalc_root_clocks(void)
 	spin_lock_irqsave(&clocks_lock, flags);
 	list_for_each_entry(pclk, &root_clks, sibling) {
 		if (pclk->recalc) {
-			ret = pclk->recalc(pclk);
+			ret = pclk->recalc(pclk, &pclk->rate, pclk->pclk->rate);
 			/*
 			 * recalc will return error if clk out is not programmed
 			 * In this case configure default clock.
@@ -903,9 +981,15 @@ void recalc_root_clocks(void)
 	spin_unlock_irqrestore(&clocks_lock, flags);
 }
 
-void __init clk_init(void)
+void __init clk_init(struct clk *dclk)
 {
 	recalc_root_clocks();
+
+	/* Mark all ancestors of DDR with special flag */
+	if (dclk) {
+		ddr_clk = dclk;
+		mark_ddr_ancestors(dclk);
+	}
 }
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
index e4cc787..c58705f 100644
--- a/arch/arm/plat-spear/include/plat/clock.h
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -19,9 +19,12 @@
 #include <linux/types.h>
 
 /* clk structure flags */
-#define	ALWAYS_ENABLED		(1 << 0) /* clock always enabled */
-#define	RESET_TO_ENABLE		(1 << 1) /* reset register bit to enable clk */
-#define	ENABLED_ON_INIT		(1 << 2) /* clocks enabled at init */
+#define ALWAYS_ENABLED		(1 << 0) /* clock always enabled */
+#define RESET_TO_ENABLE		(1 << 1) /* reset register bit to enable clk */
+#define ENABLED_ON_INIT		(1 << 2) /* clocks enabled@init */
+/* Only System clocks can call other sytem clocks set rate function */
+#define SYSTEM_CLK		(1 << 3)
+#define DDR_ANCESTOR		(1 << 4) /* ancestor clks of DDR */
 
 /**
  * struct clkops - clock operations
@@ -99,8 +102,9 @@ struct clk {
 	void __iomem *en_reg;
 	u8 en_reg_bit;
 	const struct clkops *ops;
-	int (*recalc) (struct clk *);
-	int (*set_rate) (struct clk *, unsigned long rate);
+	int (*recalc) (struct clk *clk, unsigned long *rate,
+			unsigned long prate);
+	int (*set_rate) (struct clk *clk, unsigned long rate);
 	unsigned long (*calc_rate)(struct clk *, int index);
 	struct rate_config rate_config;
 	unsigned int div_factor;
@@ -223,27 +227,42 @@ struct clcd_rate_tbl {
 	u16 div;
 };
 
+/* ddr min, max clk rate table */
+struct ddr_rate_tbl {
+	unsigned long minrate;
+	unsigned long maxrate;
+};
+
 /* platform specific clock functions */
-void __init clk_init(void);
+/*
+ * must be called from machine clock.c file, dclk is pointer to ddr_clk
+ * strucutre. Which is required by clock framework.
+ *
+ * Actually before changing rate of DDRs ancestor, we must put ddr in refresh
+ * state and then change parent.
+ */
+void __init clk_init(struct clk *dclk);
 void clk_register(struct clk_lookup *cl);
 void recalc_root_clocks(void);
 
 /* clock recalc & set rate functions */
-int follow_parent(struct clk *clk);
+int follow_parent(struct clk *clk, unsigned long *rate, unsigned long prate);
 unsigned long pll_calc_rate(struct clk *clk, int index);
-int pll_clk_recalc(struct clk *clk);
+int pll_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 unsigned long bus_calc_rate(struct clk *clk, int index);
-int bus_clk_recalc(struct clk *clk);
+int bus_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+int ahbmult2_clk_recalc(struct clk *clk, unsigned long *rate,
+		unsigned long prate);
 unsigned long gpt_calc_rate(struct clk *clk, int index);
-int gpt_clk_recalc(struct clk *clk);
+int gpt_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 unsigned long aux_calc_rate(struct clk *clk, int index);
-int aux_clk_recalc(struct clk *clk);
+int aux_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 unsigned long clcd_calc_rate(struct clk *clk, int index);
-int clcd_clk_recalc(struct clk *clk);
+int clcd_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 
 #endif /* __PLAT_CLOCK_H */
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 2/3] ST SPEAr Clock Framework: Adding support for PLL frequency change
From: Viresh Kumar @ 2011-03-01 11:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977735.git.viresh.kumar@st.com>

From: Deepak Sikri <deepak.sikri@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Deepak Sikri <deepak.sikri@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/mach-spear3xx/spear3xx.c        |    5 +
 arch/arm/mach-spear6xx/spear6xx.c        |    5 +
 arch/arm/plat-spear/Makefile             |    2 +-
 arch/arm/plat-spear/clock.c              |    6 +-
 arch/arm/plat-spear/include/plat/clock.h |    1 +
 arch/arm/plat-spear/pll_clk.S            |  187 ++++++++++++++++++++++++++++++
 6 files changed, 201 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/plat-spear/pll_clk.S

diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 2278c08..8d974d7 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -254,6 +254,11 @@ struct map_desc spear3xx_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_MISC_REG_BASE),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(SPEAR3XX_ICM3_SDRAM_CTRL_BASE),
+		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_SDRAM_CTRL_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
 	},
 };
 
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index b38bf2b..8b30817 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -397,6 +397,11 @@ static struct map_desc spear6xx_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_MISC_REG_BASE),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(SPEAR6XX_ICM3_SDRAM_CTRL_BASE),
+		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_SDRAM_CTRL_BASE),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE
 	},
 };
 
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index 0c979af..abd39dc 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y	:= clock.o time.o
+obj-y	:= clock.o pll_clk.o time.o
 
 obj-$(CONFIG_ARCH_SPEAR13XX)	+= padmux.o
 obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index 75aff7c..5f86907 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -616,11 +616,10 @@ int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
 			 * call routine to put ddr in refresh mode, and
 			 * configure pll.
 			 */
-			/* TBD */
+			pll_set_rate(tbls[i].m, tbls[i].p, tbls[i].n);
 			clk->rate = rate;
 		}
-
-		return ret;
+		return 0;
 	}
 
 	val = readl(config->mode_reg) &
@@ -646,7 +645,6 @@ int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
 			config->masks->norm_fdbk_m_shift;
 
 	writel(val, config->cfg_reg);
-
 	clk->rate = rate;
 
 	return 0;
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
index c58705f..7cef090 100644
--- a/arch/arm/plat-spear/include/plat/clock.h
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -264,5 +264,6 @@ int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 unsigned long clcd_calc_rate(struct clk *clk, int index);
 int clcd_clk_recalc(struct clk *clk, unsigned long *rate, unsigned long prate);
 int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+void pll_set_rate(u16 pdiv, u8 nmul, u8 hclkdiv);
 
 #endif /* __PLAT_CLOCK_H */
diff --git a/arch/arm/plat-spear/pll_clk.S b/arch/arm/plat-spear/pll_clk.S
new file mode 100644
index 0000000..d0687b4
--- /dev/null
+++ b/arch/arm/plat-spear/pll_clk.S
@@ -0,0 +1,187 @@
+/*
+ * arch/arm/plat-spear/pll_clk.S
+ *
+ * SPEAR3xx and SPEAR6xx specific functions that will run in
+ * cache. These funstions intend to configure the PLL.
+ *
+ * Copyright (ST) 2010 Deepak Sikri <deepak.sikri@.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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+#include <mach/suspend.h>
+
+#if defined(CONFIG_ARCH_SPEAR3XX) || defined(CONFIG_ARCH_SPEAR6XX)
+.text
+ENTRY(pll_set_rate)
+	stmfd	sp!, {r0-r12, lr}
+
+	/* Lock down the TLB entry to the current victim */
+	mrc	p15, 0, r3, c10, c0, 0	/* read the lockdown register */
+	orr	r3, r3, #1		/* set the preserved bit */
+	mcr	p15, 0, r3, c10, c0, 0	/* write to the lockdown register */
+
+	/*
+	 * set r4 to the value of the address to be locked down.
+	 * Invalidate the TLB single entry in TLB to ensure that
+	 * the locked address is not already in TLB.
+	 * MPMC, System Controller & Miscellaneous register address
+	 * are locked down below.
+	 */
+
+	ldr	r4, MPMC_BASE_VA
+	/* Invalidate the MPMC virtual address in TLB. */
+	mcr	p15, 0, r4, c8, c7, 1
+	/* TLB will miss and entry will be reloaded */
+	ldr	r4, [r4]
+	/* read the lockdown register (victim will have rloaded) */
+	mrc	p15, 0, r3, c10, c0, 0
+
+	ldr	r4, SYS_CTRL_BASE_VA
+	/* Invalidate the System controller virtual address in TLB */
+	mcr	p15, 0, r4, c8, c7, 1
+	/* TLB will miss and entry will be reloaded */
+	ldr	r4, [r4]
+	/* read the lockdown register (victim will have rloaded) */
+	mrc	p15, 0, r3, c10, c0, 0
+
+	ldr	r4, MISC_BASE_VA
+	/* Invalidate the Miscellaneous registers virtual address in TLB */
+	mcr	p15, 0, r4, c8, c7, 1
+	/* TLB will miss and entry will be reloaded */
+	ldr	r4, [r4]
+	/* read the lockdown register (victim will have rloaded) */
+	mrc	p15, 0, r3, c10, c0, 0
+
+	/* clear preserve bit */
+	bic	r3, r3, #1
+	/* write to the lockdown register */
+	mcr	p15, 0, r3, c10, c0, 0
+
+	ldr	r7, MPMC_BASE_VA
+	ldr	r8, SYS_CTRL_BASE_VA
+	ldr	r6, MISC_BASE_VA
+	/* Prefetch certain instructions in the cache. */
+	adr	r4, cache_prefetch_start1
+	adr	r5, cache_prefetch_end1
+	mvn	r3, #0x1F
+	ands	r4, r3, r4
+	/* Lock Instructions in i-cache */
+fetch_loop:
+	/*
+	 * copy a cache-line-sized block of main memory to a cache
+	 * line in the I-cache.
+	 */
+	mcr	p15, 0, r4, c7, c13, 1
+	cmp	r4, r5
+	addls	r4, r4, #0x20
+	bls	fetch_loop
+cache_prefetch_start1:
+	/* Put SDRAM in self-refresh mode */
+	ldr	r3, [r7, #0x1c]
+	/* Clear START bit(24) of MEMCTL_GP_03 register in MPMC */
+	ldr	r4, =0x1000000
+	bic	r3, r3, r4
+	str	r3, [r7, #0x1c]
+
+	ldr	r3, [r7, #0xe4]
+	ldr	r4, =0xffff0000
+	/* Latch the current self refresh time */
+	mov	r9, r3
+	/* Increase the self refresh exit time */
+	bic	r3, r3, r4
+	ldr	r4, =0xffff
+	/* Program the SDRAM self refresh exit time on read command */
+	orr	r3, r3, r4, LSL #16
+	str	r3, [r7, #0xe4]
+
+	ldr	r3, [r7, #0x1c]
+	/* Set the SREFRESH bit(16) */
+	ldr	r4, =0x10000
+	orr	r3, r3, r4
+	str	r3, [r7, #0x1c]
+
+	/* Put the system in slow mode, use system controller */
+	ldr	r3, [r8]
+	bic	r3, r3, #0x7
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	orr	r3, r3, #0x2
+	str	r3, [r8]
+
+wait_till_slow_mode:
+	ldr	r3, [r8]
+	and	r3, r3, #0x78	/* Wait for the mode to be updated */
+	cmp	r3, #0x10	/* Poll the SCCTRL register status bits (6:3) */
+	bne wait_till_slow_mode
+
+	/*
+	 * reprogram the m(r0), p(r2), n(r1) values in the PLL
+	 * control registers (PLL_FRQ register in misc space).
+	 */
+	ldr	r3, [r6, #0x0c]
+	bic	r3, r3, #0x00ff
+	/* Program the PLL post divisor: p */
+	orr	r3, r3, r2
+	str	r3, [r6, #0x0c]
+
+	ldr	r3, [r6, #0x0c]
+	ldr	r4, =0xffff0000
+	bic	r3, r3, r4
+	bic	r3, r3, #0x0700
+	/* Program the PLL pre divisor: n */
+	orr	r3, r3, r1, LSL #8
+	/* Program the PLL feedback divisor: m */
+	orr	r3, r3, r0, LSL #24
+	str	r3, [r6, #0x0c]
+
+	/* Move the system in Normal mode, use system controller */
+	ldr	r3, [r8, #0x0]
+	ldr	r4, =0xfffffff8
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	and	r3, r3, r4
+	orr	r3, r3, #0x4
+	str	r3, [r8, #0x0]
+
+wait_till_normal_mode:
+	ldr	r3, [r8, #0x0]
+	and	r3, r3, #0x78
+	cmp	r3, #0x20	/* Poll the SCCTRL register status bits (6:3) */
+	bne wait_till_normal_mode
+
+	/* Exit DDR-SDRAM from self-refresh mode */
+	ldr	r10, MPMC_BASE_VA
+	/* Clear the SREFRESH bit(16) */
+	ldr	r3, [r10, #0x1c]
+	ldr	r4, =0x10000
+	bic	r3, r3, r4
+	str	r3, [r10, #0x1c]
+	/* Restore the SDRAM self refresh exit time on read command */
+	mov	r3, r9
+	str	r3, [r7, #0xe4]
+	/* Begin the command processing in controller */
+	ldr	r4, =0x1000000
+	orr	r3, r3, r4
+	/* Set START bit(24) of MEMCTL_GP_03 register in MPMC*/
+	str	r3, [r10, #0x1c]
+
+	ldmfd	sp!, {r0-r12, pc}
+
+/* This is the end of the code to be copied */
+
+SYS_CTRL_BASE_VA :
+	.word IO_ADDRESS(SYS_CTRL_BASE_PA)
+MPMC_BASE_VA :
+	.word IO_ADDRESS(MPMC_BASE_PA)
+MISC_BASE_VA :
+	.word IO_ADDRESS(MISC_BASE_PA)
+cache_prefetch_end1 :
+
+#elif defined(CONFIG_ARCH_SPEAR13XX)
+.text
+ENTRY(pll_set_rate)
+#endif
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 3/3] ST SPEAr CPU freq: Adding support for CPU Freq framework
From: Viresh Kumar @ 2011-03-01 11:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977735.git.viresh.kumar@st.com>

From: Deepak Sikri <deepak.sikri@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Deepak Sikri <deepak.sikri@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: shiraz hashim <shiraz.hashim@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Reviewed-by: Jamie Iles <jamie@jamieiles.com>
---
 arch/arm/Kconfig                |    1 +
 arch/arm/mach-spear13xx/clock.c |    7 +-
 arch/arm/mach-spear3xx/clock.c  |    5 +-
 arch/arm/mach-spear6xx/clock.c  |    5 +-
 arch/arm/plat-spear/Makefile    |    2 +-
 arch/arm/plat-spear/cpufreq.c   |  164 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 176 insertions(+), 8 deletions(-)
 create mode 100644 arch/arm/plat-spear/cpufreq.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0aca70d..96cbae5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -872,6 +872,7 @@ config PLAT_SPEAR
 	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
+	select ARCH_HAS_CPUFREQ
 	help
 	  Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
 
diff --git a/arch/arm/mach-spear13xx/clock.c b/arch/arm/mach-spear13xx/clock.c
index 8aba6cf..5d9d6ef 100644
--- a/arch/arm/mach-spear13xx/clock.c
+++ b/arch/arm/mach-spear13xx/clock.c
@@ -91,6 +91,7 @@ static struct pll_clk_config pll1_config = {
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
 	/* PCLK 24MHz */
+	{.mode = 0, .m = 0x64, .n = 0x03, .p = 0x2}, /* 400 MHz */
 	{.mode = 0, .m = 0x7D, .n = 0x03, .p = 0x2}, /* 500 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x03, .p = 0x2}, /* 664 MHz */
 	{.mode = 0, .m = 0xC8, .n = 0x03, .p = 0x2}, /* 800 MHz */
@@ -107,7 +108,7 @@ static struct clk pll1_clk = {
 	.calc_rate = &pll_calc_rate,
 	.recalc = &pll_clk_recalc,
 	.set_rate = &pll_clk_set_rate,
-	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 3},
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 4},
 	.private_data = &pll1_config,
 };
 
@@ -144,7 +145,7 @@ static struct clk pll2_clk = {
 	.calc_rate = &pll_calc_rate,
 	.recalc = &pll_clk_recalc,
 	.set_rate = &pll_clk_set_rate,
-	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 3},
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 4},
 	.private_data = &pll2_config,
 };
 
@@ -165,7 +166,7 @@ static struct clk pll3_clk = {
 	.calc_rate = &pll_calc_rate,
 	.recalc = &pll_clk_recalc,
 	.set_rate = &pll_clk_set_rate,
-	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 3},
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 4},
 	.private_data = &pll3_config,
 };
 
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index 2392cd6..147a109 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c
@@ -56,6 +56,7 @@ static struct pll_clk_masks pll_masks = {
 
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x53, .n = 0x0C, .p = 0x1}, /* 166 MHz */
 	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
@@ -76,7 +77,7 @@ static struct clk pll1_clk = {
 	.calc_rate = &pll_calc_rate,
 	.recalc = &pll_clk_recalc,
 	.set_rate = &pll_clk_set_rate,
-	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 2},
 	.private_data = &pll1_config,
 };
 
@@ -96,7 +97,7 @@ static struct clk pll2_clk = {
 	.calc_rate = &pll_calc_rate,
 	.recalc = &pll_clk_recalc,
 	.set_rate = &pll_clk_set_rate,
-	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 2},
 	.private_data = &pll2_config,
 };
 
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index 6eb0daf..13374d7 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c
@@ -55,6 +55,7 @@ static struct pll_clk_masks pll_masks = {
 
 /* pll rate configuration table, in ascending order of rates */
 struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x53, .n = 0x0C, .p = 0x1}, /* 166 MHz */
 	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
 	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
@@ -75,7 +76,7 @@ static struct clk pll1_clk = {
 	.calc_rate = &pll_calc_rate,
 	.recalc = &pll_clk_recalc,
 	.set_rate = &pll_clk_set_rate,
-	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 2},
 	.private_data = &pll1_config,
 };
 
@@ -95,7 +96,7 @@ static struct clk pll2_clk = {
 	.calc_rate = &pll_calc_rate,
 	.recalc = &pll_clk_recalc,
 	.set_rate = &pll_clk_set_rate,
-	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 2},
 	.private_data = &pll2_config,
 };
 
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index abd39dc..a28d433 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -7,7 +7,7 @@ obj-y	:= clock.o pll_clk.o time.o
 
 obj-$(CONFIG_ARCH_SPEAR13XX)	+= padmux.o
 obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
-
+obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
 obj-$(CONFIG_MACH_SPEAR310)	+= plgpio.o
 obj-$(CONFIG_MACH_SPEAR320)	+= plgpio.o
 
diff --git a/arch/arm/plat-spear/cpufreq.c b/arch/arm/plat-spear/cpufreq.c
new file mode 100644
index 0000000..d8fb1e2
--- /dev/null
+++ b/arch/arm/plat-spear/cpufreq.c
@@ -0,0 +1,164 @@
+/*
+ * arch/arm/plat-spear/cpufreq.c
+ *
+ * CPU Frequency Scaling for SPEAr platform
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Deepak Sikri<deepak.sikri@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/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/system.h>
+#include <mach/hardware.h>
+
+#define CPU_CLK		"cpu_clk"
+
+#ifdef CONFIG_ARCH_SPEAR13XX
+#define MIN_CPU_FREQ	200000
+#define MAX_CPU_FREQ	500000
+
+static u32 spear_cpu_freq[] = {
+	200000, /* 200 MHZ */
+	250000, /* 250 MHZ */
+	332000, /* 332 MHZ */
+	400000, /* 400 MHZ */
+	500000, /* 500 MHZ */
+};
+#elif defined(CONFIG_ARCH_SPEAR6XX) || defined(CONFIG_ARCH_SPEAR3XX)
+#define MIN_CPU_FREQ	166000
+#define MAX_CPU_FREQ	332000
+
+static u32 spear_cpu_freq[] = {
+	166000, /* 166 MHZ */
+	266000, /* 266 MHZ */
+	332000, /* 333 MHZ */
+};
+#endif
+
+static struct
+	cpufreq_frequency_table spear_freq_tbl[ARRAY_SIZE(spear_cpu_freq) + 1];
+static struct clk *cpu_clk;
+
+int spear_cpufreq_verify(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, spear_freq_tbl);
+}
+
+static unsigned int spear_cpufreq_get(unsigned int cpu)
+{
+	return cpu ? 0 : clk_get_rate(cpu_clk) / 1000;
+}
+
+static int spear_cpufreq_target(struct cpufreq_policy *policy,
+		unsigned int target_freq, unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	int index, ret;
+	long newfreq;
+
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	if (cpufreq_frequency_table_target(policy, spear_freq_tbl,
+				target_freq, relation, &index))
+		return -EINVAL;
+
+	freqs.old = spear_cpufreq_get(0);
+	freqs.cpu = policy->cpu;
+
+	if (freqs.old == target_freq)
+		return 0;
+
+	newfreq = clk_round_rate(cpu_clk, spear_cpu_freq[index] * 1000);
+	if (newfreq < 0) {
+		pr_err("CPU Freq: clk_round_rate failed: %ld\n", newfreq);
+		return newfreq;
+	}
+
+	freqs.new = newfreq / 1000;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* Get current rate after clk_set_rate, for both success and failure */
+	ret = clk_set_rate(cpu_clk, freqs.new * 1000);
+	if (ret) {
+		pr_err("CPU Freq: cpu clk_set_rate failed: %d\n", ret);
+		freqs.new = clk_get_rate(cpu_clk) / 1000;
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	return ret;
+}
+
+static int spear_cpufreq_init(struct cpufreq_policy *policy)
+{
+	int i = 0;
+
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	cpu_clk = clk_get(NULL, CPU_CLK);
+	if (IS_ERR(cpu_clk))
+		return PTR_ERR(cpu_clk);
+
+	policy->cpuinfo.min_freq = MIN_CPU_FREQ;
+	policy->cpuinfo.max_freq = MAX_CPU_FREQ;
+	policy->cur = policy->min = policy->max = spear_cpufreq_get(0);
+
+	for (i = 0; i < ARRAY_SIZE(spear_cpu_freq); i++) {
+		spear_freq_tbl[i].index = i;
+		spear_freq_tbl[i].frequency = spear_cpu_freq[i];
+	}
+
+	spear_freq_tbl[i].index = i;
+	spear_freq_tbl[i].frequency = CPUFREQ_TABLE_END;
+	if (!cpufreq_frequency_table_cpuinfo(policy, spear_freq_tbl))
+		cpufreq_frequency_table_get_attr(spear_freq_tbl,
+				policy->cpu);
+
+	policy->cpuinfo.transition_latency = 300*1000; /*300 us*/
+
+	return 0;
+}
+
+static int spear_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	clk_put(cpu_clk);
+	return 0;
+}
+
+static struct freq_attr *spear_cpufreq_attr[] = {
+	 &cpufreq_freq_attr_scaling_available_freqs,
+	 NULL,
+};
+
+static struct cpufreq_driver spear_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= spear_cpufreq_verify,
+	.target		= spear_cpufreq_target,
+	.get		= spear_cpufreq_get,
+	.init		= spear_cpufreq_init,
+	.exit		= spear_cpufreq_exit,
+	.name		= "spear_cpufreq",
+	.attr		= spear_cpufreq_attr,
+};
+
+static int __init spear_cpufreq_register(void)
+{
+	return cpufreq_register_driver(&spear_driver);
+}
+
+arch_initcall(spear_cpufreq_register);
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 10/11] ST SPEAr6xx: Rework Kconfig for single image solution
From: Viresh Kumar @ 2011-03-01 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977709.git.viresh.kumar@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
---
 arch/arm/mach-spear6xx/Kconfig    |   15 ++++++++-------
 arch/arm/mach-spear6xx/Kconfig600 |   17 -----------------
 2 files changed, 8 insertions(+), 24 deletions(-)
 delete mode 100644 arch/arm/mach-spear6xx/Kconfig600

diff --git a/arch/arm/mach-spear6xx/Kconfig b/arch/arm/mach-spear6xx/Kconfig
index bddba03..ff4ae5b 100644
--- a/arch/arm/mach-spear6xx/Kconfig
+++ b/arch/arm/mach-spear6xx/Kconfig
@@ -4,17 +4,18 @@
 
 if ARCH_SPEAR6XX
 
-choice
-	prompt "SPEAr6XX Family"
-	default MACH_SPEAR600
+menu "SPEAr6xx Implementations"
+config BOARD_SPEAR600_EVB
+	bool "SPEAr600 Evaluation Board"
+	select MACH_SPEAR600
+	help
+	  Supports ST SPEAr600 Evaluation Board
+
+endmenu
 
 config MACH_SPEAR600
 	bool "SPEAr600"
 	help
 	  Supports ST SPEAr600 Machine
-endchoice
-
-# Adding SPEAr6XX machine specific configuration files
-source "arch/arm/mach-spear6xx/Kconfig600"
 
 endif #ARCH_SPEAR6XX
diff --git a/arch/arm/mach-spear6xx/Kconfig600 b/arch/arm/mach-spear6xx/Kconfig600
deleted file mode 100644
index 9e19f65..0000000
--- a/arch/arm/mach-spear6xx/Kconfig600
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# SPEAr600 machine configuration file
-#
-
-if MACH_SPEAR600
-
-choice
-	prompt "SPEAr600 Boards"
-	default BOARD_SPEAR600_EVB
-
-config	BOARD_SPEAR600_EVB
-	bool "SPEAr600 Evaluation Board"
-	help
-	  Supports ST SPEAr600 Evaluation Board
-endchoice
-
-endif	#MACH_SPEAR600
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 11/11] ST SPEAR6xx: renaming spear600_defconfig as spear6xx_defconfig
From: Viresh Kumar @ 2011-03-01 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977709.git.viresh.kumar@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
---
 .../{spear600_defconfig => spear6xx_defconfig}     |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
 rename arch/arm/configs/{spear600_defconfig => spear6xx_defconfig} (97%)

diff --git a/arch/arm/configs/spear600_defconfig b/arch/arm/configs/spear6xx_defconfig
similarity index 97%
rename from arch/arm/configs/spear600_defconfig
rename to arch/arm/configs/spear6xx_defconfig
index 6777c11..cef2e83 100644
--- a/arch/arm/configs/spear600_defconfig
+++ b/arch/arm/configs/spear6xx_defconfig
@@ -8,6 +8,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR6XX=y
+CONFIG_BOARD_SPEAR600_EVB=y
 CONFIG_BINFMT_MISC=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_BLK_DEV_RAM=y
@@ -22,7 +23,6 @@ CONFIG_MAX_RAW_DEVS=8192
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PL061=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_EXT2_FS=y
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 10/10] ST SPEAr13xx: Add padmux support
From: Viresh Kumar @ 2011-03-01 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977719.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar@st.com>

This patch adds padmux support for SPEAr1300 & SPEAr1310.

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Signed-off-by: shiraz hashim <shiraz.hashim@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |  198 +++++++++-
 arch/arm/mach-spear13xx/spear1300.c            |   17 +-
 arch/arm/mach-spear13xx/spear1300_evb.c        |   21 +-
 arch/arm/mach-spear13xx/spear1310.c            |  352 +++++++++++++++-
 arch/arm/mach-spear13xx/spear1310_evb.c        |   27 ++-
 arch/arm/mach-spear13xx/spear13xx.c            |  559 ++++++++++++++++++++++++
 arch/arm/plat-spear/Makefile                   |    1 +
 7 files changed, 1169 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 64feaa5..a75de93 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -19,6 +19,198 @@
 #include <linux/amba/bus.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <plat/padmux.h>
+
+/*
+ * Function enable (Pad multiplexing register) offsets
+ */
+/* Pad multiplexing base */
+#define SPEAR13XX_FUNC_ENB_BASE		UL(0xE0700650)
+#define SPEAR13XX_PCM_CFG_BASE		UL(0xE0700100)
+
+#define PAD_MUX_CONFIG_REG_0	UL(0xE0700650)
+#define PAD_MUX_CONFIG_REG_1	UL(0xE0700654)
+#define PAD_MUX_CONFIG_REG_2	UL(0xE0700658)
+#define PAD_MUX_CONFIG_REG_3	UL(0xE070065C)
+
+#if defined(CONFIG_MACH_SPEAR1310)
+#define SPEAR1310_FUNC_CNTL_0	UL(0x6C800000)
+
+#define PMX_SMII_MASK		(1 << 24)	/* Func cntl reg0 */
+#define PMX_EGPIO7_MASK		(1 << 2)	/* Pcm cfg reg */
+#endif
+
+/* pad mux declarations */
+#define PMX_I2S1_MASK		(1 << 3)
+#define PMX_I2S2_MASK		(1 << 16)	/* Offset 4 */
+#define PMX_CLCD1_MASK		(1 << 5)
+#define PMX_CLCD2_MASK		(1 << 3)	/* Offset 4 */
+#define PMX_EGPIO00_MASK	(1 << 6)
+#define PMX_EGPIO01_MASK	(1 << 7)
+#define PMX_EGPIO02_MASK	(1 << 8)
+#define PMX_EGPIO03_MASK	(1 << 9)
+#define PMX_EGPIO04_MASK	(1 << 10)
+#define PMX_EGPIO05_MASK	(1 << 11)
+#define PMX_EGPIO06_MASK	(1 << 12)
+#define PMX_EGPIO07_MASK	(1 << 13)
+#define PMX_EGPIO08_MASK	(1 << 14)
+#define PMX_EGPIO09_MASK	(1 << 15)
+#define PMX_EGPIO10_MASK	(1 << 5)	/* Offset 4 */
+#define PMX_EGPIO11_MASK	(1 << 6)	/* Offset 4 */
+#define PMX_EGPIO12_MASK	(1 << 7)	/* Offset 4 */
+#define PMX_EGPIO13_MASK	(1 << 8)	/* Offset 4 */
+#define PMX_EGPIO14_MASK	(1 << 9)	/* Offset 4 */
+#define PMX_EGPIO15_MASK	(1 << 10)	/* Offset 4 */
+#define PMX_EGPIO_0_GRP_MASK	(PMX_EGPIO00_MASK | PMX_EGPIO01_MASK | \
+		PMX_EGPIO02_MASK | PMX_EGPIO03_MASK | PMX_EGPIO04_MASK | \
+		PMX_EGPIO05_MASK | PMX_EGPIO06_MASK | PMX_EGPIO07_MASK | \
+		PMX_EGPIO08_MASK | PMX_EGPIO09_MASK)
+#define PMX_EGPIO_1_GRP_MASK	(PMX_EGPIO10_MASK | PMX_EGPIO11_MASK | \
+		PMX_EGPIO12_MASK | PMX_EGPIO13_MASK | PMX_EGPIO14_MASK | \
+		PMX_EGPIO15_MASK)
+
+#define PMX_SMI_MASK		(1 << 16)
+#define PMX_SMINCS2_MASK	(1 << 1)	/* Offset 4 */
+#define PMX_SMINCS3_MASK	(1 << 2)	/* Offset 4 */
+
+#define PMX_GMIICLK_MASK			(1 << 18)
+#define PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK	(1 << 19)
+#define PMX_RXCLK_RDV_TXEN_D03_MASK		(1 << 20)
+#define PMX_GMIID47_MASK			(1 << 21)
+#define PMX_MDC_MDIO_MASK			(1 << 22)
+
+#define PMX_GMII_MASK		(PMX_GMIICLK_MASK | \
+		PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK | \
+		PMX_RXCLK_RDV_TXEN_D03_MASK | PMX_GMIID47_MASK | \
+		PMX_MDC_MDIO_MASK)
+
+#define PMX_NAND8_MASK		(1 << 17)
+#define PMX_NFAD023_MASK	(1 << 24)
+#define PMX_NFAD24_MASK		(1 << 25)
+#define PMX_NFAD25_MASK		(1 << 26)
+#define PMX_NFWPRT1_MASK	(1 << 24)	/* Offset 4 */
+#define PMX_NFWPRT2_MASK	(1 << 26)	/* Offset 4 */
+#define PMX_NFWPRT3_MASK	(1 << 28)
+#define PMX_NFRSTPWDWN0_MASK	(1 << 29)
+#define PMX_NFRSTPWDWN1_MASK	(1 << 30)
+#define PMX_NFRSTPWDWN2_MASK	(1 << 31)
+#define PMX_NFRSTPWDWN3_MASK	(1 << 0)	/* Offset 4 */
+#define PMX_NFCE1_MASK		(1 << 20)	/* Offset 4 */
+#define PMX_NFCE2_MASK		(1 << 22)	/* Offset 4 */
+#define PMX_NFCE3_MASK		(1 << 27)
+#define PMX_NFIO815_MASK	(1 << 18)	/* Offset 4 */
+
+#define PMX_NAND8BIT_0_MASK	(PMX_NAND8_MASK | PMX_NFAD023_MASK | \
+		PMX_NFAD24_MASK | PMX_NFAD25_MASK | PMX_NFWPRT3_MASK | \
+		PMX_NFRSTPWDWN0_MASK | PMX_NFRSTPWDWN1_MASK | \
+		PMX_NFRSTPWDWN2_MASK | PMX_NFCE3_MASK)
+#define PMX_NAND8BIT_1_MASK	(PMX_NFRSTPWDWN3_MASK)
+
+#define PMX_NAND8BIT4DEV_0_MASK	(PMX_NAND8BIT_0_MASK)
+#define PMX_NAND8BIT4DEV_1_MASK	(PMX_NAND8BIT_1_MASK | PMX_NFCE1_MASK | \
+		PMX_NFCE2_MASK | PMX_NFWPRT1_MASK | PMX_NFWPRT2_MASK)
+
+#define PMX_NAND16BIT_0_MASK	(PMX_NAND8BIT_0_MASK)
+#define PMX_NAND16BIT_1_MASK	(PMX_NAND8BIT_1_MASK | PMX_NFIO815_MASK)
+#define PMX_NAND16BIT4DEV_0_MASK	(PMX_NAND8BIT4DEV_0_MASK)
+#define PMX_NAND16BIT4DEV_1_MASK	(PMX_NAND8BIT4DEV_1_MASK | \
+					PMX_NFIO815_MASK)
+
+#define PMX_KBD_ROW0_MASK	(1 << 25)	/* Offset 4 */
+#define PMX_KBD_ROW1_MASK	(1 << 23)	/* Offset 4 */
+#define PMX_KBD_ROWCOL25_MASK	(1 << 17)	/* Offset 4 */
+#define PMX_KBD_ROWCOL68_MASK	(1 << 4)	/* Offset 4 */
+#define PMX_KBD_COL0_MASK	(1 << 21)	/* Offset 4 */
+#define PMX_KBD_COL1_MASK	(1 << 19)	/* Offset 4 */
+#define PMX_KEYBOARD_6X6_MASK	(PMX_KBD_ROW0_MASK | PMX_KBD_ROW1_MASK | \
+		PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL0_MASK | PMX_KBD_COL1_MASK)
+
+#define PMX_UART0_MASK		(1 << 1)
+#define PMX_I2C_MASK		(1 << 2)
+#define PMX_SSP_MASK		(1 << 4)
+#define PMX_UART0_MODEM_MASK	(1 << 11)	/* Offset 4 */
+#define PMX_GPT0_TMR1_MASK	(1 << 12)	/* Offset 4 */
+#define PMX_GPT0_TMR2_MASK	(1 << 13)	/* Offset 4 */
+#define PMX_GPT1_TMR1_MASK	(1 << 14)	/* Offset 4 */
+#define PMX_GPT1_TMR2_MASK	(1 << 15)	/* Offset 4 */
+
+#define PMX_MCIDATA0_MASK	(1 << 27)	/* Offset 4 */
+#define PMX_MCIDATA1_MASK	(1 << 28)	/* Offset 4 */
+#define PMX_MCIDATA2_MASK	(1 << 29)	/* Offset 4 */
+#define PMX_MCIDATA3_MASK	(1 << 30)	/* Offset 4 */
+#define PMX_MCIDATA4_MASK	(1 << 31)	/* Offset 4 */
+#define PMX_MCIDATA5_MASK	(1 << 0)	/* Offset 8 */
+#define PMX_MCIDATA6_MASK	(1 << 1)	/* Offset 8 */
+#define PMX_MCIDATA7_MASK	(1 << 2)	/* Offset 8 */
+#define PMX_MCIDATA1SD_MASK	(1 << 3)	/* Offset 8 */
+#define PMX_MCIDATA2SD_MASK	(1 << 4)	/* Offset 8 */
+#define PMX_MCIDATA3SD_MASK	(1 << 5)	/* Offset 8 */
+#define PMX_MCIADDR0ALE_MASK	(1 << 6)	/* Offset 8 */
+#define PMX_MCIADDR1CLECLK_MASK	(1 << 7)	/* Offset 8 */
+#define PMX_MCIADDR2_MASK	(1 << 8)	/* Offset 8 */
+#define PMX_MCICECF_MASK	(1 << 9)	/* Offset 8 */
+#define PMX_MCICEXD_MASK	(1 << 10)	/* Offset 8 */
+#define PMX_MCICESDMMC_MASK	(1 << 11)	/* Offset 8 */
+#define PMX_MCICDCF1_MASK	(1 << 12)	/* Offset 8 */
+#define PMX_MCICDCF2_MASK	(1 << 13)	/* Offset 8 */
+#define PMX_MCICDXD_MASK	(1 << 14)	/* Offset 8 */
+#define PMX_MCICDSDMMC_MASK	(1 << 15)	/* Offset 8 */
+#define PMX_MCIDATADIR_MASK	(1 << 16)	/* Offset 8 */
+#define PMX_MCIDMARQWP_MASK	(1 << 17)	/* Offset 8 */
+#define PMX_MCIIORDRE_MASK	(1 << 18)	/* Offset 8 */
+#define PMX_MCIIOWRWE_MASK	(1 << 19)	/* Offset 8 */
+#define PMX_MCIRESETCF_MASK	(1 << 20)	/* Offset 8 */
+#define PMX_MCICS0CE_MASK	(1 << 21)	/* Offset 8 */
+#define PMX_MCICFINTR_MASK	(1 << 22)	/* Offset 8 */
+#define PMX_MCIIORDY_MASK	(1 << 23)	/* Offset 8 */
+#define PMX_MCICS1_MASK		(1 << 24)	/* Offset 8 */
+#define PMX_MCIDMAACK_MASK	(1 << 25)	/* Offset 8 */
+#define PMX_MCISDCMD_MASK	(1 << 26)	/* Offset 8 */
+#define PMX_MCILEDS_MASK	(1 << 27)	/* Offset 8 */
+
+#define PMX_MCIFALL_1_MASK	(0xF8000000)
+#define PMX_MCIFALL_2_MASK	(0x0FFFFFFF)
+
+/* pad mux devices */
+extern struct pmx_dev pmx_i2c;
+extern struct pmx_dev pmx_ssp;
+extern struct pmx_dev pmx_i2s1;
+extern struct pmx_dev pmx_i2s2;
+extern struct pmx_dev pmx_clcd;
+extern struct pmx_dev pmx_clcd_hires;
+extern struct pmx_dev pmx_egpio_grp;
+extern struct pmx_dev pmx_smi_2_chips;
+extern struct pmx_dev pmx_smi_4_chips;
+extern struct pmx_dev pmx_gmii;
+extern struct pmx_dev pmx_nand_8bit;
+extern struct pmx_dev pmx_nand_16bit;
+extern struct pmx_dev pmx_keyboard_6x6;
+extern struct pmx_dev pmx_keyboard_9x9;
+extern struct pmx_dev pmx_uart0;
+extern struct pmx_dev pmx_uart0_modem;
+extern struct pmx_dev pmx_gpt_0_1;
+extern struct pmx_dev pmx_gpt_0_2;
+extern struct pmx_dev pmx_gpt_1_1;
+extern struct pmx_dev pmx_gpt_1_2;
+extern struct pmx_dev pmx_mcif;
+
+#if defined(CONFIG_MACH_SPEAR1310)
+extern struct pmx_dev pmx_uart1_modem;
+extern struct pmx_dev pmx_uart_1;
+extern struct pmx_dev pmx_uart_2;
+extern struct pmx_dev pmx_uart_3_4_5;
+extern struct pmx_dev pmx_rs485_hdlc_1_2;
+extern struct pmx_dev pmx_tdm_hdlc_1_2;
+extern struct pmx_dev pmx_nand32bit;
+extern struct pmx_dev pmx_fsmc16bit_4_chips;
+extern struct pmx_dev pmx_fsmc32bit_4_chips;
+extern struct pmx_dev pmx_gmii1;
+extern struct pmx_dev pmx_rgmii;
+extern struct pmx_dev pmx_i2c1;
+extern struct pmx_dev pmx_smii_0_1_2;
+extern struct pmx_dev pmx_can;
+extern struct pmx_dev pmx_uart1_modem;
+#endif
 
 /*
  * Each GPT has 2 timer channels
@@ -43,7 +235,8 @@ void spear13xx_secondary_startup(void);
 /* spear1300 declarations */
 #ifdef CONFIG_MACH_SPEAR1300
 /* Add spear1300 machine function declarations here */
-void __init spear1300_init(void);
+void __init spear1300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count);
 
 #endif /* CONFIG_MACH_SPEAR1300 */
 
@@ -59,7 +252,8 @@ extern struct platform_device spear1310_can0_device;
 extern struct platform_device spear1310_can1_device;
 
 /* Add spear1310 machine function declarations here */
-void __init spear1310_init(void);
+void __init spear1310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count);
 void __init spear1310_map_io(void);
 
 #endif /* CONFIG_MACH_SPEAR1310 */
diff --git a/arch/arm/mach-spear13xx/spear1300.c b/arch/arm/mach-spear13xx/spear1300.c
index 9c38bec..c0f1743 100644
--- a/arch/arm/mach-spear13xx/spear1300.c
+++ b/arch/arm/mach-spear13xx/spear1300.c
@@ -14,10 +14,25 @@
 #include <mach/generic.h>
 #include <mach/hardware.h>
 
+/* pmx driver structure */
+static struct pmx_driver pmx_driver;
+
 /* Add spear1300 specific devices here */
 
-void __init spear1300_init(void)
+void __init spear1300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count)
 {
+	int ret;
+
 	/* call spear13xx family common init function */
 	spear13xx_init();
+
+	/* pmx initialization */
+	pmx_driver.mode = pmx_mode;
+	pmx_driver.devs = pmx_devs;
+	pmx_driver.devs_count = pmx_dev_count;
+
+	ret = pmx_register(&pmx_driver);
+	if (ret)
+		pr_err("padmux: registeration failed. err no: %d\n", ret);
 }
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index c95c141..2e966cf 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -17,6 +17,25 @@
 #include <mach/generic.h>
 #include <mach/hardware.h>
 
+/* padmux devices to enable */
+static struct pmx_dev *pmx_devs[] = {
+	/* spear13xx specific devices */
+	&pmx_i2c,
+	&pmx_i2s1,
+	&pmx_i2s2,
+	&pmx_clcd,
+	&pmx_egpio_grp,
+	&pmx_gmii,
+	&pmx_keyboard_6x6,
+	&pmx_mcif,
+	&pmx_nand_8bit,
+	&pmx_smi_4_chips,
+	&pmx_ssp,
+	&pmx_uart0,
+
+	/* spear1300 specific devices */
+};
+
 static struct amba_device *amba_devs[] __initdata = {
 	&spear13xx_uart_device,
 };
@@ -29,7 +48,7 @@ static void __init spear1300_evb_init(void)
 	unsigned int i;
 
 	/* call spear1300 machine init function */
-	spear1300_init();
+	spear1300_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index e4ad092..21ec388 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -17,6 +17,344 @@
 #include <mach/generic.h>
 #include <mach/hardware.h>
 
+/* pmx driver structure */
+static struct pmx_driver pmx_driver;
+
+/* Pad multiplexing for uart1_modem device */
+static struct pmx_mux_reg pmx_uart1_modem_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_I2S1_MASK | PMX_SSP_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart1_modem_modes[] = {
+	{
+		.mux_regs = pmx_uart1_modem_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart1_modem_mux),
+	},
+};
+
+struct pmx_dev pmx_uart1_modem = {
+	.name = "uart1_modem",
+	.modes = pmx_uart1_modem_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart1_modem_modes),
+};
+
+/* Pad multiplexing for uart1 device */
+static struct pmx_mux_reg pmx_uart1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SSP_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart1_modes[] = {
+	{
+		.mux_regs = pmx_uart1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart1_mux),
+	},
+};
+
+struct pmx_dev pmx_uart_1 = {
+	.name = "uart1",
+	.modes = pmx_uart1_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart1_modes),
+};
+
+/* Pad multiplexing for uart2 device */
+static struct pmx_mux_reg pmx_uart2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SSP_MASK | PMX_CLCD1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart2_modes[] = {
+	{
+		.mux_regs = pmx_uart2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart2_mux),
+	},
+};
+
+struct pmx_dev pmx_uart_2 = {
+	.name = "uart2",
+	.modes = pmx_uart2_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart2_modes),
+};
+
+/* Pad multiplexing for uart_3_4_5 device */
+static struct pmx_mux_reg pmx_uart_3_4_5_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart_3_4_5_modes[] = {
+	{
+		.mux_regs = pmx_uart_3_4_5_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart_3_4_5_mux),
+	},
+};
+
+struct pmx_dev pmx_uart_3_4_5 = {
+	.name = "uart_3_4_5",
+	.modes = pmx_uart_3_4_5_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart_3_4_5_modes),
+};
+
+/* Pad multiplexing for rs485_hdlc_1_2 device */
+static struct pmx_mux_reg pmx_rs485_hdlc_1_2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_rs485_hdlc_1_2_modes[] = {
+	{
+		.mux_regs = pmx_rs485_hdlc_1_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_rs485_hdlc_1_2_mux),
+	},
+};
+
+struct pmx_dev pmx_rs485_hdlc_1_2 = {
+	.name = "rs485_hdlc_1_2",
+	.modes = pmx_rs485_hdlc_1_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_rs485_hdlc_1_2_modes),
+};
+
+/* Pad multiplexing for tdm_hdlc_1_2 device */
+static struct pmx_mux_reg pmx_tdm_hdlc_1_2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_tdm_hdlc_1_2_modes[] = {
+	{
+		.mux_regs = pmx_tdm_hdlc_1_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_tdm_hdlc_1_2_mux),
+	},
+};
+
+struct pmx_dev pmx_tdm_hdlc_1_2 = {
+	.name = "tdm_hdlc_1_2",
+	.modes = pmx_tdm_hdlc_1_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_tdm_hdlc_1_2_modes),
+};
+
+/* Pad multiplexing for fsmc32bit device */
+static struct pmx_mux_reg pmx_fsmc32bit_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_EGPIO_0_GRP_MASK | PMX_SMI_MASK | \
+			PMX_NAND16BIT4DEV_0_MASK | PMX_CLCD1_MASK,
+		.value = 0,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_KEYBOARD_6X6_MASK | PMX_NAND16BIT4DEV_1_MASK,
+		.value = 0,
+	}, {
+		.address = SPEAR13XX_PCM_CFG_BASE,
+		.mask = PMX_EGPIO7_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_fsmc32bit_modes[] = {
+	{
+		.mux_regs = pmx_fsmc32bit_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_fsmc32bit_mux),
+	},
+};
+
+struct pmx_dev pmx_fsmc32bit_4_chips = {
+	.name = "fsmc32bit",
+	.modes = pmx_fsmc32bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_fsmc32bit_modes),
+};
+
+/* Pad multiplexing for fsmc16bit device */
+static struct pmx_mux_reg pmx_fsmc16bit_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND16BIT4DEV_0_MASK,
+		.value = 0,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_KEYBOARD_6X6_MASK | PMX_NAND16BIT4DEV_1_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_fsmc16bit_modes[] = {
+	{
+		.mux_regs = pmx_fsmc16bit_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_fsmc16bit_mux),
+	},
+};
+
+struct pmx_dev pmx_fsmc16bit_4_chips = {
+	.name = "fsmc16bit",
+	.modes = pmx_fsmc16bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_fsmc16bit_modes),
+};
+
+/* Pad multiplexing for gmii1 device */
+static struct pmx_mux_reg pmx_gmii1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_GMII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_gmii1_modes[] = {
+	{
+		.mux_regs = pmx_gmii1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gmii1_mux),
+	},
+};
+
+struct pmx_dev pmx_gmii1 = {
+	.name = "gmii1",
+	.modes = pmx_gmii1_modes,
+	.mode_count = ARRAY_SIZE(pmx_gmii1_modes),
+};
+
+/* Pad multiplexing for rgmii device */
+static struct pmx_mux_reg pmx_rgmii_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_GMII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_rgmii_modes[] = {
+	{
+		.mux_regs = pmx_rgmii_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_rgmii_mux),
+	},
+};
+
+struct pmx_dev pmx_rgmii = {
+	.name = "rgmii",
+	.modes = pmx_rgmii_modes,
+	.mode_count = ARRAY_SIZE(pmx_rgmii_modes),
+};
+
+/* Pad multiplexing for i2c1 device */
+static struct pmx_mux_reg pmx_i2c1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2c1_modes[] = {
+	{
+		.mux_regs = pmx_i2c1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2c1_mux),
+	},
+};
+
+struct pmx_dev pmx_i2c1 = {
+	.name = "i2c1",
+	.modes = pmx_i2c1_modes,
+	.mode_count = ARRAY_SIZE(pmx_i2c1_modes),
+};
+
+/* Pad multiplexing for smii_0_1_2 device */
+static struct pmx_mux_reg pmx_smii_0_1_2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_CLCD2_MASK | PMX_KBD_ROWCOL68_MASK | \
+			PMX_EGPIO_1_GRP_MASK | PMX_GPT0_TMR1_MASK | \
+			PMX_GPT0_TMR2_MASK | PMX_GPT1_TMR1_MASK | \
+			PMX_GPT1_TMR2_MASK,
+		.value = 0,
+	}, {
+		.address = SPEAR1310_FUNC_CNTL_0,
+		.mask = PMX_SMII_MASK,
+		.value = PMX_SMII_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_smii_0_1_2_modes[] = {
+	{
+		.mux_regs = pmx_smii_0_1_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_smii_0_1_2_mux),
+	},
+};
+
+struct pmx_dev pmx_smii_0_1_2 = {
+	.name = "smii_0_1_2",
+	.modes = pmx_smii_0_1_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_smii_0_1_2_modes),
+};
+
+/* Pad multiplexing for pci1 device */
+static struct pmx_mux_reg pmx_pci1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_CLCD2_MASK | PMX_KBD_ROWCOL68_MASK | \
+			PMX_EGPIO_1_GRP_MASK | PMX_GPT0_TMR1_MASK | \
+			PMX_GPT0_TMR2_MASK | PMX_GPT1_TMR1_MASK | \
+			PMX_GPT1_TMR2_MASK,
+		.value = 0,
+	}, {
+		.address = SPEAR1310_FUNC_CNTL_0,
+		.mask = PMX_SMII_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_pci1_modes[] = {
+	{
+		.mux_regs = pmx_pci1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_pci1_mux),
+	},
+};
+
+struct pmx_dev pmx_pci1 = {
+	.name = "pci1",
+	.modes = pmx_pci1_modes,
+	.mode_count = ARRAY_SIZE(pmx_pci1_modes),
+};
+
+/* Pad multiplexing for can device */
+static struct pmx_mux_reg pmx_can_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_I2S2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_can_modes[] = {
+	{
+		.mux_regs = pmx_can_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_can_mux),
+	},
+};
+
+struct pmx_dev pmx_can = {
+	.name = "can",
+	.modes = pmx_can_modes,
+	.mode_count = ARRAY_SIZE(pmx_can_modes),
+};
+
 /* Add spear1310 specific devices here */
 /* uart1 device registeration */
 struct amba_device spear1310_uart1_device = {
@@ -137,8 +475,20 @@ void __init spear1310_map_io(void)
 	spear13xx_map_io();
 }
 
-void __init spear1310_init(void)
+void __init spear1310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
+		u8 pmx_dev_count)
 {
+	int ret;
+
 	/* call spear13xx family common init function */
 	spear13xx_init();
+
+	/* pmx initialization */
+	pmx_driver.mode = pmx_mode;
+	pmx_driver.devs = pmx_devs;
+	pmx_driver.devs_count = pmx_dev_count;
+
+	ret = pmx_register(&pmx_driver);
+	if (ret)
+		pr_err("padmux: registeration failed. err no: %d\n", ret);
 }
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index a87e82b..42625c8 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -17,6 +17,31 @@
 #include <mach/generic.h>
 #include <mach/hardware.h>
 
+/* padmux devices to enable */
+static struct pmx_dev *pmx_devs[] = {
+	/* spear13xx specific devices */
+	&pmx_i2c,
+	&pmx_i2s1,
+	&pmx_egpio_grp,
+	&pmx_gmii,
+	&pmx_keyboard_6x6,
+	&pmx_mcif,
+	&pmx_nand_8bit,
+	&pmx_smi_2_chips,
+	&pmx_uart0,
+
+	/* spear1310 specific devices */
+	&pmx_can,
+	&pmx_i2c1,
+	&pmx_smii_0_1_2,
+	&pmx_fsmc16bit_4_chips,
+	&pmx_rs485_hdlc_1_2,
+	&pmx_tdm_hdlc_1_2,
+	&pmx_uart_1,
+	&pmx_uart_2,
+	&pmx_uart_3_4_5,
+};
+
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear13xx specific devices */
 	&spear13xx_uart_device,
@@ -42,7 +67,7 @@ static void __init spear1310_evb_init(void)
 	unsigned int i;
 
 	/* call spear1310 machine init function */
-	spear1310_init();
+	spear1310_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index b5da555..7832c1a 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -136,3 +136,562 @@ static void __init spear13xx_timer_init(void)
 struct sys_timer spear13xx_timer = {
 	.init = spear13xx_timer_init,
 };
+
+/* pad multiplexing support */
+/* devices */
+
+/* Pad multiplexing for i2c device */
+static struct pmx_mux_reg pmx_i2c_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_I2C_MASK,
+		.value = PMX_I2C_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2c_modes[] = {
+	{
+		.mux_regs = pmx_i2c_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2c_mux),
+	},
+};
+
+struct pmx_dev pmx_i2c = {
+	.name = "i2c",
+	.modes = pmx_i2c_modes,
+	.mode_count = ARRAY_SIZE(pmx_i2c_modes),
+};
+
+/* Pad multiplexing for ssp device */
+static struct pmx_mux_reg pmx_ssp_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SSP_MASK,
+		.value = PMX_SSP_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_ssp_modes[] = {
+	{
+		.mux_regs = pmx_ssp_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_ssp_mux),
+	},
+};
+
+struct pmx_dev pmx_ssp = {
+	.name = "ssp",
+	.modes = pmx_ssp_modes,
+	.mode_count = ARRAY_SIZE(pmx_ssp_modes),
+};
+
+/* Pad multiplexing for i2s1 device */
+static struct pmx_mux_reg pmx_i2s1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_I2S1_MASK,
+		.value = PMX_I2S1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2s1_modes[] = {
+	{
+		.mux_regs = pmx_i2s1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2s1_mux),
+	},
+};
+
+struct pmx_dev pmx_i2s1 = {
+	.name = "i2s1",
+	.modes = pmx_i2s1_modes,
+	.mode_count = ARRAY_SIZE(pmx_i2s1_modes),
+};
+
+/* Pad multiplexing for i2s2 device */
+static struct pmx_mux_reg pmx_i2s2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_I2S2_MASK,
+		.value = PMX_I2S2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_i2s2_modes[] = {
+	{
+		.mux_regs = pmx_i2s2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_i2s2_mux),
+	},
+};
+
+struct pmx_dev pmx_i2s2 = {
+	.name = "i2s2",
+	.modes = pmx_i2s2_modes,
+	.mode_count = ARRAY_SIZE(pmx_i2s2_modes),
+};
+
+/* Pad multiplexing for clcd device */
+static struct pmx_mux_reg pmx_clcd_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = PMX_CLCD1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_clcd_modes[] = {
+	{
+		.mux_regs = pmx_clcd_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd_mux),
+	},
+};
+
+struct pmx_dev pmx_clcd = {
+	.name = "clcd",
+	.modes = pmx_clcd_modes,
+	.mode_count = ARRAY_SIZE(pmx_clcd_modes),
+};
+
+/* Pad multiplexing for clcd_hires device */
+static struct pmx_mux_reg pmx_clcd_hires_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_CLCD1_MASK,
+		.value = PMX_CLCD1_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_CLCD2_MASK,
+		.value = PMX_CLCD2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_clcd_hires_modes[] = {
+	{
+		.mux_regs = pmx_clcd_hires_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_clcd_hires_mux),
+	},
+};
+
+struct pmx_dev pmx_clcd_hires = {
+	.name = "clcd_high_res",
+	.modes = pmx_clcd_hires_modes,
+	.mode_count = ARRAY_SIZE(pmx_clcd_hires_modes),
+};
+
+/*
+ * By default, all EGPIOs are enabled.
+ * TBD : Board specific enabling of specific GPIOs only
+ */
+static struct pmx_mux_reg pmx_egpio_grp_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_EGPIO_0_GRP_MASK,
+		.value = PMX_EGPIO_0_GRP_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_EGPIO_1_GRP_MASK,
+		.value = PMX_EGPIO_1_GRP_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_egpio_grp_modes[] = {
+	{
+		.mux_regs = pmx_egpio_grp_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_egpio_grp_mux),
+	},
+};
+
+struct pmx_dev pmx_egpio_grp = {
+	.name = "egpios",
+	.modes = pmx_egpio_grp_modes,
+	.mode_count = ARRAY_SIZE(pmx_egpio_grp_modes),
+};
+
+/* Pad multiplexing for smi 2 chips device */
+static struct pmx_mux_reg pmx_smi_2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SMI_MASK,
+		.value = PMX_SMI_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_smi_2_modes[] = {
+	{
+		.mux_regs = pmx_smi_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_smi_2_mux),
+	},
+};
+
+struct pmx_dev pmx_smi_2_chips = {
+	.name = "smi_2_chips",
+	.modes = pmx_smi_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_smi_2_modes),
+};
+
+/* Pad multiplexing for smi 4 chips device */
+static struct pmx_mux_reg pmx_smi_4_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_SMI_MASK,
+		.value = PMX_SMI_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+		.value = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_smi_4_modes[] = {
+	{
+		.mux_regs = pmx_smi_4_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_smi_4_mux),
+	},
+};
+
+struct pmx_dev pmx_smi_4_chips = {
+	.name = "smi_4_chips",
+	.modes = pmx_smi_4_modes,
+	.mode_count = ARRAY_SIZE(pmx_smi_4_modes),
+};
+
+/* Pad multiplexing for gmii device */
+static struct pmx_mux_reg pmx_gmii_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_GMII_MASK,
+		.value = PMX_GMII_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gmii_modes[] = {
+	{
+		.mux_regs = pmx_gmii_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gmii_mux),
+	},
+};
+
+struct pmx_dev pmx_gmii = {
+	.name = "gmii",
+	.modes = pmx_gmii_modes,
+	.mode_count = ARRAY_SIZE(pmx_gmii_modes),
+};
+
+/* Pad multiplexing for nand 8bit (4 chips) */
+static struct pmx_mux_reg pmx_nand8_4_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND8BIT4DEV_0_MASK,
+		.value = PMX_NAND8BIT4DEV_0_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND8BIT4DEV_1_MASK | PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_NAND8BIT4DEV_1_MASK | PMX_KEYBOARD_6X6_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_nand8_4_modes[] = {
+	{
+		.mux_regs = pmx_nand8_4_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_nand8_4_mux),
+	},
+};
+
+struct pmx_dev pmx_nand_8bit_4_chips = {
+	.name = "nand-8bit_4_chips",
+	.modes = pmx_nand8_4_modes,
+	.mode_count = ARRAY_SIZE(pmx_nand8_4_modes),
+};
+
+/* Pad multiplexing for nand 8bit device (cs0 only) */
+static struct pmx_mux_reg pmx_nand8_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND8BIT_0_MASK,
+		.value = PMX_NAND8BIT_0_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND8BIT_1_MASK | PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_NAND8BIT_1_MASK | PMX_KEYBOARD_6X6_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_nand8_modes[] = {
+	{
+		.mux_regs = pmx_nand8_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_nand8_mux),
+	},
+};
+
+struct pmx_dev pmx_nand_8bit = {
+	.name = "nand-8bit",
+	.modes = pmx_nand8_modes,
+	.mode_count = ARRAY_SIZE(pmx_nand8_modes),
+};
+
+/*
+ * Pad multiplexing for nand 16bit device
+ * Note : Enabling pmx_nand_16bit means that all the required pads for
+ *   16bit nand device operations are enabled. These also include pads
+ *   for 8bit devices
+ */
+static struct pmx_mux_reg pmx_nand16_4_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND16BIT4DEV_0_MASK,
+		.value = PMX_NAND16BIT4DEV_0_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND16BIT4DEV_1_MASK | PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_NAND16BIT4DEV_1_MASK | PMX_KEYBOARD_6X6_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_nand16_4_modes[] = {
+	{
+		.mux_regs = pmx_nand16_4_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_nand16_4_mux),
+	},
+};
+
+struct pmx_dev pmx_nand_16bit_4_chips = {
+	.name = "nand-16bit_4_chips",
+	.modes = pmx_nand16_4_modes,
+	.mode_count = ARRAY_SIZE(pmx_nand16_4_modes),
+};
+
+/* Pad multiplexing for nand 16bit device (cs0 only) */
+static struct pmx_mux_reg pmx_nand16_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_NAND16BIT_0_MASK,
+		.value = PMX_NAND16BIT_0_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NAND16BIT_1_MASK | PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_NAND16BIT_1_MASK | PMX_KEYBOARD_6X6_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_nand16_modes[] = {
+	{
+		.mux_regs = pmx_nand16_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_nand16_mux),
+	},
+};
+
+struct pmx_dev pmx_nand_16bit = {
+	.name = "nand-16bit",
+	.modes = pmx_nand16_modes,
+	.mode_count = ARRAY_SIZE(pmx_nand16_modes),
+};
+
+/* Pad multiplexing for keyboard_6x6 device */
+static struct pmx_mux_reg pmx_keyboard_6x6_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_KEYBOARD_6X6_MASK,
+		.value = PMX_KEYBOARD_6X6_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NFIO815_MASK | PMX_NFCE1_MASK | \
+			PMX_NFCE2_MASK | PMX_NFWPRT1_MASK | PMX_NFWPRT2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_keyboard_6x6_modes[] = {
+	{
+		.mux_regs = pmx_keyboard_6x6_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_keyboard_6x6_mux),
+	},
+};
+
+struct pmx_dev pmx_keyboard_6x6 = {
+	.name = "keyboard_6x6",
+	.modes = pmx_keyboard_6x6_modes,
+	.mode_count = ARRAY_SIZE(pmx_keyboard_6x6_modes),
+};
+
+/* Pad multiplexing for keyboard_9x9 device */
+static struct pmx_mux_reg pmx_keyboard_9x9_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_KEYBOARD_6X6_MASK | PMX_KBD_ROWCOL68_MASK,
+		.value = PMX_KEYBOARD_6X6_MASK | PMX_KBD_ROWCOL68_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_NFIO815_MASK | PMX_NFCE1_MASK | \
+			PMX_NFCE2_MASK | PMX_NFWPRT1_MASK | PMX_NFWPRT2_MASK,
+		.value = 0,
+	},
+};
+
+static struct pmx_dev_mode pmx_keyboard_9x9_modes[] = {
+	{
+		.mux_regs = pmx_keyboard_9x9_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_keyboard_9x9_mux),
+	},
+};
+
+struct pmx_dev pmx_keyboard_9x9 = {
+	.name = "keyboard_9x9",
+	.modes = pmx_keyboard_9x9_modes,
+	.mode_count = ARRAY_SIZE(pmx_keyboard_9x9_modes),
+};
+
+/* Pad multiplexing for uart0 device */
+static struct pmx_mux_reg pmx_uart0_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_0,
+		.mask = PMX_UART0_MASK,
+		.value = PMX_UART0_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart0_modes[] = {
+	{
+		.mux_regs = pmx_uart0_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart0_mux),
+	},
+};
+
+struct pmx_dev pmx_uart0 = {
+	.name = "uart0",
+	.modes = pmx_uart0_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart0_modes),
+};
+
+/* Pad multiplexing for uart0_modem device */
+static struct pmx_mux_reg pmx_uart0_modem_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_UART0_MODEM_MASK,
+		.value = PMX_UART0_MODEM_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_uart0_modem_modes[] = {
+	{
+		.mux_regs = pmx_uart0_modem_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_uart0_modem_mux),
+	},
+};
+
+struct pmx_dev pmx_uart0_modem = {
+	.name = "uart0_modem",
+	.modes = pmx_uart0_modem_modes,
+	.mode_count = ARRAY_SIZE(pmx_uart0_modem_modes),
+};
+
+/* Pad multiplexing for gpt_0_1 device */
+static struct pmx_mux_reg pmx_gpt_0_1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_GPT0_TMR1_MASK,
+		.value = PMX_GPT0_TMR1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpt_0_1_modes[] = {
+	{
+		.mux_regs = pmx_gpt_0_1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpt_0_1_mux),
+	},
+};
+
+struct pmx_dev pmx_gpt_0_1 = {
+	.name = "gpt_0_1",
+	.modes = pmx_gpt_0_1_modes,
+	.mode_count = ARRAY_SIZE(pmx_gpt_0_1_modes),
+};
+
+/* Pad multiplexing for gpt_0_2 device */
+static struct pmx_mux_reg pmx_gpt_0_2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_GPT0_TMR2_MASK,
+		.value = PMX_GPT0_TMR2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpt_0_2_modes[] = {
+	{
+		.mux_regs = pmx_gpt_0_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpt_0_2_mux),
+	},
+};
+
+struct pmx_dev pmx_gpt_0_2 = {
+	.name = "gpt_0_2",
+	.modes = pmx_gpt_0_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_gpt_0_2_modes),
+};
+
+/* Pad multiplexing for gpt_1_1 device */
+static struct pmx_mux_reg pmx_gpt_1_1_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_GPT1_TMR1_MASK,
+		.value = PMX_GPT1_TMR1_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpt_1_1_modes[] = {
+	{
+		.mux_regs = pmx_gpt_1_1_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpt_1_1_mux),
+	},
+};
+
+struct pmx_dev pmx_gpt_1_1 = {
+	.name = "gpt_1_1",
+	.modes = pmx_gpt_1_1_modes,
+	.mode_count = ARRAY_SIZE(pmx_gpt_1_1_modes),
+};
+
+/* Pad multiplexing for gpt_1_2 device */
+static struct pmx_mux_reg pmx_gpt_1_2_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_GPT1_TMR2_MASK,
+		.value = PMX_GPT1_TMR2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_gpt_1_2_modes[] = {
+	{
+		.mux_regs = pmx_gpt_1_2_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_gpt_1_2_mux),
+	},
+};
+
+struct pmx_dev pmx_gpt_1_2 = {
+	.name = "gpt_1_2",
+	.modes = pmx_gpt_1_2_modes,
+	.mode_count = ARRAY_SIZE(pmx_gpt_1_2_modes),
+};
+
+/* Pad multiplexing for mcif device */
+static struct pmx_mux_reg pmx_mcif_mux[] = {
+	{
+		.address = PAD_MUX_CONFIG_REG_1,
+		.mask = PMX_MCIFALL_1_MASK,
+		.value = PMX_MCIFALL_1_MASK,
+	}, {
+		.address = PAD_MUX_CONFIG_REG_2,
+		.mask = PMX_MCIFALL_2_MASK,
+		.value = PMX_MCIFALL_2_MASK,
+	},
+};
+
+static struct pmx_dev_mode pmx_mcif_modes[] = {
+	{
+		.mux_regs = pmx_mcif_mux,
+		.mux_reg_cnt = ARRAY_SIZE(pmx_mcif_mux),
+	},
+};
+
+struct pmx_dev pmx_mcif = {
+	.name = "mcif",
+	.modes = pmx_mcif_modes,
+	.mode_count = ARRAY_SIZE(pmx_mcif_modes),
+};
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index b4f340b..03f9acc 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -5,4 +5,5 @@
 # Common support
 obj-y	:= clock.o time.o
 
+obj-$(CONFIG_ARCH_SPEAR13XX)	+= padmux.o
 obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 10/17] ST SPEAr: adding support for synopsis i2c designware
From: Viresh Kumar @ 2011-03-01 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

From: Rajeev Kumar <rajeev-dlh.kumar@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    3 ++
 arch/arm/mach-spear13xx/spear1300_evb.c        |    4 +++
 arch/arm/mach-spear13xx/spear1310.c            |   22 ++++++++++++++++++
 arch/arm/mach-spear13xx/spear1310_evb.c        |    5 ++++
 arch/arm/mach-spear13xx/spear13xx.c            |   22 ++++++++++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    3 ++
 arch/arm/mach-spear3xx/spear300_evb.c          |    4 +++
 arch/arm/mach-spear3xx/spear310_evb.c          |    4 +++
 arch/arm/mach-spear3xx/spear320.c              |   22 ++++++++++++++++++
 arch/arm/mach-spear3xx/spear320_evb.c          |    5 ++++
 arch/arm/mach-spear3xx/spear3xx.c              |   22 ++++++++++++++++++
 arch/arm/mach-spear6xx/include/mach/generic.h  |    2 +
 arch/arm/mach-spear6xx/spear600_evb.c          |    4 +++
 arch/arm/mach-spear6xx/spear6xx.c              |   22 ++++++++++++++++++
 arch/arm/plat-spear/Makefile                   |    7 +++++
 arch/arm/plat-spear/i2c_eval_board.c           |   29 ++++++++++++++++++++++++
 16 files changed, 180 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-spear/i2c_eval_board.c

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index b598236..991abda 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -223,10 +223,12 @@ extern struct pmx_dev pmx_uart1_modem;
 /* Add spear13xx family device structure declarations here */
 extern struct amba_device spear13xx_gpio_device[];
 extern struct amba_device spear13xx_uart_device;
+extern struct platform_device spear13xx_i2c_device;
 extern struct platform_device spear13xx_rtc_device;
 extern struct sys_timer spear13xx_timer;
 
 /* Add spear13xx family function declarations here */
+void __init i2c_register_default_devices(void);
 void __init spear13xx_clk_init(void);
 void __init spear_setup_timer(void);
 void __init spear13xx_map_io(void);
@@ -252,6 +254,7 @@ extern struct amba_device spear1310_uart4_device;
 extern struct amba_device spear1310_uart5_device;
 extern struct platform_device spear1310_can0_device;
 extern struct platform_device spear1310_can1_device;
+extern struct platform_device spear1310_i2c1_device;
 
 /* Add spear1310 machine function declarations here */
 void __init spear1310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 796d04c..69accb2 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -44,6 +44,7 @@ static struct amba_device *amba_devs[] __initdata = {
 };
 
 static struct platform_device *plat_devs[] __initdata = {
+	&spear13xx_i2c_device,
 	&spear13xx_rtc_device,
 };
 
@@ -84,6 +85,9 @@ static void __init spear1300_evb_init(void)
 	pcie_init(spear1300_pcie_port_is_host);
 #endif
 
+	/* Register slave devices on the I2C buses */
+	i2c_register_default_devices();
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 21ec388..18e38c9 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -458,6 +458,28 @@ struct platform_device spear1310_can1_device = {
 	.resource = can1_resources,
 };
 
+/* i2c1 device registeration */
+static struct resource i2c1_resources[] = {
+	{
+		.start = SPEAR1310_I2C1_BASE,
+		.end = SPEAR1310_I2C1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_I2C_CNTR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear1310_i2c1_device = {
+	.name = "i2c_designware",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.num_resources = ARRAY_SIZE(i2c1_resources),
+	.resource = i2c1_resources,
+};
+
 /* Following will create 1310 specific static virtual/physical mappings */
 struct map_desc spear1310_io_desc[] __initdata = {
 	{
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index 1eea995..891018e 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -59,11 +59,13 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear13xx specific devices */
+	&spear13xx_i2c_device,
 	&spear13xx_rtc_device,
 
 	/* spear1310 specific devices */
 	&spear1310_can0_device,
 	&spear1310_can1_device,
+	&spear1310_i2c1_device,
 };
 
 #ifdef CONFIG_PCIEPORTBUS
@@ -103,6 +105,9 @@ static void __init spear1310_evb_init(void)
 	pcie_init(spear1310_pcie_port_is_host);
 #endif
 
+	/* Register slave devices on the I2C buses */
+	i2c_register_default_devices();
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index e9ba888..1ee23e6 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -76,6 +76,28 @@ struct amba_device spear13xx_uart_device = {
 	.irq = {IRQ_UART, NO_IRQ},
 };
 
+/* i2c device registeration */
+static struct resource i2c_resources[] = {
+	{
+		.start = SPEAR13XX_I2C_BASE,
+		.end = SPEAR13XX_I2C_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_I2C,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear13xx_i2c_device = {
+	.name = "i2c_designware",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.num_resources = ARRAY_SIZE(i2c_resources),
+	.resource = i2c_resources,
+};
+
 /* rtc device registration */
 static struct resource rtc_resources[] = {
 	{
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 73f3f3b..97e9235 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -34,10 +34,12 @@
 extern struct amba_device spear3xx_gpio_device;
 extern struct amba_device spear3xx_uart_device;
 extern struct amba_device spear3xx_wdt_device;
+extern struct platform_device spear3xx_i2c_device;
 extern struct platform_device spear3xx_rtc_device;
 extern struct sys_timer spear3xx_timer;
 
 /* Add spear3xx family function declarations here */
+void __init i2c_register_default_devices(void);
 void __init spear3xx_clk_init(void);
 void __init spear_setup_timer(void);
 void __init spear3xx_map_io(void);
@@ -178,6 +180,7 @@ extern struct amba_device spear320_uart1_device;
 extern struct amba_device spear320_uart2_device;
 extern struct platform_device spear320_can0_device;
 extern struct platform_device spear320_can1_device;
+extern struct platform_device spear320_i2c1_device;
 extern struct platform_device spear320_plgpio_device;
 extern struct platform_device spear320_pwm_device;
 
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index e4a9a4f..0d2b365 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -44,6 +44,7 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
+	&spear3xx_i2c_device,
 	&spear3xx_rtc_device,
 
 	/* spear300 specific devices */
@@ -57,6 +58,9 @@ static void __init spear300_evb_init(void)
 	spear300_init(&spear300_photo_frame_mode, pmx_devs,
 			ARRAY_SIZE(pmx_devs));
 
+	/* Register slave devices on the I2C buses */
+	i2c_register_default_devices();
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 97c9551..59f69d5 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -87,6 +87,7 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
+	&spear3xx_i2c_device,
 	&spear3xx_rtc_device,
 
 	/* spear310 specific devices */
@@ -104,6 +105,9 @@ static void __init spear310_evb_init(void)
 	/* Initialize emi regiters */
 	emi_init(SPEAR310_EMI_REG_BASE, 0, EMI_FLASH_WIDTH32);
 
+	/* Register slave devices on the I2C buses */
+	i2c_register_default_devices();
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 3f058c7..047dcae 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -775,6 +775,28 @@ struct platform_device spear320_can1_device = {
 	.resource = can1_resources,
 };
 
+/* i2c1 device registeration */
+static struct resource i2c1_resources[] = {
+	{
+		.start = SPEAR320_I2C_BASE,
+		.end = SPEAR320_I2C_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = SPEAR320_VIRQ_I2C1 ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear320_i2c1_device = {
+	.name = "i2c_designware",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.num_resources = ARRAY_SIZE(i2c1_resources),
+	.resource = i2c1_resources,
+};
+
 /* plgpio device registeration */
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 17248f4..40d62ae 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -81,11 +81,13 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
+	&spear3xx_i2c_device,
 	&spear3xx_rtc_device,
 
 	/* spear320 specific devices */
 	&spear320_can0_device,
 	&spear320_can1_device,
+	&spear320_i2c1_device,
 	&spear320_emi_nor_device,
 	&spear320_plgpio_device,
 	&spear320_pwm_device,
@@ -102,6 +104,9 @@ static void __init spear320_evb_init(void)
 	/* Initialize emi regiters */
 	emi_init(SPEAR320_EMI_CTRL_BASE, 0, EMI_FLASH_WIDTH16);
 
+	/* Register slave devices on the I2C buses */
+	i2c_register_default_devices();
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 6e8bcd0..f9b5bb1 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -66,6 +66,28 @@ struct amba_device spear3xx_wdt_device = {
 	},
 };
 
+/* i2c device registeration */
+static struct resource i2c_resources[] = {
+	{
+		.start = SPEAR3XX_ICM1_I2C_BASE,
+		.end = SPEAR3XX_ICM1_I2C_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = SPEAR3XX_IRQ_I2C,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear3xx_i2c_device = {
+	.name = "i2c_designware",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.num_resources = ARRAY_SIZE(i2c_resources),
+	.resource = i2c_resources,
+};
+
 /* rtc device registration */
 static struct resource rtc_resources[] = {
 	{
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index 9b7a758..fee7f69 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -32,10 +32,12 @@
 extern struct amba_device gpio_device[];
 extern struct amba_device uart_device[];
 extern struct amba_device wdt_device;
+extern struct platform_device i2c_device;
 extern struct platform_device rtc_device;
 extern struct sys_timer spear6xx_timer;
 
 /* Add spear6xx family function declarations here */
+void __init i2c_register_default_devices(void);
 void __init spear_setup_timer(void);
 void __init spear6xx_map_io(void);
 void __init spear6xx_init_irq(void);
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index 2b8cd87..d8af2bd 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -26,6 +26,7 @@ static struct amba_device *amba_devs[] __initdata = {
 };
 
 static struct platform_device *plat_devs[] __initdata = {
+	&i2c_device,
 	&rtc_device,
 };
 
@@ -36,6 +37,9 @@ static void __init spear600_evb_init(void)
 	/* call spear600 machine init function */
 	spear600_init();
 
+	/* Register slave devices on the I2C buses */
+	i2c_register_default_devices();
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index f976377..fb0a46b 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -111,6 +111,28 @@ struct amba_device wdt_device = {
 	},
 };
 
+/* i2c device registeration */
+static struct resource i2c_resources[] = {
+	{
+		.start = SPEAR6XX_ICM1_I2C_BASE,
+		.end = SPEAR6XX_ICM1_I2C_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_I2C,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device i2c_device = {
+	.name = "i2c_designware",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.num_resources = ARRAY_SIZE(i2c_resources),
+	.resource = i2c_resources,
+};
+
 /* rtc device registration */
 static struct resource rtc_resources[] = {
 	{
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index 636678a..44923e9 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -11,3 +11,10 @@ obj-$(CONFIG_MACH_SPEAR310)	+= plgpio.o
 obj-$(CONFIG_MACH_SPEAR320)	+= plgpio.o
 
 obj-$(CONFIG_SPEAR_PWM)		+= pwm.o
+
+obj-$(CONFIG_BOARD_SPEAR1300_EVB)	+= i2c_eval_board.o
+obj-$(CONFIG_BOARD_SPEAR1310_EVB)	+= i2c_eval_board.o
+obj-$(CONFIG_BOARD_SPEAR300_EVB)	+= i2c_eval_board.o
+obj-$(CONFIG_BOARD_SPEAR310_EVB)	+= i2c_eval_board.o
+obj-$(CONFIG_BOARD_SPEAR320_EVB)	+= i2c_eval_board.o
+obj-$(CONFIG_BOARD_SPEAR600_EVB)	+= i2c_eval_board.o
diff --git a/arch/arm/plat-spear/i2c_eval_board.c b/arch/arm/plat-spear/i2c_eval_board.c
new file mode 100644
index 0000000..869d9c9
--- /dev/null
+++ b/arch/arm/plat-spear/i2c_eval_board.c
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/plat-spear/i2c_eval_board.c
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Rajeev Kumar<rajeev-dlh.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/i2c.h>
+#include <linux/kernel.h>
+
+static struct i2c_board_info __initdata i2c_board_info[] = {
+	{
+		.type = "eeprom",
+		.addr = 0x50,
+	}, {
+		.type = "eeprom",
+		.addr = 0x51,
+	},
+};
+
+void __init i2c_register_default_devices(void)
+{
+	i2c_register_board_info(0, i2c_board_info,
+				ARRAY_SIZE(i2c_board_info));
+}
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 11/17] ST SPEAr: Adding machine support for USB host
From: Viresh Kumar @ 2011-03-01 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

From: Deepak Sikri <deepak.sikri@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Deepak Sikri <deepak.sikri@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    4 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |    4 +
 arch/arm/mach-spear13xx/spear1310_evb.c        |    4 +
 arch/arm/mach-spear13xx/spear13xx.c            |  106 +++++++++++++++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    3 +
 arch/arm/mach-spear3xx/spear300_evb.c          |    3 +
 arch/arm/mach-spear3xx/spear310_evb.c          |    3 +
 arch/arm/mach-spear3xx/spear320_evb.c          |    3 +
 arch/arm/mach-spear3xx/spear3xx.c              |   77 +++++++++++++++++
 arch/arm/mach-spear6xx/include/mach/generic.h  |    4 +
 arch/arm/mach-spear6xx/spear600_evb.c          |    4 +
 arch/arm/mach-spear6xx/spear6xx.c              |  108 ++++++++++++++++++++++++
 12 files changed, 323 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 991abda..9a9b6a3 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -223,7 +223,11 @@ extern struct pmx_dev pmx_uart1_modem;
 /* Add spear13xx family device structure declarations here */
 extern struct amba_device spear13xx_gpio_device[];
 extern struct amba_device spear13xx_uart_device;
+extern struct platform_device spear13xx_ehci0_device;
+extern struct platform_device spear13xx_ehci1_device;
 extern struct platform_device spear13xx_i2c_device;
+extern struct platform_device spear13xx_ohci0_device;
+extern struct platform_device spear13xx_ohci1_device;
 extern struct platform_device spear13xx_rtc_device;
 extern struct sys_timer spear13xx_timer;
 
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 69accb2..c0066a6 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -44,7 +44,11 @@ static struct amba_device *amba_devs[] __initdata = {
 };
 
 static struct platform_device *plat_devs[] __initdata = {
+	&spear13xx_ehci0_device,
+	&spear13xx_ehci1_device,
 	&spear13xx_i2c_device,
+	&spear13xx_ohci0_device,
+	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
 };
 
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index 891018e..d58d3ff 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -59,7 +59,11 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear13xx specific devices */
+	&spear13xx_ehci0_device,
+	&spear13xx_ehci1_device,
 	&spear13xx_i2c_device,
+	&spear13xx_ohci0_device,
+	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
 
 	/* spear1310 specific devices */
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 1ee23e6..69ead0f 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -98,6 +98,112 @@ struct platform_device spear13xx_i2c_device = {
 	.resource = i2c_resources,
 };
 
+/* usb host device registeration */
+static struct resource ehci0_resources[] = {
+	[0] = {
+		.start = SPEAR13XX_UHC0_EHCI_BASE,
+		.end = SPEAR13XX_UHC0_EHCI_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH_EHCI0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ehci1_resources[] = {
+	[0] = {
+		.start = SPEAR13XX_UHC1_EHCI_BASE,
+		.end = SPEAR13XX_UHC1_EHCI_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH_EHCI1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ohci0_resources[] = {
+	[0] = {
+		.start = SPEAR13XX_UHC0_OHCI_BASE,
+		.end = SPEAR13XX_UHC0_OHCI_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH_OHCI0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+static struct resource ohci1_resources[] = {
+	[0] = {
+		.start = SPEAR13XX_UHC1_OHCI_BASE,
+		.end = SPEAR13XX_UHC1_OHCI_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USBH_OHCI1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/* usbh0_id defaults to 0, being static variable */
+static int usbh0_id;
+static int usbh1_id = 1;
+static u64 ehci0_dmamask = ~0;
+
+struct platform_device spear13xx_ehci0_device = {
+	.name = "spear-ehci",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ehci0_dmamask,
+		.platform_data = &usbh0_id,
+	},
+	.num_resources = ARRAY_SIZE(ehci0_resources),
+	.resource = ehci0_resources,
+};
+
+static u64 ehci1_dmamask = ~0;
+
+struct platform_device spear13xx_ehci1_device = {
+	.name = "spear-ehci",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ehci1_dmamask,
+		.platform_data = &usbh1_id,
+	},
+	.num_resources = ARRAY_SIZE(ehci1_resources),
+	.resource = ehci1_resources,
+};
+
+static u64 ohci0_dmamask = ~0;
+
+struct platform_device spear13xx_ohci0_device = {
+	.name = "spear-ohci",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ohci0_dmamask,
+		.platform_data = &usbh0_id,
+	},
+	.num_resources = ARRAY_SIZE(ohci0_resources),
+	.resource = ohci0_resources,
+};
+
+static u64 ohci1_dmamask = ~0;
+struct platform_device spear13xx_ohci1_device = {
+	.name = "spear-ohci",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ohci1_dmamask,
+		.platform_data = &usbh1_id,
+	},
+	.num_resources = ARRAY_SIZE(ohci1_resources),
+	.resource = ohci1_resources,
+};
+
 /* rtc device registration */
 static struct resource rtc_resources[] = {
 	{
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 97e9235..ea21478 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -34,7 +34,10 @@
 extern struct amba_device spear3xx_gpio_device;
 extern struct amba_device spear3xx_uart_device;
 extern struct amba_device spear3xx_wdt_device;
+extern struct platform_device spear3xx_ehci_device;
 extern struct platform_device spear3xx_i2c_device;
+extern struct platform_device spear3xx_ohci0_device;
+extern struct platform_device spear3xx_ohci1_device;
 extern struct platform_device spear3xx_rtc_device;
 extern struct sys_timer spear3xx_timer;
 
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 0d2b365..1dd0e18 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -44,7 +44,10 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
+	&spear3xx_ehci_device,
 	&spear3xx_i2c_device,
+	&spear3xx_ohci0_device,
+	&spear3xx_ohci1_device,
 	&spear3xx_rtc_device,
 
 	/* spear300 specific devices */
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 59f69d5..38f2331 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -87,7 +87,10 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
+	&spear3xx_ehci_device,
 	&spear3xx_i2c_device,
+	&spear3xx_ohci0_device,
+	&spear3xx_ohci1_device,
 	&spear3xx_rtc_device,
 
 	/* spear310 specific devices */
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 40d62ae..75f1495 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -81,7 +81,10 @@ static struct amba_device *amba_devs[] __initdata = {
 
 static struct platform_device *plat_devs[] __initdata = {
 	/* spear3xx specific devices */
+	&spear3xx_ehci_device,
 	&spear3xx_i2c_device,
+	&spear3xx_ohci0_device,
+	&spear3xx_ohci1_device,
 	&spear3xx_rtc_device,
 
 	/* spear320 specific devices */
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index f9b5bb1..574e93a 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -88,6 +88,83 @@ struct platform_device spear3xx_i2c_device = {
 	.resource = i2c_resources,
 };
 
+/* usb host device registeration */
+static int usbh_id = -1;
+static struct resource ehci_resources[] = {
+	[0] = {
+		.start = SPEAR3XX_ICM4_USB_EHCI0_1_BASE,
+		.end = SPEAR3XX_ICM4_USB_EHCI0_1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = SPEAR3XX_IRQ_USB_H_EHCI_0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ohci0_resources[] = {
+	[0] = {
+		.start = SPEAR3XX_ICM4_USB_OHCI0_BASE,
+		.end = SPEAR3XX_ICM4_USB_OHCI0_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = SPEAR3XX_IRQ_USB_H_OHCI_0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ohci1_resources[] = {
+	[0] = {
+		.start = SPEAR3XX_ICM4_USB_OHCI1_BASE,
+		.end = SPEAR3XX_ICM4_USB_OHCI1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = SPEAR3XX_IRQ_USB_H_OHCI_1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static u64 ehci_dmamask = ~0;
+struct platform_device spear3xx_ehci_device = {
+	.name = "spear-ehci",
+	.id = -1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ehci_dmamask,
+		.platform_data = &usbh_id,
+	},
+	.num_resources = ARRAY_SIZE(ehci_resources),
+	.resource = ehci_resources,
+};
+
+static u64 ohci0_dmamask = ~0;
+struct platform_device spear3xx_ohci0_device = {
+	.name = "spear-ohci",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ohci0_dmamask,
+		.platform_data = &usbh_id,
+	},
+	.num_resources = ARRAY_SIZE(ohci0_resources),
+	.resource = ohci0_resources,
+};
+
+static u64 ohci1_dmamask = ~0;
+struct platform_device spear3xx_ohci1_device = {
+	.name = "spear-ohci",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ohci1_dmamask,
+		.platform_data = &usbh_id,
+	},
+	.num_resources = ARRAY_SIZE(ohci1_resources),
+	.resource = ohci1_resources,
+};
+
 /* rtc device registration */
 static struct resource rtc_resources[] = {
 	{
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index fee7f69..62d8b09 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -32,7 +32,11 @@
 extern struct amba_device gpio_device[];
 extern struct amba_device uart_device[];
 extern struct amba_device wdt_device;
+extern struct platform_device ehci0_device;
+extern struct platform_device ehci1_device;
 extern struct platform_device i2c_device;
+extern struct platform_device ohci0_device;
+extern struct platform_device ohci1_device;
 extern struct platform_device rtc_device;
 extern struct sys_timer spear6xx_timer;
 
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index d8af2bd..d8a13a1 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -26,7 +26,11 @@ static struct amba_device *amba_devs[] __initdata = {
 };
 
 static struct platform_device *plat_devs[] __initdata = {
+	&ehci0_device,
+	&ehci1_device,
 	&i2c_device,
+	&ohci0_device,
+	&ohci1_device,
 	&rtc_device,
 };
 
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index fb0a46b..fb1a804 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -133,6 +133,114 @@ struct platform_device i2c_device = {
 	.resource = i2c_resources,
 };
 
+/* usb host device registeration */
+static struct resource ehci0_resources[] = {
+	[0] = {
+		.start = SPEAR6XX_ICM4_USB_EHCI0_BASE,
+		.end = SPEAR6XX_ICM4_USB_EHCI0_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USB_H_EHCI_0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ehci1_resources[] = {
+	[0] = {
+		.start = SPEAR6XX_ICM4_USB_EHCI1_BASE,
+		.end = SPEAR6XX_ICM4_USB_EHCI1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USB_H_EHCI_1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ohci0_resources[] = {
+	[0] = {
+		.start = SPEAR6XX_ICM4_USB_OHCI0_BASE,
+		.end = SPEAR6XX_ICM4_USB_OHCI0_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USB_H_OHCI_0,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource ohci1_resources[] = {
+	[0] = {
+		.start = SPEAR6XX_ICM4_USB_OHCI1_BASE,
+		.end = SPEAR6XX_ICM4_USB_OHCI1_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_USB_H_OHCI_1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/* usbh0_id defaults to 0, being static variable */
+static int usbh0_id;
+static int usbh1_id = 1;
+static u64 ehci0_dmamask = ~0;
+
+struct platform_device ehci0_device = {
+	.name = "spear-ehci",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ehci0_dmamask,
+		.platform_data = &usbh0_id,
+	},
+	.num_resources = ARRAY_SIZE(ehci0_resources),
+	.resource = ehci0_resources,
+};
+
+static u64 ehci1_dmamask = ~0;
+
+struct platform_device ehci1_device = {
+	.name = "spear-ehci",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ehci1_dmamask,
+		.platform_data = &usbh1_id,
+	},
+	.num_resources = ARRAY_SIZE(ehci1_resources),
+	.resource = ehci1_resources,
+};
+
+static u64 ohci0_dmamask = ~0;
+
+struct platform_device ohci0_device = {
+	.name = "spear-ohci",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ohci0_dmamask,
+		.platform_data = &usbh0_id,
+	},
+	.num_resources = ARRAY_SIZE(ohci0_resources),
+	.resource = ohci0_resources,
+};
+
+static u64 ohci1_dmamask = ~0;
+
+struct platform_device ohci1_device = {
+	.name = "spear-ohci",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.dma_mask = &ohci1_dmamask,
+		.platform_data = &usbh1_id,
+	},
+	.num_resources = ARRAY_SIZE(ohci1_resources),
+	.resource = ohci1_resources,
+};
+
 /* rtc device registration */
 static struct resource rtc_resources[] = {
 	{
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 12/17] ST SPEAr: Adding machine support for keyboard
From: Viresh Kumar @ 2011-03-01 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

From: Rajeev Kumar <rajeev-dlh.kumar@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |   20 ++++++++++++++++++++
 arch/arm/mach-spear13xx/spear1310_evb.c        |   20 ++++++++++++++++++++
 arch/arm/mach-spear13xx/spear13xx.c            |   19 +++++++++++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    1 +
 arch/arm/mach-spear3xx/spear300.c              |   19 +++++++++++++++++++
 arch/arm/mach-spear3xx/spear300_evb.c          |   20 ++++++++++++++++++++
 arch/arm/plat-spear/include/plat/keyboard.h    |    7 -------
 8 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 9a9b6a3..f86f097 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -226,6 +226,7 @@ extern struct amba_device spear13xx_uart_device;
 extern struct platform_device spear13xx_ehci0_device;
 extern struct platform_device spear13xx_ehci1_device;
 extern struct platform_device spear13xx_i2c_device;
+extern struct platform_device spear13xx_kbd_device;
 extern struct platform_device spear13xx_ohci0_device;
 extern struct platform_device spear13xx_ohci1_device;
 extern struct platform_device spear13xx_rtc_device;
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index c0066a6..19be757 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <plat/keyboard.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
 #include <mach/pcie.h>
@@ -47,11 +48,24 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_ehci0_device,
 	&spear13xx_ehci1_device,
 	&spear13xx_i2c_device,
+	&spear13xx_kbd_device,
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
 };
 
+/* keyboard specific platform data */
+static const __initconst DECLARE_KEYMAP(keymap);
+static const struct matrix_keymap_data keymap_data __initconst = {
+	.keymap = keymap,
+	.keymap_size = ARRAY_SIZE(keymap),
+};
+
+static const struct kbd_platform_data kbd_data __initconst = {
+	.keymap = &keymap_data,
+	.rep = 1,
+};
+
 #ifdef CONFIG_PCIEPORTBUS
 /*
  * This function is needed for PCIE host and device driver. Same
@@ -83,6 +97,12 @@ static void __init spear1300_evb_init(void)
 	/* call spear1300 machine init function */
 	spear1300_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
+	/* set keyboard plat data */
+	if (platform_device_add_data(&spear13xx_kbd_device, &kbd_data,
+				sizeof(kbd_data)))
+		printk(KERN_WARNING "%s: couldn't add plat_data",
+				spear13xx_kbd_device.name);
+
 #ifdef CONFIG_PCIEPORTBUS
 	/* Enable PCIE0 clk */
 	enable_pcie0_clk();
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index d58d3ff..e196223 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <plat/keyboard.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
 #include <mach/pcie.h>
@@ -62,6 +63,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_ehci0_device,
 	&spear13xx_ehci1_device,
 	&spear13xx_i2c_device,
+	&spear13xx_kbd_device,
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
@@ -72,6 +74,18 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear1310_i2c1_device,
 };
 
+/* keyboard specific platform data */
+static const __initconst DECLARE_KEYMAP(keymap);
+static const struct matrix_keymap_data keymap_data __initconst = {
+	.keymap = keymap,
+	.keymap_size = ARRAY_SIZE(keymap),
+};
+
+static const struct kbd_platform_data kbd_data __initconst = {
+	.keymap = &keymap_data,
+	.rep = 1,
+};
+
 #ifdef CONFIG_PCIEPORTBUS
 /*
  * This function is needed for PCIE host and device driver. Same
@@ -103,6 +117,12 @@ static void __init spear1310_evb_init(void)
 	/* call spear1310 machine init function */
 	spear1310_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
+	/* set keyboard plat data */
+	if (platform_device_add_data(&spear13xx_kbd_device, &kbd_data,
+				sizeof(kbd_data)))
+		printk(KERN_WARNING "%s: couldn't add plat_data",
+				spear13xx_kbd_device.name);
+
 #ifdef CONFIG_PCIEPORTBUS
 	/* Enable PCIE0 clk */
 	enable_pcie0_clk();
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 69ead0f..3856161 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -204,6 +204,25 @@ struct platform_device spear13xx_ohci1_device = {
 	.resource = ohci1_resources,
 };
 
+/* keyboard device registration */
+static struct resource kbd_resources[] = {
+	{
+		.start = SPEAR13XX_KBD_BASE,
+		.end = SPEAR13XX_KBD_BASE + SZ_1K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = IRQ_KBD,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear13xx_kbd_device = {
+	.name = "keyboard",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(kbd_resources),
+	.resource = kbd_resources,
+};
+
 /* rtc device registration */
 static struct resource rtc_resources[] = {
 	{
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index ea21478..0307f7e 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -107,6 +107,7 @@ extern struct pmx_dev spear3xx_pmx_plgpio_45_46_49_50;
 #ifdef CONFIG_MACH_SPEAR300
 /* Add spear300 machine device structure declarations here */
 extern struct amba_device spear300_gpio1_device;
+extern struct platform_device spear300_kbd_device;
 
 /* pad mux modes */
 extern struct pmx_mode spear300_nand_mode;
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 89999bf..6b75fe8 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -595,6 +595,25 @@ struct amba_device spear300_gpio1_device = {
 	.irq = {SPEAR300_VIRQ_GPIO1, NO_IRQ},
 };
 
+/* keyboard device registration */
+static struct resource kbd_resources[] = {
+	{
+		.start = SPEAR300_KEYBOARD_BASE,
+		.end = SPEAR300_KEYBOARD_BASE + SZ_1K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = SPEAR300_VIRQ_KEYBOARD,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device spear300_kbd_device = {
+	.name = "keyboard",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(kbd_resources),
+	.resource = kbd_resources,
+};
+
 /* spear300 routines */
 void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 		u8 pmx_dev_count)
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 1dd0e18..280bf80 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -13,6 +13,7 @@
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <plat/keyboard.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
 
@@ -51,6 +52,19 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear3xx_rtc_device,
 
 	/* spear300 specific devices */
+	&spear300_kbd_device,
+};
+
+/* keyboard specific platform data */
+static const __initconst DECLARE_KEYMAP(keymap);
+static const struct matrix_keymap_data keymap_data __initconst = {
+	.keymap = keymap,
+	.keymap_size = ARRAY_SIZE(keymap),
+};
+
+static const struct kbd_platform_data kbd_data __initconst = {
+	.keymap = &keymap_data,
+	.rep = 1,
 };
 
 static void __init spear300_evb_init(void)
@@ -61,6 +75,12 @@ static void __init spear300_evb_init(void)
 	spear300_init(&spear300_photo_frame_mode, pmx_devs,
 			ARRAY_SIZE(pmx_devs));
 
+	/* set keyboard plat data */
+	if (platform_device_add_data(&spear300_kbd_device, &kbd_data,
+				sizeof(kbd_data)))
+		printk(KERN_WARNING "%s: couldn't add plat_data",
+				spear300_kbd_device.name);
+
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
diff --git a/arch/arm/plat-spear/include/plat/keyboard.h b/arch/arm/plat-spear/include/plat/keyboard.h
index 68b5394..63908cc 100644
--- a/arch/arm/plat-spear/include/plat/keyboard.h
+++ b/arch/arm/plat-spear/include/plat/keyboard.h
@@ -131,11 +131,4 @@ struct kbd_platform_data {
 	bool rep;
 };
 
-/* This function is used to set platform data field of pdev->dev */
-static inline void
-kbd_set_plat_data(struct platform_device *pdev, struct kbd_platform_data *data)
-{
-	pdev->dev.platform_data = data;
-}
-
 #endif /* __PLAT_KEYBOARD_H */
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 13/17] ST SPEAr: Adding machine support for nand
From: Viresh Kumar @ 2011-03-01 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

From: Vipin Kumar <vipin.kumar@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    3 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |   17 +++++
 arch/arm/mach-spear13xx/spear1310_evb.c        |   17 +++++
 arch/arm/mach-spear13xx/spear13xx.c            |   53 +++++++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    6 ++
 arch/arm/mach-spear3xx/spear300.c              |   85 ++++++++++++++++++++++++
 arch/arm/mach-spear3xx/spear300_evb.c          |   15 ++++
 arch/arm/mach-spear3xx/spear310.c              |   22 ++++++
 arch/arm/mach-spear3xx/spear310_evb.c          |   15 ++++
 arch/arm/mach-spear3xx/spear320.c              |   22 ++++++
 arch/arm/mach-spear3xx/spear320_evb.c          |   15 ++++
 arch/arm/mach-spear6xx/include/mach/generic.h  |    1 +
 arch/arm/mach-spear6xx/spear600_evb.c          |   15 ++++
 arch/arm/mach-spear6xx/spear6xx.c              |   22 ++++++
 14 files changed, 308 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index f86f097..f332f96 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -227,6 +227,7 @@ extern struct platform_device spear13xx_ehci0_device;
 extern struct platform_device spear13xx_ehci1_device;
 extern struct platform_device spear13xx_i2c_device;
 extern struct platform_device spear13xx_kbd_device;
+extern struct platform_device spear13xx_nand_device;
 extern struct platform_device spear13xx_ohci0_device;
 extern struct platform_device spear13xx_ohci1_device;
 extern struct platform_device spear13xx_rtc_device;
@@ -239,6 +240,8 @@ void __init spear_setup_timer(void);
 void __init spear13xx_map_io(void);
 void __init spear13xx_init_irq(void);
 void __init spear13xx_init(void);
+void __init nand_mach_init(u32 busw);
+void nand_select_bank(u32 bank, u32 busw);
 void spear13xx_secondary_startup(void);
 
 /* spear1300 declarations */
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 19be757..9aafa91 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -12,6 +12,8 @@
  */
 
 #include <linux/types.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <plat/keyboard.h>
@@ -49,11 +51,19 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_ehci1_device,
 	&spear13xx_i2c_device,
 	&spear13xx_kbd_device,
+	&spear13xx_nand_device,
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
 };
 
+/* fsmc platform data */
+static const struct fsmc_nand_platform_data nand_plat_data __initconst = {
+	.select_bank = nand_select_bank,
+	.options = NAND_SKIP_BBTSCAN,
+	.width = FSMC_NAND_BW8,
+};
+
 /* keyboard specific platform data */
 static const __initconst DECLARE_KEYMAP(keymap);
 static const struct matrix_keymap_data keymap_data __initconst = {
@@ -97,6 +107,13 @@ static void __init spear1300_evb_init(void)
 	/* call spear1300 machine init function */
 	spear1300_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
+	/* set nand device's plat data */
+	nand_mach_init(FSMC_NAND_BW8);
+	if (platform_device_add_data(&spear13xx_nand_device, &nand_plat_data,
+				sizeof(nand_plat_data)))
+		printk(KERN_WARNING "%s: couldn't add plat_data",
+				spear13xx_nand_device.name);
+
 	/* set keyboard plat data */
 	if (platform_device_add_data(&spear13xx_kbd_device, &kbd_data,
 				sizeof(kbd_data)))
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index e196223..d4ef083 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -12,6 +12,8 @@
  */
 
 #include <linux/types.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <plat/keyboard.h>
@@ -64,6 +66,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_ehci1_device,
 	&spear13xx_i2c_device,
 	&spear13xx_kbd_device,
+	&spear13xx_nand_device,
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
@@ -74,6 +77,13 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear1310_i2c1_device,
 };
 
+/* fsmc platform data */
+static const struct fsmc_nand_platform_data nand_plat_data __initconst = {
+	.select_bank = nand_select_bank,
+	.options = NAND_SKIP_BBTSCAN,
+	.width = FSMC_NAND_BW8,
+};
+
 /* keyboard specific platform data */
 static const __initconst DECLARE_KEYMAP(keymap);
 static const struct matrix_keymap_data keymap_data __initconst = {
@@ -117,6 +127,13 @@ static void __init spear1310_evb_init(void)
 	/* call spear1310 machine init function */
 	spear1310_init(NULL, pmx_devs, ARRAY_SIZE(pmx_devs));
 
+	/* set nand device's plat data */
+	nand_mach_init(FSMC_NAND_BW8);
+	if (platform_device_add_data(&spear13xx_nand_device, &nand_plat_data,
+				sizeof(nand_plat_data)))
+		printk(KERN_WARNING "%s: couldn't add plat_data",
+				spear13xx_nand_device.name);
+
 	/* set keyboard plat data */
 	if (platform_device_add_data(&spear13xx_kbd_device, &kbd_data,
 				sizeof(kbd_data)))
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 3856161..4e8cd35 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -15,6 +15,7 @@
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
+#include <linux/mtd/fsmc.h>
 #include <asm/hardware/gic.h>
 #include <asm/irq.h>
 #include <asm/localtimer.h>
@@ -24,6 +25,7 @@
 #include <mach/generic.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
+#include <mach/misc_regs.h>
 
 /* Add spear13xx machines common devices here */
 /* gpio device registeration */
@@ -98,6 +100,57 @@ struct platform_device spear13xx_i2c_device = {
 	.resource = i2c_resources,
 };
 
+/* nand device registeration */
+void __init nand_mach_init(u32 busw)
+{
+	u32 fsmc_cfg = readl(FSMC_CFG);
+	fsmc_cfg &= ~(FSMC_MEMSEL_MASK << FSMC_MEMSEL_SHIFT);
+	fsmc_cfg |= (FSMC_MEM_NAND << FSMC_MEMSEL_SHIFT);
+
+	if (busw == FSMC_NAND_BW16)
+		fsmc_cfg |= 1 << NAND_DEV_WIDTH16;
+	else
+		fsmc_cfg &= ~(1 << NAND_DEV_WIDTH16);
+
+	writel(fsmc_cfg, FSMC_CFG);
+}
+
+void nand_select_bank(u32 bank, u32 busw)
+{
+	u32 fsmc_cfg = readl(FSMC_CFG);
+
+	fsmc_cfg &= ~(NAND_BANK_MASK << NAND_BANK_SHIFT);
+	fsmc_cfg |= (bank << NAND_BANK_SHIFT);
+
+	if (busw)
+		fsmc_cfg |= 1 << NAND_DEV_WIDTH16;
+	else
+		fsmc_cfg &= ~(1 << NAND_DEV_WIDTH16);
+
+	writel(fsmc_cfg, FSMC_CFG);
+}
+
+static struct resource nand_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR13XX_FSMC_MEM_BASE,
+		.end = SPEAR13XX_FSMC_MEM_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR13XX_FSMC_BASE,
+		.end = SPEAR13XX_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear13xx_nand_device = {
+	.name = "fsmc-nand",
+	.id = -1,
+	.resource = nand_resources,
+	.num_resources = ARRAY_SIZE(nand_resources),
+};
+
 /* usb host device registeration */
 static struct resource ehci0_resources[] = {
 	[0] = {
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 0307f7e..189aed4 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -108,6 +108,10 @@ extern struct pmx_dev spear3xx_pmx_plgpio_45_46_49_50;
 /* Add spear300 machine device structure declarations here */
 extern struct amba_device spear300_gpio1_device;
 extern struct platform_device spear300_kbd_device;
+extern struct platform_device spear300_nand0_device;
+extern struct platform_device spear300_nand1_device;
+extern struct platform_device spear300_nand2_device;
+extern struct platform_device spear300_nand3_device;
 
 /* pad mux modes */
 extern struct pmx_mode spear300_nand_mode;
@@ -158,6 +162,7 @@ extern struct amba_device spear310_uart2_device;
 extern struct amba_device spear310_uart3_device;
 extern struct amba_device spear310_uart4_device;
 extern struct amba_device spear310_uart5_device;
+extern struct platform_device spear310_nand_device;
 extern struct platform_device spear310_plgpio_device;
 
 /* pad mux devices */
@@ -185,6 +190,7 @@ extern struct amba_device spear320_uart2_device;
 extern struct platform_device spear320_can0_device;
 extern struct platform_device spear320_can1_device;
 extern struct platform_device spear320_i2c1_device;
+extern struct platform_device spear320_nand_device;
 extern struct platform_device spear320_plgpio_device;
 extern struct platform_device spear320_pwm_device;
 
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 6b75fe8..3a46551 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -614,6 +614,91 @@ struct platform_device spear300_kbd_device = {
 	.resource = kbd_resources,
 };
 
+/* nand device registeration */
+static struct resource nand0_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR300_NAND_0_BASE,
+		.end = SPEAR300_NAND_0_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR300_FSMC_BASE,
+		.end = SPEAR300_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear300_nand0_device = {
+	.name = "fsmc-nand",
+	.id = 0,
+	.resource = nand0_resources,
+	.num_resources = ARRAY_SIZE(nand0_resources),
+};
+
+static struct resource nand1_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR300_NAND_1_BASE,
+		.end = SPEAR300_NAND_1_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR300_FSMC_BASE,
+		.end = SPEAR300_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear300_nand1_device = {
+	.name = "fsmc-nand",
+	.id = 1,
+	.resource = nand1_resources,
+	.num_resources = ARRAY_SIZE(nand1_resources),
+};
+
+static struct resource nand2_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR300_NAND_2_BASE,
+		.end = SPEAR300_NAND_2_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR300_FSMC_BASE,
+		.end = SPEAR300_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear300_nand2_device = {
+	.name = "fsmc-nand",
+	.id = 2,
+	.resource = nand2_resources,
+	.num_resources = ARRAY_SIZE(nand2_resources),
+};
+
+static struct resource nand3_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR300_NAND_3_BASE,
+		.end = SPEAR300_NAND_3_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR300_FSMC_BASE,
+		.end = SPEAR300_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear300_nand3_device = {
+	.name = "fsmc-nand",
+	.id = 3,
+	.resource = nand3_resources,
+	.num_resources = ARRAY_SIZE(nand3_resources),
+};
+
 /* spear300 routines */
 void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 		u8 pmx_dev_count)
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 280bf80..92f9346 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -11,6 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/mtd/nand.h>
+#include <linux/mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <plat/keyboard.h>
@@ -53,6 +55,13 @@ static struct platform_device *plat_devs[] __initdata = {
 
 	/* spear300 specific devices */
 	&spear300_kbd_device,
+	&spear300_nand0_device,
+};
+
+/* fsmc platform data */
+static const struct fsmc_nand_platform_data nand0_plat_data __initconst = {
+	.options = NAND_SKIP_BBTSCAN,
+	.width = FSMC_NAND_BW8,
 };
 
 /* keyboard specific platform data */
@@ -75,6 +84,12 @@ static void __init spear300_evb_init(void)
 	spear300_init(&spear300_photo_frame_mode, pmx_devs,
 			ARRAY_SIZE(pmx_devs));
 
+	/* set nand0 device's plat data */
+	if (platform_device_add_data(&spear300_nand0_device, &nand0_plat_data,
+				sizeof(nand0_plat_data)))
+		printk(KERN_WARNING "%s: couldn't add plat_data",
+				spear300_nand0_device.name);
+
 	/* set keyboard plat data */
 	if (platform_device_add_data(&spear300_kbd_device, &kbd_data,
 				sizeof(kbd_data)))
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index ba21b75..9a1bea7 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -374,6 +374,28 @@ struct amba_device spear310_uart5_device = {
 	.irq = {SPEAR310_VIRQ_UART5, NO_IRQ},
 };
 
+/* nand device registeration */
+static struct resource nand_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR310_NAND_BASE,
+		.end = SPEAR310_NAND_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR310_FSMC_BASE,
+		.end = SPEAR310_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear310_nand_device = {
+	.name = "fsmc-nand",
+	.id = -1,
+	.resource = nand_resources,
+	.num_resources = ARRAY_SIZE(nand_resources),
+};
+
 /* plgpio device registeration */
 /*
  * pin to offset and offset to pin converter functions
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 38f2331..9c5c9b1 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -11,6 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/mtd/nand.h>
+#include <linux/mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/emi.h>
@@ -95,9 +97,16 @@ static struct platform_device *plat_devs[] __initdata = {
 
 	/* spear310 specific devices */
 	&spear310_emi_nor_device,
+	&spear310_nand_device,
 	&spear310_plgpio_device,
 };
 
+/* fsmc platform data */
+static const struct fsmc_nand_platform_data nand_plat_data __initconst = {
+	.options = NAND_SKIP_BBTSCAN,
+	.width = FSMC_NAND_BW8,
+};
+
 static void __init spear310_evb_init(void)
 {
 	unsigned int i;
@@ -108,6 +117,12 @@ static void __init spear310_evb_init(void)
 	/* Initialize emi regiters */
 	emi_init(SPEAR310_EMI_REG_BASE, 0, EMI_FLASH_WIDTH32);
 
+	/* set nand device's plat data */
+	if (platform_device_add_data(&spear310_nand_device, &nand_plat_data,
+				sizeof(nand_plat_data)))
+		printk(KERN_WARNING "%s: couldn't add plat_data",
+				spear310_nand_device.name);
+
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 047dcae..4a5041f 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -797,6 +797,28 @@ struct platform_device spear320_i2c1_device = {
 	.resource = i2c1_resources,
 };
 
+/* nand device registeration */
+static struct resource nand_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR320_NAND_BASE,
+		.end = SPEAR320_NAND_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR320_FSMC_BASE,
+		.end = SPEAR320_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device spear320_nand_device = {
+	.name = "fsmc-nand",
+	.id = -1,
+	.resource = nand_resources,
+	.num_resources = ARRAY_SIZE(nand_resources),
+};
+
 /* plgpio device registeration */
 static struct plgpio_platform_data plgpio_plat_data = {
 	.gpio_base = 8,
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 75f1495..bfe5d09 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -11,6 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/mtd/nand.h>
+#include <linux/mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/emi.h>
@@ -92,10 +94,17 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear320_can1_device,
 	&spear320_i2c1_device,
 	&spear320_emi_nor_device,
+	&spear320_nand_device,
 	&spear320_plgpio_device,
 	&spear320_pwm_device,
 };
 
+/* fsmc platform data */
+static const struct fsmc_nand_platform_data nand_plat_data __initconst = {
+	.options = NAND_SKIP_BBTSCAN,
+	.width = FSMC_NAND_BW8,
+};
+
 static void __init spear320_evb_init(void)
 {
 	unsigned int i;
@@ -107,6 +116,12 @@ static void __init spear320_evb_init(void)
 	/* Initialize emi regiters */
 	emi_init(SPEAR320_EMI_CTRL_BASE, 0, EMI_FLASH_WIDTH16);
 
+	/* set nand device's plat data */
+	if (platform_device_add_data(&spear320_nand_device, &nand_plat_data,
+				sizeof(nand_plat_data)))
+		printk(KERN_WARNING "%s: couldn't add plat_data",
+				spear320_nand_device.name);
+
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index 62d8b09..df2606f 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -35,6 +35,7 @@ extern struct amba_device wdt_device;
 extern struct platform_device ehci0_device;
 extern struct platform_device ehci1_device;
 extern struct platform_device i2c_device;
+extern struct platform_device nand_device;
 extern struct platform_device ohci0_device;
 extern struct platform_device ohci1_device;
 extern struct platform_device rtc_device;
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index d8a13a1..93cc614 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -11,6 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/mtd/nand.h>
+#include <linux/mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
@@ -31,13 +33,26 @@ static struct platform_device *plat_devs[] __initdata = {
 	&i2c_device,
 	&ohci0_device,
 	&ohci1_device,
+	&nand_device,
 	&rtc_device,
 };
 
+/* fsmc platform data */
+static const struct fsmc_nand_platform_data nand_plat_data __initconst = {
+	.options = NAND_SKIP_BBTSCAN,
+	.width = FSMC_NAND_BW8,
+};
+
 static void __init spear600_evb_init(void)
 {
 	unsigned int i;
 
+	/* set nand device's plat data */
+	if (platform_device_add_data(&nand_device, &nand_plat_data,
+				sizeof(nand_plat_data)))
+		printk(KERN_WARNING "%s: couldn't add plat_data",
+				nand_device.name);
+
 	/* call spear600 machine init function */
 	spear600_init();
 
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index fb1a804..927812d 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -133,6 +133,28 @@ struct platform_device i2c_device = {
 	.resource = i2c_resources,
 };
 
+/* nand device registeration */
+static struct resource nand_resources[] = {
+	{
+		.name = "nand_data",
+		.start = SPEAR6XX_ICM1_NAND_BASE,
+		.end = SPEAR6XX_ICM1_NAND_BASE + SZ_16 - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.name = "fsmc_regs",
+		.start = SPEAR6XX_ICM1_FSMC_BASE,
+		.end = SPEAR6XX_ICM1_FSMC_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device nand_device = {
+	.name = "fsmc-nand",
+	.id = -1,
+	.resource = nand_resources,
+	.num_resources = ARRAY_SIZE(nand_resources),
+};
+
 /* usb host device registeration */
 static struct resource ehci0_resources[] = {
 	[0] = {
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 14/17] ST SPEAr: Adding support for SSP PL022
From: Viresh Kumar @ 2011-03-01 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |   10 +++
 arch/arm/mach-spear13xx/spear1310_evb.c        |   10 +++
 arch/arm/mach-spear13xx/spear13xx.c            |   31 ++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    2 +
 arch/arm/mach-spear3xx/spear300_evb.c          |   25 ++++++++
 arch/arm/mach-spear3xx/spear310_evb.c          |   37 ++++++++++++
 arch/arm/mach-spear3xx/spear320.c              |   42 +++++++++++++
 arch/arm/mach-spear3xx/spear320_evb.c          |   13 ++++
 arch/arm/mach-spear3xx/spear3xx.c              |   31 ++++++++++
 arch/arm/mach-spear6xx/include/mach/generic.h  |    1 +
 arch/arm/mach-spear6xx/spear600_evb.c          |   12 ++++
 arch/arm/mach-spear6xx/spear6xx.c              |   68 ++++++++++++++++++++++
 arch/arm/plat-spear/include/plat/spi.h         |   74 ++++++++++++++++++++++++
 14 files changed, 357 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-spear/include/plat/spi.h

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index f332f96..15f5e03 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -222,6 +222,7 @@ extern struct pmx_dev pmx_uart1_modem;
 
 /* Add spear13xx family device structure declarations here */
 extern struct amba_device spear13xx_gpio_device[];
+extern struct amba_device spear13xx_ssp_device;
 extern struct amba_device spear13xx_uart_device;
 extern struct platform_device spear13xx_ehci0_device;
 extern struct platform_device spear13xx_ehci1_device;
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 9aafa91..8500e10 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -12,11 +12,15 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/mtd/nand.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <linux/mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <plat/keyboard.h>
+#include <plat/spi.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
 #include <mach/pcie.h>
@@ -43,6 +47,7 @@ static struct pmx_dev *pmx_devs[] = {
 static struct amba_device *amba_devs[] __initdata = {
 	&spear13xx_gpio_device[0],
 	&spear13xx_gpio_device[1],
+	&spear13xx_ssp_device,
 	&spear13xx_uart_device,
 };
 
@@ -76,6 +81,9 @@ static const struct kbd_platform_data kbd_data __initconst = {
 	.rep = 1,
 };
 
+static struct spi_board_info __initdata spi_board_info[] = {
+};
+
 #ifdef CONFIG_PCIEPORTBUS
 /*
  * This function is needed for PCIE host and device driver. Same
@@ -129,6 +137,8 @@ static void __init spear1300_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index d4ef083..ec3d617 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -12,11 +12,15 @@
  */
 
 #include <linux/types.h>
+#include <linux/gpio.h>
 #include <linux/mtd/nand.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <linux/mtd/fsmc.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <plat/keyboard.h>
+#include <plat/spi.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
 #include <mach/pcie.h>
@@ -50,6 +54,7 @@ static struct amba_device *amba_devs[] __initdata = {
 	/* spear13xx specific devices */
 	&spear13xx_gpio_device[0],
 	&spear13xx_gpio_device[1],
+	&spear13xx_ssp_device,
 	&spear13xx_uart_device,
 
 	/* spear1310 specific devices */
@@ -96,6 +101,9 @@ static const struct kbd_platform_data kbd_data __initconst = {
 	.rep = 1,
 };
 
+static struct spi_board_info __initdata spi_board_info[] = {
+};
+
 #ifdef CONFIG_PCIEPORTBUS
 /*
  * This function is needed for PCIE host and device driver. Same
@@ -152,6 +160,8 @@ static void __init spear1310_evb_init(void)
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
 	/* Add Amba Devices */
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
 		amba_device_register(amba_devs[i], &iomem_resource);
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 4e8cd35..47f45d5 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/amba/pl022.h>
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
@@ -65,6 +66,36 @@ struct amba_device spear13xx_gpio_device[] = {
 	}
 };
 
+/* ssp device registeration */
+static struct pl022_ssp_controller ssp_platform_data = {
+	.bus_id = 0,
+	.enable_dma = 0,
+	/*
+	 * This is number of spi devices that can be connected to spi. There are
+	 * two type of chipselects on which slave devices can work. One is chip
+	 * select provided by spi masters other is controlled through external
+	 * gpio's. We can't use chipselect provided from spi master (because as
+	 * soon as FIFO becomes empty, CS is disabled and transfer ends). So
+	 * this number now depends on number of gpios available for spi. each
+	 * slave on each master requires a separate gpio pin.
+	 */
+	.num_chipselect = 2,
+};
+
+struct amba_device spear13xx_ssp_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.init_name = "ssp-pl022",
+		.platform_data = &ssp_platform_data,
+	},
+	.res = {
+		.start = SPEAR13XX_SSP_BASE,
+		.end = SPEAR13XX_SSP_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {IRQ_SSP, NO_IRQ},
+};
+
 /* uart device registeration */
 struct amba_device spear13xx_uart_device = {
 	.dev = {
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 189aed4..39cc43f 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -32,6 +32,7 @@
 
 /* Add spear3xx family device structure declarations here */
 extern struct amba_device spear3xx_gpio_device;
+extern struct amba_device spear3xx_ssp0_device;
 extern struct amba_device spear3xx_uart_device;
 extern struct amba_device spear3xx_wdt_device;
 extern struct platform_device spear3xx_ehci_device;
@@ -185,6 +186,7 @@ void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 /* spear320 declarations */
 #ifdef CONFIG_MACH_SPEAR320
 /* Add spear320 machine device structure declarations here */
+extern struct amba_device spear320_ssp_device[];
 extern struct amba_device spear320_uart1_device;
 extern struct amba_device spear320_uart2_device;
 extern struct platform_device spear320_can0_device;
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 92f9346..7ab29d4 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -11,11 +11,15 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/gpio.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/fsmc.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <plat/keyboard.h>
+#include <plat/spi.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
 
@@ -38,6 +42,7 @@ static struct pmx_dev *pmx_devs[] = {
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&spear3xx_gpio_device,
+	&spear3xx_ssp0_device,
 	&spear3xx_uart_device,
 	&spear3xx_wdt_device,
 
@@ -76,6 +81,24 @@ static const struct kbd_platform_data kbd_data __initconst = {
 	.rep = 1,
 };
 
+/* spi board information */
+/* spi0 flash Chip Select Control function, controlled by gpio pin mentioned */
+DECLARE_SPI_CS_CONTROL(0, flash, RAS_GPIO_3);
+/* spi0 flash Chip Info structure */
+DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control);
+
+static struct spi_board_info __initdata spi_board_info[] = {
+	/* spi0 board info */
+	{
+		.modalias = "m25p80",
+		.controller_data = &spi0_flash_chip_info,
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.mode = SPI_MODE_1,
+	}
+};
+
 static void __init spear300_evb_init(void)
 {
 	unsigned int i;
@@ -99,6 +122,8 @@ static void __init spear300_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 9c5c9b1..45abb1c 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -11,10 +11,14 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/gpio.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/fsmc.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <plat/spi.h>
 #include <mach/emi.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
@@ -76,6 +80,7 @@ static struct pmx_dev *pmx_devs[] = {
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&spear3xx_gpio_device,
+	&spear3xx_ssp0_device,
 	&spear3xx_uart_device,
 	&spear3xx_wdt_device,
 
@@ -107,6 +112,36 @@ static const struct fsmc_nand_platform_data nand_plat_data __initconst = {
 	.width = FSMC_NAND_BW8,
 };
 
+/* spi board information */
+/* spi0 flash Chip Select Control function, controlled by gpio pin mentioned */
+DECLARE_SPI_CS_CONTROL(0, flash, BASIC_GPIO_3);
+/* spi0 flash Chip Info structure */
+DECLARE_SPI_CHIP_INFO(0, flash, spi0_flash_cs_control);
+
+/* spi0 spidev Chip Select Control function, controlled by gpio pin mentioned */
+DECLARE_SPI_CS_CONTROL(0, dev, BASIC_GPIO_4);
+/* spi0 spidev Chip Info structure */
+DECLARE_SPI_CHIP_INFO(0, dev, spi0_dev_cs_control);
+
+static struct spi_board_info __initdata spi_board_info[] = {
+	/* spi0 board info */
+	{
+		.modalias = "spidev",
+		.controller_data = &spi0_dev_chip_info,
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 0,
+		.mode = SPI_MODE_1,
+	}, {
+		.modalias = "m25p80",
+		.controller_data = &spi0_flash_chip_info,
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.mode = SPI_MODE_1,
+	}
+};
+
 static void __init spear310_evb_init(void)
 {
 	unsigned int i;
@@ -126,6 +161,8 @@ static void __init spear310_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 4a5041f..ac5dfb4 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -11,6 +11,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/amba/pl022.h>
 #include <linux/ptrace.h>
 #include <asm/irq.h>
 #include <plat/gpio.h>
@@ -712,6 +713,47 @@ static struct spear_shirq shirq_intrcomm_ras = {
 };
 
 /* Add spear320 specific devices here */
+/* ssp device registeration */
+static struct pl022_ssp_controller ssp_platform_data[] = {
+	{
+		.bus_id = 1,
+		.enable_dma = 0,
+		.num_chipselect = 2,
+	}, {
+		.bus_id = 2,
+		.enable_dma = 0,
+		.num_chipselect = 2,
+	}
+};
+
+struct amba_device spear320_ssp_device[] = {
+	{
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.1",
+			.platform_data = &ssp_platform_data[0],
+		},
+		.res = {
+			.start = SPEAR320_SSP0_BASE,
+			.end = SPEAR320_SSP0_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {SPEAR320_VIRQ_SSP1, NO_IRQ},
+	}, {
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.2",
+			.platform_data = &ssp_platform_data[1],
+		},
+		.res = {
+			.start = SPEAR320_SSP1_BASE,
+			.end = SPEAR320_SSP1_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {SPEAR320_VIRQ_SSP2, NO_IRQ},
+	}
+};
+
 /* uart1 device registeration */
 struct amba_device spear320_uart1_device = {
 	.dev = {
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index bfe5d09..a1a76f2 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -11,10 +11,14 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/gpio.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/fsmc.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <plat/spi.h>
 #include <mach/emi.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
@@ -73,10 +77,13 @@ static struct pmx_dev *pmx_devs[] = {
 static struct amba_device *amba_devs[] __initdata = {
 	/* spear3xx specific devices */
 	&spear3xx_gpio_device,
+	&spear3xx_ssp0_device,
 	&spear3xx_uart_device,
 	&spear3xx_wdt_device,
 
 	/* spear320 specific devices */
+	&spear320_ssp_device[0],
+	&spear320_ssp_device[1],
 	&spear320_uart1_device,
 	&spear320_uart2_device,
 };
@@ -105,6 +112,10 @@ static const struct fsmc_nand_platform_data nand_plat_data __initconst = {
 	.width = FSMC_NAND_BW8,
 };
 
+/* spi board information */
+static struct spi_board_info __initdata spi_board_info[] = {
+};
+
 static void __init spear320_evb_init(void)
 {
 	unsigned int i;
@@ -125,6 +136,8 @@ static void __init spear320_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 574e93a..16ca683 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/amba/pl022.h>
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
@@ -41,6 +42,36 @@ struct amba_device spear3xx_gpio_device = {
 	.irq = {SPEAR3XX_IRQ_BASIC_GPIO, NO_IRQ},
 };
 
+/* ssp device registration */
+static struct pl022_ssp_controller ssp_platform_data = {
+	.bus_id = 0,
+	.enable_dma = 0,
+	/*
+	 * This is number of spi devices that can be connected to spi. There are
+	 * two type of chipselects on which slave devices can work. One is chip
+	 * select provided by spi masters other is controlled through external
+	 * gpio's. We can't use chipselect provided from spi master (because as
+	 * soon as FIFO becomes empty, CS is disabled and transfer ends). So
+	 * this number now depends on number of gpios available for spi. each
+	 * slave on each master requires a separate gpio pin.
+	 */
+	.num_chipselect = 2,
+};
+
+struct amba_device spear3xx_ssp0_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+		.init_name = "ssp-pl022.0",
+		.platform_data = &ssp_platform_data,
+	},
+	.res = {
+		.start = SPEAR3XX_ICM1_SSP_BASE,
+		.end = SPEAR3XX_ICM1_SSP_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {SPEAR3XX_IRQ_SSP, NO_IRQ},
+};
+
 /* uart device registration */
 struct amba_device spear3xx_uart_device = {
 	.dev = {
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index df2606f..c802cb3 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -30,6 +30,7 @@
 
 /* Add spear6xx family device structure declarations here */
 extern struct amba_device gpio_device[];
+extern struct amba_device ssp_device[];
 extern struct amba_device uart_device[];
 extern struct amba_device wdt_device;
 extern struct platform_device ehci0_device;
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index 93cc614..dbfab1d 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -11,10 +11,14 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/gpio.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/fsmc.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
+#include <plat/spi.h>
 #include <mach/generic.h>
 #include <mach/hardware.h>
 
@@ -22,6 +26,9 @@ static struct amba_device *amba_devs[] __initdata = {
 	&gpio_device[0],
 	&gpio_device[1],
 	&gpio_device[2],
+	&ssp_device[0],
+	&ssp_device[1],
+	&ssp_device[2],
 	&uart_device[0],
 	&uart_device[1],
 	&wdt_device,
@@ -43,6 +50,9 @@ static const struct fsmc_nand_platform_data nand_plat_data __initconst = {
 	.width = FSMC_NAND_BW8,
 };
 
+static struct spi_board_info __initdata spi_board_info[] = {
+};
+
 static void __init spear600_evb_init(void)
 {
 	unsigned int i;
@@ -59,6 +69,8 @@ static void __init spear600_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
 
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index 927812d..00336e9 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/amba/pl022.h>
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <linux/io.h>
@@ -23,6 +24,73 @@
 #include <mach/irqs.h>
 
 /* Add spear6xx machines common devices here */
+/* ssp device registration */
+static struct pl022_ssp_controller ssp_platform_data[] = {
+	{
+		.bus_id = 0,
+		.enable_dma = 0,
+		/*
+		 * This is number of spi devices that can be connected to spi.
+		 * There are two type of chipselects on which slave devices can
+		 * work. One is chip select provided by spi masters other is
+		 * controlled through external gpio's. We can't use chipselect
+		 * provided from spi master (because as soon as FIFO becomes
+		 * empty, CS is disabled and transfer ends). So this number now
+		 * depends on number of gpios available for spi. each slave on
+		 * each master requires a separate gpio pin.
+		 */
+		.num_chipselect = 2,
+	}, {
+		.bus_id = 1,
+		.enable_dma = 0,
+		.num_chipselect = 2,
+	}, {
+		.bus_id = 2,
+		.enable_dma = 0,
+		.num_chipselect = 2,
+	}
+};
+
+struct amba_device ssp_device[] = {
+	{
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.0",
+			.platform_data = &ssp_platform_data[0],
+		},
+		.res = {
+			.start = SPEAR6XX_ICM1_SSP0_BASE,
+			.end = SPEAR6XX_ICM1_SSP0_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {IRQ_SSP_1, NO_IRQ},
+	}, {
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.1",
+			.platform_data = &ssp_platform_data[1],
+		},
+		.res = {
+			.start = SPEAR6XX_ICM1_SSP1_BASE,
+			.end = SPEAR6XX_ICM1_SSP1_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {IRQ_SSP_2, NO_IRQ},
+	}, {
+		.dev = {
+			.coherent_dma_mask = ~0,
+			.init_name = "ssp-pl022.2",
+			.platform_data = &ssp_platform_data[2],
+		},
+		.res = {
+			.start = SPEAR6XX_ICM2_SSP2_BASE,
+			.end = SPEAR6XX_ICM2_SSP2_BASE + SZ_4K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+		.irq = {IRQ_APPL_SSP, NO_IRQ},
+	}
+};
+
 /* uart device registration */
 struct amba_device uart_device[] = {
 	{
diff --git a/arch/arm/plat-spear/include/plat/spi.h b/arch/arm/plat-spear/include/plat/spi.h
new file mode 100644
index 0000000..24d57e1
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/spi.h
@@ -0,0 +1,74 @@
+/*
+ * arch/arm/plat-spear/include/plat/spi.h
+ *
+ * SPI board specific definitions common to multiple boards on multiple
+ * machines.
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Viresh Kumar<viresh.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 __PLAT_SPI_H
+#define __PLAT_SPI_H
+
+#include <linux/amba/pl022.h>
+#include <linux/gpio.h>
+
+/* spi board information */
+static inline int spi_cs_gpio_request(u32 gpio_pin)
+{
+	int ret;
+
+	ret = gpio_request(gpio_pin, "SPI_CS");
+	if (ret < 0) {
+		printk(KERN_ERR "SPI: gpio:%d request fail\n", gpio_pin);
+		return ret;
+	} else {
+		ret = gpio_direction_output(gpio_pin, 1);
+		if (ret) {
+			printk(KERN_ERR "SPI: gpio:%d direction set fail\n",
+					gpio_pin);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+/* This will define cs_control function for a specific spi slave */
+#define DECLARE_SPI_CS_CONTROL(id, type, gpio)		\
+static void spi##id##_##type##_cs_control(u32 control)	\
+{							\
+	static int count, ret;				\
+							\
+	if (unlikely(!count)) {				\
+		count++;				\
+		ret = spi_cs_gpio_request(gpio);	\
+	}						\
+							\
+	if (!ret)					\
+		gpio_set_value(gpio, control);		\
+}
+
+/* This will define CHIP_INFO structure for a specific spi slave */
+#define DECLARE_SPI_CHIP_INFO(id, type, chip_select_control)	\
+static struct pl022_config_chip spi##id##_##type##_chip_info = {\
+	.iface = SSP_INTERFACE_MOTOROLA_SPI,		\
+	.hierarchy = SSP_MASTER,			\
+	.slave_tx_disable = 0,				\
+	.com_mode = INTERRUPT_TRANSFER,			\
+	.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,		\
+	.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,	\
+	.ctrl_len = SSP_BITS_12,			\
+	.wait_state = SSP_MWIRE_WAIT_ZERO,		\
+	.duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,	\
+	.cs_control = chip_select_control,		\
+};
+
+#define DECLARE_SPI_CHIP_INFO_NULL_ID(chip_select_control)	\
+DECLARE_SPI_CHIP_INFO(, chip_select_control)
+
+#endif /* __PLAT_SPI_H */
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 15/17] ST SPEAr: Adding support for SDHCI (SDIO)
From: Viresh Kumar @ 2011-03-01 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
---
 arch/arm/mach-spear13xx/include/mach/generic.h |    1 +
 arch/arm/mach-spear13xx/spear1300_evb.c        |    1 +
 arch/arm/mach-spear13xx/spear1310_evb.c        |    1 +
 arch/arm/mach-spear13xx/spear13xx.c            |   34 +++++++++++++++++++
 arch/arm/mach-spear3xx/include/mach/generic.h  |    6 +++
 arch/arm/mach-spear3xx/spear300.c              |   42 ++++++++++++++++++++++++
 arch/arm/mach-spear3xx/spear300_evb.c          |   16 +++++++++
 arch/arm/mach-spear3xx/spear320.c              |   23 +++++++++++++
 arch/arm/mach-spear3xx/spear320_evb.c          |   13 +++++++
 9 files changed, 137 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index 15f5e03..d918368 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -232,6 +232,7 @@ extern struct platform_device spear13xx_nand_device;
 extern struct platform_device spear13xx_ohci0_device;
 extern struct platform_device spear13xx_ohci1_device;
 extern struct platform_device spear13xx_rtc_device;
+extern struct platform_device spear13xx_sdhci_device;
 extern struct sys_timer spear13xx_timer;
 
 /* Add spear13xx family function declarations here */
diff --git a/arch/arm/mach-spear13xx/spear1300_evb.c b/arch/arm/mach-spear13xx/spear1300_evb.c
index 8500e10..3b619e5 100644
--- a/arch/arm/mach-spear13xx/spear1300_evb.c
+++ b/arch/arm/mach-spear13xx/spear1300_evb.c
@@ -60,6 +60,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
+	&spear13xx_sdhci_device,
 };
 
 /* fsmc platform data */
diff --git a/arch/arm/mach-spear13xx/spear1310_evb.c b/arch/arm/mach-spear13xx/spear1310_evb.c
index ec3d617..11aafd8 100644
--- a/arch/arm/mach-spear13xx/spear1310_evb.c
+++ b/arch/arm/mach-spear13xx/spear1310_evb.c
@@ -75,6 +75,7 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear13xx_ohci0_device,
 	&spear13xx_ohci1_device,
 	&spear13xx_rtc_device,
+	&spear13xx_sdhci_device,
 
 	/* spear1310 specific devices */
 	&spear1310_can0_device,
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 47f45d5..5370b5b 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -326,6 +326,38 @@ struct platform_device spear13xx_rtc_device = {
 	.resource = rtc_resources,
 };
 
+/* sdhci (sdio) device declaration */
+static struct resource sdhci_resources[] = {
+	{
+		.start	= SPEAR13XX_MCIF_SDHCI_BASE,
+		.end	= SPEAR13XX_MCIF_SDHCI_BASE + SZ_256 - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_SDHCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device spear13xx_sdhci_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.name = "sdhci",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(sdhci_resources),
+	.resource = sdhci_resources,
+};
+
+static void sdhci_enable(void)
+{
+	unsigned val = readl(PERIP_CFG);
+
+	/* This function enables SD/MMC interface out of SD/MMC, CF, XD */
+	val &= ~(MCIF_SEL_MASK << MCIF_SEL_SHIFT);
+	val |= SD_MMC_ACTIVE << MCIF_SEL_SHIFT;
+	writel(val, PERIP_CFG);
+}
+
 #ifdef CONFIG_PCIEPORTBUS
 /* PCIE0 clock always needs to be enabled if any of the three PCIE port
  * have to be used. So call this function from the board initilization
@@ -367,6 +399,8 @@ void __init spear13xx_init(void)
 	 */
 	l2x0_init(__io_address(SPEAR13XX_L2CC_BASE), 0x00260249, 0xfe00ffff);
 #endif
+
+	sdhci_enable();
 }
 
 /* This will initialize vic */
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index 39cc43f..54540e2 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -113,6 +113,7 @@ extern struct platform_device spear300_nand0_device;
 extern struct platform_device spear300_nand1_device;
 extern struct platform_device spear300_nand2_device;
 extern struct platform_device spear300_nand3_device;
+extern struct platform_device spear300_sdhci_device;
 
 /* pad mux modes */
 extern struct pmx_mode spear300_nand_mode;
@@ -152,6 +153,10 @@ extern struct pmx_dev spear300_pmx_gpio1;
 /* Add spear300 machine function declarations here */
 void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 		u8 pmx_dev_count);
+#define SDHCI_MEM_ENB		0x1
+#define I2S_MEM_ENB		0x2
+#define SDHCI_MEM_SELECT	0x20000000
+void sdhci_i2s_mem_enable(u8 mask);
 
 #endif /* CONFIG_MACH_SPEAR300 */
 
@@ -195,6 +200,7 @@ extern struct platform_device spear320_i2c1_device;
 extern struct platform_device spear320_nand_device;
 extern struct platform_device spear320_plgpio_device;
 extern struct platform_device spear320_pwm_device;
+extern struct platform_device spear320_sdhci_device;
 
 /* pad mux modes */
 extern struct pmx_mode spear320_auto_net_smii_mode;
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 3a46551..3643b79 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -699,6 +699,48 @@ struct platform_device spear300_nand3_device = {
 	.num_resources = ARRAY_SIZE(nand3_resources),
 };
 
+/* sdhci (sdio) device declaration */
+static struct resource sdhci_resources[] = {
+	{
+		.start	= SPEAR300_SDHCI_BASE,
+		.end	= SPEAR300_SDHCI_BASE + SZ_256 - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= SPEAR300_IRQ_SDHCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device spear300_sdhci_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.name = "sdhci",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(sdhci_resources),
+	.resource = sdhci_resources,
+};
+
+/* Function handling sdhci and i2s memory sharing */
+void sdhci_i2s_mem_enable(u8 mask)
+{
+	u32 val;
+	void __iomem *config = ioremap(SPEAR300_MODE_CONFIG_REG, SZ_16);
+	if (!config) {
+		pr_debug("sdhci_i2s_enb: ioremap fail\n");
+		return;
+	}
+
+	val = readl(config);
+	if (mask == SDHCI_MEM_ENB)
+		val |= SDHCI_MEM_SELECT;
+	else
+		val &= ~SDHCI_MEM_SELECT;
+	writel(val, config);
+
+	iounmap(config);
+}
+
 /* spear300 routines */
 void __init spear300_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 		u8 pmx_dev_count)
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index 7ab29d4..30b5a1c 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/gpio.h>
+#include <linux/mmc/sdhci-spear.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/fsmc.h>
 #include <linux/spi/flash.h>
@@ -61,6 +62,15 @@ static struct platform_device *plat_devs[] __initdata = {
 	/* spear300 specific devices */
 	&spear300_kbd_device,
 	&spear300_nand0_device,
+	&spear300_sdhci_device,
+};
+
+/* sdhci board specific information */
+static struct sdhci_plat_data sdhci_plat_data = {
+	.card_power_gpio = RAS_GPIO_2,
+	.power_active_high = 0,
+	.power_always_enb = 0,
+	.card_int_gpio = RAS_GPIO_0,
 };
 
 /* fsmc platform data */
@@ -122,6 +132,12 @@ static void __init spear300_evb_init(void)
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
+	/* set sdhci device platform data */
+	sdhci_set_plat_data(&spear300_sdhci_device, &sdhci_plat_data);
+
+	/* Enable sdhci memory */
+	sdhci_i2s_mem_enable(SDHCI_MEM_ENB);
+
 	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 
 	/* Add Platform Devices */
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index ac5dfb4..34e66cf 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -13,6 +13,7 @@
 
 #include <linux/amba/pl022.h>
 #include <linux/ptrace.h>
+#include <linux/mmc/sdhci-spear.h>
 #include <asm/irq.h>
 #include <plat/gpio.h>
 #include <plat/shirq.h>
@@ -905,6 +906,28 @@ struct platform_device spear320_pwm_device = {
 	.resource = pwm_resources,
 };
 
+/* sdhci (sdio) device registeration */
+static struct resource sdhci_resources[] = {
+	{
+		.start	= SPEAR320_SDHCI_BASE,
+		.end	= SPEAR320_SDHCI_BASE + SZ_256 - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= SPEAR320_IRQ_SDHCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+struct platform_device spear320_sdhci_device = {
+	.dev = {
+		.coherent_dma_mask = ~0,
+	},
+	.name = "sdhci",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(sdhci_resources),
+	.resource = sdhci_resources,
+};
+
 /* spear320 routines */
 void __init spear320_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
 		u8 pmx_dev_count)
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index a1a76f2..2b27383 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -15,6 +15,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/fsmc.h>
 #include <linux/spi/flash.h>
+#include <linux/mmc/sdhci-spear.h>
 #include <linux/spi/spi.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -104,6 +105,15 @@ static struct platform_device *plat_devs[] __initdata = {
 	&spear320_nand_device,
 	&spear320_plgpio_device,
 	&spear320_pwm_device,
+	&spear320_sdhci_device,
+};
+
+/* sdhci board specific information */
+static struct sdhci_plat_data sdhci_plat_data = {
+	.card_power_gpio = PLGPIO_61,
+	.power_active_high = 0,
+	.power_always_enb = 1,
+	.card_int_gpio = -1,
 };
 
 /* fsmc platform data */
@@ -133,6 +143,9 @@ static void __init spear320_evb_init(void)
 		printk(KERN_WARNING "%s: couldn't add plat_data",
 				spear320_nand_device.name);
 
+	/* set sdhci device platform data */
+	sdhci_set_plat_data(&spear320_sdhci_device, &sdhci_plat_data);
+
 	/* Register slave devices on the I2C buses */
 	i2c_register_default_devices();
 
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 16/17] ST SPEAr Power Management: Added the support for Standby mode.
From: Viresh Kumar @ 2011-03-01 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

From: Deepak Sikri <deepak.sikri@st.com>

Open Points:
	-> Suspend to RAM support needs to be added.
	-> SPEAr13xx: The power domains need to be added.
	-> For SPEAr13xx: PLL-4 has not been switch off while moving
	   into sleep. There is some problem in getting the pll back to on.

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Deepak Sikri <deepak.sikri@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: shiraz hashim <shiraz.hashim@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/mach-spear13xx/Makefile               |    1 +
 arch/arm/mach-spear13xx/include/mach/suspend.h |   47 +++
 arch/arm/mach-spear13xx/pm.c                   |  107 ++++++
 arch/arm/mach-spear13xx/sleep.S                |  435 ++++++++++++++++++++++++
 arch/arm/mach-spear13xx/spear13xx.c            |    5 +
 arch/arm/mach-spear3xx/include/mach/suspend.h  |   44 +++
 arch/arm/mach-spear3xx/spear3xx.c              |    7 +-
 arch/arm/mach-spear6xx/include/mach/suspend.h  |   44 +++
 arch/arm/mach-spear6xx/spear6xx.c              |    9 +-
 arch/arm/plat-spear/Makefile                   |    6 +
 arch/arm/plat-spear/pm.c                       |  104 ++++++
 arch/arm/plat-spear/sleep.S                    |  288 ++++++++++++++++
 12 files changed, 1095 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/suspend.h
 create mode 100644 arch/arm/mach-spear13xx/pm.c
 create mode 100644 arch/arm/mach-spear13xx/sleep.S
 create mode 100644 arch/arm/mach-spear3xx/include/mach/suspend.h
 create mode 100644 arch/arm/mach-spear6xx/include/mach/suspend.h
 create mode 100644 arch/arm/plat-spear/pm.c
 create mode 100644 arch/arm/plat-spear/sleep.S

diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
index 2a113b0..42d378e 100644
--- a/arch/arm/mach-spear13xx/Makefile
+++ b/arch/arm/mach-spear13xx/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
 obj-$(CONFIG_PCIEPORTBUS)		+= pcie.o
+obj-$(CONFIG_PM)			+= pm.o sleep.o
 
 # spear1300 specific files
 obj-$(CONFIG_MACH_SPEAR1300)		+= spear1300.o
diff --git a/arch/arm/mach-spear13xx/include/mach/suspend.h b/arch/arm/mach-spear13xx/include/mach/suspend.h
new file mode 100644
index 0000000..98d7db9
--- /dev/null
+++ b/arch/arm/mach-spear13xx/include/mach/suspend.h
@@ -0,0 +1,47 @@
+/*
+ * arch/arm/mach-spear13xx/include/mach/suspend.h
+ *
+ * Sleep mode defines for SPEAr13xx machine family
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * AUTHOR : Deepak Sikri <deepak.sikri@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_SUSPEND_H
+#define __MACH_SUSPEND_H
+
+#include <mach/hardware.h>
+
+#ifndef __ASSEMBLER__
+extern void spear_sleep_mode(suspend_state_t state);
+extern unsigned int spear_sleep_mode_sz;
+extern void spear_wakeup(void);
+extern unsigned int spear_wakeup_sz;
+#endif
+
+/* SRAM related defines*/
+#define SRAM_STACK_STRT_OFF	0x500
+#define SRAM_STACK_SCR_OFFS	0xF00
+#define SPEAR_START_SRAM	SPEAR13XX_SYSRAM1_BASE
+#define SPEAR_LIMIT_SRAM	(SPEAR_START_SRAM + SZ_4K - 1)
+#define SPEAR_SRAM_STACK_PA	(SPEAR_START_SRAM + SRAM_STACK_STRT_OFF)
+#define SPEAR_SRAM_SCR_REG	(SPEAR_START_SRAM + SRAM_STACK_SCR_OFFS)
+/* SPEAr subsystem physical addresses */
+#define MPMC_BASE_PA		SPEAR13XX_MPMC_BASE
+#define MISC_BASE_PA		SPEAR13XX_MISC_BASE
+
+/* ARM Modes of Operation */
+#define MODE_USR_32		0x10
+#define MODE_FIQ_32		0x11
+#define MODE_IRQ_32		0x12
+#define MODE_SVC_32		0x13
+#define MODE_ABT_32		0x17
+#define MODE_UND_32		0x1B
+#define MODE_SYS_32		0x1F
+#define MODE_BITS		0x1F
+
+#endif /* __MACH_SUSPEND_H */
diff --git a/arch/arm/mach-spear13xx/pm.c b/arch/arm/mach-spear13xx/pm.c
new file mode 100644
index 0000000..6df799d
--- /dev/null
+++ b/arch/arm/mach-spear13xx/pm.c
@@ -0,0 +1,107 @@
+/*
+ * arch/arm/mach-spear13xx/pm.c
+ *
+ * SPEAr13xx Power Management source file
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Deepak Sikri <deepak.sikri@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/suspend.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <asm/cacheflush.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/suspend.h>
+
+static int spear_pm_sleep(suspend_state_t state)
+{
+	void (*spear_sram_sleep)(suspend_state_t state) = NULL;
+	void (*spear_sram_wake)(void) = NULL;
+	void *sram_dest = (void *)IO_ADDRESS(SPEAR_START_SRAM);
+
+	if (state == PM_SUSPEND_MEM) {
+		spear_sram_wake = memcpy(sram_dest, (void *)spear_wakeup,
+				spear_wakeup_sz);
+		/* Increment destination pointer by the size copied*/
+		sram_dest += roundup(spear_wakeup_sz, 4);
+	}
+
+	/* Copy the Sleep code on to the SRAM*/
+	spear_sram_sleep = memcpy(sram_dest, (void *)spear_sleep_mode,
+			spear_sleep_mode_sz);
+	flush_cache_all();
+	/* Jump to the suspend routines in sram */
+	spear_sram_sleep(state);
+	return 0;
+}
+
+/*
+ *	spear_pm_prepare - Do preliminary suspend work.
+ *
+ */
+static int spear_pm_prepare(void)
+{
+	/* We cannot sleep in idle until we have resumed */
+	disable_hlt();
+	return 0;
+}
+
+/*
+ *	spear_pm_enter - Actually enter a sleep state.
+ *	@state:		State we're entering.
+ *
+ */
+static int spear_pm_enter(suspend_state_t state)
+{
+	int ret;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = spear_pm_sleep(state);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/*
+ *	spear_pm_finish - Finish up suspend sequence.
+ *
+ *	This is called after we wake back up (or if entering the sleep state
+ *	failed).
+ */
+static void spear_pm_finish(void)
+{
+	enable_hlt();
+}
+
+static struct platform_suspend_ops spear_pm_ops = {
+	.prepare	= spear_pm_prepare,
+	.enter		= spear_pm_enter,
+	.finish		= spear_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+static int __init spear_pm_init(void)
+{
+	void * sram_limit_va = (void *)IO_ADDRESS(SPEAR_LIMIT_SRAM);
+	void * sram_st_va = (void *)IO_ADDRESS(SPEAR_START_SRAM);
+
+	/* In case the suspend code size is more than sram size return */
+	if (spear_sleep_mode_sz > (sram_limit_va - sram_st_va))
+		return	-ENOMEM;
+
+	suspend_set_ops(&spear_pm_ops);
+
+	return 0;
+}
+arch_initcall(spear_pm_init);
diff --git a/arch/arm/mach-spear13xx/sleep.S b/arch/arm/mach-spear13xx/sleep.S
new file mode 100644
index 0000000..9c7f12b
--- /dev/null
+++ b/arch/arm/mach-spear13xx/sleep.S
@@ -0,0 +1,435 @@
+/*
+ * linux/arch/arm/mach-spear13xx/sleep.S
+ *
+ * SPEAR13xx specific functions that will run in internal SRAM.
+ * The functions are used in power management.
+ *
+ * Copyright (C) 2010 ST MicroElectronics
+ * Deepak Sikri <deepak.sikri@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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+#include <mach/suspend.h>
+
+/* #define DDR_PLL_SREFRESH */
+/* #define TEST_PWRDOMAINS */
+.text
+ENTRY(spear_wakeup)
+
+spear_wakeup:
+	b	spear_wakeup
+	adr	r0, spear_sleep_restore
+	bx	r0
+
+ENTRY(spear_wakeup_sz)
+	.word	. - spear_wakeup
+/*
+ * spear_sleep_mode()
+ * Forces SPEAr into sleep
+ */
+ENTRY(spear_sleep_mode)
+	stmfd	sp!, {r0-r12, lr}		@ save registers on stack
+	/* Store Stack address in r8 */
+	ldr	r8, SRAM_STACK_VA
+
+	/* Store sp and spsr to SDRAM */
+	mov	r4, sp
+	mrs	r5, spsr
+	mov	r6, lr
+	stmia	r8!, {r4-r6}
+
+	/* Save all ARM registers */
+	/* Coprocessor access control register */
+	mrc	p15, 0, r6, c1, c0, 2
+	stmia	r8!, {r6}
+	/* TTBR0, TTBR1 and Translation table base control */
+	mrc	p15, 0, r4, c2, c0, 0
+	mrc	p15, 0, r5, c2, c0, 1
+	mrc	p15, 0, r6, c2, c0, 2
+	stmia	r8!, {r4-r6}
+	/*
+	 * Domain access control register, data fault status register,
+	 * and instruction fault status register
+	 */
+	mrc	p15, 0, r4, c3, c0, 0
+	mrc	p15, 0, r5, c5, c0, 0
+	mrc	p15, 0, r6, c5, c0, 1
+	stmia	r8!, {r4-r6}
+	/*
+	 * Data aux fault status register, instruction aux fault status,
+	 * data fault address register and instruction fault address register
+	 */
+	mrc	p15, 0, r4, c5, c1, 0
+	mrc	p15, 0, r5, c5, c1, 1
+	mrc	p15, 0, r6, c6, c0, 0
+	mrc	p15, 0, r7, c6, c0, 2
+	stmia	r8!, {r4-r7}
+	/*
+	 * user r/w thread and process ID, user r/o thread and process ID,
+	 * priv only thread and process ID, cache size selection
+	 */
+	mrc	p15, 0, r4, c13, c0, 2
+	mrc	p15, 0, r5, c13, c0, 3
+	mrc	p15, 0, r6, c13, c0, 4
+	mrc	p15, 2, r7, c0, c0, 0
+	stmia	r8!, {r4-r7}
+	/* Data TLB lockdown, instruction TLB lockdown registers */
+	mrc	p15, 0, r5, c10, c0, 0
+	mrc	p15, 0, r6, c10, c0, 1
+	stmia	r8!, {r5-r6}
+	/* Secure or non secure vector base address, FCSE PID, Context PID*/
+	mrc	p15, 0, r4, c12, c0, 0
+	mrc	p15, 0, r5, c13, c0, 0
+	mrc	p15, 0, r6, c13, c0, 1
+	stmia	r8!, {r4-r6}
+	/* Primary remap, normal remap registers */
+	mrc	p15, 0, r4, c10, c2, 0
+	mrc	p15, 0, r5, c10, c2, 1
+	stmia	r8!, {r4-r5}
+	/* Store current cpsr*/
+	mrs	r2, cpsr
+	stmia	r8!, {r2}
+	mrc	p15, 0, r4, c1, c0, 0
+	/* save control register */
+	stmia	r8!, {r4}
+	/* Data memory barrier and Data sync barrier */
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c10, 4
+	mcr	p15, 0, r1, c7, c10, 5
+	dsb
+	isb
+	/* Extract the physical address to jump to */
+	adr	r0, mmu_off
+	mov	r1, #0xcfffffff
+	and	r0, r0, r1
+	ldr	r1, =0x20000000
+	orr	r0, r0, r1
+	mov	r2, r0
+
+	/* Disable MMU */
+	mrc	p15, 0, r0, c1, c0, 0
+	ldr	r1, DISABLE_I_C_M_V
+	bic	r0, r0, r1
+	mcr	p15, 0, r0, c1, c0, 0
+	/* Move the Physical address into PC */
+	bx	r2
+	nop
+mmu_off:
+	/* Put the DDR in self refresh mode */
+	ldr	r6, MISC_BASE_P
+	/* Program MPMC Control Status register in Misc Space */
+	ldr	r0, [r6, #0x334]
+	/* Set srefresh_enter bit(2) */
+	orr	r0, r0, #0x4
+	str	r0, [r6, #0x334]
+wait_till_srefresh_on:
+	ldr	r0, [r6, #0x334]
+	/* check for cke_status bit(13) */
+	tst	r0, #0x2000
+	beq	wait_till_srefresh_on
+
+	/* Put the system in slow mode */
+	ldr	r0, [r6, #0x200]
+	bic	r0, r0, #0x4
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	orr	r0, r0, #0x2
+	str	r0, [r6, #0x200]	/* System is now in slow mode */
+wait_till_slow_mode:
+	ldr	r0, [r6, #0x200]
+	/* Wait for the mode to be updated */
+	and	r0, r0, #0xF0000
+	/* Poll the SCCTRL register status bits (6:3) */
+	cmp	r0, #0xA0000
+	bne wait_till_slow_mode
+
+	/*
+	 * Put the all the system pll's to off state
+	 * The loop of count 3 is provided below to
+	 * switch off the pll-1/2/3.
+	 * r1 contains the offset for the pll control
+	 * registers in the misc space.
+	 * DDR pll-4 requires different processing.
+	 */
+	ldr	r1, MISC_PLL_OFFS
+	ldr	r2, =0x0	/* PLL Counter 1, 2, 3, 4 */
+swoff_pll:
+	ldr	r0, [r6, r1]
+	/* Clear pll_enable bit(1) of PLL1_CTR register in Misc registers */
+	bic	r0, r0, #0x02
+	str	r0, [r6, r1]
+	add	r1, #0xc
+	add	r2, #0x1
+	cmp	r2, #0x3	/* Switch off pll-1/2/3 */
+	bne	swoff_pll
+
+#ifdef DDR_PLL_SREFRESH
+	/* Switch off pll-4 */
+	ldr	r0, [r6, r1]
+	/* Clear pll_enable bit(2) of PLL1_CTR register in Misc registers */
+	bic	r0, r0, #0x04
+	str	r0, [r6, r1]
+#endif
+
+#ifdef TEST_PWRDOMAINS
+	/* Switch off the undesired PLL's */
+	nop
+	ldr	r6, MISC_BASE_P
+	ldr	r0, [r6, #0x200]
+	bic	r0, r0, #0x7
+	orr	r0, r0, #0x2
+	str	r0, [r6, #0x200	]
+wait_ack0:
+	ldr	r0, [r6, #0x200]
+	and	r0, r0, #0xF0000
+	cmp	r0, #0xA0000
+	bne	wait_ack0
+	ldr	r6, MISC_BASE_P
+	ldr	r0, [r6, #0x100]
+
+	/*
+	 * Switch off the power domains.
+	 * Clear the ack bit
+	 */
+	bic	r0, r0, #0xc000
+	str	r0, [r6, #0x100]
+
+	bic	r0, r0, #0x1000
+	str	r0, [r6, #0x100]
+
+wait_ack1:
+	ldr	r0, [r6, #0x100]
+	tst	r0, #0x4000
+	beq	wait_ack1
+
+	/* Clear the ack bit */
+	bic	r0, r0, #0xc000
+	str	r0, [r6, #0x100]
+
+	bic	r0, r0, #0x0800
+	str	r0, [r6, #0x100]
+wait_ack2:
+	ldr	r0, [r6, #0x100]
+	tst	r0, #0x4000
+	beq	wait_ack2
+
+	/* Clear the ack bit */
+	bic	r0, r0, #0xc000
+	str	r0, [r6, #0x100]
+
+	bic	r0, r0, #0x2400
+	str	r0, [r6, #0x100]
+wait_ack3:
+	ldr	r0, [r6, #0x100]
+	tst	r0, #0x4000
+	beq	wait_ack3
+#endif
+	wfi				@ wait for interrupt
+	nop
+spear_sleep_restore:
+	/*
+	 * Reenable the switched off pll's. The Pll's are
+	 * enabled using loop count of 4 to activalte all the
+	 * pll-1/2/3/4.
+	 * The strobing is done for pll-4 only.
+	 */
+
+	ldr	r6, MISC_BASE_P
+	ldr	r1, MISC_PLL_OFFS
+	ldr	r2, =0x0	/* PLL Counter 1, 2, 3, 4 */
+swon_pll_1_3:
+	/* Switch on Pll-1/2/3 */
+	ldr	r0, [r6, r1]
+	orr	r0, r0, #0x2
+	str	r0, [r6, r1]
+pll_lock_1_3:
+	/* Set the pll_lock bit(0) in PLLX_CTR register in misc space*/
+	ldr	r5, [r6, r1]
+	and	r5, r5, #0x1
+	/* Wait for pll lock status */
+	cmp	r5, #0x1
+	bne	pll_lock_1_3
+
+	/* Loop for all the pll's */
+	add	r1, #0xc
+	add	r2, #0x1
+	cmp	r2, #0x3	/* Switch on till pll-3 */
+	bne	swon_pll_1_3
+
+#ifdef DDR_PLL_SREFRESH
+	/* Switch on PLL-4, strobe the pll also */
+	ldr	r0, [r6, r1]
+	ldr	r0, PLL_VAL1
+	str	r0, [r6, r1]
+	ldr	r0, PLL_VAL2
+	str	r0, [r6, r1]
+	ldr	r0, PLL_VAL3
+	str	r0, [r6, r1]
+	ldr	r0, PLL_VAL2
+	str	r0, [r6, r1]
+pll_lock_4:
+	/* Set the pll_lock bit(0) in PLLX_CTR register in misc space*/
+	ldr	r5, [r6, r1]
+	and	r5, r5, #0x1
+	/* Wait for pll lock status */
+	cmp	r5, #0x1
+	bne	pll_lock_4
+#endif
+
+	/* Put the system in normal mode */
+	ldr	r0, [r6, #0x200]
+	bic	r0, r0, #0x7
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	orr	r0, r0, #0x4
+	str	r0, [r6, #0x200]	/* System is now in slow mode */
+wait_till_normal_mode:
+	ldr	r0, [r6, #0x200]
+	/* Wait for the mode to be updated */
+	and	r0, r0, #0xF0000
+	/* Poll the SCCTRL register status bits (6:3) */
+	cmp	r0, #0xf0000
+	bne wait_till_normal_mode
+
+	/*
+	 * Invalidate all instruction caches to PoU
+	 * and flush branch target cache
+	 */
+	mov	r1, #0
+	mcr	p15, 0, r1, c7, c5, 0
+
+	ldr	r3, SRAM_STACK_PA
+	ldmia	r3!, {r4-r6}
+	mov	sp, r4
+	msr	spsr_cxsf, r5
+	mov	lr, r6
+
+	ldmia	r3!, {r4-r9}
+	/* Coprocessor access Control Register */
+	mcr	p15, 0, r4, c1, c0, 2
+
+	/* TTBR0 */
+	mcr	p15, 0, r5, c2, c0, 0
+	/* TTBR1 */
+	mcr	p15, 0, r6, c2, c0, 1
+	/* Translation table base control register */
+	mcr	p15, 0, r7, c2, c0, 2
+	/*domain access Control Register */
+	mcr	p15, 0, r8, c3, c0, 0
+	/* data fault status Register */
+	mcr	p15, 0, r9, c5, c0, 0
+
+	ldmia	r3!, {r4-r8}
+	/* instruction fault status Register */
+	mcr	p15, 0, r4, c5, c0, 1
+	/*Data Auxiliary Fault Status Register */
+	mcr	p15, 0, r5, c5, c1, 0
+	/*Instruction Auxiliary Fault Status Register*/
+	mcr	p15, 0, r6, c5, c1, 1
+	/*Data Fault Address Register */
+	mcr	p15, 0, r7, c6, c0, 0
+	/*Instruction Fault Address Register*/
+	mcr	p15, 0, r8, c6, c0, 2
+	ldmia	r3!, {r4-r7}
+
+	/* user r/w thread and process ID */
+	mcr	p15, 0, r4, c13, c0, 2
+	/* user ro thread and process ID */
+	mcr	p15, 0, r5, c13, c0, 3
+	/*Privileged only thread and process ID */
+	mcr	p15, 0, r6, c13, c0, 4
+	/* cache size selection */
+	mcr	p15, 2, r7, c0, c0, 0
+	ldmia	r3!, {r4-r8}
+	/* Data TLB lockdown registers */
+	mcr	p15, 0, r4, c10, c0, 0
+	/* Instruction TLB lockdown registers */
+	mcr	p15, 0, r5, c10, c0, 1
+	/* Secure or Nonsecure Vector Base Address */
+	mcr	p15, 0, r6, c12, c0, 0
+	/* FCSE PID */
+	mcr	p15, 0, r7, c13, c0, 0
+	/* Context PID */
+	mcr	p15, 0, r8, c13, c0, 1
+
+	ldmia	r3!, {r4-r5}
+	/* primary memory remap register */
+	mcr	p15, 0, r4, c10, c2, 0
+	/*normal memory remap register */
+	mcr	p15, 0, r5, c10, c2, 1
+
+	/* Restore cpsr */
+	ldmfd	r3!, {r4}	/*load CPSR from SDRAM*/
+	msr	cpsr, r4	/*store cpsr */
+	dsb
+	isb
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 4	@ Flush prefetch buffer
+	mcr	p15, 0, r0, c7, c5, 6	@ Invalidate branch predictor array
+	mcr	p15, 0, r0, c8, c5, 0	@ Invalidate instruction TLB
+	mcr	p15, 0, r0, c8, c6, 0	@ Invalidate data TLB
+
+	adr	r5, mmu_on
+	mov	r1, #0xcfffffff
+	and	r5, r5, r1
+	ldr	r1, =0x30000000
+	orr	r5, r5, r1
+	mov	r4, r5
+
+	/* Move the DDR out of self refresh mode */
+	ldr	r6, MISC_BASE_P
+	ldr	r7, MPMC_BASE_P
+	/* Program MPMC Control Status register in Misc Space */
+	ldr	r0, [r6, #0x334]
+	/* Clear srefresh_enter bit(2) */
+	bic	r0, r0, #0x4
+	str	r0, [r6, #0x334]
+	/* Additional clearance is required in the mpmc space */
+	ldr	r0, [r7, #0x2c]
+	/*
+	 * Clear bit srefresh bit (2) of MPMC_11 register
+	 * The misc wrapper does not works fine by itself till
+	 * this bit is also cleared.
+	 */
+	bic	r0, r0, #0x10000
+	str	r0, [r7, #0x2c]
+wait_for_refresh_exit:
+	ldr	r0, [r6, #0x334]
+	tst	r0, #0x2000
+	bne	wait_for_refresh_exit
+
+	ldmfd	r3!, {r2}
+	/* restore the MMU control register from stack to enable mmu */
+	mcr	p15, 0, r2, c1, c0, 0
+	bx	r4
+
+mmu_on:
+	ldmfd	sp!, {r0-r12, pc}		@ restore regs and return
+	nop
+
+MPMC_BASE_P :
+	.word MPMC_BASE_PA
+MISC_BASE_P :
+	.word MISC_BASE_PA
+SRAM_STACK_VA :
+	.word IO_ADDRESS(SPEAR_SRAM_STACK_PA)
+SRAM_STACK_PA :
+	.word SPEAR_SRAM_STACK_PA
+DISABLE_I_C_M_V:
+	.word 0x1805
+MISC_PLL_OFFS:
+	.word 0x214
+#ifdef DDR_PLL_SREFRESH
+PLL_VAL1:
+	.word 0x060a
+PLL_VAL2:
+	.word 0x060e
+PLL_VAL3:
+	.word 0x0606
+#endif
+ENTRY(spear_sleep_mode_sz)
+	.word	. - spear_sleep_mode
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index 5370b5b..515b8c9 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -439,6 +439,11 @@ struct map_desc spear13xx_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(SPEAR13XX_SYSRAM0_BASE),
 		.length		= SZ_32K,
 		.type		= MT_DEVICE
+	}, {
+		.virtual	= IO_ADDRESS(SPEAR13XX_SYSRAM1_BASE),
+		.pfn		= __phys_to_pfn(SPEAR13XX_SYSRAM1_BASE),
+		.length		= SZ_1M,
+		.type		= MT_MEMORY_NONCACHED
 	},
 };
 
diff --git a/arch/arm/mach-spear3xx/include/mach/suspend.h b/arch/arm/mach-spear3xx/include/mach/suspend.h
new file mode 100644
index 0000000..2435886
--- /dev/null
+++ b/arch/arm/mach-spear3xx/include/mach/suspend.h
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/mach-spear3xx/include/mach/suspend.h
+ *
+ * Sleep mode defines for SPEAr3xx machine family
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * AUTHOR : Deepak Sikri <deepak.sikri@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_SUSPEND_H
+#define __MACH_SUSPEND_H
+
+#include <mach/hardware.h>
+
+#ifndef __ASSEMBLER__
+extern void spear_sleep_mode(suspend_state_t state);
+extern unsigned int spear_sleep_mode_sz;
+#endif
+
+/* SRAM related defines*/
+#define SRAM_STACK_SCR_OFFS	0xF00
+#define SPEAR_START_SRAM	SPEAR3XX_ICM1_SRAM_BASE
+#define SPEAR_SRAM_SIZE		SZ_4K
+#define SPEAR_SRAM_SCR_REG	(SPEAR_START_SRAM + SRAM_STACK_SCR_OFFS)
+/* SPEAr subsystem physical addresses */
+#define SYS_CTRL_BASE_PA	SPEAR3XX_ICM3_SYS_CTRL_BASE
+#define MPMC_BASE_PA		SPEAR3XX_ICM3_SDRAM_CTRL_BASE
+#define MISC_BASE_PA		SPEAR3XX_ICM3_MISC_REG_BASE
+
+/* ARM Modes of Operation */
+#define MODE_USR_32		0x10
+#define MODE_FIQ_32		0x11
+#define MODE_IRQ_32		0x12
+#define MODE_SVC_32		0x13
+#define MODE_ABT_32		0x17
+#define MODE_UND_32		0x1B
+#define MODE_SYS_32		0x1F
+#define MODE_BITS		0x1F
+
+#endif /* __MACH_SUSPEND_H */
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 16ca683..2278c08 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -22,6 +22,10 @@
 #include <mach/generic.h>
 #include <mach/hardware.h>
 
+#define SPEAR3XX_WKUP_SRCS	(1 << SPEAR3XX_IRQ_MAC_1 | 1 << \
+		SPEAR3XX_IRQ_USB_DEV | 1 << SPEAR3XX_IRQ_BASIC_RTC | 1 << \
+		SPEAR3XX_IRQ_BASIC_GPIO)
+
 /* Add spear3xx machines common devices here */
 /* gpio device registration */
 static struct pl061_platform_data gpio_plat_data = {
@@ -224,7 +228,8 @@ void __init spear3xx_init(void)
 /* This will initialize vic */
 void __init spear3xx_init_irq(void)
 {
-	vic_init((void __iomem *)VA_SPEAR3XX_ML1_VIC_BASE, 0, ~0, 0);
+	vic_init((void __iomem *)VA_SPEAR3XX_ML1_VIC_BASE, 0, ~0,
+			SPEAR3XX_WKUP_SRCS);
 }
 
 /* Following will create static virtual/physical mappings */
diff --git a/arch/arm/mach-spear6xx/include/mach/suspend.h b/arch/arm/mach-spear6xx/include/mach/suspend.h
new file mode 100644
index 0000000..bf870fc
--- /dev/null
+++ b/arch/arm/mach-spear6xx/include/mach/suspend.h
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/mach-spear6xx/include/mach/suspend.h
+ *
+ * Sleep mode defines for SPEAr6xx machine family
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * AUTHOR : Deepak Sikri <deepak.sikri@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_SUSPEND_H
+#define __MACH_SUSPEND_H
+
+#include <mach/hardware.h>
+
+#ifndef __ASSEMBLER__
+extern void spear_sleep_mode(suspend_state_t state);
+extern unsigned int spear_sleep_mode_sz;
+#endif
+
+/* SRAM related defines*/
+#define SRAM_STACK_SCR_OFFS	0xF00
+#define SPEAR_START_SRAM	SPEAR6XX_ICM1_SRAM_BASE
+#define SPEAR_SRAM_SIZE		SZ_4K
+#define SPEAR_SRAM_SCR_REG	(SPEAR_START_SRAM + SRAM_STACK_SCR_OFFS)
+/* SPEAr subsystem physical addresses */
+#define SYS_CTRL_BASE_PA	SPEAR6XX_ICM3_SYS_CTRL_BASE
+#define MPMC_BASE_PA		SPEAR6XX_ICM3_SDRAM_CTRL_BASE
+#define MISC_BASE_PA		SPEAR6XX_ICM3_MISC_REG_BASE
+
+/* ARM Modes of Operation */
+#define MODE_USR_32		0x10
+#define MODE_FIQ_32		0x11
+#define MODE_IRQ_32		0x12
+#define MODE_SVC_32		0x13
+#define MODE_ABT_32		0x17
+#define MODE_UND_32		0x1B
+#define MODE_SYS_32		0x1F
+#define MODE_BITS		0x1F
+
+#endif /* __MACH_SUSPEND_H */
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index 00336e9..b38bf2b 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -23,6 +23,12 @@
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 
+/* The wake sources are routed through vic-2 */
+#define SPEAR6XX_WKUP_SRCS_VIC2		(1 << (IRQ_GMAC_1 - 32) | \
+					1 << (IRQ_USB_DEV - 32) | \
+					1 << (IRQ_BASIC_RTC - 32) |\
+					1 << (IRQ_BASIC_GPIO - 32))
+
 /* Add spear6xx machines common devices here */
 /* ssp device registration */
 static struct pl022_ssp_controller ssp_platform_data[] = {
@@ -360,7 +366,8 @@ void __init spear6xx_init(void)
 void __init spear6xx_init_irq(void)
 {
 	vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_PRI_BASE, 0, ~0, 0);
-	vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_SEC_BASE, 32, ~0, 0);
+	vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_SEC_BASE, 32, ~0,
+			SPEAR6XX_WKUP_SRCS_VIC2);
 }
 
 /* Following will create static virtual/physical mappings */
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index 44923e9..0c979af 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -7,6 +7,7 @@ obj-y	:= clock.o time.o
 
 obj-$(CONFIG_ARCH_SPEAR13XX)	+= padmux.o
 obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
+
 obj-$(CONFIG_MACH_SPEAR310)	+= plgpio.o
 obj-$(CONFIG_MACH_SPEAR320)	+= plgpio.o
 
@@ -18,3 +19,8 @@ obj-$(CONFIG_BOARD_SPEAR300_EVB)	+= i2c_eval_board.o
 obj-$(CONFIG_BOARD_SPEAR310_EVB)	+= i2c_eval_board.o
 obj-$(CONFIG_BOARD_SPEAR320_EVB)	+= i2c_eval_board.o
 obj-$(CONFIG_BOARD_SPEAR600_EVB)	+= i2c_eval_board.o
+
+ifeq ($(CONFIG_PM),y)
+obj-$(CONFIG_ARCH_SPEAR3XX)	+= pm.o sleep.o
+obj-$(CONFIG_ARCH_SPEAR6XX)	+= pm.o sleep.o
+endif
diff --git a/arch/arm/plat-spear/pm.c b/arch/arm/plat-spear/pm.c
new file mode 100644
index 0000000..0cb2d0c
--- /dev/null
+++ b/arch/arm/plat-spear/pm.c
@@ -0,0 +1,104 @@
+/*
+ * arch/arm/plat-spear/pm.c
+ *
+ * SPEAr3xx & SPEAr6xx Power Management source file
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Deepak Sikri <deepak.sikri@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/suspend.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+#include <mach/irqs.h>
+#include <mach/suspend.h>
+
+static void (*saved_idle)(void);
+static void __iomem *spear_sram_base;
+
+static int spear_pm_sleep(suspend_state_t state)
+{
+	void (*spear_sram_sleep)(suspend_state_t state) = NULL;
+
+	/* Copy the Sleep code on to the SRAM*/
+	spear_sram_sleep = memcpy((void *)spear_sram_base,
+			(void *)spear_sleep_mode, spear_sleep_mode_sz);
+	flush_cache_all();
+	/* Jump to the suspend routines in sram */
+	spear_sram_sleep(state);
+	return 0;
+}
+
+/*
+ *	spear_pm_prepare - Do preliminary suspend work.
+ *
+ */
+static int spear_pm_prepare(void)
+{
+	/* We cannot sleep in idle until we have resumed */
+	saved_idle = pm_idle;
+	pm_idle = NULL;
+	return 0;
+}
+
+/*
+ *	spear_pm_enter - Actually enter a sleep state.
+ *	@state:		State we're entering.
+ *
+ */
+static int spear_pm_enter(suspend_state_t state)
+{
+	int ret;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		ret = spear_pm_sleep(state);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/*
+ *	spear_pm_finish - Finish up suspend sequence.
+ *
+ *	This is called after we wake back up (or if entering the sleep state
+ *	failed).
+ */
+static void spear_pm_finish(void)
+{
+	pm_idle = saved_idle;
+}
+
+static struct platform_suspend_ops spear_pm_ops = {
+	.prepare	= spear_pm_prepare,
+	.enter		= spear_pm_enter,
+	.finish		= spear_pm_finish,
+	.valid		= suspend_valid_only_mem,
+};
+
+static int __init spear_pm_init(void)
+{
+
+	spear_sram_base = ioremap(SPEAR_START_SRAM, SPEAR_SRAM_SIZE);
+
+	if (!spear_sram_base)
+		return -ENOMEM;
+
+	/* In case the suspend code size is more than sram size return */
+	if (spear_sleep_mode_sz > (SPEAR_SRAM_SIZE))
+		return	-ENOMEM;
+
+	suspend_set_ops(&spear_pm_ops);
+	return 0;
+}
+arch_initcall(spear_pm_init);
diff --git a/arch/arm/plat-spear/sleep.S b/arch/arm/plat-spear/sleep.S
new file mode 100644
index 0000000..5347789
--- /dev/null
+++ b/arch/arm/plat-spear/sleep.S
@@ -0,0 +1,288 @@
+/*
+ * arch/arm/plat-spear/sleep.S
+ *
+ * SPEAR3xx and SPEAR6xx specific functions that will run in
+ * internal SRAM. The functions are used in power management.
+ *
+ * Copyright (ST) 2010 Deepak Sikri <deepak.sikri@.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/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+#include <mach/suspend.h>
+
+.text
+ENTRY(spear_sleep_mode)
+	stmfd	sp!, {r0-r12, lr}
+
+	/* Latch some of MMU registers on to stack */
+	mrc	p15, 0, r0, c5, c0, 0 /* FSR--Domain Fault */
+	mrc	p15, 0, r1, c5, c0, 1 /* FSR--Instruction Fault */
+	mrc	p15, 0, r2, c6, c0, 0 /* FAR */
+	mrc	p15, 0, r3, c9, c0, 0 /* Read Dcache Lockdown */
+	mrc	p15, 0, r4, c9, c0, 1 /* Read ICache Lockdown */
+	mrc	p15, 0, r5, c9, c1, 0 /* Read Data TLB */
+	mrc	p15, 0, r6, c9, c1, 1 /* Read Instr TCM region register */
+
+	mrc	p15, 0, r7, c10, c0, 0 /* Data TLBLock Down operation */
+	mrc	p15, 0, r8, c13, c0, 0 /* FCSE--PID */
+	mrc	p15, 0, r9, c13, c0, 1 /* Context-ID */
+
+	/* Save all these registers onto the stack */
+	stmfd	sp!, {r0-r9}
+	/* Save the stack pointer */
+	mov	r3, sp
+	/* Store the two mode registers */
+	stmfd	r3!, {sp, lr}
+	/* Save the current mode with irq disabled */
+	mrs	r0, cpsr
+	stmfd	r3!, {r0}
+	/*
+	 * Save the MMU registers on the SRAM Stack
+	 * Domain Register on Back-up RAM structure
+	 */
+	mrc	p15, 0, r2, c3, c0, 0
+	/* TTB Register */
+	mrc	p15, 0, r1, c2, c0, 0
+	/* MMU Enable Register */
+	mrc	p15, 0, r0, c1, c0, 0
+	stmfd	r3!, {r0, r1, r2}
+	/*
+	 * Capture the Physical Address.
+	 * This will be used once MMU is Off
+	 */
+	adr	r0, mmu_off
+	adr	r1, spear_sleep_mode
+	/* Store the virtual address on to DDR */
+	stmfd	r3!, {r1}
+	sub	r1, r0, r1
+	ldr	r0, SRAM_START_P
+	add	r2, r1, r0
+
+	/* Disable MMU */
+	mrc	p15, 0, r0, c1, c0, 0
+	ldr	r1, DISABLE_I_C_M_V
+	bic	r0, r0, r1
+	mcr	p15, 0, r0, c1, c0, 0
+	/* Move the Physical address into PC */
+	bx	r2
+
+	/*
+	 * This portion of code is executed from SRAM
+	 * post MMU has been turned off
+	 */
+mmu_off:
+	/* Store the DDR stack address onto scratch pad location */
+	ldr	r0, SCRATCH_PAD
+	str	r3, [r0]
+
+	ldr	r6, MISC_BASE_P
+	ldr	r7, MPMC_BASE_P
+	ldr	r8, SYS_CTRL_BASE_P
+
+	/*
+	 * Put SDRAM in self-refresh mode
+	 * Clear START bit(24) of MEMCTL_GP_03 register in MPMC
+	 */
+	ldr	r0, [r7, #0x1c]
+	ldr	r4, =0x1000000
+	/* Begin the command processing in controller */
+	bic	r0, r0, r4
+	str	r0, [r7, #0x1c]
+	ldr	r0, [r7, #0x1c]
+	/* set the SREFRESH bit(16) */
+	ldr	r4, =0x10000
+	orr	r0, r0, r4
+	str	r0, [r7, #0x1c]
+
+	/* Put the DDR into low power mode */
+	ldr	r0, [r6, #0xf0]
+	ldr	r4, =0x00000001
+	/* Clear DDR_LOW_POWER_DDR2_MODE bit(1) of DDR_PAD register */
+	bic	r0, r0, r4
+	str	r0, [r6, #0xf0]
+
+	/* Put the system in slow mode, use system controller */
+	ldr	r0, [r8]
+	bic	r0, r0, #0x4
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	orr	r0, r0, #0x2
+	str	r0, [r8]	/* System is now in slow mode */
+
+wait_till_slow_mode:
+	ldr	r0, [r8]
+	and	r0, r0, #0x78	/* Wait for the mode to be updated */
+	cmp	r0, #0x10	/* Poll the SCCTRL register status bits (6:3) */
+	bne wait_till_slow_mode
+
+	/* Put the Pll-1 to off. */
+	ldr	r0, [r6, #0x08]
+	/* Clear pll_enable bit(2) of PLL1_CTR register in Misc registers */
+	bic	r0, r0, #0x04
+	str	r0, [r6, #0x08]
+
+	/* Put the Pll-2 to off */
+	ldr	r0, [r6, #0x14]
+	/* Clear pll_enable bit(2) of PLL2_CTR register in Misc registers */
+	bic	r0, r0, #0x04
+	str	r0, [r6, #0x14]
+	mov	r2, #0
+	/* Put the system in sleep */
+	ldr	r0, [r8]
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	bic	r0, r0, #0x7
+#ifdef TEST_SLOW
+	orr	r0, r0, #0x2 /* Slow Mode */
+#endif
+	str	r0, [r8]
+	/* Put system in WFI */
+	mcr	p15, 0, r2, c7, c0, 4
+wakeup_addr:
+	ldr	r6, MISC_BASE_P
+	ldr	r7, MPMC_BASE_P
+	ldr	r8, SYS_CTRL_BASE_P
+	/* Reenable pll1 and pll2 */
+	ldr	r0, PLL_VAL1
+	str	r0, [r6, #0x08]
+	str	r0, [r6, #0x14]
+	ldr	r0, PLL_VAL2
+	str	r0, [r6, #0x08]
+	str	r0, [r6, #0x14]
+	/* Strobe */
+	ldr	r2, PLL_VAL3
+	str	r2, [r6, #0x08]
+	str	r2, [r6, #0x14]
+	ldr	r2, PLL_VAL2
+	str	r2, [r6, #0x08]
+	str	r2, [r6, #0x14]
+pll1_lock_1:
+	/* Set the pll_lock bit(0) in PLL1_CTR register in misc space*/
+	ldr	r2, [r6, #0x08]
+	and	r2, r2, #0x1
+	/* Wait for pll-1 lock status */
+	cmp	r2, #0x1
+	bne	pll1_lock_1
+
+pll2_lock_2:
+	/* Set the pll_lock bit(0) in PLL2_CTR register in misc space*/
+	ldr	r2, [r6, #0x14]
+	and	r2, r2, #0x1
+	/* Wait for pll-2 lock status */
+	cmp	r2, #0x1
+	bne	pll2_lock_2
+
+	/* Move the system in Normal mode, use system controller */
+	ldr	r3, [r8]
+	/* Set the apt mode bits(2:0) in SCCTRL register */
+	bic	r3, r3, #0x7
+	orr	r3, r3, #0x4
+	str	r3, [r8]
+
+wait_till_norm_mode:
+	ldr	r3, [r8]
+	and	r3, r3, #0x78
+	cmp	r3, #0x20	/* Poll the SCCTRL register status bits (6:3) */
+	bne	wait_till_norm_mode
+
+	/* Resume the DDR from Low power mode. */
+	ldr	r0, [r6, #0xf0]
+	/* Set DDR_LOW_POWER_DDR2_MODE bit(1) of DDR_PAD register */
+	orr	r0, r0, #0x01
+	str	r0, [r6, #0xf0]
+
+	/* Exit DDR-SDRAM from self-refresh mode */
+	ldr	r1, [r7, #0x1c]
+	/* clear the SREFRESH bit(16) */
+	ldr	r4, =0x10000
+	bic	r1, r1, r4
+	str	r1, [r7, #0x1c]
+
+	/* Begin the command processing in controller */
+	ldr	r4, =0x1000000
+	/* Set START bit(24) of MEMCTL_GP_03 register in MPMC*/
+	orr	r1, r1, r4
+	str	r1, [r7, #0x1c]
+
+	mov	r0, r0
+	/* Start the Restore Processing */
+	ldr	r0, SCRATCH_PAD
+	ldr	r6, [r0]
+
+	/* Restore the Virtual Address to be used */
+	/* Once MMU is made on */
+	ldr	r0, SRAM_START_P
+	adr	r1, mmu_on
+	sub	r0, r1, r0
+	/* Get the physical Address */
+	mov	r3, #0xc0000000
+	sub	r6, r6, r3
+	/* Fetch the sram virtual address */
+	ldmfd	r6!, {r1}
+	add	r4, r1, r0
+
+	/* Fetch the MMU Related information latched on SDRAM */
+	ldmfd	r6!, {r0, r1, r2}
+	/* Enable the MMU */
+	mcr	p15, 0, r2, c3, c0, 0
+	mcr	p15, 0, r1, c2, c0, 0
+	mcr	p15, 0, r0, c1, c0, 0
+	bx	r4
+mmu_on:
+	add	r6, r6, r3
+	/* Store the value of cpsr in R0 */
+	mrs	r0, cpsr
+	bic	r0, r0, #MODE_BITS
+
+	/* Here we will restore our cpsr IRQ/FIQ Disabled */
+	ldr	r0, [r6]
+	msr	cpsr_cxsf, r0
+	add	r6, r6, #4
+
+	/* Now only two user-mode registers are left */
+	ldmfd	r6!, {sp, lr}
+	mov	r0, r0
+
+	/* Restore stack pointer for the current mode */
+	mov	sp, r6
+
+	ldmfd	sp!, {r0-r9}
+	mcr	p15, 0, r0, c5, c0, 0 /* FSR--Domain Fault */
+	mcr	p15, 0, r1, c5, c0, 1 /* FSR--Instruction Fault */
+	mcr	p15, 0, r2, c6, c0, 0 /* FAR */
+	mcr	p15, 0, r3, c9, c0, 0 /* Read Dcache Lockdown */
+	mcr	p15, 0, r4, c9, c0, 1 /* Read ICache Lockdown */
+	mcr 	p15, 0, r5, c9, c1, 0 /* Read Data TLB */
+	mcr	p15, 0, r6, c9, c1, 1 /* Read Instruction Lockdown */
+
+	mcr	p15, 0, r7, c10, c0, 0 /* Data TLB LockDown operation */
+	mcr	p15, 0, r8, c13, c0, 0 /* FCSE--PID */
+	mcr	p15, 0, r9, c13, c0, 1 /* Context-ID */
+
+	mov	r0, #0
+	ldmfd	sp!, {r0-r12, pc}
+
+SYS_CTRL_BASE_P :
+	.word SYS_CTRL_BASE_PA
+MPMC_BASE_P :
+	.word MPMC_BASE_PA
+MISC_BASE_P :
+	.word MISC_BASE_PA
+SRAM_START_P:
+	.word SPEAR_START_SRAM
+SCRATCH_PAD:
+	.word SPEAR_SRAM_SCR_REG
+DISABLE_I_C_M_V:
+	.word 0x1005
+PLL_VAL1:
+	.word 0x1c0a
+PLL_VAL2:
+	.word 0x1c0e
+PLL_VAL3:
+	.word 0x1c06
+ENTRY(spear_sleep_mode_sz)
+	.word . - spear_sleep_mode
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V6 17/17] ST SPEAr: Updating defconfigs
From: Viresh Kumar @ 2011-03-01 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1298977727.git.viresh.kumar@st.com>

Reviewed-by: Stanley Miao <stanley.miao@windriver.com>
Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
Signed-off-by: Rajeev Kumar <rajeev-dlh.kumar@st.com>
Signed-off-by: shiraz hashim <shiraz.hashim@st.com>
---
 arch/arm/configs/spear13xx_defconfig |   78 ++++++++++++++++++++++++++++++---
 arch/arm/configs/spear3xx_defconfig  |   80 +++++++++++++++++++++++++++++++---
 arch/arm/configs/spear6xx_defconfig  |   72 ++++++++++++++++++++++++++++---
 3 files changed, 211 insertions(+), 19 deletions(-)

diff --git a/arch/arm/configs/spear13xx_defconfig b/arch/arm/configs/spear13xx_defconfig
index 9f3baf8..d764fee 100644
--- a/arch/arm/configs/spear13xx_defconfig
+++ b/arch/arm/configs/spear13xx_defconfig
@@ -10,31 +10,94 @@ CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR13XX=y
 CONFIG_BOARD_SPEAR1300_EVB=y
 CONFIG_BOARD_SPEAR1310_EVB=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEAER is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_AEABI=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_VFP=y
 CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_NET_IPIP=y
+CONFIG_ARPD=y
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_OSST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_NETDEVICES=y
+# CONFIG_WLAN is not set
 CONFIG_INPUT_FF_MEMLESS=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_SPEAR=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=8192
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_PL061=y
 # CONFIG_HWMON is not set
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_TEST=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_RTC_CLASS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
@@ -42,16 +105,18 @@ CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_AUTOFS4_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=m
+CONFIG_NLS_ASCII=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
@@ -59,3 +124,4 @@ CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
+# CONFIG_ARM_UNWIND is not set
diff --git a/arch/arm/configs/spear3xx_defconfig b/arch/arm/configs/spear3xx_defconfig
index fea7e1f..5a210ce 100644
--- a/arch/arm/configs/spear3xx_defconfig
+++ b/arch/arm/configs/spear3xx_defconfig
@@ -10,13 +10,54 @@ CONFIG_PLAT_SPEAR=y
 CONFIG_BOARD_SPEAR300_EVB=y
 CONFIG_BOARD_SPEAR310_EVB=y
 CONFIG_BOARD_SPEAR320_EVB=y
+CONFIG_AEABI=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_ARPD=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_OSST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_NETDEVICES=y
+# CONFIG_WLAN is not set
 CONFIG_INPUT_FF_MEMLESS=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_SPEAR=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
@@ -24,30 +65,55 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=8192
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SPIDEV=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PL061=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SAMSUNG_LMS700=y
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_TEST=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SPEAR=y
+CONFIG_RTC_CLASS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_AUTOFS4_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
 CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=m
+CONFIG_NLS_ASCII=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_CRC32 is not set
+# CONFIG_ARM_UNWIND is not set
diff --git a/arch/arm/configs/spear6xx_defconfig b/arch/arm/configs/spear6xx_defconfig
index cef2e83..5217396 100644
--- a/arch/arm/configs/spear6xx_defconfig
+++ b/arch/arm/configs/spear6xx_defconfig
@@ -9,10 +9,48 @@ CONFIG_MODVERSIONS=y
 CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR6XX=y
 CONFIG_BOARD_SPEAR600_EVB=y
+CONFIG_AEABI=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_ARPD=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_CHR_DEV_OSST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_NETDEVICES=y
+# CONFIG_WLAN is not set
 CONFIG_INPUT_FF_MEMLESS=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_SERIAL_AMBA_PL011=y
@@ -20,30 +58,52 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=8192
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE=y
+CONFIG_SPI=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SPIDEV=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PL061=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SAMSUNG_LMS700=y
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_TEST=y
+CONFIG_RTC_CLASS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_AUTOFS4_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
 CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
 CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="utf8"
 CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=m
+CONFIG_NLS_ASCII=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
-# CONFIG_CRC32 is not set
+# CONFIG_ARM_UNWIND is not set
-- 
1.7.2.2

^ permalink raw reply related

* [PATCH V3 4/4] mmc: sdhci-esdhc: enable esdhc on imx53
From: Wolfram Sang @ 2011-03-01 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <010C9052C42A00499CE76D637FA5EE900C7B7B@039-SN1MPN1-001.039d.mgd.msft.net>

Hi Richard,

> Thanks a lot for your review-comments firstly. :)

You are welcome :)

> > > +/* Abort type definition in the command register  */
> > > +#define  SDHCI_CMD_ABORTCMD        0xC0
> >
> > Won't that belong into sd.h (unless I misunderstood your last mail)?
> This is the bit definitions of the ABORTCMD CMD-TYPE on the bit6~7 of CMD register.
> Here is the definition of the CMD register derived from SDHC spec. FYI.
> D15   D14 D13  D08     D07 D06       D05                  D04                          D03                       D02         D01 D00
> Rsvd  Command  Index   Command Type  Data Present Select  Command Index Check Enable   Command CRC Check Enable  Rsvd        Response Type Select

Ack, I found that, too. Exactly because it is in the standard, I thought
this should rather go into sd.h than sdhci-esdhc-imx.c. Would be a
seperate patch, though.

> >
> > > +/* VENDOR SPEC register */
> > > +#define SDHCI_VENDOR_SPEC  0xC0
> > > +
> > > +/*
> > > + * The CMDTYPE of the CMD register(offset 0xE) should be set to
> >
> > Check spaces.
> I used the <kernel_dir>/./scripts/checkpatch.pl script to check the patches, and didn't find that there are issues about the spaces.
> Can you tell me what's kinds of spaces issue should be fixed?

Space before opening brace -> "register (offset ..."

> No, we can't keep it enabled all the time.
> This bit should be set to '1'/clear to '0' at the begin/end of the transfer.
> Unfortunately, We can't use it to fix CMD12 issue either, this bit is only used to fix SDIO Multi-BLK NO INT case.

Ok, thanks for checking.

> IC guy insist that the CMD12 case is not a bug refer to the SD HOST controller spec, the bit7-6 should be
> Set to 11b when the abort CMD is issued.

That's a flaw in the core then? Need to investigate that.

> > Hmm, to me, just using cpu_is_mx53() is more readable than introducing
> > another layer of flags/quirks.
> Hi Wolfram:
> I discussed it with Richard Zhao before sending out these V3 patches.
> As we know that there is not only mx53 has this issue, maybe some following SOCs have this issue too.
> So we make a decision that we introduce another flags/quirks to declare it for all those SOCs that required this
> mechanism in the end.

Seems I am outnumbered on this matter, so OK. I just got a bit afraid
of that approach seeing it didn't scale very well with sdhci.c.

> > > +
> > > +static struct sdhci_ops sdhci_esdhc_ops;
> > > +
> >
> > Move them to the front. But I did this already, so no worries :) I will
> > ping Chris to merge my series, so we will have something better to
> > develop on.
> >
> Thanks.:)

He pulled the changes now, so please rebase your patches against
mmc-next. There is already a write_le-function now, but this should be
not too hard, hopefully.

Keep in mind that you don't need to cast void*.

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110301/acca923e/attachment.sig>

^ permalink raw reply

* [PATCH 3/8] Add a mfd IPUv3 driver
From: Sascha Hauer @ 2011-03-01 11:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1103011054440.2701@localhost6.localdomain6>

On Tue, Mar 01, 2011 at 11:00:09AM +0100, Thomas Gleixner wrote:
> On Tue, 1 Mar 2011, Sascha Hauer wrote:
> > On Mon, Feb 28, 2011 at 07:33:05PM +0100, Thomas Gleixner wrote:
> > > > +void ipu_idmac_put(struct ipu_channel *channel)
> > > > +{
> > > > +	dev_dbg(ipu_dev, "%s %d\n", __func__, channel->num);
> > > 
> > > Do we really need this debug stuff in all these functions ?
> > 
> > Reading this comment I expected tons of dev_dbg in the driver. The one
> > you mentioned above (plus the corresponding one in ipu_idmac_get) are
> > indeed not particularly useful, but do you think there is still too much
> > debug code left?
> 
> Well, I don't see a point in having useless debug stuff around.
> > > > +	DECLARE_IPU_IRQ_BITMAP(irqs);
> > > 
> > > Why the hell do we need this? It's a bog standard bitmap, right ?
> > 
> > It's defined as:
> > 
> > #define DECLARE_IPU_IRQ_BITMAP(name)     DECLARE_BITMAP(name, IPU_IRQ_COUNT)
> > 
> > So yes, it's a standard bitmask. It can be used in client drivers
> > aswell. Where's the problem of adding a define for this so that client
> > drivers do not have to care about the size of the bitmap?
> 
> That's nonsense. You have to know about the size of the bitmap for any
> operation on it. Or are you going to provide wrappers around
> bitmap_zero() and all other possible bitmap_* functions as well?

Ok, you're right.

> 
> > > 
> > > > +	bitmap_zero(irqs, IPU_IRQ_COUNT);
> > > > +	ret = ipu_submodules_init(pdev, ipu_base, ipu_clk);
> > > > +	if (ret)
> > > > +		goto failed_submodules_init;
> > > > +
> > > > +	/* Set sync refresh channels as high priority */
> > > > +	ipu_idmac_write(0x18800000, IDMAC_CHA_PRI(0));
> > > 
> > > Hmm, this random prio setting here is odd.
> > 
> > This is 1:1 from the Freescale Kernel and I never thought about it. We
> > can remove it and see what happens. Maybe then some day we'll learn
> > *why* this is done.
> 
> Well, the point is to move that to the init function which deals with
> IDMAC and not have it at some random place in the code.

Ok, will move it there.

>  
> > > > +	/* Wait for DC triple buffer to empty */
> > > > +	if (dc_channels[dc_chan].di == 0)
> > > > +		while ((__raw_readl(DC_STAT) & 0x00000002)
> > > > +			!= 0x00000002) {
> > > > +			msleep(2);
> > > > +			timeout -= 2;
> > > > +			if (timeout <= 0)
> > > > +				break;
> > > 
> > > So we poll stuff which is updated from some other function ?
> > 
> > We poll the DC_STAT register here which is updated from the hardware.
> 
> And there is no interrupt for this ?

Given the sheer amount of interrupt bits it's a bit surprising, but no,
I haven't found an interrupt for this (This of course doesn't mean it
doesn't exist...)

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* [PATCH 3/8] Add a mfd IPUv3 driver
From: Arnd Bergmann @ 2011-03-01 11:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110301111220.GN29521@pengutronix.de>

On Tuesday 01 March 2011, Sascha Hauer wrote:
> > Taking one step back from this, have you considered making this
> > a regular interrupt controller? That would make the client drivers
> > more standard -- you could define the interrupt numbers as resources
> > of a platform device or in the device tree, for instance.
> > The cost might be more complex code, e.g. when a device requires
> > many interrupts, but I think it will be at least as efficient
> > at run-time, and less surprising for readers and authors of
> > client drivers.
> 
> I thought about this, but hesitated to increase NR_IRQS by 463. Do you
> think we should do this instead?

I think there is a plan to virtualize the interrupt numbers on ARM,
and in that case NR_IRQS becomes rather meaningless. I don't know
exactly how far that effort has come.

	Arnd

^ permalink raw reply

* [PATCH 3/6] ARM: tegra: update GPIO chained IRQ handler to use EOI in parent chip
From: Sergei Shtylyov @ 2011-03-01 13:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298900022-21516-4-git-send-email-will.deacon@arm.com>

Hello.

On 28-02-2011 16:33, Will Deacon wrote:

> The chained GPIO IRQ handler on Tegra calls ->irq_ack on the parent
> chip prior to handling the interrupt.

> This patch updates the code to use ->irq_eoi now that the GIC has moved
> to using the fasteoi flow model.

> Acked-by: Colin Cross<ccross@android.com>
> Signed-off-by: Will Deacon<will.deacon@arm.com>
> ---
>   arch/arm/mach-tegra/gpio.c |   17 +----------------
>   1 files changed, 1 insertions(+), 16 deletions(-)
>
> diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
> index ad80488..5019b01 100644
> --- a/arch/arm/mach-tegra/gpio.c
> +++ b/arch/arm/mach-tegra/gpio.c
> @@ -219,9 +219,6 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
>   	struct tegra_gpio_bank *bank;
>   	int port;
>   	int pin;
> -	int unmasked = 0;
> -
> -	desc->irq_data.chip->irq_ack(&desc->irq_data);

    Won't this code break after the first patch as it removes irq_ack() 
method? I.e. shouldn't the patches be combined to keep them bisectable?

WBR, Sergei

^ permalink raw reply

* [PATCH 4/6] ARM: s5pv310: update IRQ combiner to use EOI in parent chip
From: Sergei Shtylyov @ 2011-03-01 13:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298900022-21516-5-git-send-email-will.deacon@arm.com>

On 28-02-2011 16:33, Will Deacon wrote:

> The IRQ combiner code invokes the ->irq_{un}mask routines of the parent
> chip.

> This patch updates the cascaded handler to use EOI now that the GIC has
> moved to using the fasteoi flow model.

> Tested-by: Kyungmin Park<kyungmin.park@samsung.com>
> Signed-off-by: Will Deacon<will.deacon@arm.com>
> ---
>   arch/arm/mach-s5pv310/irq-combiner.c |    7 ++-----
>   1 files changed, 2 insertions(+), 5 deletions(-)

> diff --git a/arch/arm/mach-s5pv310/irq-combiner.c b/arch/arm/mach-s5pv310/irq-combiner.c
> index 1ea4a9e..24d5604 100644
> --- a/arch/arm/mach-s5pv310/irq-combiner.c
> +++ b/arch/arm/mach-s5pv310/irq-combiner.c
> @@ -59,9 +59,6 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
>   	unsigned int cascade_irq, combiner_irq;
>   	unsigned long status;
>
> -	/* primary controller ack'ing */
> -	chip->irq_ack(&desc->irq_data);
> -

    Same question about bisectability here...

WBR, Sergei

^ permalink raw reply

* [PATCH 0/3] arm: support pmu irq routed from CTI
From: tom.leiming at gmail.com @ 2011-03-01 13:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This patches support pmu irq routed from CTI, such as implemented
on OMAP4:

	- introduce some CTI helpers and registers' definition
	- introduce platform_data to pmu driver, so perf irq handler
	can handle irq correctly if it is routed from CTI
	- configure CTI on OMAP4 so that perf can work on OMAP4

The patches have been tested Ok on Pandaboard, and 'perf' does work
after applying them.


 arch/arm/include/asm/cti.h    |  177 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/include/asm/pmu.h    |   12 +++
 arch/arm/kernel/perf_event.c  |   51 ++++++++++--
 arch/arm/mach-omap2/devices.c |   54 ++++++++++++-
 4 files changed, 286 insertions(+), 8 deletions(-)

thanks,
Ming Lei

^ permalink raw reply

* [PATCH 1/3] arm: introduce cross trigger interface helpers
From: tom.leiming at gmail.com @ 2011-03-01 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298985434-3009-1-git-send-email-tom.leiming@gmail.com>

From: Ming Lei <tom.leiming@gmail.com>

OMAP4 uses cross trigger interface(CTI) to route
performance monitor irq to GIC, so introduce cti
helpers to make access for cti easily.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 arch/arm/include/asm/cti.h |  177 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 177 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/include/asm/cti.h

diff --git a/arch/arm/include/asm/cti.h b/arch/arm/include/asm/cti.h
new file mode 100644
index 0000000..c9addd3
--- /dev/null
+++ b/arch/arm/include/asm/cti.h
@@ -0,0 +1,177 @@
+/*
+ *  arch/arm/include/asm/cti.h
+ */
+#ifndef __ASMARM_CTI_H
+#define __ASMARM_CTI_H
+
+#include	<asm/io.h>
+
+/*The registers' definition is from section 3.2 of
+ * 	Embedded Cross Trigger Revision: r0p0
+ **/
+#define		CTICONTROL		0x000
+#define		CTISTATUS		0x004
+#define		CTILOCK			0x008
+#define		CTIPROTECTION		0x00C
+#define		CTIINTACK		0x010
+#define		CTIAPPSET		0x014
+#define		CTIAPPCLEAR		0x018
+#define		CTIAPPPULSE		0x01c
+#define		CTIINEN			0x020
+#define		CTIOUTEN		0x0A0
+#define		CTITRIGINSTATUS		0x130
+#define		CTITRIGOUTSTATUS	0x134
+#define		CTICHINSTATUS		0x138
+#define		CTICHOUTSTATUS		0x13c
+#define		CTIPERIPHID0		0xFE0
+#define		CTIPERIPHID1		0xFE4
+#define		CTIPERIPHID2		0xFE8
+#define		CTIPERIPHID3		0xFEC
+#define		CTIPCELLID0		0xFF0
+#define		CTIPCELLID1		0xFF4
+#define		CTIPCELLID2		0xFF8
+#define		CTIPCELLID3		0xFFC
+
+/*The two below are from section 3.6.4 of
+ * 	CoreSight v1.0 Architecture Specification
+ **/
+#define		LOCKACCESS		0xFB0
+#define		LOCKSTATUS		0xFB4
+
+/**
+ * struct cti - cross trigger interface struct
+ * @base: mapped virtual address for the cti base
+ * @irq: irq number for the cti
+ * @trig_out_for_irq: triger out number which will cause
+ * 	the @irq happen
+ *
+ * cti struct used to operate cti registers.
+ */
+struct cti {
+	void *base;
+	int irq;
+	int trig_out_for_irq;
+};
+
+/**
+ * cti_init - initialize the cti instance
+ * @cti: cti instance
+ * @base: mapped virtual address for the cti base
+ * @irq: irq number for the cti
+ * @trig_out: triger out number which will cause
+ * 	the @irq happen
+ *
+ * called by machine code to pass the board dependent
+ * @base, @irq and @trig_out to cti.
+ */
+static inline void cti_init(struct cti *cti,
+	void *base, int irq, int trig_out)
+{
+	cti->base = base;
+	cti->irq  = irq;
+	cti->trig_out_for_irq = trig_out;
+}
+
+/**
+ * cti_map_trigger - use the @chan to map @trig_in to @trig_out
+ * @cti: cti instance
+ * @trig_in: trigger in number
+ * @trig_out: trigger out number
+ * @channel: channel number
+ *
+ * This function maps one trigger in of @trig_in to one trigger
+ * out of @trig_out using the channel @chan.
+ */
+static inline void cti_map_trigger(struct cti *cti,
+	int trig_in, int trig_out, int chan)
+{
+	void *base = cti->base;
+	unsigned long val;
+
+	val = __raw_readl(base + CTIINEN + trig_in * 4);
+	val |= 1 << chan;
+	__raw_writel(val, base + CTIINEN + trig_in * 4);
+
+	val = __raw_readl(base + CTIOUTEN + trig_out * 4);
+	val |= 1 << chan;
+	__raw_writel(val, base + CTIOUTEN + trig_out * 4);
+}
+
+/**
+ * cti_enable - enable the cti module
+ * @cti: cti instance
+ *
+ * enable the cti module
+ */
+static inline void cti_enable(struct cti *cti)
+{
+	__raw_writel(0x1, cti->base);
+}
+
+/**
+ * cti_disable - disable the cti module
+ * @cti: cti instance
+ *
+ * enable the cti module
+ */
+static inline void cti_disable(struct cti *cti)
+{
+	__raw_writel(0, cti->base);
+}
+
+/**
+ * cti_irq_ack - clear the cti irq
+ * @cti: cti instance
+ *
+ * clear the cti irq
+ */
+static inline void cti_irq_ack(struct cti *cti)
+{
+	void *base = cti->base;
+	unsigned long val;
+
+	val = __raw_readl(base + CTIINTACK);
+	val |= 1 << cti->trig_out_for_irq;
+	__raw_writel(val, base + CTIINTACK);
+}
+
+/**
+ * cti_unlock - unlock cti module
+ * @cti: cti instance
+ *
+ * unlock the cti module, or else any writes to the cti
+ * module is not allowed.
+ */
+static inline void cti_unlock(struct cti *cti)
+{
+	void *base = cti->base;
+	unsigned long val;
+
+	val = __raw_readl(base + LOCKSTATUS);
+
+	if (val & 1) {
+		val = 0xC5ACCE55;
+		__raw_writel(val, base + LOCKACCESS);
+	}
+}
+
+/**
+ * cti_unlock - lock cti module
+ * @cti: cti instance
+ *
+ * lock the cti module, so any writes to the cti
+ * module will be not allowed.
+ */
+static inline void cti_lock(struct cti *cti)
+{
+	void *base = cti->base;
+	unsigned long val;
+
+	val = __raw_readl(base + LOCKSTATUS);
+
+	if (!(val & 1)) {
+		val = ~0xC5ACCE55;
+		__raw_writel(val, base + LOCKACCESS);
+	}
+}
+#endif
-- 
1.7.3

^ permalink raw reply related

* [PATCH 2/3] arm: pmu: support pmu irq routed from CTI
From: tom.leiming at gmail.com @ 2011-03-01 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298985434-3009-1-git-send-email-tom.leiming@gmail.com>

From: Ming Lei <tom.leiming@gmail.com>

This patch introduces pmu_platform_data struct to
support pmu irq routed from CTI, such as implemented
on OMAP4.

Generally speaking, clearing cti irq should be done in
irq handler, also enabling cti module after calling
request_irq and disabling cti module before calling
free_irq.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
 arch/arm/include/asm/pmu.h   |   12 ++++++++++
 arch/arm/kernel/perf_event.c |   51 ++++++++++++++++++++++++++++++++++++-----
 2 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 8ccea012..afb879e 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -12,11 +12,23 @@
 #ifndef __ARM_PMU_H__
 #define __ARM_PMU_H__
 
+#include <asm/cti.h>
+
 enum arm_pmu_type {
 	ARM_PMU_DEVICE_CPU	= 0,
 	ARM_NUM_PMU_DEVICES,
 };
 
+#define MAX_CTI_NUM  4
+/*If the irq of pmu is routed from CTI, the pmu_platfrom_data
+ * instance must be passed to pmu driver via platform_data of
+ * platform_devic.dev*/
+struct pmu_platform_data {
+	int use_cti_irq;
+	int cti_cnt;
+	struct cti cti[MAX_CTI_NUM];
+};
+
 #ifdef CONFIG_CPU_HAS_PMU
 
 /**
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index d150ad1..85791b0 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -377,10 +377,38 @@ validate_group(struct perf_event *event)
 	return 0;
 }
 
+static inline int cti_irq(struct pmu_platform_data *data)
+{
+	return data && data->use_cti_irq;
+}
+
+static inline struct cti *irq_to_cti(struct pmu_platform_data *data,
+	int irq)
+{
+	int idx;
+
+	for(idx = 0; idx < data->cti_cnt; idx++)
+		if (data->cti[idx].irq == irq)
+			return &data->cti[idx];
+	return NULL;
+}
+
+static inline irqreturn_t armpmu_handle_irq(int irq_num, void *dev)
+{
+	struct pmu_platform_data *data = dev;
+
+	if (cti_irq(data))
+		cti_irq_ack(irq_to_cti(data, irq_num));
+
+	return armpmu->handle_irq(irq_num, NULL);
+}
+
+
 static int
 armpmu_reserve_hardware(void)
 {
 	int i, err = -ENODEV, irq;
+	struct pmu_platform_data *data;
 
 	pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
 	if (IS_ERR(pmu_device)) {
@@ -395,26 +423,31 @@ armpmu_reserve_hardware(void)
 		return -ENODEV;
 	}
 
+	data = pmu_device->dev.platform_data;
 	for (i = 0; i < pmu_device->num_resources; ++i) {
 		irq = platform_get_irq(pmu_device, i);
 		if (irq < 0)
 			continue;
 
-		err = request_irq(irq, armpmu->handle_irq,
+		err = request_irq(irq, armpmu_handle_irq,
 				  IRQF_DISABLED | IRQF_NOBALANCING,
-				  "armpmu", NULL);
+				  "armpmu", data);
 		if (err) {
 			pr_warning("unable to request IRQ%d for ARM perf "
 				"counters\n", irq);
 			break;
-		}
+		} else if (cti_irq(data))
+			cti_enable(irq_to_cti(data, irq));
 	}
 
 	if (err) {
 		for (i = i - 1; i >= 0; --i) {
 			irq = platform_get_irq(pmu_device, i);
-			if (irq >= 0)
-				free_irq(irq, NULL);
+			if (irq >= 0) {
+				if (cti_irq(data))
+					cti_enable(irq_to_cti(data, irq));
+				free_irq(irq, data);
+			}
 		}
 		release_pmu(pmu_device);
 		pmu_device = NULL;
@@ -427,11 +460,15 @@ static void
 armpmu_release_hardware(void)
 {
 	int i, irq;
+	struct pmu_platform_data *data = pmu_device->dev.platform_data;
 
 	for (i = pmu_device->num_resources - 1; i >= 0; --i) {
 		irq = platform_get_irq(pmu_device, i);
-		if (irq >= 0)
-			free_irq(irq, NULL);
+		if (irq >= 0) {
+			if (cti_irq(data))
+				cti_enable(irq_to_cti(data, irq));
+			free_irq(irq, data);
+		}
 	}
 	armpmu->stop();
 
-- 
1.7.3

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox