Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 04/14] mtd: nand: omap: read nand using register address
From: Afzal Mohammed @ 2012-10-08  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

Now that gpmc-nand registers are available in driver, use it
to read nand data.

"65b97cf  mtd: nand: omap2: handle nand on gpmc" modified all
other instances. After initial versions of that patch, a new
change added reading nand data using gpmc exposed function.
In the final version this change was not taken care.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/nand/omap2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 4c33135..abfc602 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -996,7 +996,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 		cond_resched();
 	}
 
-	status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
+	status = readb(info->reg.gpmc_nand_data);
 	return status;
 }
 
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 05/14] ARM: OMAP2+: onenand: connected soc info in pdata
From: Afzal Mohammed @ 2012-10-08  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

onenand driver needs to know whether soc is falling under
34xx family to properly handle onenand. But driver is not
supposed to do cpu_is_* check, hence educate platform data
with this information. Driver can make use of it to avoid
cpu_is_* check.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-onenand.c              | 5 +++++
 include/linux/platform_data/mtd-onenand-omap2.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 544d501..f0b677a 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -409,6 +409,11 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 	}
 
+	if (cpu_is_omap34xx())
+		gpmc_onenand_data->flags |= ONENAND_IN_OMAP34XX;
+	else
+		gpmc_onenand_data->flags &= ~ONENAND_IN_OMAP34XX;
+
 	err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
 				(unsigned long *)&gpmc_onenand_resource.start);
 	if (err < 0) {
diff --git a/include/linux/platform_data/mtd-onenand-omap2.h b/include/linux/platform_data/mtd-onenand-omap2.h
index 21bb0ff..ef9c60d 100644
--- a/include/linux/platform_data/mtd-onenand-omap2.h
+++ b/include/linux/platform_data/mtd-onenand-omap2.h
@@ -14,6 +14,7 @@
 
 #define ONENAND_SYNC_READ	(1 << 0)
 #define ONENAND_SYNC_READWRITE	(1 << 1)
+#define	ONENAND_IN_OMAP34XX	(1 << 2)
 
 struct omap_onenand_platform_data {
 	int			cs;
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 06/14] mtd: onenand: omap: use pdata info instead of cpu_is
From: Afzal Mohammed @ 2012-10-08  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

platform data now contains a field to indicate whether
soc belongs to omap34xx family, use it instead of
cpu_is_* check.

This helps in removing dependency of platform specific
header file - cpu.h

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/onenand/omap2.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index d7ef2c9..959f465 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -42,7 +42,6 @@
 #include <asm/gpio.h>
 
 #include <plat/dma.h>
-#include <plat/cpu.h>
 
 #define DRIVER_NAME "omap2-onenand"
 
@@ -62,6 +61,7 @@ struct omap2_onenand {
 	int freq;
 	int (*setup)(void __iomem *base, int *freq_ptr);
 	struct regulator *regulator;
+	u8 flags;
 };
 
 static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
@@ -154,7 +154,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
 		if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
 			syscfg |= ONENAND_SYS_CFG1_IOBE;
 			write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
-			if (cpu_is_omap34xx())
+			if (c->flags & ONENAND_IN_OMAP34XX)
 				/* Add a delay to let GPIO settle */
 				syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
 		}
@@ -638,6 +638,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 
 	init_completion(&c->irq_done);
 	init_completion(&c->dma_done);
+	c->flags = pdata->flags;
 	c->gpmc_cs = pdata->cs;
 	c->gpio_irq = pdata->gpio_irq;
 	c->dma_channel = pdata->dma_channel;
@@ -728,7 +729,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	this = &c->onenand;
 	if (c->dma_channel >= 0) {
 		this->wait = omap2_onenand_wait;
-		if (cpu_is_omap34xx()) {
+		if (c->flags & ONENAND_IN_OMAP34XX) {
 			this->read_bufferram = omap3_onenand_read_bufferram;
 			this->write_bufferram = omap3_onenand_write_bufferram;
 		} else {
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 07/14] ARM: OMAP2+: onenand: header cleanup
From: Afzal Mohammed @ 2012-10-08  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

For common arm zImage existing onenand header file
in platform specific location was moved to generic
platform data location, but it contained more than
platform data, remove it. New local header has been
created for exposing functions.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-flash.c               |  1 +
 arch/arm/mach-omap2/board-igep0020.c            |  1 +
 arch/arm/mach-omap2/board-n8x0.c                |  1 +
 arch/arm/mach-omap2/board-rm680.c               |  1 +
 arch/arm/mach-omap2/board-rx51-peripherals.c    |  1 +
 arch/arm/mach-omap2/gpmc-onenand.c              |  1 +
 arch/arm/mach-omap2/gpmc-onenand.h              | 24 ++++++++++++++++++++++++
 include/linux/platform_data/mtd-onenand-omap2.h | 19 +++----------------
 8 files changed, 33 insertions(+), 16 deletions(-)
 create mode 100644 arch/arm/mach-omap2/gpmc-onenand.h

diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index f8b30cb..de68fdf 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -25,6 +25,7 @@
 
 #include "common.h"
 #include "board-flash.h"
+#include "gpmc-onenand.h"
 
 #define REG_FPGA_REV			0x10
 #define REG_FPGA_DIP_SWITCH_INPUT2	0x60
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index f6b3ed0..83c6efa 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -43,6 +43,7 @@
 #include "common-board-devices.h"
 #include "board-flash.h"
 #include "control.h"
+#include "gpmc-onenand.h"
 
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index d95f727..92b1916 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -32,6 +32,7 @@
 #include <plat/mmc.h>
 
 #include "mux.h"
+#include "gpmc-onenand.h"
 
 #define TUSB6010_ASYNC_CS	1
 #define TUSB6010_SYNC_CS	4
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 45997bf..154cf33 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -33,6 +33,7 @@
 #include "hsmmc.h"
 #include "sdram-nokia.h"
 #include "common-board-devices.h"
+#include "gpmc-onenand.h"
 
 static struct regulator_consumer_supply rm680_vemmc_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index ed85fb8..aa6a2a4 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -54,6 +54,7 @@
 #include "mux.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
+#include "gpmc-onenand.h"
 
 #define SYSTEM_REV_B_USES_VAUX3	0x1699
 #define SYSTEM_REV_S_USES_VAUX3 0x8
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index f0b677a..29671cc 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -23,6 +23,7 @@
 #include <plat/gpmc.h>
 
 #include "soc.h"
+#include "gpmc-onenand.h"
 
 #define	ONENAND_IO_SIZE	SZ_128K
 
diff --git a/arch/arm/mach-omap2/gpmc-onenand.h b/arch/arm/mach-omap2/gpmc-onenand.h
new file mode 100644
index 0000000..216f23a
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc-onenand.h
@@ -0,0 +1,24 @@
+/*
+ *  arch/arm/mach-omap2/gpmc-onenand.h
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef	__OMAP2_GPMC_ONENAND_H
+#define	__OMAP2_GPMC_ONENAND_H
+
+#include <linux/platform_data/mtd-onenand-omap2.h>
+
+#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2)
+extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
+#else
+#define board_onenand_data	NULL
+static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
+{
+}
+#endif
+
+#endif
diff --git a/include/linux/platform_data/mtd-onenand-omap2.h b/include/linux/platform_data/mtd-onenand-omap2.h
index ef9c60d..685af7e 100644
--- a/include/linux/platform_data/mtd-onenand-omap2.h
+++ b/include/linux/platform_data/mtd-onenand-omap2.h
@@ -9,6 +9,9 @@
  * published by the Free Software Foundation.
  */
 
+#ifndef	__MTD_ONENAND_OMAP2_H
+#define	__MTD_ONENAND_OMAP2_H
+
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
@@ -27,20 +30,4 @@ struct omap_onenand_platform_data {
 	u8			regulator_can_sleep;
 	u8			skip_initial_unlocking;
 };
-
-#define ONENAND_MAX_PARTITIONS 8
-
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
-	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
-
-extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
-
-#else
-
-#define board_onenand_data	NULL
-
-static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
-{
-}
-
 #endif
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 08/14] ARM: OMAP2+: nand: header cleanup
From: Afzal Mohammed @ 2012-10-08  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

For common arm zImage existing nand header file
in platform specific location was moved to generic
platform data location, but it contained more than
platform data, remove it. New local header has been
created for exposing functions.

Also move gpmc-nand platform data to platform header
meant for nand from gpmc header file

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-cm-t35.c           |  3 +-
 arch/arm/mach-omap2/board-cm-t3517.c         |  3 +-
 arch/arm/mach-omap2/board-flash.c            |  4 +--
 arch/arm/mach-omap2/board-omap3pandora.c     |  3 +-
 arch/arm/mach-omap2/common-board-devices.c   |  1 -
 arch/arm/mach-omap2/gpmc-nand.c              | 54 +++++++++++++++-------------
 arch/arm/mach-omap2/gpmc-nand.h              | 27 ++++++++++++++
 arch/arm/mach-omap2/gpmc.c                   |  2 ++
 arch/arm/plat-omap/include/plat/gpmc.h       | 28 ++-------------
 include/linux/platform_data/mtd-nand-omap2.h | 41 ++++++++++++++-------
 10 files changed, 98 insertions(+), 68 deletions(-)
 create mode 100644 arch/arm/mach-omap2/gpmc-nand.h

diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 376d26e..fef68de 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -53,6 +53,7 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
+#include "gpmc-nand.h"
 
 #define CM_T35_GPIO_PENDOWN		57
 #define SB_T35_USB_HUB_RESET_GPIO	167
@@ -181,7 +182,7 @@ static struct omap_nand_platform_data cm_t35_nand_data = {
 
 static void __init cm_t35_init_nand(void)
 {
-	if (gpmc_nand_init(&cm_t35_nand_data) < 0)
+	if (gpmc_nand_init(&cm_t35_nand_data, NULL) < 0)
 		pr_err("CM-T35: Unable to register NAND device\n");
 }
 #else
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 59c0a45..3a19e80 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -49,6 +49,7 @@
 #include "control.h"
 #include "common-board-devices.h"
 #include "am35xx-emac.h"
+#include "gpmc-nand.h"
 
 #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
 static struct gpio_led cm_t3517_leds[] = {
@@ -240,7 +241,7 @@ static struct omap_nand_platform_data cm_t3517_nand_data = {
 
 static void __init cm_t3517_init_nand(void)
 {
-	if (gpmc_nand_init(&cm_t3517_nand_data) < 0)
+	if (gpmc_nand_init(&cm_t3517_nand_data, NULL) < 0)
 		pr_err("CM-T3517: NAND initialization failed\n");
 }
 #else
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index de68fdf..776e57a 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -26,6 +26,7 @@
 #include "common.h"
 #include "board-flash.h"
 #include "gpmc-onenand.h"
+#include "gpmc-nand.h"
 
 #define REG_FPGA_REV			0x10
 #define REG_FPGA_DIP_SWITCH_INPUT2	0x60
@@ -139,10 +140,9 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
 	board_nand_data.parts		= nand_parts;
 	board_nand_data.nr_parts	= nr_parts;
 	board_nand_data.devsize		= nand_type;
-	board_nand_data.gpmc_t		= gpmc_t;
 
 	board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
-	gpmc_nand_init(&board_nand_data);
+	gpmc_nand_init(&board_nand_data, gpmc_t);
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
 
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 00a1f4a..f286b4b 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -50,6 +50,7 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
+#include "gpmc-nand.h"
 
 #define PANDORA_WIFI_IRQ_GPIO		21
 #define PANDORA_WIFI_NRESET_GPIO	23
@@ -602,7 +603,7 @@ static void __init omap3pandora_init(void)
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
 	usbhs_init(&usbhs_bdata);
 	usb_musb_init(NULL);
-	gpmc_nand_init(&pandora_nand_data);
+	gpmc_nand_init(&pandora_nand_data, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 90e0597..ad85609 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -25,7 +25,6 @@
 #include <linux/spi/ads7846.h>
 
 #include <linux/platform_data/spi-omap2-mcspi.h>
-#include <linux/platform_data/mtd-nand-omap2.h>
 
 #include "common.h"
 #include "common-board-devices.h"
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 4eceaca..c1b9b1d 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -20,6 +20,10 @@
 #include <plat/gpmc.h>
 
 #include "soc.h"
+#include "gpmc-nand.h"
+
+/* minimum size for IO mapping */
+#define	NAND_IO_SIZE	4
 
 static struct resource gpmc_nand_resource[] = {
 	{
@@ -40,37 +44,36 @@ static struct platform_device gpmc_nand_device = {
 	.resource	= gpmc_nand_resource,
 };
 
-static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
+static int omap2_nand_gpmc_retime(
+				struct omap_nand_platform_data *gpmc_nand_data,
+				struct gpmc_timings *gpmc_t)
 {
 	struct gpmc_timings t;
 	int err;
 
-	if (!gpmc_nand_data->gpmc_t)
-		return 0;
-
 	memset(&t, 0, sizeof(t));
-	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
-	t.cs_on = gpmc_nand_data->gpmc_t->cs_on;
-	t.adv_on = gpmc_nand_data->gpmc_t->adv_on;
+	t.sync_clk = gpmc_t->sync_clk;
+	t.cs_on = gpmc_t->cs_on;
+	t.adv_on = gpmc_t->adv_on;
 
 	/* Read */
-	t.adv_rd_off = gpmc_nand_data->gpmc_t->adv_rd_off;
+	t.adv_rd_off = gpmc_t->adv_rd_off;
 	t.oe_on  = t.adv_on;
-	t.access = gpmc_nand_data->gpmc_t->access;
-	t.oe_off = gpmc_nand_data->gpmc_t->oe_off;
-	t.cs_rd_off = gpmc_nand_data->gpmc_t->cs_rd_off;
-	t.rd_cycle = gpmc_nand_data->gpmc_t->rd_cycle;
+	t.access = gpmc_t->access;
+	t.oe_off = gpmc_t->oe_off;
+	t.cs_rd_off = gpmc_t->cs_rd_off;
+	t.rd_cycle = gpmc_t->rd_cycle;
 
 	/* Write */
-	t.adv_wr_off = gpmc_nand_data->gpmc_t->adv_wr_off;
+	t.adv_wr_off = gpmc_t->adv_wr_off;
 	t.we_on  = t.oe_on;
 	if (cpu_is_omap34xx()) {
-		t.wr_data_mux_bus = gpmc_nand_data->gpmc_t->wr_data_mux_bus;
-		t.wr_access = gpmc_nand_data->gpmc_t->wr_access;
+		t.wr_data_mux_bus = gpmc_t->wr_data_mux_bus;
+		t.wr_access = gpmc_t->wr_access;
 	}
-	t.we_off = gpmc_nand_data->gpmc_t->we_off;
-	t.cs_wr_off = gpmc_nand_data->gpmc_t->cs_wr_off;
-	t.wr_cycle = gpmc_nand_data->gpmc_t->wr_cycle;
+	t.we_off = gpmc_t->we_off;
+	t.cs_wr_off = gpmc_t->cs_wr_off;
+	t.wr_cycle = gpmc_t->wr_cycle;
 
 	/* Configure GPMC */
 	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
@@ -87,7 +90,8 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data
 	return 0;
 }
 
-int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
+int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
+			  struct gpmc_timings *gpmc_t)
 {
 	int err	= 0;
 	struct device *dev = &gpmc_nand_device.dev;
@@ -108,11 +112,13 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 				gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
 	gpmc_nand_resource[2].start =
 				gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
-	 /* Set timings in GPMC */
-	err = omap2_nand_gpmc_retime(gpmc_nand_data);
-	if (err < 0) {
-		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
-		return err;
+
+	if (gpmc_t) {
+		err = omap2_nand_gpmc_retime(gpmc_nand_data, gpmc_t);
+		if (err < 0) {
+			dev_err(dev, "Unable to set gpmc timings: %d\n", err);
+			return err;
+		}
 	}
 
 	/* Enable RD PIN Monitoring Reg */
diff --git a/arch/arm/mach-omap2/gpmc-nand.h b/arch/arm/mach-omap2/gpmc-nand.h
new file mode 100644
index 0000000..11a377f
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc-nand.h
@@ -0,0 +1,27 @@
+/*
+ *  arch/arm/mach-omap2/gpmc-nand.h
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef	__OMAP2_GPMC_NAND_H
+#define	__OMAP2_GPMC_NAND_H
+
+#include <plat/gpmc.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
+
+#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2)
+extern int gpmc_nand_init(struct omap_nand_platform_data *d,
+			  struct gpmc_timings *gpmc_t);
+#else
+static inline int gpmc_nand_init(struct omap_nand_platform_data *d,
+				 struct gpmc_timings *gpmc_t)
+{
+	return 0;
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 163458d..3a73196 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -26,6 +26,8 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 
+#include <linux/platform_data/mtd-nand-omap2.h>
+
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
 
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 1cafbfd..17fc1e7 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -11,6 +11,8 @@
 #ifndef __OMAP2_GPMC_H
 #define __OMAP2_GPMC_H
 
+#include <linux/platform_data/mtd-nand-omap2.h>
+
 /* Maximum Number of Chip Selects */
 #define GPMC_CS_NUM		8
 
@@ -86,16 +88,6 @@
 #define PREFETCH_FIFOTHRESHOLD_MAX	0x40
 #define PREFETCH_FIFOTHRESHOLD(val)	((val) << 8)
 
-enum omap_ecc {
-		/* 1-bit ecc: stored at end of spare area */
-	OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */
-	OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */
-		/* 1-bit ecc: stored@beginning of spare area as romcode */
-	OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
-	OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */
-	OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */
-};
-
 /* bool type time settings */
 struct gpmc_bool_timings {
 	bool cycle2cyclediffcsen;
@@ -152,22 +144,6 @@ struct gpmc_timings {
 	struct gpmc_bool_timings bool_timings;
 };
 
-struct gpmc_nand_regs {
-	void __iomem	*gpmc_status;
-	void __iomem	*gpmc_nand_command;
-	void __iomem	*gpmc_nand_address;
-	void __iomem	*gpmc_nand_data;
-	void __iomem	*gpmc_prefetch_config1;
-	void __iomem	*gpmc_prefetch_config2;
-	void __iomem	*gpmc_prefetch_control;
-	void __iomem	*gpmc_prefetch_status;
-	void __iomem	*gpmc_ecc_config;
-	void __iomem	*gpmc_ecc_control;
-	void __iomem	*gpmc_ecc_size_config;
-	void __iomem	*gpmc_ecc1_result;
-	void __iomem	*gpmc_bch_result0;
-};
-
 extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
 extern int gpmc_get_client_irq(unsigned irq_config);
 
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 1a68c1e..e1965fe 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -8,7 +8,9 @@
  * published by the Free Software Foundation.
  */
 
-#include <plat/gpmc.h>
+#ifndef	_MTD_NAND_OMAP2_H
+#define	_MTD_NAND_OMAP2_H
+
 #include <linux/mtd/partitions.h>
 
 enum nand_io {
@@ -18,10 +20,35 @@ enum nand_io {
 	NAND_OMAP_PREFETCH_IRQ		/* prefetch enabled irq mode */
 };
 
+enum omap_ecc {
+		/* 1-bit ecc: stored at end of spare area */
+	OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */
+	OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */
+		/* 1-bit ecc: stored at beginning of spare area as romcode */
+	OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
+	OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */
+	OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */
+};
+
+struct gpmc_nand_regs {
+	void __iomem	*gpmc_status;
+	void __iomem	*gpmc_nand_command;
+	void __iomem	*gpmc_nand_address;
+	void __iomem	*gpmc_nand_data;
+	void __iomem	*gpmc_prefetch_config1;
+	void __iomem	*gpmc_prefetch_config2;
+	void __iomem	*gpmc_prefetch_control;
+	void __iomem	*gpmc_prefetch_status;
+	void __iomem	*gpmc_ecc_config;
+	void __iomem	*gpmc_ecc_control;
+	void __iomem	*gpmc_ecc_size_config;
+	void __iomem	*gpmc_ecc1_result;
+	void __iomem	*gpmc_bch_result0;
+};
+
 struct omap_nand_platform_data {
 	int			cs;
 	struct mtd_partition	*parts;
-	struct gpmc_timings	*gpmc_t;
 	int			nr_parts;
 	bool			dev_ready;
 	enum nand_io		xfer_type;
@@ -30,14 +57,4 @@ struct omap_nand_platform_data {
 	struct gpmc_nand_regs	reg;
 };
 
-/* minimum size for IO mapping */
-#define	NAND_IO_SIZE	4
-
-#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern int gpmc_nand_init(struct omap_nand_platform_data *d);
-#else
-static inline int gpmc_nand_init(struct omap_nand_platform_data *d)
-{
-	return 0;
-}
 #endif
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 09/14] mtd: nand: omap: bring in gpmc nand macros
From: Afzal Mohammed @ 2012-10-08  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

Bring onto driver the macros defined in gpmc.h that are
not necessary outside driver, helps in removing inclusion
of gpmc.h too. Also remove GPMC prefix on those macros to
make clear it's independence with gpmc header.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/nand/omap2.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index abfc602..f0a1b1d 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -110,6 +110,11 @@
 #define	ECC1RESULTSIZE			0x1
 #define	ECCCLEAR			0x100
 #define	ECC1				0x1
+#define	PREFETCH_FIFOTHRESHOLD_MAX	0x40
+#define	PREFETCH_FIFOTHRESHOLD(val)	((val) << 8)
+#define	PREFETCH_STATUS_COUNT(val)	(val & 0x00003fff)
+#define	PREFETCH_STATUS_FIFO_CNT(val)	((val >> 24) & 0x7F)
+#define	STATUS_BUFF_EMPTY		0x00000001
 
 /* oob info generated runtime depending on ecc algorithm and layout selected */
 static struct nand_ecclayout omap_oobinfo;
@@ -269,7 +274,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
 		/* wait until buffer is available for write */
 		do {
 			status = readl(info->reg.gpmc_status) &
-					GPMC_STATUS_BUFF_EMPTY;
+					STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -307,7 +312,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
 		/* wait until buffer is available for write */
 		do {
 			status = readl(info->reg.gpmc_status) &
-					GPMC_STATUS_BUFF_EMPTY;
+					STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -348,7 +353,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 	} else {
 		do {
 			r_count = readl(info->reg.gpmc_prefetch_status);
-			r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
+			r_count = PREFETCH_STATUS_FIFO_CNT(r_count);
 			r_count = r_count >> 2;
 			ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
 			p += r_count;
@@ -395,7 +400,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	} else {
 		while (len) {
 			w_count = readl(info->reg.gpmc_prefetch_status);
-			w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
+			w_count = PREFETCH_STATUS_FIFO_CNT(w_count);
 			w_count = w_count >> 1;
 			for (i = 0; (i < w_count) && len; i++, len -= 2)
 				iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -407,7 +412,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 		do {
 			cpu_relax();
 			val = readl(info->reg.gpmc_prefetch_status);
-			val = GPMC_PREFETCH_STATUS_COUNT(val);
+			val = PREFETCH_STATUS_COUNT(val);
 		} while (val && (tim++ < limit));
 
 		/* disable and stop the PFPW engine */
@@ -493,7 +498,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	do {
 		cpu_relax();
 		val = readl(info->reg.gpmc_prefetch_status);
-		val = GPMC_PREFETCH_STATUS_COUNT(val);
+		val = PREFETCH_STATUS_COUNT(val);
 	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
@@ -556,7 +561,7 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 	u32 bytes;
 
 	bytes = readl(info->reg.gpmc_prefetch_status);
-	bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
+	bytes = PREFETCH_STATUS_FIFO_CNT(bytes);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
 		if (this_irq == info->gpmc_irq_count)
@@ -682,7 +687,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
 	do {
 		val = readl(info->reg.gpmc_prefetch_status);
-		val = GPMC_PREFETCH_STATUS_COUNT(val);
+		val = PREFETCH_STATUS_COUNT(val);
 		cpu_relax();
 	} while (val && (tim++ < limit));
 
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 10/14] ARM: OMAP2+: nand: bch capability check
From: Afzal Mohammed @ 2012-10-08  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

Capability of bch schemes could be discovered using soc
revision checks. If soc revision indicates that selected
ecc scheme is not supported bail out.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc-nand.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index c1b9b1d..7983d54 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -90,6 +90,27 @@ static int omap2_nand_gpmc_retime(
 	return 0;
 }
 
+static bool __init gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
+{
+	/* support only OMAP3 class */
+	if (!cpu_is_omap34xx()) {
+		pr_err("BCH ecc is not supported on this CPU\n");
+		return 0;
+	}
+
+	/*
+	 * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1.
+	 * Other chips may be added if confirmed to work.
+	 */
+	if ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) &&
+	    (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) {
+		pr_err("BCH 4-bit mode is not supported on this CPU\n");
+		return 0;
+	}
+
+	return 1;
+}
+
 int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 			  struct gpmc_timings *gpmc_t)
 {
@@ -128,6 +149,9 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 
 	gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
 
+	if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt))
+		return -EINVAL;
+
 	err = platform_device_register(&gpmc_nand_device);
 	if (err < 0) {
 		dev_err(dev, "Unable to register NAND device\n");
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 11/14] ARM: OMAP2+: gpmc: nand register helper bch update
From: Afzal Mohammed @ 2012-10-08  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

Update helper function that provides gpmc-nand register
details for nand driver with bch register information.
Using this nand driver can be made self sufficient to
handle remaining gpmc-nand operations by itself instead
of relying on gpmc exported nand functions.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c                   | 18 +++++++++++++++++-
 include/linux/platform_data/mtd-nand-omap2.h |  7 ++++++-
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 3a73196..eb577c5 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -61,6 +61,9 @@
 #define GPMC_ECC_SIZE_CONFIG	0x1fc
 #define GPMC_ECC1_RESULT        0x200
 #define GPMC_ECC_BCH_RESULT_0   0x240   /* not available on OMAP2 */
+#define	GPMC_ECC_BCH_RESULT_1	0x244	/* not available on OMAP2 */
+#define	GPMC_ECC_BCH_RESULT_2	0x248	/* not available on OMAP2 */
+#define	GPMC_ECC_BCH_RESULT_3	0x24c	/* not available on OMAP2 */
 
 /* GPMC ECC control settings */
 #define GPMC_ECC_CTRL_ECCCLEAR		0x100
@@ -84,6 +87,7 @@
 
 #define GPMC_CS0_OFFSET		0x60
 #define GPMC_CS_SIZE		0x30
+#define	GPMC_BCH_SIZE		0x10
 
 #define GPMC_MEM_START		0x00000000
 #define GPMC_MEM_END		0x3FFFFFFF
@@ -779,6 +783,8 @@ EXPORT_SYMBOL(gpmc_prefetch_reset);
 
 void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 {
+	int i;
+
 	reg->gpmc_status = gpmc_base + GPMC_STATUS;
 	reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET +
 				GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
@@ -794,7 +800,17 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 	reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL;
 	reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG;
 	reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT;
-	reg->gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0;
+
+	for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) {
+		reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
+					   GPMC_BCH_SIZE * i;
+	}
 }
 
 int gpmc_get_client_irq(unsigned irq_config)
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index e1965fe..24d32ca 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -13,6 +13,8 @@
 
 #include <linux/mtd/partitions.h>
 
+#define	GPMC_BCH_NUM_REMAINDER	8
+
 enum nand_io {
 	NAND_OMAP_PREFETCH_POLLED = 0,	/* prefetch polled mode, default */
 	NAND_OMAP_POLLED,		/* polled mode, without prefetch */
@@ -43,7 +45,10 @@ struct gpmc_nand_regs {
 	void __iomem	*gpmc_ecc_control;
 	void __iomem	*gpmc_ecc_size_config;
 	void __iomem	*gpmc_ecc1_result;
-	void __iomem	*gpmc_bch_result0;
+	void __iomem	*gpmc_bch_result0[GPMC_BCH_NUM_REMAINDER];
+	void __iomem	*gpmc_bch_result1[GPMC_BCH_NUM_REMAINDER];
+	void __iomem	*gpmc_bch_result2[GPMC_BCH_NUM_REMAINDER];
+	void __iomem	*gpmc_bch_result3[GPMC_BCH_NUM_REMAINDER];
 };
 
 struct omap_nand_platform_data {
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 12/14] mtd: nand: omap: handle gpmc bch[48]
From: Afzal Mohammed @ 2012-10-08  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

gpmc-nand bch registers are now available in driver,
make use of it to handle bch[48] instead of relying
on gpmc exported functions.

And so nand driver no longer needs gpmc header, remove it.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 drivers/mtd/nand/omap2.c | 100 +++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 89 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index f0a1b1d..3282b15 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -28,7 +28,6 @@
 #endif
 
 #include <plat/dma.h>
-#include <plat/gpmc.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
 
 #define	DRIVER_NAME	"omap2-nand"
@@ -106,6 +105,7 @@
 #define	CS_MASK				0x7
 #define	ENABLE_PREFETCH			(0x1 << 7)
 #define	DMA_MPU_MODE_SHIFT		2
+#define	ECCSIZE0_SHIFT			12
 #define	ECCSIZE1_SHIFT			22
 #define	ECC1RESULTSIZE			0x1
 #define	ECCCLEAR			0x100
@@ -1034,19 +1034,45 @@ static int omap_dev_ready(struct mtd_info *mtd)
 static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
 {
 	int nerrors;
-	unsigned int dev_width;
+	unsigned int dev_width, nsectors;
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
 	struct nand_chip *chip = mtd->priv;
+	u32 val;
 
 	nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4;
 	dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+	nsectors = 1;
 	/*
 	 * Program GPMC to perform correction on one 512-byte sector at a time.
 	 * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and
 	 * gives a slight (5%) performance gain (but requires additional code).
 	 */
-	(void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors);
+
+	writel(ECC1, info->reg.gpmc_ecc_control);
+
+	/*
+	 * When using BCH, sector size is hardcoded to 512 bytes.
+	 * Here we are using wrapping mode 6 both for reading and writing, with:
+	 *  size0 = 0  (no additional protected byte in spare area)
+	 *  size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
+	 */
+	val = (32 << ECCSIZE1_SHIFT) | (0 << ECCSIZE0_SHIFT);
+	writel(val, info->reg.gpmc_ecc_size_config);
+
+	/* BCH configuration */
+	val = ((1                        << 16) | /* enable BCH */
+	       (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
+	       (0x06                     <<  8) | /* wrap mode = 6 */
+	       (dev_width                <<  7) | /* bus width */
+	       (((nsectors-1) & 0x7)     <<  4) | /* number of sectors */
+	       (info->gpmc_cs            <<  1) | /* ECC CS */
+	       (0x1));                            /* enable ECC */
+
+	writel(val, info->reg.gpmc_ecc_config);
+
+	/* clear ecc and enable bits */
+	writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
 }
 
 /**
@@ -1060,7 +1086,32 @@ static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat,
 {
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
-	return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code);
+	unsigned long nsectors, val1, val2;
+	int i;
+
+	nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+	for (i = 0; i < nsectors; i++) {
+
+		/* Read hw-computed remainder */
+		val1 = readl(info->reg.gpmc_bch_result0[i]);
+		val2 = readl(info->reg.gpmc_bch_result1[i]);
+
+		/*
+		 * Add constant polynomial to remainder, in order to get an ecc
+		 * sequence of 0xFFs for a buffer filled with 0xFFs; and
+		 * left-justify the resulting polynomial.
+		 */
+		*ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF);
+		*ecc_code++ = 0x13 ^ ((val2 >>  4) & 0xFF);
+		*ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF));
+		*ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF);
+		*ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF);
+		*ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF);
+		*ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4);
+	}
+
+	return 0;
 }
 
 /**
@@ -1074,7 +1125,39 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
 {
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
-	return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code);
+	unsigned long nsectors, val1, val2, val3, val4;
+	int i;
+
+	nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+	for (i = 0; i < nsectors; i++) {
+
+		/* Read hw-computed remainder */
+		val1 = readl(info->reg.gpmc_bch_result0[i]);
+		val2 = readl(info->reg.gpmc_bch_result1[i]);
+		val3 = readl(info->reg.gpmc_bch_result2[i]);
+		val4 = readl(info->reg.gpmc_bch_result3[i]);
+
+		/*
+		 * Add constant polynomial to remainder, in order to get an ecc
+		 * sequence of 0xFFs for a buffer filled with 0xFFs.
+		 */
+		*ecc_code++ = 0xef ^ (val4 & 0xFF);
+		*ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF);
+		*ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF);
+		*ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF);
+		*ecc_code++ = 0xed ^ (val3 & 0xFF);
+		*ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF);
+		*ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF);
+		*ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
+		*ecc_code++ = 0x97 ^ (val2 & 0xFF);
+		*ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF);
+		*ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
+		*ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF);
+		*ecc_code++ = 0xb5 ^ (val1 & 0xFF);
+	}
+
+	return 0;
 }
 
 /**
@@ -1130,7 +1213,7 @@ static void omap3_free_bch(struct mtd_info *mtd)
  */
 static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
 {
-	int ret, max_errors;
+	int max_errors;
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 						   mtd);
 #ifdef CONFIG_MTD_NAND_OMAP_BCH8
@@ -1147,11 +1230,6 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
 		goto fail;
 	}
 
-	/* initialize GPMC BCH engine */
-	ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors);
-	if (ret)
-		goto fail;
-
 	/* software bch library is only used to detect and locate errors */
 	info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */);
 	if (!info->bch)
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 13/14] ARM: OMAP2+: gpmc: remove exported nand functions
From: Afzal Mohammed @ 2012-10-08  5:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

nand driver handles gpmc-nand block fully, hence no more
users for these exported nand functions, remove it.

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/gpmc.c             | 432 ---------------------------------
 arch/arm/plat-omap/include/plat/gpmc.h |  31 ---
 2 files changed, 463 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index eb577c5..1121248 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -150,7 +150,6 @@ static struct resource	gpmc_mem_root;
 static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
 static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
-static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
 static struct device *gpmc_dev;
 static int gpmc_irq;
 static resource_size_t phys_base, mem_size;
@@ -171,22 +170,6 @@ static u32 gpmc_read_reg(int idx)
 	return __raw_readl(gpmc_base + idx);
 }
 
-static void gpmc_cs_write_byte(int cs, int idx, u8 val)
-{
-	void __iomem *reg_addr;
-
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writeb(val, reg_addr);
-}
-
-static u8 gpmc_cs_read_byte(int cs, int idx)
-{
-	void __iomem *reg_addr;
-
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readb(reg_addr);
-}
-
 void gpmc_cs_write_reg(int cs, int idx, u32 val)
 {
 	void __iomem *reg_addr;
@@ -563,44 +546,6 @@ void gpmc_cs_free(int cs)
 EXPORT_SYMBOL(gpmc_cs_free);
 
 /**
- * gpmc_read_status - read access request to get the different gpmc status
- * @cmd: command type
- * @return status
- */
-int gpmc_read_status(int cmd)
-{
-	int	status = -EINVAL;
-	u32	regval = 0;
-
-	switch (cmd) {
-	case GPMC_GET_IRQ_STATUS:
-		status = gpmc_read_reg(GPMC_IRQSTATUS);
-		break;
-
-	case GPMC_PREFETCH_FIFO_CNT:
-		regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
-		status = GPMC_PREFETCH_STATUS_FIFO_CNT(regval);
-		break;
-
-	case GPMC_PREFETCH_COUNT:
-		regval = gpmc_read_reg(GPMC_PREFETCH_STATUS);
-		status = GPMC_PREFETCH_STATUS_COUNT(regval);
-		break;
-
-	case GPMC_STATUS_BUFFER:
-		regval = gpmc_read_reg(GPMC_STATUS);
-		/* 1 : buffer is available to write */
-		status = regval & GPMC_STATUS_BUFF_EMPTY;
-		break;
-
-	default:
-		printk(KERN_ERR "gpmc_read_status: Not supported\n");
-	}
-	return status;
-}
-EXPORT_SYMBOL(gpmc_read_status);
-
-/**
  * gpmc_cs_configure - write request to configure gpmc
  * @cs: chip select number
  * @cmd: command type
@@ -668,119 +613,6 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
 }
 EXPORT_SYMBOL(gpmc_cs_configure);
 
-/**
- * gpmc_nand_read - nand specific read access request
- * @cs: chip select number
- * @cmd: command type
- */
-int gpmc_nand_read(int cs, int cmd)
-{
-	int rval = -EINVAL;
-
-	switch (cmd) {
-	case GPMC_NAND_DATA:
-		rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA);
-		break;
-
-	default:
-		printk(KERN_ERR "gpmc_read_nand_ctrl: Not supported\n");
-	}
-	return rval;
-}
-EXPORT_SYMBOL(gpmc_nand_read);
-
-/**
- * gpmc_nand_write - nand specific write request
- * @cs: chip select number
- * @cmd: command type
- * @wval: value to write
- */
-int gpmc_nand_write(int cs, int cmd, int wval)
-{
-	int err = 0;
-
-	switch (cmd) {
-	case GPMC_NAND_COMMAND:
-		gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval);
-		break;
-
-	case GPMC_NAND_ADDRESS:
-		gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval);
-		break;
-
-	case GPMC_NAND_DATA:
-		gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval);
-
-	default:
-		printk(KERN_ERR "gpmc_write_nand_ctrl: Not supported\n");
-		err = -EINVAL;
-	}
-	return err;
-}
-EXPORT_SYMBOL(gpmc_nand_write);
-
-
-
-/**
- * gpmc_prefetch_enable - configures and starts prefetch transfer
- * @cs: cs (chip select) number
- * @fifo_th: fifo threshold to be used for read/ write
- * @dma_mode: dma mode enable (1) or disable (0)
- * @u32_count: number of bytes to be transferred
- * @is_write: prefetch read(0) or write post(1) mode
- */
-int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
-				unsigned int u32_count, int is_write)
-{
-
-	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
-		pr_err("gpmc: fifo threshold is not supported\n");
-		return -1;
-	} else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
-		/* Set the amount of bytes to be prefetched */
-		gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
-
-		/* Set dma/mpu mode, the prefetch read / post write and
-		 * enable the engine. Set which cs is has requested for.
-		 */
-		gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
-					PREFETCH_FIFOTHRESHOLD(fifo_th) |
-					ENABLE_PREFETCH |
-					(dma_mode << DMA_MPU_MODE) |
-					(0x1 & is_write)));
-
-		/*  Start the prefetch engine */
-		gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x1);
-	} else {
-		return -EBUSY;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(gpmc_prefetch_enable);
-
-/**
- * gpmc_prefetch_reset - disables and stops the prefetch engine
- */
-int gpmc_prefetch_reset(int cs)
-{
-	u32 config1;
-
-	/* check if the same module/cs is trying to reset */
-	config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
-	if (((config1 >> CS_NUM_SHIFT) & 0x7) != cs)
-		return -EINVAL;
-
-	/* Stop the PFPW engine */
-	gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0);
-
-	/* Reset/disable the PFPW engine */
-	gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0);
-
-	return 0;
-}
-EXPORT_SYMBOL(gpmc_prefetch_reset);
-
 void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 {
 	int i;
@@ -1145,267 +977,3 @@ void omap3_gpmc_restore_context(void)
 	}
 }
 #endif /* CONFIG_ARCH_OMAP3 */
-
-/**
- * gpmc_enable_hwecc - enable hardware ecc functionality
- * @cs: chip select number
- * @mode: read/write mode
- * @dev_width: device bus width(1 for x16, 0 for x8)
- * @ecc_size: bytes for which ECC will be generated
- */
-int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
-{
-	unsigned int val;
-
-	/* check if ecc module is in used */
-	if (gpmc_ecc_used != -EINVAL)
-		return -EINVAL;
-
-	gpmc_ecc_used = cs;
-
-	/* clear ecc and enable bits */
-	gpmc_write_reg(GPMC_ECC_CONTROL,
-			GPMC_ECC_CTRL_ECCCLEAR |
-			GPMC_ECC_CTRL_ECCREG1);
-
-	/* program ecc and result sizes */
-	val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F));
-	gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val);
-
-	switch (mode) {
-	case GPMC_ECC_READ:
-	case GPMC_ECC_WRITE:
-		gpmc_write_reg(GPMC_ECC_CONTROL,
-				GPMC_ECC_CTRL_ECCCLEAR |
-				GPMC_ECC_CTRL_ECCREG1);
-		break;
-	case GPMC_ECC_READSYN:
-		gpmc_write_reg(GPMC_ECC_CONTROL,
-				GPMC_ECC_CTRL_ECCCLEAR |
-				GPMC_ECC_CTRL_ECCDISABLE);
-		break;
-	default:
-		printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode);
-		break;
-	}
-
-	/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
-	val = (dev_width << 7) | (cs << 1) | (0x1);
-	gpmc_write_reg(GPMC_ECC_CONFIG, val);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_enable_hwecc);
-
-/**
- * gpmc_calculate_ecc - generate non-inverted ecc bytes
- * @cs: chip select number
- * @dat: data pointer over which ecc is computed
- * @ecc_code: ecc code buffer
- *
- * Using non-inverted ECC is considered ugly since writing a blank
- * page (padding) will clear the ECC bytes. This is not a problem as long
- * no one is trying to write data on the seemingly unused page. Reading
- * an erased page will produce an ECC mismatch between generated and read
- * ECC bytes that has to be dealt with separately.
- */
-int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
-{
-	unsigned int val = 0x0;
-
-	if (gpmc_ecc_used != cs)
-		return -EINVAL;
-
-	/* read ecc result */
-	val = gpmc_read_reg(GPMC_ECC1_RESULT);
-	*ecc_code++ = val;          /* P128e, ..., P1e */
-	*ecc_code++ = val >> 16;    /* P128o, ..., P1o */
-	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
-	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
-
-	gpmc_ecc_used = -EINVAL;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_calculate_ecc);
-
-#ifdef CONFIG_ARCH_OMAP3
-
-/**
- * gpmc_init_hwecc_bch - initialize hardware BCH ecc functionality
- * @cs: chip select number
- * @nsectors: how many 512-byte sectors to process
- * @nerrors: how many errors to correct per sector (4 or 8)
- *
- * This function must be executed before any call to gpmc_enable_hwecc_bch.
- */
-int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors)
-{
-	/* check if ecc module is in use */
-	if (gpmc_ecc_used != -EINVAL)
-		return -EINVAL;
-
-	/* support only OMAP3 class */
-	if (!cpu_is_omap34xx()) {
-		printk(KERN_ERR "BCH ecc is not supported on this CPU\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * For now, assume 4-bit mode is only supported on OMAP3630 ES1.x, x>=1.
-	 * Other chips may be added if confirmed to work.
-	 */
-	if ((nerrors == 4) &&
-	    (!cpu_is_omap3630() || (GET_OMAP_REVISION() == 0))) {
-		printk(KERN_ERR "BCH 4-bit mode is not supported on this CPU\n");
-		return -EINVAL;
-	}
-
-	/* sanity check */
-	if (nsectors > 8) {
-		printk(KERN_ERR "BCH cannot process %d sectors (max is 8)\n",
-		       nsectors);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_init_hwecc_bch);
-
-/**
- * gpmc_enable_hwecc_bch - enable hardware BCH ecc functionality
- * @cs: chip select number
- * @mode: read/write mode
- * @dev_width: device bus width(1 for x16, 0 for x8)
- * @nsectors: how many 512-byte sectors to process
- * @nerrors: how many errors to correct per sector (4 or 8)
- */
-int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors,
-			  int nerrors)
-{
-	unsigned int val;
-
-	/* check if ecc module is in use */
-	if (gpmc_ecc_used != -EINVAL)
-		return -EINVAL;
-
-	gpmc_ecc_used = cs;
-
-	/* clear ecc and enable bits */
-	gpmc_write_reg(GPMC_ECC_CONTROL, 0x1);
-
-	/*
-	 * When using BCH, sector size is hardcoded to 512 bytes.
-	 * Here we are using wrapping mode 6 both for reading and writing, with:
-	 *  size0 = 0  (no additional protected byte in spare area)
-	 *  size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
-	 */
-	gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, (32 << 22) | (0 << 12));
-
-	/* BCH configuration */
-	val = ((1                        << 16) | /* enable BCH */
-	       (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
-	       (0x06                     <<  8) | /* wrap mode = 6 */
-	       (dev_width                <<  7) | /* bus width */
-	       (((nsectors-1) & 0x7)     <<  4) | /* number of sectors */
-	       (cs                       <<  1) | /* ECC CS */
-	       (0x1));                            /* enable ECC */
-
-	gpmc_write_reg(GPMC_ECC_CONFIG, val);
-	gpmc_write_reg(GPMC_ECC_CONTROL, 0x101);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_enable_hwecc_bch);
-
-/**
- * gpmc_calculate_ecc_bch4 - Generate 7 ecc bytes per sector of 512 data bytes
- * @cs:  chip select number
- * @dat: The pointer to data on which ecc is computed
- * @ecc: The ecc output buffer
- */
-int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc)
-{
-	int i;
-	unsigned long nsectors, reg, val1, val2;
-
-	if (gpmc_ecc_used != cs)
-		return -EINVAL;
-
-	nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1;
-
-	for (i = 0; i < nsectors; i++) {
-
-		reg = GPMC_ECC_BCH_RESULT_0 + 16*i;
-
-		/* Read hw-computed remainder */
-		val1 = gpmc_read_reg(reg + 0);
-		val2 = gpmc_read_reg(reg + 4);
-
-		/*
-		 * Add constant polynomial to remainder, in order to get an ecc
-		 * sequence of 0xFFs for a buffer filled with 0xFFs; and
-		 * left-justify the resulting polynomial.
-		 */
-		*ecc++ = 0x28 ^ ((val2 >> 12) & 0xFF);
-		*ecc++ = 0x13 ^ ((val2 >>  4) & 0xFF);
-		*ecc++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF));
-		*ecc++ = 0x39 ^ ((val1 >> 20) & 0xFF);
-		*ecc++ = 0x96 ^ ((val1 >> 12) & 0xFF);
-		*ecc++ = 0xac ^ ((val1 >> 4) & 0xFF);
-		*ecc++ = 0x7f ^ ((val1 & 0xF) << 4);
-	}
-
-	gpmc_ecc_used = -EINVAL;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch4);
-
-/**
- * gpmc_calculate_ecc_bch8 - Generate 13 ecc bytes per block of 512 data bytes
- * @cs:  chip select number
- * @dat: The pointer to data on which ecc is computed
- * @ecc: The ecc output buffer
- */
-int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc)
-{
-	int i;
-	unsigned long nsectors, reg, val1, val2, val3, val4;
-
-	if (gpmc_ecc_used != cs)
-		return -EINVAL;
-
-	nsectors = ((gpmc_read_reg(GPMC_ECC_CONFIG) >> 4) & 0x7) + 1;
-
-	for (i = 0; i < nsectors; i++) {
-
-		reg = GPMC_ECC_BCH_RESULT_0 + 16*i;
-
-		/* Read hw-computed remainder */
-		val1 = gpmc_read_reg(reg + 0);
-		val2 = gpmc_read_reg(reg + 4);
-		val3 = gpmc_read_reg(reg + 8);
-		val4 = gpmc_read_reg(reg + 12);
-
-		/*
-		 * Add constant polynomial to remainder, in order to get an ecc
-		 * sequence of 0xFFs for a buffer filled with 0xFFs.
-		 */
-		*ecc++ = 0xef ^ (val4 & 0xFF);
-		*ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF);
-		*ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF);
-		*ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF);
-		*ecc++ = 0xed ^ (val3 & 0xFF);
-		*ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF);
-		*ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF);
-		*ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
-		*ecc++ = 0x97 ^ (val2 & 0xFF);
-		*ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF);
-		*ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
-		*ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF);
-		*ecc++ = 0xb5 ^ (val1 & 0xFF);
-	}
-
-	gpmc_ecc_used = -EINVAL;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(gpmc_calculate_ecc_bch8);
-
-#endif /* CONFIG_ARCH_OMAP3 */
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 17fc1e7..e08a51a 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -34,15 +34,6 @@
 #define GPMC_SET_IRQ_STATUS	0x00000004
 #define GPMC_CONFIG_WP		0x00000005
 
-#define GPMC_GET_IRQ_STATUS	0x00000006
-#define GPMC_PREFETCH_FIFO_CNT	0x00000007 /* bytes available in FIFO for r/w */
-#define GPMC_PREFETCH_COUNT	0x00000008 /* remaining bytes to be read/write*/
-#define GPMC_STATUS_BUFFER	0x00000009 /* 1: buffer is available to write */
-
-#define GPMC_NAND_COMMAND	0x0000000a
-#define GPMC_NAND_ADDRESS	0x0000000b
-#define GPMC_NAND_DATA		0x0000000c
-
 #define GPMC_ENABLE_IRQ		0x0000000d
 
 /* ECC commands */
@@ -78,15 +69,10 @@
 #define GPMC_DEVICETYPE_NOR		0
 #define GPMC_DEVICETYPE_NAND		2
 #define GPMC_CONFIG_WRITEPROTECT	0x00000010
-#define GPMC_STATUS_BUFF_EMPTY		0x00000001
 #define WR_RD_PIN_MONITORING		0x00600000
-#define GPMC_PREFETCH_STATUS_FIFO_CNT(val)	((val >> 24) & 0x7F)
-#define GPMC_PREFETCH_STATUS_COUNT(val)	(val & 0x00003fff)
 #define GPMC_IRQ_FIFOEVENTENABLE	0x01
 #define GPMC_IRQ_COUNT_EVENT		0x02
 
-#define PREFETCH_FIFOTHRESHOLD_MAX	0x40
-#define PREFETCH_FIFOTHRESHOLD(val)	((val) << 8)
 
 /* bool type time settings */
 struct gpmc_bool_timings {
@@ -161,25 +147,8 @@ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
 extern int gpmc_cs_set_reserved(int cs, int reserved);
 extern int gpmc_cs_reserved(int cs);
-extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
-					unsigned int u32_count, int is_write);
-extern int gpmc_prefetch_reset(int cs);
 extern void omap3_gpmc_save_context(void);
 extern void omap3_gpmc_restore_context(void);
-extern int gpmc_read_status(int cmd);
 extern int gpmc_cs_configure(int cs, int cmd, int wval);
-extern int gpmc_nand_read(int cs, int cmd);
-extern int gpmc_nand_write(int cs, int cmd, int wval);
-
-int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size);
-int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
-
-#ifdef CONFIG_ARCH_OMAP3
-int gpmc_init_hwecc_bch(int cs, int nsectors, int nerrors);
-int gpmc_enable_hwecc_bch(int cs, int mode, int dev_width, int nsectors,
-			  int nerrors);
-int gpmc_calculate_ecc_bch4(int cs, const u_char *dat, u_char *ecc);
-int gpmc_calculate_ecc_bch8(int cs, const u_char *dat, u_char *ecc);
-#endif /* CONFIG_ARCH_OMAP3 */
 
 #endif
-- 
1.7.12

^ permalink raw reply related

* [PATCH v2 14/14] ARM: OMAP2+: gpmc: localize gpmc header
From: Afzal Mohammed @ 2012-10-08  5:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

Requirement of gpmc header outside of mach-omap2 has been
cutoff, move gpmc header file in plat-omap folder to local
mach-omap2 folder

Objective - common zImage participation of omap

Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
 arch/arm/mach-omap2/board-2430sdp.c          |   2 +-
 arch/arm/mach-omap2/board-3430sdp.c          |   2 +-
 arch/arm/mach-omap2/board-apollon.c          |   2 +-
 arch/arm/mach-omap2/board-cm-t35.c           |   2 +-
 arch/arm/mach-omap2/board-cm-t3517.c         |   2 +-
 arch/arm/mach-omap2/board-devkit8000.c       |   2 +-
 arch/arm/mach-omap2/board-flash.c            |   2 +-
 arch/arm/mach-omap2/board-flash.h            |   2 +-
 arch/arm/mach-omap2/board-h4.c               |   2 +-
 arch/arm/mach-omap2/board-igep0020.c         |   2 +-
 arch/arm/mach-omap2/board-ldp.c              |   2 +-
 arch/arm/mach-omap2/board-omap3beagle.c      |   2 +-
 arch/arm/mach-omap2/board-omap3logic.c       |   2 +-
 arch/arm/mach-omap2/board-omap3stalker.c     |   2 +-
 arch/arm/mach-omap2/board-omap3touchbook.c   |   2 +-
 arch/arm/mach-omap2/board-overo.c            |   2 +-
 arch/arm/mach-omap2/board-rm680.c            |   2 +-
 arch/arm/mach-omap2/board-rx51-peripherals.c |   2 +-
 arch/arm/mach-omap2/board-rx51.c             |   2 +-
 arch/arm/mach-omap2/board-zoom-debugboard.c  |   2 +-
 arch/arm/mach-omap2/gpmc-nand.c              |   3 +-
 arch/arm/mach-omap2/gpmc-nand.h              |   2 +-
 arch/arm/mach-omap2/gpmc-onenand.c           |   3 +-
 arch/arm/mach-omap2/gpmc-smc91x.c            |   2 +-
 arch/arm/mach-omap2/gpmc-smsc911x.c          |   2 +-
 arch/arm/mach-omap2/gpmc.c                   |   3 +-
 arch/arm/mach-omap2/gpmc.h                   | 154 +++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm34xx.c                 |   2 +-
 arch/arm/mach-omap2/usb-tusb6010.c           |   2 +-
 arch/arm/plat-omap/include/plat/gpmc.h       | 154 ---------------------------
 30 files changed, 182 insertions(+), 185 deletions(-)
 create mode 100644 arch/arm/mach-omap2/gpmc.h
 delete mode 100644 arch/arm/plat-omap/include/plat/gpmc.h

diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 95b384d..49e49d0 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -34,7 +34,7 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <plat/usb.h>
 #include "gpmc-smc91x.h"
 
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 96cd369..5ad0901 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -33,7 +33,7 @@
 #include <plat/usb.h>
 #include "common.h"
 #include <plat/dma.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <video/omapdss.h>
 #include <video/omap-panel-tfp410.h>
 
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index cea3aba..8cdd186 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -35,7 +35,7 @@
 
 #include <plat/led.h>
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index fef68de..73e2ba9 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -40,7 +40,7 @@
 
 #include "common.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 3a19e80..b5495e4 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -41,7 +41,7 @@
 #include "common.h"
 #include <plat/usb.h>
 #include <linux/platform_data/mtd-nand-omap2.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 
 #include "am35xx.h"
 
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 9933966..3eedb8f 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -39,7 +39,7 @@
 #include <asm/mach/flash.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/usb.h>
 #include <video/omapdss.h>
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 776e57a..c56986f 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -18,7 +18,7 @@
 #include <linux/io.h>
 
 #include <plat/cpu.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <linux/platform_data/mtd-onenand-omap2.h>
 #include <plat/tc.h>
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index a3aa5fc..2fb5d41 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -12,7 +12,7 @@
  */
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 
 #define PDC_NOR		1
 #define PDC_NAND	2
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 8d04bf8..65ebf58 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -33,7 +33,6 @@
 
 #include <plat/menelaus.h>
 #include <plat/dma.h>
-#include <plat/gpmc.h>
 #include "debug-devices.h"
 
 #include <video/omapdss.h>
@@ -42,6 +41,7 @@
 #include "common.h"
 #include "mux.h"
 #include "control.h"
+#include "gpmc.h"
 
 #define H4_FLASH_CS	0
 #define H4_SMC91X_CS	1
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 83c6efa..9a9a9b5 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -30,7 +30,7 @@
 #include <asm/mach/arch.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <plat/usb.h>
 
 #include <video/omapdss.h>
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 83383f3..e1628cd 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -35,7 +35,7 @@
 #include <asm/mach/map.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <mach/board-zoom.h>
 #include <plat/usb.h>
 #include "gpmc-smsc911x.h"
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index f240e21..65eaaee 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -41,7 +41,7 @@
 #include "common.h"
 #include <video/omapdss.h>
 #include <video/omap-panel-tfp410.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/usb.h>
 #include <plat/omap_device.h>
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 7bd8253..5cfade2 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -35,7 +35,7 @@
 #include <asm/mach/map.h>
 
 #include "gpmc-smsc911x.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <plat/sdrc.h>
 #include <plat/usb.h>
 
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index c7f3d02..11fcc73 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -40,7 +40,7 @@
 #include <asm/mach/flash.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/usb.h>
 #include <video/omapdss.h>
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 3f013c8..cd282ae 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -44,7 +44,7 @@
 #include <asm/system_info.h>
 
 #include "common.h"
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/usb.h>
 
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index e2cf0f7..3a9d1fa 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -49,7 +49,7 @@
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <plat/usb.h>
 
 #include "mux.h"
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 154cf33..3c3a473 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -25,7 +25,7 @@
 #include <plat/i2c.h>
 #include <plat/mmc.h>
 #include <plat/usb.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include "common.h"
 #include <plat/serial.h>
 
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index aa6a2a4..5ba8942 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -32,7 +32,7 @@
 
 #include "common.h"
 #include <plat/dma.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <plat/omap-pm.h>
 #include "gpmc-smc91x.h"
 
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 7bbb05d..88ba5be 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -25,7 +25,7 @@
 
 #include "common.h"
 #include <plat/dma.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <plat/usb.h>
 
 #include "mux.h"
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index afb2278..be9f71d 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -17,7 +17,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include "gpmc-smsc911x.h"
 
 #include <mach/board-zoom.h>
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 7983d54..db969a5 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -17,8 +17,7 @@
 
 #include <asm/mach/flash.h>
 
-#include <plat/gpmc.h>
-
+#include "gpmc.h"
 #include "soc.h"
 #include "gpmc-nand.h"
 
diff --git a/arch/arm/mach-omap2/gpmc-nand.h b/arch/arm/mach-omap2/gpmc-nand.h
index 11a377f..d59e128 100644
--- a/arch/arm/mach-omap2/gpmc-nand.h
+++ b/arch/arm/mach-omap2/gpmc-nand.h
@@ -10,7 +10,7 @@
 #ifndef	__OMAP2_GPMC_NAND_H
 #define	__OMAP2_GPMC_NAND_H
 
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <linux/platform_data/mtd-nand-omap2.h>
 
 #if IS_ENABLED(CONFIG_MTD_NAND_OMAP2)
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 29671cc..54e2255 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -20,8 +20,7 @@
 
 #include <asm/mach/flash.h>
 
-#include <plat/gpmc.h>
-
+#include "gpmc.h"
 #include "soc.h"
 #include "gpmc-onenand.h"
 
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
index 5654753..6eed907 100644
--- a/arch/arm/mach-omap2/gpmc-smc91x.c
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -17,7 +17,7 @@
 #include <linux/io.h>
 #include <linux/smc91x.h>
 
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include "gpmc-smc91x.h"
 
 #include "soc.h"
diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
index 249a0b4..ef99011 100644
--- a/arch/arm/mach-omap2/gpmc-smsc911x.c
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.c
@@ -20,7 +20,7 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include "gpmc-smsc911x.h"
 
 static struct resource gpmc_smsc911x_resources[] = {
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 1121248..285070e 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -29,15 +29,14 @@
 #include <linux/platform_data/mtd-nand-omap2.h>
 
 #include <asm/mach-types.h>
-#include <plat/gpmc.h>
 
 #include <plat/cpu.h>
-#include <plat/gpmc.h>
 #include <plat/sdrc.h>
 #include <plat/omap_device.h>
 
 #include "soc.h"
 #include "common.h"
+#include "gpmc.h"
 
 #define	DEVICE_NAME		"omap-gpmc"
 
diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h
new file mode 100644
index 0000000..e08a51a
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc.h
@@ -0,0 +1,154 @@
+/*
+ * General-Purpose Memory Controller for OMAP2
+ *
+ * Copyright (C) 2005-2006 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __OMAP2_GPMC_H
+#define __OMAP2_GPMC_H
+
+#include <linux/platform_data/mtd-nand-omap2.h>
+
+/* Maximum Number of Chip Selects */
+#define GPMC_CS_NUM		8
+
+#define GPMC_CS_CONFIG1		0x00
+#define GPMC_CS_CONFIG2		0x04
+#define GPMC_CS_CONFIG3		0x08
+#define GPMC_CS_CONFIG4		0x0c
+#define GPMC_CS_CONFIG5		0x10
+#define GPMC_CS_CONFIG6		0x14
+#define GPMC_CS_CONFIG7		0x18
+#define GPMC_CS_NAND_COMMAND	0x1c
+#define GPMC_CS_NAND_ADDRESS	0x20
+#define GPMC_CS_NAND_DATA	0x24
+
+/* Control Commands */
+#define GPMC_CONFIG_RDY_BSY	0x00000001
+#define GPMC_CONFIG_DEV_SIZE	0x00000002
+#define GPMC_CONFIG_DEV_TYPE	0x00000003
+#define GPMC_SET_IRQ_STATUS	0x00000004
+#define GPMC_CONFIG_WP		0x00000005
+
+#define GPMC_ENABLE_IRQ		0x0000000d
+
+/* ECC commands */
+#define GPMC_ECC_READ		0 /* Reset Hardware ECC for read */
+#define GPMC_ECC_WRITE		1 /* Reset Hardware ECC for write */
+#define GPMC_ECC_READSYN	2 /* Reset before syndrom is read back */
+
+#define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
+#define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
+#define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
+#define GPMC_CONFIG1_READTYPE_SYNC      (1 << 29)
+#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28)
+#define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
+#define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
+#define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
+#define GPMC_CONFIG1_WAIT_READ_MON      (1 << 22)
+#define GPMC_CONFIG1_WAIT_WRITE_MON     (1 << 21)
+#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
+#define GPMC_CONFIG1_WAIT_PIN_SEL(val)  ((val & 3) << 16)
+#define GPMC_CONFIG1_DEVICESIZE(val)    ((val & 3) << 12)
+#define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(1)
+#define GPMC_CONFIG1_DEVICETYPE(val)    ((val & 3) << 10)
+#define GPMC_CONFIG1_DEVICETYPE_NOR     GPMC_CONFIG1_DEVICETYPE(0)
+#define GPMC_CONFIG1_MUXADDDATA         (1 << 9)
+#define GPMC_CONFIG1_TIME_PARA_GRAN     (1 << 4)
+#define GPMC_CONFIG1_FCLK_DIV(val)      (val & 3)
+#define GPMC_CONFIG1_FCLK_DIV2          (GPMC_CONFIG1_FCLK_DIV(1))
+#define GPMC_CONFIG1_FCLK_DIV3          (GPMC_CONFIG1_FCLK_DIV(2))
+#define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
+#define GPMC_CONFIG7_CSVALID		(1 << 6)
+
+#define GPMC_DEVICETYPE_NOR		0
+#define GPMC_DEVICETYPE_NAND		2
+#define GPMC_CONFIG_WRITEPROTECT	0x00000010
+#define WR_RD_PIN_MONITORING		0x00600000
+#define GPMC_IRQ_FIFOEVENTENABLE	0x01
+#define GPMC_IRQ_COUNT_EVENT		0x02
+
+
+/* bool type time settings */
+struct gpmc_bool_timings {
+	bool cycle2cyclediffcsen;
+	bool cycle2cyclesamecsen;
+	bool we_extra_delay;
+	bool oe_extra_delay;
+	bool adv_extra_delay;
+	bool cs_extra_delay;
+	bool time_para_granularity;
+};
+
+/*
+ * Note that all values in this struct are in nanoseconds except sync_clk
+ * (which is in picoseconds), while the register values are in gpmc_fck cycles.
+ */
+struct gpmc_timings {
+	/* Minimum clock period for synchronous mode (in picoseconds) */
+	u32 sync_clk;
+
+	/* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
+	u16 cs_on;		/* Assertion time */
+	u16 cs_rd_off;		/* Read deassertion time */
+	u16 cs_wr_off;		/* Write deassertion time */
+
+	/* ADV signal timings corresponding to GPMC_CONFIG3 */
+	u16 adv_on;		/* Assertion time */
+	u16 adv_rd_off;		/* Read deassertion time */
+	u16 adv_wr_off;		/* Write deassertion time */
+
+	/* WE signals timings corresponding to GPMC_CONFIG4 */
+	u16 we_on;		/* WE assertion time */
+	u16 we_off;		/* WE deassertion time */
+
+	/* OE signals timings corresponding to GPMC_CONFIG4 */
+	u16 oe_on;		/* OE assertion time */
+	u16 oe_off;		/* OE deassertion time */
+
+	/* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
+	u16 page_burst_access;	/* Multiple access word delay */
+	u16 access;		/* Start-cycle to first data valid delay */
+	u16 rd_cycle;		/* Total read cycle time */
+	u16 wr_cycle;		/* Total write cycle time */
+
+	u16 bus_turnaround;
+	u16 cycle2cycle_delay;
+
+	u16 wait_monitoring;
+	u16 clk_activation;
+
+	/* The following are only on OMAP3430 */
+	u16 wr_access;		/* WRACCESSTIME */
+	u16 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
+
+	struct gpmc_bool_timings bool_timings;
+};
+
+extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
+extern int gpmc_get_client_irq(unsigned irq_config);
+
+extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
+extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
+extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
+extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
+extern unsigned long gpmc_get_fclk_period(void);
+
+extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
+extern u32 gpmc_cs_read_reg(int cs, int idx);
+extern int gpmc_calc_divider(unsigned int sync_clk);
+extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
+extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
+extern void gpmc_cs_free(int cs);
+extern int gpmc_cs_set_reserved(int cs, int reserved);
+extern int gpmc_cs_reserved(int cs);
+extern void omap3_gpmc_save_context(void);
+extern void omap3_gpmc_restore_context(void);
+extern int gpmc_cs_configure(int cs, int cmd, int wval);
+
+#endif
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index ba670db..ed98f4f 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -40,7 +40,7 @@
 #include "powerdomain.h"
 #include <plat/sdrc.h>
 #include <plat/prcm.h>
-#include <plat/gpmc.h>
+#include "gpmc.h"
 #include <plat/dma.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index 7a85ebe..8ee73fc 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -18,7 +18,7 @@
 
 #include <linux/usb/musb.h>
 
-#include <plat/gpmc.h>
+#include "gpmc.h"
 
 #include "mux.h"
 
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
deleted file mode 100644
index e08a51a..0000000
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * General-Purpose Memory Controller for OMAP2
- *
- * Copyright (C) 2005-2006 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __OMAP2_GPMC_H
-#define __OMAP2_GPMC_H
-
-#include <linux/platform_data/mtd-nand-omap2.h>
-
-/* Maximum Number of Chip Selects */
-#define GPMC_CS_NUM		8
-
-#define GPMC_CS_CONFIG1		0x00
-#define GPMC_CS_CONFIG2		0x04
-#define GPMC_CS_CONFIG3		0x08
-#define GPMC_CS_CONFIG4		0x0c
-#define GPMC_CS_CONFIG5		0x10
-#define GPMC_CS_CONFIG6		0x14
-#define GPMC_CS_CONFIG7		0x18
-#define GPMC_CS_NAND_COMMAND	0x1c
-#define GPMC_CS_NAND_ADDRESS	0x20
-#define GPMC_CS_NAND_DATA	0x24
-
-/* Control Commands */
-#define GPMC_CONFIG_RDY_BSY	0x00000001
-#define GPMC_CONFIG_DEV_SIZE	0x00000002
-#define GPMC_CONFIG_DEV_TYPE	0x00000003
-#define GPMC_SET_IRQ_STATUS	0x00000004
-#define GPMC_CONFIG_WP		0x00000005
-
-#define GPMC_ENABLE_IRQ		0x0000000d
-
-/* ECC commands */
-#define GPMC_ECC_READ		0 /* Reset Hardware ECC for read */
-#define GPMC_ECC_WRITE		1 /* Reset Hardware ECC for write */
-#define GPMC_ECC_READSYN	2 /* Reset before syndrom is read back */
-
-#define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
-#define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
-#define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
-#define GPMC_CONFIG1_READTYPE_SYNC      (1 << 29)
-#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28)
-#define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
-#define GPMC_CONFIG1_WRITETYPE_SYNC     (1 << 27)
-#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25)
-#define GPMC_CONFIG1_PAGE_LEN(val)      ((val & 3) << 23)
-#define GPMC_CONFIG1_WAIT_READ_MON      (1 << 22)
-#define GPMC_CONFIG1_WAIT_WRITE_MON     (1 << 21)
-#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18)
-#define GPMC_CONFIG1_WAIT_PIN_SEL(val)  ((val & 3) << 16)
-#define GPMC_CONFIG1_DEVICESIZE(val)    ((val & 3) << 12)
-#define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(1)
-#define GPMC_CONFIG1_DEVICETYPE(val)    ((val & 3) << 10)
-#define GPMC_CONFIG1_DEVICETYPE_NOR     GPMC_CONFIG1_DEVICETYPE(0)
-#define GPMC_CONFIG1_MUXADDDATA         (1 << 9)
-#define GPMC_CONFIG1_TIME_PARA_GRAN     (1 << 4)
-#define GPMC_CONFIG1_FCLK_DIV(val)      (val & 3)
-#define GPMC_CONFIG1_FCLK_DIV2          (GPMC_CONFIG1_FCLK_DIV(1))
-#define GPMC_CONFIG1_FCLK_DIV3          (GPMC_CONFIG1_FCLK_DIV(2))
-#define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
-#define GPMC_CONFIG7_CSVALID		(1 << 6)
-
-#define GPMC_DEVICETYPE_NOR		0
-#define GPMC_DEVICETYPE_NAND		2
-#define GPMC_CONFIG_WRITEPROTECT	0x00000010
-#define WR_RD_PIN_MONITORING		0x00600000
-#define GPMC_IRQ_FIFOEVENTENABLE	0x01
-#define GPMC_IRQ_COUNT_EVENT		0x02
-
-
-/* bool type time settings */
-struct gpmc_bool_timings {
-	bool cycle2cyclediffcsen;
-	bool cycle2cyclesamecsen;
-	bool we_extra_delay;
-	bool oe_extra_delay;
-	bool adv_extra_delay;
-	bool cs_extra_delay;
-	bool time_para_granularity;
-};
-
-/*
- * Note that all values in this struct are in nanoseconds except sync_clk
- * (which is in picoseconds), while the register values are in gpmc_fck cycles.
- */
-struct gpmc_timings {
-	/* Minimum clock period for synchronous mode (in picoseconds) */
-	u32 sync_clk;
-
-	/* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
-	u16 cs_on;		/* Assertion time */
-	u16 cs_rd_off;		/* Read deassertion time */
-	u16 cs_wr_off;		/* Write deassertion time */
-
-	/* ADV signal timings corresponding to GPMC_CONFIG3 */
-	u16 adv_on;		/* Assertion time */
-	u16 adv_rd_off;		/* Read deassertion time */
-	u16 adv_wr_off;		/* Write deassertion time */
-
-	/* WE signals timings corresponding to GPMC_CONFIG4 */
-	u16 we_on;		/* WE assertion time */
-	u16 we_off;		/* WE deassertion time */
-
-	/* OE signals timings corresponding to GPMC_CONFIG4 */
-	u16 oe_on;		/* OE assertion time */
-	u16 oe_off;		/* OE deassertion time */
-
-	/* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
-	u16 page_burst_access;	/* Multiple access word delay */
-	u16 access;		/* Start-cycle to first data valid delay */
-	u16 rd_cycle;		/* Total read cycle time */
-	u16 wr_cycle;		/* Total write cycle time */
-
-	u16 bus_turnaround;
-	u16 cycle2cycle_delay;
-
-	u16 wait_monitoring;
-	u16 clk_activation;
-
-	/* The following are only on OMAP3430 */
-	u16 wr_access;		/* WRACCESSTIME */
-	u16 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
-
-	struct gpmc_bool_timings bool_timings;
-};
-
-extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
-extern int gpmc_get_client_irq(unsigned irq_config);
-
-extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
-extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
-extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
-extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
-extern unsigned long gpmc_get_fclk_period(void);
-
-extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
-extern u32 gpmc_cs_read_reg(int cs, int idx);
-extern int gpmc_calc_divider(unsigned int sync_clk);
-extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
-extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
-extern void gpmc_cs_free(int cs);
-extern int gpmc_cs_set_reserved(int cs, int reserved);
-extern int gpmc_cs_reserved(int cs);
-extern void omap3_gpmc_save_context(void);
-extern void omap3_gpmc_restore_context(void);
-extern int gpmc_cs_configure(int cs, int cmd, int wval);
-
-#endif
-- 
1.7.12

^ permalink raw reply related

* [PATCH 00/15] OMAP-GPMC related cleanup for common zImage
From: Mohammed, Afzal @ 2012-10-08  5:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349450454.git.afzal@ti.com>

Hi,

On Fri, Oct 05, 2012 at 21:22:50, Mohammed, Afzal wrote:

> This series cleans up omap-gpmc related code so that omap can
> be a part of common zImage.

Upon selecting BCH CONFIG option, build breaks, updated
series - v2 that fixes it has been posted.

Regards
Afzal

^ permalink raw reply

* [PATCH] pwm: Get rid of HAVE_PWM
From: Thierry Reding @ 2012-10-08  5:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMPhdO-PiKwYstKrGwdhrUG3+KWhPioAtzPVqtk52vss-4M+iw@mail.gmail.com>

On Mon, Oct 08, 2012 at 10:45:44AM +0800, Eric Miao wrote:
> On Fri, Oct 5, 2012 at 3:13 AM, Thierry Reding
> <thierry.reding@avionic-design.de> wrote:
> > On Thu, Oct 04, 2012 at 08:48:54PM +0200, Lars-Peter Clausen wrote:
> >> On 10/04/2012 08:29 PM, Thierry Reding wrote:
> >> > On Thu, Oct 04, 2012 at 05:00:23PM +0200, Lars-Peter Clausen wrote:
> >> >> On 10/04/2012 08:06 AM, Thierry Reding wrote:
> >> >>> [...]
> >> >>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> >> >>> index 331d574..b38f23d 100644
> >> >>> --- a/arch/mips/Kconfig
> >> >>> +++ b/arch/mips/Kconfig
> >> >>> @@ -219,7 +219,8 @@ config MACH_JZ4740
> >> >>>   select GENERIC_GPIO
> >> >>>   select ARCH_REQUIRE_GPIOLIB
> >> >>>   select SYS_HAS_EARLY_PRINTK
> >> >>> - select HAVE_PWM
> >> >>> + select PWM
> >> >>> + select PWM_JZ4740
> >> >>>   select HAVE_CLK
> >> >>>   select GENERIC_IRQ_CHIP
> >> >>
> >> >> I'm not sure if this is such a good idea, not all jz4740 based board
> >> >> necessarily require PWM.
> >> >
> >> > This really only restores previous behaviour. But I agree that this is
> >> > potentially not what we want. Maybe we should just not select this for
> >> > any boards but rather leave it up to some default configuration. If so
> >> > the patch can be made simpler by just removing the HAVE_PWM entries.
> >>
> >> At least for JZ4740 I think that is the better solution.
> >
> > Okay, I'll give other people the chance to comment on this. Especially
> > for PXA there are many boards that use the PWM for backlight and it
> > would be interesting to hear from them how they want this to be handled.
> 
> I'd say the original intention to introduce HAVE_PWM (although PXA
> makes a lot use of this, but I remember Russell was the first to propose
> this), is for board config to indicate its potential usage of the PWM or
> rather if PWM is available for use on the board, and then leave the
> developer another config option to build or not-to-build.

But with HAVE_PWM there was never a different configuration option to
enable the PWM driver. All architectures that used the HAVE_PWM symbol
built the driver based on its selection. The meaning seemed more like
"the PWM API is available" rather than anything else.

Given that, HAVE_PWM would now be replaced by just PWM since that makes
the API available. Client drivers would still be able to compile
properly but fail at runtime if no driver actually provided any PWM
devices.

Note that starting with 3.7 the API will even be available in the form
of dummy implementations if PWM is not selected.

> Personally I think removing HAVE_PWM will simplify the code a bit
> and that's a good thing, on the other hand, how to keep a certain level
> of flexibility mentioned above remains a small question. I guess with
> device tree, this can be mitigated a bit.

I think, given the above, that the best solution would be to not select
any PWM-related symbols from boards and handle this via the board
default configurations. I was just worrying that we were changing
existing behaviour. On the other hand behaviour was already changed by
making the drivers no longer conditional on HAVE_PWM.

If nobody has any objections, my tendency would be to just not replace
HAVE_PWM but just get rid of it. Of course, as I mentioned above, it
would require the board default configurations to be updated and select
the PWM and corresponding driver symbol in order to restore previous
behaviour.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121008/cd02ed20/attachment.sig>

^ permalink raw reply

* [PATCH 01/16] ARM: warnings in arch/arm/include/asm/uaccess.h
From: Greg Ungerer @ 2012-10-08  5:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349448930-23976-2-git-send-email-arnd@arndb.de>

On 06/10/12 00:55, Arnd Bergmann wrote:
> On NOMMU ARM, the __addr_ok() and __range_ok() macros do not evaluate
> their arguments, which may lead to harmless build warnings in some
> code where the variables are not used otherwise. Adding a cast to void
> gets rid of the warning and does not make any semantic changes.
>
> Without this patch, building at91x40_defconfig results in:
>
> fs/read_write.c: In function 'rw_copy_check_uvector':
> fs/read_write.c:684:9: warning: unused variable 'buf' [-Wunused-variable]
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Cc: Greg Ungerer <gerg@uclinux.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>

Acked-by: Greg Ungerer <gerg@uclinux.org>

I can pick it up and push to the arm-soc tree.

Regards
Greg


> ---
>   arch/arm/include/asm/uaccess.h |    4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
> index 77bd79f..7e1f760 100644
> --- a/arch/arm/include/asm/uaccess.h
> +++ b/arch/arm/include/asm/uaccess.h
> @@ -200,8 +200,8 @@ extern int __put_user_8(void *, unsigned long long);
>   #define USER_DS			KERNEL_DS
>
>   #define segment_eq(a,b)		(1)
> -#define __addr_ok(addr)		(1)
> -#define __range_ok(addr,size)	(0)
> +#define __addr_ok(addr)		((void)(addr),1)
> +#define __range_ok(addr,size)	((void)(addr),0)
>   #define get_fs()		(KERNEL_DS)
>
>   static inline void set_fs(mm_segment_t fs)
>


-- 
------------------------------------------------------------------------
Greg Ungerer  --  Principal Engineer        EMAIL:     gerg at snapgear.com
SnapGear Group, McAfee                      PHONE:       +61 7 3435 2888
8 Gardner Close                             FAX:         +61 7 3217 5323
Milton, QLD, 4064, Australia                WEB: http://www.SnapGear.com

^ permalink raw reply

* [PATCH 02/16] ARM: binfmt_flat: unused variable 'persistent'
From: Greg Ungerer @ 2012-10-08  5:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349448930-23976-3-git-send-email-arnd@arndb.de>

On 06/10/12 00:55, Arnd Bergmann wrote:
> The flat_get_addr_from_rp() macro does not use the 'persistent' argument
> on ARM, causing a harmless compiler warning. A cast to void removes
> that warning.
>
> Without this patch, building at91x40_defconfig results in:
>
> fs/binfmt_flat.c: In function 'load_flat_file':
> fs/binfmt_flat.c:746:17: warning: unused variable 'persistent' [-Wunused-variable]
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Cc: Greg Ungerer <gerg@uclinux.org>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Bryan Wu <bryan.wu@canonical.com>

Acked-by: Greg Ungerer <gerg@uclinux.org>

I can pick this one up to, and push to the arm-soc tree.

Regards
Greg


> ---
>   arch/arm/include/asm/flat.h |    2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/include/asm/flat.h b/arch/arm/include/asm/flat.h
> index 59426a4..e847d23 100644
> --- a/arch/arm/include/asm/flat.h
> +++ b/arch/arm/include/asm/flat.h
> @@ -8,7 +8,7 @@
>   #define	flat_argvp_envp_on_stack()		1
>   #define	flat_old_ram_flag(flags)		(flags)
>   #define	flat_reloc_valid(reloc, size)		((reloc) <= (size))
> -#define	flat_get_addr_from_rp(rp, relval, flags, persistent) get_unaligned(rp)
> +#define	flat_get_addr_from_rp(rp, relval, flags, persistent) ((void)persistent,get_unaligned(rp))
>   #define	flat_put_addr_at_rp(rp, val, relval)	put_unaligned(val,rp)
>   #define	flat_get_relocate_addr(rel)		(rel)
>   #define	flat_set_persistent(relval, p)		0
>


-- 
------------------------------------------------------------------------
Greg Ungerer  --  Principal Engineer        EMAIL:     gerg at snapgear.com
SnapGear Group, McAfee                      PHONE:       +61 7 3435 2888
8 Gardner Close                             FAX:         +61 7 3217 5323
Milton, QLD, 4064, Australia                WEB: http://www.SnapGear.com

^ permalink raw reply

* [PATCH v2 0/3] ocp2scp: add non-dt support
From: Kishon Vijay Abraham I @ 2012-10-08  5:59 UTC (permalink / raw)
  To: linux-arm-kernel

This patch series allows ocp2scp driver to create its child devices
from the platform data.

In omap platforms, usb phy is connected to ocp2scp and usb phy is needed
for MUSB to be functional. When ocp2scp driver was added, it had only dt
support which means it wont create usb phy devices for non-dt boot.

This patch series adds non-dt support to ocp2scp and this series is needed
for getting MUSB functional in non-dt boot.

Changes from v1:
* Fixed Sergei's comments on memory leaks

This patch series is rebased on linux-next. 
commit: 080aa9c61ad0a6ed17de5643b32bb4660a0eb29d
Let me know if it had to be based on some other tree/commit.

Did a quick testing for g_zero enumeration in panda board.

Kishon Vijay Abraham I (3):
  drivers: bus: ocp2scp: add pdata support
  ARM: OMAP4: add _dev_attr_ to ocp2scp for representing usb_phy
  ARM: OMAP: ocp2scp: create omap device for ocp2scp

 arch/arm/mach-omap2/devices.c              |   76 ++++++++++++++++++++++++++++
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   28 ++++++++++
 drivers/bus/omap-ocp2scp.c                 |   67 ++++++++++++++++++++++--
 include/linux/platform_data/omap_ocp2scp.h |   31 ++++++++++++
 4 files changed, 199 insertions(+), 3 deletions(-)
 create mode 100644 include/linux/platform_data/omap_ocp2scp.h

-- 
1.7.9.5

^ permalink raw reply

* [PATCH v2 1/3] drivers: bus: ocp2scp: add pdata support
From: Kishon Vijay Abraham I @ 2012-10-08  5:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349675983-23803-1-git-send-email-kishon@ti.com>

ocp2scp was not having pdata support which makes *musb* fail for non-dt
boot in OMAP platform. The pdata will have information about the devices
that is connected to ocp2scp. ocp2scp driver will now make use of this
information to create the devices that is attached to ocp2scp.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/bus/omap-ocp2scp.c                 |   67 ++++++++++++++++++++++++++--
 include/linux/platform_data/omap_ocp2scp.h |   31 +++++++++++++
 2 files changed, 95 insertions(+), 3 deletions(-)
 create mode 100644 include/linux/platform_data/omap_ocp2scp.h

diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c
index ff63560..5db8297 100644
--- a/drivers/bus/omap-ocp2scp.c
+++ b/drivers/bus/omap-ocp2scp.c
@@ -22,6 +22,26 @@
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/platform_data/omap_ocp2scp.h>
+
+/**
+ * _count_resources - count for the number of resources
+ * @res: struct resource *
+ *
+ * Count and return the number of resources populated for the device that is
+ * connected to ocp2scp.
+ */
+static unsigned _count_resources(struct resource *res)
+{
+	int cnt	= 0;
+
+	while (res->start != res->end) {
+		cnt++;
+		res++;
+	}
+
+	return cnt;
+}
 
 static int ocp2scp_remove_devices(struct device *dev, void *c)
 {
@@ -34,20 +54,61 @@ static int ocp2scp_remove_devices(struct device *dev, void *c)
 
 static int __devinit omap_ocp2scp_probe(struct platform_device *pdev)
 {
-	int			ret;
-	struct device_node	*np = pdev->dev.of_node;
+	int ret;
+	unsigned res_cnt, i;
+	struct device_node *np = pdev->dev.of_node;
+	struct platform_device *pdev_child;
+	struct omap_ocp2scp_platform_data *pdata = pdev->dev.platform_data;
+	struct omap_ocp2scp_dev *dev;
 
 	if (np) {
 		ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
 		if (ret) {
-			dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n");
+			dev_err(&pdev->dev,
+			    "failed to add resources for ocp2scp child\n");
 			goto err0;
 		}
+	} else if (pdata) {
+		for (i = 0, dev = *pdata->devices; i < pdata->dev_cnt; i++,
+		    dev++) {
+			res_cnt = _count_resources(dev->res);
+
+			pdev_child = platform_device_alloc(dev->drv_name, -1);
+			if (!pdev_child) {
+				dev_err(&pdev->dev,
+				  "failed to allocate mem for ocp2scp child\n");
+				goto err0;
+			}
+
+			ret = platform_device_add_resources(pdev_child,
+			    dev->res, res_cnt);
+			if (ret) {
+				dev_err(&pdev->dev,
+				 "failed to add resources for ocp2scp child\n");
+				goto err1;
+			}
+
+			pdev_child->dev.parent	= &pdev->dev;
+
+			ret = platform_device_add(pdev_child);
+			if (ret) {
+				dev_err(&pdev->dev,
+				   "failed to register ocp2scp child device\n");
+				goto err1;
+			}
+		}
+	} else {
+		dev_err(&pdev->dev, "OCP2SCP initialized without plat data\n");
+		return -EINVAL;
 	}
+
 	pm_runtime_enable(&pdev->dev);
 
 	return 0;
 
+err1:
+	platform_device_put(pdev_child);
+
 err0:
 	device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices);
 
diff --git a/include/linux/platform_data/omap_ocp2scp.h b/include/linux/platform_data/omap_ocp2scp.h
new file mode 100644
index 0000000..5c6c393
--- /dev/null
+++ b/include/linux/platform_data/omap_ocp2scp.h
@@ -0,0 +1,31 @@
+/*
+ * omap_ocp2scp.h -- ocp2scp header file
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DRIVERS_OMAP_OCP2SCP_H
+#define __DRIVERS_OMAP_OCP2SCP_H
+
+struct omap_ocp2scp_dev {
+	const char			*drv_name;
+	struct resource			*res;
+};
+
+struct omap_ocp2scp_platform_data {
+	int				dev_cnt;
+	struct omap_ocp2scp_dev		**devices;
+};
+#endif /* __DRIVERS_OMAP_OCP2SCP_H */
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 2/3] ARM: OMAP4: add _dev_attr_ to ocp2scp for representing usb_phy
From: Kishon Vijay Abraham I @ 2012-10-08  5:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349675983-23803-1-git-send-email-kishon@ti.com>

In order to reflect devices(usb_phy) attached to ocp2scp bus, ocp2scp
is assigned a device attribute to represent the attached devices.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |   28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 652d028..cf579b5 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/power/smartreflex.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/i2c.h>
@@ -2681,6 +2682,32 @@ static struct omap_hwmod_class omap44xx_ocp2scp_hwmod_class = {
 	.sysc	= &omap44xx_ocp2scp_sysc,
 };
 
+/* ocp2scp dev_attr */
+static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
+	{
+		.name		= "usb_phy",
+		.start		= 0x4a0ad080,
+		.end		= 0x4a0ae000,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		/* XXX: Remove this once control module driver is in place */
+		.name		= "ctrl_dev",
+		.start		= 0x4a002300,
+		.end		= 0x4a002303,
+		.flags		= IORESOURCE_MEM,
+	},
+	{ }
+};
+
+static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = {
+	{
+		.drv_name       = "omap-usb2",
+		.res		= omap44xx_usb_phy_and_pll_addrs,
+	},
+	{ }
+};
+
 /* ocp2scp_usb_phy */
 static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
 	.name		= "ocp2scp_usb_phy",
@@ -2694,6 +2721,7 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
 			.modulemode   = MODULEMODE_HWCTRL,
 		},
 	},
+	.dev_attr	= ocp2scp_dev_attr,
 };
 
 /*
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 3/3] ARM: OMAP: ocp2scp: create omap device for ocp2scp
From: Kishon Vijay Abraham I @ 2012-10-08  5:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349675983-23803-1-git-send-email-kishon@ti.com>

Platfrom device for ocp2scp is created using omap_device_build in
devices file. This is used for both omap4(musb) and omap5(dwc3).

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 arch/arm/mach-omap2/devices.c |   76 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c8c2117..ac2bfce 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
@@ -613,6 +614,80 @@ static void omap_init_vout(void)
 static inline void omap_init_vout(void) {}
 #endif
 
+#if defined(CONFIG_OMAP_OCP2SCP) || defined(CONFIG_OMAP_OCP2SCP_MODULE)
+static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev)
+{
+	int cnt	= 0;
+
+	while (ocp2scp_dev->drv_name != NULL) {
+		cnt++;
+		ocp2scp_dev++;
+	}
+
+	return cnt;
+}
+
+static void omap_init_ocp2scp(void)
+{
+	struct omap_hwmod	*oh;
+	struct platform_device	*pdev;
+	int			bus_id = -1, dev_cnt = 0, i;
+	struct omap_ocp2scp_dev	*ocp2scp_dev;
+	const char		*oh_name, *name;
+	struct omap_ocp2scp_platform_data *pdata;
+
+	oh_name = "ocp2scp_usb_phy";
+	name	= "omap-ocp2scp";
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("%s: could not find omap_hwmod for %s\n", __func__,
+								oh_name);
+		return;
+	}
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for ocp2scp pdata\n", __func__);
+		return;
+	}
+
+	ocp2scp_dev = oh->dev_attr;
+	dev_cnt = count_ocp2scp_devices(ocp2scp_dev);
+
+	if (!dev_cnt) {
+		pr_err("%s: No devices connected to ocp2scp\n", __func__);
+		kfree(pdata);
+		return;
+	}
+
+	pdata->devices = kzalloc(sizeof(struct omap_ocp2scp_dev *)
+					* dev_cnt, GFP_KERNEL);
+	if (!pdata->devices) {
+		pr_err("%s: No memory for ocp2scp pdata devices\n", __func__);
+		kfree(pdata);
+		return;
+	}
+
+	for (i = 0; i < dev_cnt; i++, ocp2scp_dev++)
+		pdata->devices[i] = ocp2scp_dev;
+
+	pdata->dev_cnt	= dev_cnt;
+
+	pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata), NULL,
+								0, false);
+	if (IS_ERR(pdev)) {
+		pr_err("Could not build omap_device for %s %s\n",
+						name, oh_name);
+		kfree(pdata->devices);
+		kfree(pdata);
+		return;
+	}
+}
+#else
+static inline void omap_init_ocp2scp(void) { }
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)
@@ -640,6 +715,7 @@ static int __init omap2_init_devices(void)
 	omap_init_sham();
 	omap_init_aes();
 	omap_init_vout();
+	omap_init_ocp2scp();
 
 	return 0;
 }
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] ARM: imx6q: let users input debug uart port number
From: Shawn Guo @ 2012-10-08  6:06 UTC (permalink / raw)
  To: linux-arm-kernel

imx6q gets 5 uart ports in total.  Different board design may choose
different port as debug uart.  For example, imx6q-sabresd uses UART1,
imx6q-sabrelite uses UART2 and imx6q-arm2 uses UART4.  Rather than
bloating DEBUG_LL choice list with all these uart ports, the patch
introduces DEBUG_IMX6Q_UART_PORT for users to input uart port number
when DEBUG_IMX6Q_UART is selected inside DEBUG_LL choice.

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
---
 arch/arm/Kconfig.debug       |   26 +++++++++++++-------------
 arch/arm/include/debug/imx.S |   20 ++++++++++++++++----
 arch/arm/mach-imx/lluart.c   |   28 ++++++++++++++++++----------
 arch/arm/mach-imx/mx6q.h     |    4 ----
 4 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 5566520..5dc7109 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -209,20 +209,12 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on i.MX50 or i.MX53.
 
-	config DEBUG_IMX6Q_UART2
-		bool "i.MX6Q Debug UART2"
+	config DEBUG_IMX6Q_UART
+		bool "i.MX6Q Debug UART"
 		depends on SOC_IMX6Q
 		help
 		  Say Y here if you want kernel low-level debugging support
-		  on i.MX6Q UART2. This is correct for e.g. the SabreLite
-                  board.
-
-	config DEBUG_IMX6Q_UART4
-		bool "i.MX6Q Debug UART4"
-		depends on SOC_IMX6Q
-		help
-		  Say Y here if you want kernel low-level debugging support
-		  on i.MX6Q UART4.
+		  on i.MX6Q.
 
 	config DEBUG_MMP_UART2
 		bool "Kernel low-level debugging message via MMP UART2"
@@ -409,6 +401,15 @@ choice
 
 endchoice
 
+config DEBUG_IMX6Q_UART_PORT
+	int "i.MX6Q Debug UART Port (1-5)" if DEBUG_IMX6Q_UART
+	range 1 5
+	default 1
+	depends on SOC_IMX6Q
+	help
+	  Choose UART port on which kernel low-level debug messages
+	  should be output.
+
 config DEBUG_LL_INCLUDE
 	string
 	default "debug/icedcc.S" if DEBUG_ICEDCC
@@ -418,8 +419,7 @@ config DEBUG_LL_INCLUDE
 				 DEBUG_IMX31_IMX35_UART || \
 				 DEBUG_IMX51_UART || \
 				 DEBUG_IMX50_IMX53_UART ||\
-				 DEBUG_IMX6Q_UART2 || \
-				 DEBUG_IMX6Q_UART4
+				 DEBUG_IMX6Q_UART
 	default "debug/highbank.S" if DEBUG_HIGHBANK_UART
 	default "debug/mvebu.S" if DEBUG_MVEBU_UART
 	default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
diff --git a/arch/arm/include/debug/imx.S b/arch/arm/include/debug/imx.S
index 0b65d79..0c4e17d 100644
--- a/arch/arm/include/debug/imx.S
+++ b/arch/arm/include/debug/imx.S
@@ -10,6 +10,20 @@
  * published by the Free Software Foundation.
  *
  */
+#define IMX6Q_UART1_BASE_ADDR	0x02020000
+#define IMX6Q_UART2_BASE_ADDR	0x021e8000
+#define IMX6Q_UART3_BASE_ADDR	0x021ec000
+#define IMX6Q_UART4_BASE_ADDR	0x021f0000
+#define IMX6Q_UART5_BASE_ADDR	0x021f4000
+
+/*
+ * IMX6Q_UART_BASE_ADDR is put in the middle to force the expansion
+ * of IMX6Q_UART##n##_BASE_ADDR.
+ */
+#define IMX6Q_UART_BASE_ADDR(n)	IMX6Q_UART##n##_BASE_ADDR
+#define IMX6Q_UART_BASE(n)	IMX6Q_UART_BASE_ADDR(n)
+#define IMX6Q_DEBUG_UART_BASE	IMX6Q_UART_BASE(CONFIG_DEBUG_IMX6Q_UART_PORT)
+
 #ifdef CONFIG_DEBUG_IMX1_UART
 #define UART_PADDR	0x00206000
 #elif defined (CONFIG_DEBUG_IMX25_UART)
@@ -22,10 +36,8 @@
 #define UART_PADDR	0x73fbc000
 #elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
 #define UART_PADDR	0x53fbc000
-#elif defined (CONFIG_DEBUG_IMX6Q_UART2)
-#define UART_PADDR	0x021e8000
-#elif defined (CONFIG_DEBUG_IMX6Q_UART4)
-#define UART_PADDR	0x021f0000
+#elif defined (CONFIG_DEBUG_IMX6Q_UART)
+#define UART_PADDR	IMX6Q_DEBUG_UART_BASE
 #endif
 
 /*
diff --git a/arch/arm/mach-imx/lluart.c b/arch/arm/mach-imx/lluart.c
index 5f15103..2fdc9bf 100644
--- a/arch/arm/mach-imx/lluart.c
+++ b/arch/arm/mach-imx/lluart.c
@@ -17,17 +17,25 @@
 
 #include "hardware.h"
 
+#define IMX6Q_UART1_BASE_ADDR	0x02020000
+#define IMX6Q_UART2_BASE_ADDR	0x021e8000
+#define IMX6Q_UART3_BASE_ADDR	0x021ec000
+#define IMX6Q_UART4_BASE_ADDR	0x021f0000
+#define IMX6Q_UART5_BASE_ADDR	0x021f4000
+
+/*
+ * IMX6Q_UART_BASE_ADDR is put in the middle to force the expansion
+ * of IMX6Q_UART##n##_BASE_ADDR.
+ */
+#define IMX6Q_UART_BASE_ADDR(n)	IMX6Q_UART##n##_BASE_ADDR
+#define IMX6Q_UART_BASE(n)	IMX6Q_UART_BASE_ADDR(n)
+#define IMX6Q_DEBUG_UART_BASE	IMX6Q_UART_BASE(CONFIG_DEBUG_IMX6Q_UART_PORT)
+
 static struct map_desc imx_lluart_desc = {
-#ifdef CONFIG_DEBUG_IMX6Q_UART2
-	.virtual	= MX6Q_IO_P2V(MX6Q_UART2_BASE_ADDR),
-	.pfn		= __phys_to_pfn(MX6Q_UART2_BASE_ADDR),
-	.length		= MX6Q_UART2_SIZE,
-	.type		= MT_DEVICE,
-#endif
-#ifdef CONFIG_DEBUG_IMX6Q_UART4
-	.virtual	= MX6Q_IO_P2V(MX6Q_UART4_BASE_ADDR),
-	.pfn		= __phys_to_pfn(MX6Q_UART4_BASE_ADDR),
-	.length		= MX6Q_UART4_SIZE,
+#ifdef CONFIG_DEBUG_IMX6Q_UART
+	.virtual	= IMX_IO_P2V(IMX6Q_DEBUG_UART_BASE),
+	.pfn		= __phys_to_pfn(IMX6Q_DEBUG_UART_BASE),
+	.length		= 0x4000,
 	.type		= MT_DEVICE,
 #endif
 };
diff --git a/arch/arm/mach-imx/mx6q.h b/arch/arm/mach-imx/mx6q.h
index f7e7dba..19d3f54 100644
--- a/arch/arm/mach-imx/mx6q.h
+++ b/arch/arm/mach-imx/mx6q.h
@@ -27,9 +27,5 @@
 #define MX6Q_CCM_SIZE			0x4000
 #define MX6Q_ANATOP_BASE_ADDR		0x020c8000
 #define MX6Q_ANATOP_SIZE		0x1000
-#define MX6Q_UART2_BASE_ADDR		0x021e8000
-#define MX6Q_UART2_SIZE			0x4000
-#define MX6Q_UART4_BASE_ADDR		0x021f0000
-#define MX6Q_UART4_SIZE			0x4000
 
 #endif	/* __MACH_MX6Q_H__ */
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v2 00/14] OMAP-GPMC related cleanup for common zImage
From: Mohammed, Afzal @ 2012-10-08  6:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1349672877.git.afzal@ti.com>

Hi Ivan,

On Mon, Oct 08, 2012 at 11:05:56, Mohammed, Afzal wrote:

> This series cleans up omap-gpmc related code so that omap can
> be a part of common zImage.

> This series moves gpmc.h from plat-omap/include/plat to mach-omap2
> so that header file is local.

> Patches 7 & 8 cleans up the already moved platform data header files
> to contain only platform data. Also gpmc-nand information is moved
> to nand platform data header.
> 
> Patches 9-13 makes nand driver independent of gpmc header file
> 
> And the final patch localizes gpmc header.

BCH[48] support that you have added on OMAP using gpmc exported
symbols has been changed such that nand driver now takes care
of BCH support without relying on gpmc exported symbols.

This is more or less a cut & paste of your implementation, which was
necessitated now due to common ARM zImage cleanup w.r.t header files.

Please verify that BCH[48] works as earlier with this series.

Regards
Afzal

> This series is available
>         @ git://gitorious.org/x0148406-public/linux-kernel.git gpmc-czimage-v2
> and is based on
>         linux-next (next-20121005)
> and is dependent on
> 	http://marc.info/?l=linux-omap&m=134945131602622&w=2

^ permalink raw reply

* [PATCH 0/2] ARM: Exynos4: Migrate to common clock framework.
From: Thomas Abraham @ 2012-10-08  6:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2779610.RIGYtRk86h@amdc1227>

Hi Tomasz,

Thanks for reviewing this patch series.

On 3 October 2012 16:26, Tomasz Figa <t.figa@samsung.com> wrote:
> Hi Chander, Thomas,
>
> On Monday 01 of October 2012 17:39:19 chander.kashyap at linaro.org wrote:
>> From: Thomas Abraham <thomas.abraham@linaro.org>
>>
>> This patch series migrates Exynos4 clock support to common clock
>> framework. The first patch in this series removes the existing Exynos4
>> clock support that uses the Samsung specific clock framework. The second
>> patch in this series add Exynos4 clock support using common clock
>> framework.
>>
>> Thomas Abraham (2):
>>   ARM: Exynos4: Remove Samsung clock type support
>>   ARM: Exynos4: Register clocks via common clock framework
>
> I think the order of changes is a little bit off here:
>  - patch 1 will break all exynos4-based boards (what about bisects?)
>  - patch 2 will be still broken until all related drivers get converted to
> use clk_prepare(_enable) and clk_(disable_)unprepare.

Ok. I got the sequence wrong and I have fixed this in the next version.

>
> Shouldn't the order be exactly opposite, i.e.:
>  - all the patches for prepare/unprepare first
>  - then the patch adding common clock frameworks support for exynos4
> (disabling the old clock code)
>  - and finally the patch removing remaining (disabled by previous patch)
> code.

Right.

>
> Also, I assume that these patches doesn't consider native device tree
> support (without auxdata, using OF-based clock lookup), correct me if I'm
> wrong. If I'm right, since Exynos SoCs are going to be DT-only, is there
> really a point for adding common clock framework support for non-DT
> platforms (which are going to be eventually dropped anyway)?

The non-dt Exynos4 platforms require some effort to get basic device
tree support into them. Until then, the common clock support for them
are required. I have added device tree support as well in the second
version of this patch series.

Thanks,
Thomas.

>
> Best regards,
> --
> Tomasz Figa
> Samsung Poland R&D Center
>

^ permalink raw reply

* [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework
From: Thomas Abraham @ 2012-10-08  6:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3324947.79dxGcG09s@amdc1227>

Hi Tomasz,

On 3 October 2012 17:25, Tomasz Figa <t.figa@samsung.com> wrote:
> Hi Chander, Thomas,
>
> I think this patch could be split into several smaller, while retaining logical integrity of particular patches, e.g.:
>  - the change introduced to __clk_init (with proper description and rationale why the generic code is being touched)
>  - generic exynos4 code
>  - exynos4210-specific code
>  - exynos4x12-specific code
>  - patch enabling common clock framework on exynos4.
>
> Also, see some nitpicks inline.
>
> On Monday 01 of October 2012 17:39:21 chander.kashyap at linaro.org wrote:
>> From: Thomas Abraham <thomas.abraham@linaro.org>
>>
>> Register clocks for Exynos4 platfotms using common clock framework.
>> Also included are set of helper functions for clock registration
>> that can be reused on other Samsung platforms as well.
>>
>> Cc: Mike Turquette <mturquette@linaro.org>
>> Cc: Kukjin Kim <kgene.kim@samsung.com>
>> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
>> ---
>>  arch/arm/mach-exynos/Kconfig      |    1 +
>>  arch/arm/mach-exynos/common.h     |    3 +
>>  arch/arm/mach-exynos/mct.c        |   11 +-
>>  arch/arm/plat-samsung/Kconfig     |    4 +-
>>  drivers/clk/Makefile              |    1 +
>>  drivers/clk/clk.c                 |   12 +-
>>  drivers/clk/samsung/Makefile      |    6 +
>>  drivers/clk/samsung/clk-exynos4.c |  585
>> +++++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk.c
>> |  231 +++++++++++++++
>>  drivers/clk/samsung/clk.h         |  190 ++++++++++++
>>  10 files changed, 1037 insertions(+), 7 deletions(-)
>>  create mode 100644 drivers/clk/samsung/Makefile
>>  create mode 100644 drivers/clk/samsung/clk-exynos4.c
>>  create mode 100644 drivers/clk/samsung/clk.c
>>  create mode 100644 drivers/clk/samsung/clk.h
>>
>> diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
>> index b5b4c8c..4866ec7 100644
>> --- a/arch/arm/mach-exynos/Kconfig
>> +++ b/arch/arm/mach-exynos/Kconfig
>> @@ -15,6 +15,7 @@ config ARCH_EXYNOS4
>>       bool "SAMSUNG EXYNOS4"
>>       default y
>>       select HAVE_SMP
>> +     select COMMON_CLK
>>       select MIGHT_HAVE_CACHE_L2X0
>>       help
>>         Samsung EXYNOS4 SoCs based systems
>> diff --git a/arch/arm/mach-exynos/common.h
>> b/arch/arm/mach-exynos/common.h index aed2eeb..2274431 100644
>> --- a/arch/arm/mach-exynos/common.h
>> +++ b/arch/arm/mach-exynos/common.h
>> @@ -21,6 +21,9 @@ void exynos4_restart(char mode, const char *cmd);
>>  void exynos5_restart(char mode, const char *cmd);
>>  void exynos_init_late(void);
>>
>> +void exynos4210_clk_init(void);
>> +void exynos4212_clk_init(void);
>
> exynos4x12_clk_init?
>
>> +
>>  #ifdef CONFIG_PM_GENERIC_DOMAINS
>>  int exynos_pm_late_initcall(void);
>>  #else
>> diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
>> index b601fb8..a7cace0 100644
>> --- a/arch/arm/mach-exynos/mct.c
>> +++ b/arch/arm/mach-exynos/mct.c
>> @@ -30,6 +30,8 @@
>>  #include <mach/regs-mct.h>
>>  #include <asm/mach/time.h>
>>
>> +#include "common.h"
>> +
>>  #define TICK_BASE_CNT        1
>>
>>  enum {
>> @@ -457,7 +459,7 @@ static struct local_timer_ops exynos4_mct_tick_ops
>> __cpuinitdata = { static void __init exynos4_timer_resources(void)
>>  {
>>       struct clk *mct_clk;
>> -     mct_clk = clk_get(NULL, "xtal");
>> +     mct_clk = clk_get(NULL, "fin_pll");
>>
>>       clk_rate = clk_get_rate(mct_clk);
>>
>> @@ -478,6 +480,13 @@ static void __init exynos4_timer_resources(void)
>>
>>  static void __init exynos4_timer_init(void)
>>  {
>> +#ifdef CONFIG_COMMON_CLK
>> +     if (soc_is_exynos4210())
>> +             exynos4210_clk_init();
>> +     else if (soc_is_exynos4212() || soc_is_exynos4412())
>> +             exynos4212_clk_init();
>
> exynos4x12_clk_init?

Ok.

>
>> +#endif
>> +
>>       if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
>>               mct_int_type = MCT_INT_SPI;
>>       else
>> diff --git a/arch/arm/plat-samsung/Kconfig
>> b/arch/arm/plat-samsung/Kconfig index 9c3b90c..35b4cb8 100644
>> --- a/arch/arm/plat-samsung/Kconfig
>> +++ b/arch/arm/plat-samsung/Kconfig
>> @@ -26,7 +26,7 @@ config PLAT_S5P
>>       select S5P_GPIO_DRVSTR
>>       select SAMSUNG_GPIOLIB_4BIT
>>       select PLAT_SAMSUNG
>> -     select SAMSUNG_CLKSRC
>> +     select SAMSUNG_CLKSRC if !COMMON_CLK
>>       select SAMSUNG_IRQ_VIC_TIMER
>>       help
>>         Base platform code for Samsung's S5P series SoC.
>> @@ -89,7 +89,7 @@ config SAMSUNG_CLKSRC
>>         used by newer systems such as the S3C64XX.
>>
>>  config S5P_CLOCK
>> -     def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
>> +     def_bool ((ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
>> && !COMMON_CLK) help
>>         Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
>>
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 6327536..5f5b060 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_MMP)              += mmp/
>>  endif
>>  obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
>>  obj-$(CONFIG_ARCH_U8500)     += ux500/
>> +obj-$(CONFIG_PLAT_SAMSUNG)   += samsung/
>>
>>  # Chip specific
>>  obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>> index 56e4495..456c50b 100644
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -1196,6 +1196,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
>>  int __clk_init(struct device *dev, struct clk *clk)
>>  {
>>       int i, ret = 0;
>> +     u8 index;
>>       struct clk *orphan;
>>       struct hlist_node *tmp, *tmp2;
>>
>> @@ -1259,6 +1260,7 @@ int __clk_init(struct device *dev, struct clk *clk)
>> __clk_lookup(clk->parent_names[i]);
>>       }
>>
>> +
>
>
> Unnecessary extra blank line?

Ok.

>
>>       clk->parent = __clk_init_parent(clk);
>>
>>       /*
>> @@ -1298,11 +1300,13 @@ int __clk_init(struct device *dev, struct clk
>> *clk) * this clock
>>        */
>>       hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list,
>> child_node) -         for (i = 0; i < orphan->num_parents; i++)
>> -                     if (!strcmp(clk->name, orphan->parent_names[i])) {
>> +             if (orphan->num_parents > 1) {
>> +                     index = orphan->ops->get_parent(orphan->hw);
>> +                     if (!strcmp(clk->name, orphan->parent_names[index]))
>>                               __clk_reparent(orphan, clk);
>> -                             break;
>> -                     }
>> +             } else if (!strcmp(clk->name, orphan->parent_names[0])) {
>> +                     __clk_reparent(orphan, clk);
>> +             }
>>
>>       /*
>>        * optional platform-specific magic
>> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
>> new file mode 100644
>> index 0000000..69487f7
>> --- /dev/null
>> +++ b/drivers/clk/samsung/Makefile
>> @@ -0,0 +1,6 @@
>> +#
>> +# Samsung Clock specific Makefile
>> +#
>> +
>> +obj-$(CONFIG_PLAT_SAMSUNG)   += clk.o
>> +obj-$(CONFIG_ARCH_EXYNOS4)   += clk-exynos4.o
>> diff --git a/drivers/clk/samsung/clk-exynos4.c
>> b/drivers/clk/samsung/clk-exynos4.c new file mode 100644
>> index 0000000..74a6f03
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk-exynos4.c
>> @@ -0,0 +1,585 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * Common Clock Framework support for all Exynos4 platforms
>> +*/
>> +
>> +#include <linux/clk.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/io.h>
>> +#include <linux/clk-provider.h>
>> +
>> +#include <plat/pll.h>
>> +#include <plat/cpu.h>
>> +#include <mach/regs-clock.h>
>> +#include <mach/sysmmu.h>
>> +#include <plat/map-s5p.h>
>> +
>> +#include "clk.h"
>> +
>> +#define EXYNOS4_OP_MODE              (S5P_VA_CHIPID + 8)
>> +
>> +static const char *pll_parent_names[] __initdata = { "fin_pll" };
>> +static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
>> +static const char *mout_apll_parents[] __initdata = { "fin_pll",
>> "fout_apll", }; +static const char *mout_mpll_parents[] __initdata = {
>> "fin_pll", "fout_mpll", }; +static const char *mout_epll_parents[]
>> __initdata = { "fin_pll", "fout_epll", }; +
>> +static const char *sclk_ampll_parents[] __initdata = {
>> +             "mout_mpll", "sclk_apll", };
>> +
>> +static const char *sclk_evpll_parents[] __initdata = {
>> +             "mout_epll", "mout_vpll", };
>> +
>> +static const char *mout_core_parents[] __initdata = {
>> +             "mout_apll", "mout_mpll", };
>> +
>> +static const char *mout_mfc_parents[] __initdata = {
>> +             "mout_mfc0", "mout_mfc1", };
>> +
>> +static const char *mout_dac_parents[] __initdata = {
>> +             "mout_vpll", "sclk_hdmiphy", };
>> +
>> +static const char *mout_hdmi_parents[] __initdata = {
>> +             "sclk_pixel", "sclk_hdmiphy", };
>> +
>> +static const char *mout_mixer_parents[] __initdata = {
>> +             "sclk_dac", "sclk_hdmi", };
>> +
>> +static const char *group1_parents[] __initdata = {
>> +             "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
>> +             "none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
>> +             "mout_vpll" };
>> +
>> +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
>> +     FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
>> +     FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
>> +     FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
>> +     FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
>> +     FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
>> +};
>> +
>> +static struct samsung_mux_clock exynos4_mux_clks[] = {
>> +     MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
>> +                     EXYNOS4_OP_MODE, 0, 1, 0),
>> +     MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
>> +                     EXYNOS4_CLKSRC_CPU, 0, 1, 0),
>> +     MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
>> +     MUXCLK(NULL, "mout_core", mout_core_parents, 0,
>> +                     EXYNOS4_CLKSRC_CPU, 16, 1, 0),
>> +     MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
>> +     MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
>> +     MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
>> +     MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
>> +     MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
>> +     MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
>> +     MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
>> +     MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
>> +     MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
>> +     MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
>> +     MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
>> +     MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
>> +     MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
>> +     MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
>> +     MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
>> +     MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
>> +     MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_MFC, 0, 1, 0),
>> +     MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
>> +                     EXYNOS4_CLKSRC_MFC, 4, 1, 0),
>> +     MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
>> +                     EXYNOS4_CLKSRC_MFC, 8, 1, 0),
>> +     MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 24, 4, 0),
>> +     MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 28, 4, 0),
>> +     MUXCLK(NULL, "mout_cam0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 16, 4, 0),
>> +     MUXCLK(NULL, "mout_cam1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 20, 4, 0),
>> +     MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 0, 4, 0),
>> +     MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 4, 4, 0),
>> +     MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 8, 4, 0),
>> +     MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 12, 4, 0),
>> +     MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
>> +     MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
>> +                     EXYNOS4_CLKSRC_TV, 8, 1, 0),
>> +     MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
>> +                     EXYNOS4_CLKSRC_TV, 0, 1, 0),
>> +     MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
>> +                     EXYNOS4_CLKSRC_TV, 4, 1, 0),
>> +};
>> +
>> +static struct samsung_div_clock exynos4_div_clks[] = {
>> +     DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
>> +                     EXYNOS4_CLKDIV_CPU, 24, 3, 0),
>> +     DIVCLK(NULL, "div_core", "mout_core", 0,
>> +                     EXYNOS4_CLKDIV_CPU, 0, 3, 0),
>> +     DIVCLK(NULL, "armclk", "div_core", 0,
>> +                     EXYNOS4_CLKDIV_CPU, 28, 3, 0),
>> +     DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
>> +                     EXYNOS4_CLKDIV_TOP, 0, 3, 0),
>> +     DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
>> +                     EXYNOS4_CLKDIV_TOP, 4, 4, 0),
>> +     DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
>> +                     EXYNOS4_CLKDIV_TOP, 8, 3, 0),
>> +     DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
>> +                     EXYNOS4_CLKDIV_TOP, 12, 3, 0),
>> +     DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
>> +                     EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
>> +     DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
>> +                     EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
>> +     DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
>> +                     EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
>> +     DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
>> +                     EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
>> +     DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
>> +     DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
>> +     DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
>> +     DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
>> +     DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
>> +     DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
>> +     DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
>> +     DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
>> +     DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
>> +                     EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
>> +     DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
>> +                     EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
>> +     DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
>> +                     EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
>> +     DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
>> +                     EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
>> +     DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
>> +                     EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
>> +     DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
>> +                     EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
>> +     DIVCLK(NULL, "div_sata", "mout_sata", 0,
>> +                     EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
>> +     DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
>> +                     EXYNOS4_CLKDIV_MFC, 0, 4, 0),
>> +     DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 24, 4, 0),
>> +     DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 28, 4, 0),
>> +     DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 16, 4, 0),
>> +     DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 20, 4, 0),
>> +     DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 0, 4, 0),
>> +     DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> +     DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> +     DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> +     DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
>> +                     EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
>> +     DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
>> +                     EXYNOS4_CLKDIV_TV, 0, 4, 0),
>> +};
>> +
>> +struct samsung_gate_clock exynos4_gate_clks[] = {
>> +     GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
>> +     GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
>> +     GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
>> +     GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
>> +     GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
>> +     GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
>> +     GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
>> +     GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
>> +     GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
>> +     GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
>> +     GATECLK(NULL, "timers", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
>> +     GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
>> +     GATECLK(NULL, "jpeg", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
>> +     GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
>> +     GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
>> +     GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
>> +     GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
>> +     GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
>> +     GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
>> +     GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
>> +     GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
>> +     GATECLK(NULL, "dwmmc", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
>> +     GATECLK("s5p-sdo", "dac", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 2, NULL),
>> +     GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 1, NULL),
>> +     GATECLK("s5p-mixer", "vp", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 0, NULL),
>> +     GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 3, NULL),
>> +     GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
>> +                     S5P_HDMI_PHY_CONTROL, 0, NULL),
>> +     GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
>> +                     S5P_DAC_PHY_CONTROL, 0, NULL),
>> +     GATECLK(NULL, "adc", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
>> +     GATECLK(NULL, "keypad", "aclk_100", 0,
>> +                     EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
>> +     GATECLK(NULL, "rtc", "aclk_100", 0,
>> +                     EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
>> +     GATECLK(NULL, "watchdog", "aclk_100", 0,
>> +                     EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
>> +     GATECLK(NULL, "usbhost", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
>> +     GATECLK(NULL, "otg", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
>> +     GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
>> +     GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
>> +     GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
>> +     GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
>> +     GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
>> +     GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
>> +     GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
>> +     GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
>> +     GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
>> +     GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
>> +     GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
>> +     GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
>> +     GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
>> +     GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
>> +     GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
>> +     GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
>> +     GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
>> +                     EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
>> +     GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
>> +     GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
>> +     GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
>> +     GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
>> +     GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
>> +     GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
>> +     GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
>> +     GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
>> +     GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
>> +     GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
>> +     GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
>> +     GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
>> +     GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
>> +     GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
>> +     GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
>
> +       GATECLK("exynos4-fimc.0", "sclk_fimc0", "div_fimc0", 0,
> +                       EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
>
>> +     GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
>
> +       GATECLK("exynos4-fimc.1", "sclk_fimc1", "div_fimc1", 0,
> +                       EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
>
>> +     GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
>
> +       GATECLK("exynos4-fimc.2", "sclk_fimc2", "div_fimc2", 0,
> +                       EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
>
>> +     GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
>
> +       GATECLK("exynos4-fimc.3", "sclk_fimc3", "div_fimc3", 0,
> +                       EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
>
>> +     GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
>> +                     EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
>> +};
>> +
>> +/* register clock common to all Exynos4 platforms */
>> +void __init exynos4_clk_init(void)
>> +{
>> +     samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
>> +                     ARRAY_SIZE(exynos4_fixed_rate_clks));
>> +     samsung_clk_register_mux(exynos4_mux_clks,
>> +                     ARRAY_SIZE(exynos4_mux_clks));
>> +     samsung_clk_register_div(exynos4_div_clks,
>> +                     ARRAY_SIZE(exynos4_div_clks));
>> +     samsung_clk_register_gate(exynos4_gate_clks,
>> +                     ARRAY_SIZE(exynos4_gate_clks));
>> +}
>> +
>> +/*
>> + * Exynos4210 Specific Clocks
>> + */
>> +
>> +static const char *exynos4210_vpll_parent_names[] __initdata = {
>> +             "mout_vpll_src" };
>> +static const char *mout_vpll_src_parents[] __initdata = {
>> +             "fin_pll", "sclk_hdmi24m" };
>> +static const char *exynos4210_mout_vpll_parents[] __initdata = {
>> +             "mout_vpll_src", "fout_vpll", };
>> +
>> +/* Exynos4210 specific fixed rate clocks */
>> +static struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] = {
>> +     FRATE_CLK(NULL, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
>> +};
>> +
>> +/* Exynos4210 specific mux-type clocks */
>> +static struct samsung_mux_clock exynos4210_mux_clks[] = {
>> +     MUXCLK(NULL, "mout_vpll_src", mout_vpll_src_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP1, 0, 1, 0),
>> +     MUXCLK(NULL, "mout_vpll", exynos4210_mout_vpll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
>> +     MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
>> +                     EXYNOS4_CLKSRC_CPU, 8, 1, 0),
>> +};
>> +
>> +static unsigned long exynos4210_get_rate_apll(unsigned long xtal_rate)
>> +{
>> +     return s5p_get_pll45xx(xtal_rate,
>> +             __raw_readl(EXYNOS4_APLL_CON0), pll_4508);
>> +}
>> +
>> +static unsigned long exynos4210_get_rate_mpll(unsigned long xtal_rate)
>> +{
>> +     return s5p_get_pll45xx(xtal_rate,
>> +             __raw_readl(EXYNOS4_MPLL_CON0), pll_4508);
>> +}
>> +
>> +static unsigned long exynos4210_get_rate_epll(unsigned long xtal_rate)
>> +{
>> +     return s5p_get_pll46xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
>> +             __raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
>> +}
>> +
>> +static unsigned long exynos4210_get_rate_vpll(unsigned long
>> vpllsrc_rate) +{
>> +     return s5p_get_pll46xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
>> +             __raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
>> +}
>> +
>> +static u32 exynos4_vpll_div[][8] = {
>> +     {  54000000, 3, 53, 3, 1024, 0, 17, 0 },
>> +     { 108000000, 3, 53, 2, 1024, 0, 17, 0 },
>> +};
>> +
>> +static int exynos4210_vpll_set_rate(unsigned long rate)
>> +{
>> +     unsigned int vpll_con0, vpll_con1 = 0;
>> +     unsigned int i;
>> +
>> +     vpll_con0 = __raw_readl(EXYNOS4_VPLL_CON0);
>> +     vpll_con0 &= ~(0x1 << 27 |                                      \
>> +                     PLL90XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |       \
>> +                     PLL90XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |       \
>> +                     PLL90XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
>> +
>> +     vpll_con1 = __raw_readl(EXYNOS4_VPLL_CON1);
>> +     vpll_con1 &= ~(PLL46XX_MRR_MASK << PLL46XX_MRR_SHIFT |  \
>> +                     PLL46XX_MFR_MASK << PLL46XX_MFR_SHIFT | \
>> +                     PLL4650C_KDIV_MASK << PLL46XX_KDIV_SHIFT);
>> +
>> +     for (i = 0; i < ARRAY_SIZE(exynos4_vpll_div); i++) {
>> +             if (exynos4_vpll_div[i][0] == rate) {
>> +                     vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
>> +                     vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
>> +                     vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
>> +                     vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
>> +                     vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
>> +                     vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
>> +                     vpll_con0 |= exynos4_vpll_div[i][7] << 27;
>> +                     break;
>> +             }
>> +     }
>> +
>> +     if (i == ARRAY_SIZE(exynos4_vpll_div)) {
>> +             pr_err("%s: Invalid Clock VPLL Frequency\n", __func__);
>> +             return -EINVAL;
>> +     }
>> +
>> +     __raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
>> +     __raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
>> +
>> +     /* Wait for VPLL lock */
>> +     while (!(__raw_readl(EXYNOS4_VPLL_CON0) & (1 << PLL46XX_LOCKED_SHIFT)))
>> +             continue;
>
> Is it guaranteed to lock in some reasonable time? Maybe some kind of
> timeout should be added?

Yes, a timeout mechanism is needed here. I have just migrated the
existing clock code over to common clock framework.

>
>> +
>> +     return 0;
>> +}
>> +
>> +/* Exynos4210 specific clock registration */
>> +void __init exynos4210_clk_init(void)
>> +{
>> +     group1_parents[4] = "sclk_usbphy1";
>> +
>> +     exynos4_clk_init();
>> +
>> +     samsung_clk_register_pll("fout_apll", pll_parent_names,
>> +             NULL, exynos4210_get_rate_apll);
>> +     samsung_clk_register_pll("fout_mpll", pll_parent_names,
>> +             NULL, exynos4210_get_rate_mpll);
>> +     samsung_clk_register_pll("fout_epll", pll_parent_names,
>> +             NULL, exynos4210_get_rate_epll);
>> +     samsung_clk_register_pll("fout_vpll", exynos4210_vpll_parent_names,
>> +             exynos4210_vpll_set_rate, exynos4210_get_rate_vpll);
>> +
>> +     samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
>> +                     ARRAY_SIZE(exynos4210_fixed_rate_clks));
>> +     samsung_clk_register_mux(exynos4210_mux_clks,
>> +                     ARRAY_SIZE(exynos4210_mux_clks));
>> +
>> +     pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
>> +             _get_rate("fout_apll"), _get_rate("fout_mpll"),
>> +             _get_rate("fout_epll"), _get_rate("fout_vpll"));
>> +
>> +     pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
>> +             "         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
>> +             _get_rate("aclk_200"), _get_rate("aclk_100"),
>> +             _get_rate("aclk_160"), _get_rate("aclk_133"));
>> +}
>> +
>> +/*
>> + * Exynos4212 Specific Clocks
>> + */
>> +
>> +static const char *exynos4212_mout_vpll_parents[] __initdata = {
>> +             "fin_pll", "fout_vpll", };
>> +
>> +/* Exynos4212 specific mux clocks */
>> +static struct samsung_mux_clock exynos4212_mux_clks[] = {
>> +     MUXCLK(NULL, "mout_mpll", mout_mpll_parents, 0,
>> +                     EXYNOS4_CLKSRC_DMC, 12, 1, 0),
>> +     MUXCLK(NULL, "mout_vpll", exynos4212_mout_vpll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 8, 1, 0),
>> +};
>> +
>> +static unsigned long exynos4212_get_rate_apll(unsigned long xtal_rate)
>> +{
>> +     return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
>> +}
>> +
>> +static unsigned long exynos4212_get_rate_mpll(unsigned long xtal_rate)
>> +{
>> +     return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_MPLL_CON0));
>> +}
>> +
>> +static unsigned long exynos4212_get_rate_epll(unsigned long xtal_rate)
>> +{
>> +     return s5p_get_pll36xx(xtal_rate, __raw_readl(EXYNOS4_EPLL_CON0),
>> +             __raw_readl(EXYNOS4_EPLL_CON1));
>> +}
>> +
>> +static unsigned long exynos4212_get_rate_vpll(unsigned long
>> vpllsrc_rate) +{
>> +     return s5p_get_pll36xx(vpllsrc_rate, __raw_readl(EXYNOS4_VPLL_CON0),
>> +             __raw_readl(EXYNOS4_VPLL_CON1));
>> +}
>> +
>> +/* Exynos4212 specific clock registeration */
>> +void __init exynos4212_clk_init(void)
>> +{
>> +     exynos4_clk_init();
>> +
>> +     samsung_clk_register_pll("fout_apll", pll_parent_names,
>> +             NULL, exynos4212_get_rate_apll);
>> +     samsung_clk_register_pll("fout_mpll", pll_parent_names,
>> +             NULL, exynos4212_get_rate_mpll);
>> +     samsung_clk_register_pll("fout_epll", pll_parent_names,
>> +             NULL, exynos4212_get_rate_epll);
>> +     samsung_clk_register_pll("fout_vpll", pll_parent_names,
>> +             NULL, exynos4212_get_rate_vpll);
>> +
>> +     samsung_clk_register_mux(exynos4212_mux_clks,
>> +                     ARRAY_SIZE(exynos4212_mux_clks));
>> +
>> +     pr_info("EXYNOS4210: PLL settings: A=%ld, M=%ld, E=%ld, V=%ld\n",
>> +             _get_rate("fout_apll"), _get_rate("fout_mpll"),
>> +             _get_rate("fout_epll"), _get_rate("fout_vpll"));
>> +
>> +     pr_info("EXYNOS4210: ARMCLK=%ld, ACLK200=%ld, ACLK100=%ld\n"
>> +             "         ACLK160=%ld, ACLK133=%ld\n", _get_rate("armclk"),
>> +             _get_rate("aclk_200"), _get_rate("aclk_100"),
>> +             _get_rate("aclk_160"), _get_rate("aclk_133"));
>> +}
>> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
>> new file mode 100644
>> index 0000000..65156b9
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk.c
>> @@ -0,0 +1,231 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This file includes utility functions to register clocks to common
>> + * clock framework for Samsung platforms. This includes an
>> implementation + * of Samsung 'pll type' clock to represent the
>> implementation of the + * pll found on Samsung platforms. In addition to
>> that, utility functions + * to register mux, div, gate and fixed rate
>> types of clocks are included. +*/
>> +
>> +#include "clk.h"
>> +
>> +static DEFINE_SPINLOCK(lock);
>> +
>> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
>> +
>> +/* determine the output clock speed of the pll */
>> +static unsigned long samsung_clk_pll_recalc_rate(struct clk_hw *hw,
>> +                             unsigned long parent_rate)
>> +{
>> +     struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
>> +
>> +     if (clk_pll->get_rate)
>> +             return to_clk_pll(hw)->get_rate(parent_rate);
>> +
>> +     return 0;
>> +}
>> +
>> +/* round operation not supported */
>> +static long samsung_clk_pll_round_rate(struct clk_hw *hw, unsigned long
>> drate, +                              unsigned long *prate)
>> +{
>> +     return samsung_clk_pll_recalc_rate(hw, *prate);
>> +}
>> +
>> +/* set the clock output rate of the pll */
>> +static int samsung_clk_pll_set_rate(struct clk_hw *hw, unsigned long
>> drate, +                              unsigned long prate)
>> +{
>> +     struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
>> +
>> +     if (clk_pll->set_rate)
>> +             return to_clk_pll(hw)->set_rate(drate);
>> +
>> +     return 0;
>> +}
>> +
>> +/* clock operations for samsung pll clock type */
>> +static const struct clk_ops samsung_clk_pll_ops = {
>> +     .recalc_rate = samsung_clk_pll_recalc_rate,
>> +     .round_rate = samsung_clk_pll_round_rate,
>> +     .set_rate = samsung_clk_pll_set_rate,
>> +};
>> +
>> +/* register a samsung pll type clock */
>> +void __init samsung_clk_register_pll(const char *name, const char
>> **pnames, +                           int (*set_rate)(unsigned long rate),
>> +                             unsigned long (*get_rate)(unsigned long rate))
>> +{
>> +     struct samsung_clk_pll *clk_pll;
>> +     struct clk *clk;
>> +     struct clk_init_data init;
>> +     int ret;
>> +
>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>> +     if (!clk_pll) {
>> +             pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>> +             return;
>> +     }
>> +
>> +     init.name = name;
>> +     init.ops = &samsung_clk_pll_ops;
>> +     init.flags = CLK_GET_RATE_NOCACHE;
>> +     init.parent_names = pnames;
>> +     init.num_parents = 1;
>> +
>> +     clk_pll->set_rate = set_rate;
>> +     clk_pll->get_rate = get_rate;
>> +     clk_pll->hw.init = &init;
>> +
>> +     /* register the clock */
>> +     clk = clk_register(NULL, &clk_pll->hw);
>> +     if (IS_ERR(clk)) {
>> +             pr_err("%s: failed to register pll clock %s\n", __func__,
>> +                             name);
>> +             kfree(clk_pll);
>> +             return;
>> +     }
>> +
>> +     ret = clk_register_clkdev(clk, name, NULL);
>> +     if (ret)
>> +             pr_err("%s: failed to register clock lookup for %s", __func__,
>> +                             name);
>> +}
>> +
>> +/* register a list of fixed clocks */
>> +void __init samsung_clk_register_fixed_rate(
>> +             struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_fixed_rate(NULL, clk_list->name,
>> +                             clk_list->parent_name, clk_list->flags,
>> +                             clk_list->fixed_rate);
>> +             if (IS_ERR_OR_NULL(clk)) {
>
> Is the check for NULL needed here? Looking at samsung_fixed_rate_clock
> and clk_register, the convention is to always return ERR_PTR on error.

Ok, check for NULL is not really required. I will remove it.

>
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +     }
>> +}
>> +
>> +/* register a list of mux clocks */
>> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_mux(NULL, clk_list->name,
>> +                     clk_list->parent_names, clk_list->num_parents,
>> +                     clk_list->flags, clk_list->reg, clk_list->shift,
>> +                     clk_list->width, clk_list->mux_flags, &lock);
>> +             if (IS_ERR_OR_NULL(clk)) {
>
> See my comment for samsung_clk_register_fixed_rate .
>
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +
>> +             if (clk_list->alias)
>> +                     clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +     }
>> +}
>> +
>> +/* reguster a list of div clocks */
>> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_divider(NULL, clk_list->name,
>> +                     clk_list->parent_name, clk_list->flags, clk_list->reg,
>> +                     clk_list->shift, clk_list->width, clk_list->div_flags,
>> +                     &lock);
>> +             if (IS_ERR_OR_NULL(clk)) {
>
> See my comment for samsung_clk_register_fixed_rate .
>
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +
>> +             if (clk_list->alias)
>> +                     clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +     }
>> +}
>> +
>> +/* register a list of gate clocks */
>> +void __init samsung_clk_register_gate(struct samsung_gate_clock
>> *clk_list, +                                          unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx < nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_gate(NULL, clk_list->name,
>> +                     clk_list->parent_name, clk_list->flags, clk_list->reg,
>> +                     clk_list->bit_idx, clk_list->gate_flags, &lock);
>> +             if (IS_ERR_OR_NULL(clk)) {
>
> See my comment for samsung_clk_register_fixed_rate .
>
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret) {
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register alias %s for clock "
>> +                                     " %s", clk_list->alias, clk_list->name);
>> +     }
>> +}
>> +
>> +/* utility function to get the rate of a specified clock */
>> +unsigned long _get_rate(const char *clk_name)
>> +{
>> +     struct clk *clk;
>> +     unsigned long rate;
>> +
>> +     clk = clk_get(NULL, clk_name);
>> +     if (IS_ERR(clk))
>> +             return 0;
>> +     rate = clk_get_rate(clk);
>> +     clk_put(clk);
>> +     return rate;
>> +}
>
> Shouldn't it be moved to clk-exynos4.c and made static?

This can be used on any platform and not just specific to Exynos4.

Thanks,
Thomas.

>
> Best regards,
> --
> Tomasz Figa
> Samsung Poland R&D Center
>

^ permalink raw reply

* [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework
From: Thomas Abraham @ 2012-10-08  6:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <2552746.GKROWAIKW8@amdc1227>

Hi Tomasz,

On 3 October 2012 19:40, Tomasz Figa <t.figa@samsung.com> wrote:
> Hi Chander, Thomas,
>
> I can see one more problem here.
>
> Based on the fact that sdhci-s3c driver receives only the endpoint gate
> clock (hsmmc), doesn't the following setup make the driver unable to change
> the frequency of this clock?

The driver never changes the clock frequency of the core system clocks
nor of the endpoint. There are internal dividers inside the sdhci
controller which are divide to acheive required clock speed.

Thanks,
Thomas.

>
> On Monday 01 of October 2012 17:39:21 chander.kashyap at linaro.org wrote:
>> +static struct samsung_mux_clock exynos4_mux_clks[] = {
> [snip]
>> +     MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
>> +     MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
>> +     MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
>> +     MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
> [snip]
>> +};
>> +
>> +static struct samsung_div_clock exynos4_div_clks[] = {
> [snip]
>> +     DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
>> +     DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
>> +     DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
>> +     DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
>> +     DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
>> +     DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
>> +     DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
>> +     DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
> [snip]
>> +};
>> +
>> +struct samsung_gate_clock exynos4_gate_clks[] = {
> [snip]
>> +     GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
>> +     GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
>> +     GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
>> +     GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
> [snip]
>> +};
>
> Best regards,
> --
> Tomasz Figa
> Samsung Poland R&D Center
>

^ permalink raw reply

* [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework
From: Thomas Abraham @ 2012-10-08  6:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <506EFB06.7010201@gmail.com>

Hi Sylwester,

Thanks for reviewing this patch series.

On 6 October 2012 00:21, Sylwester Nawrocki
<sylvester.nawrocki@gmail.com> wrote:
> Hello,
>
> On 10/01/2012 02:09 PM, chander.kashyap at linaro.org wrote:
>> From: Thomas Abraham<thomas.abraham@linaro.org>
>>
>> Register clocks for Exynos4 platfotms using common clock framework.
>> Also included are set of helper functions for clock registration
>> that can be reused on other Samsung platforms as well.
>>
>> Cc: Mike Turquette<mturquette@linaro.org>
>> Cc: Kukjin Kim<kgene.kim@samsung.com>
>> Signed-off-by: Thomas Abraham<thomas.abraham@linaro.org>
>> ---
>>   arch/arm/mach-exynos/Kconfig      |    1 +
>>   arch/arm/mach-exynos/common.h     |    3 +
>>   arch/arm/mach-exynos/mct.c        |   11 +-
>>   arch/arm/plat-samsung/Kconfig     |    4 +-
>>   drivers/clk/Makefile              |    1 +
>>   drivers/clk/clk.c                 |   12 +-
>>   drivers/clk/samsung/Makefile      |    6 +
>>   drivers/clk/samsung/clk-exynos4.c |  585 +++++++++++++++++++++++++++++++++++++
>>   drivers/clk/samsung/clk.c         |  231 +++++++++++++++
>>   drivers/clk/samsung/clk.h         |  190 ++++++++++++
>>   10 files changed, 1037 insertions(+), 7 deletions(-)
>>   create mode 100644 drivers/clk/samsung/Makefile
>>   create mode 100644 drivers/clk/samsung/clk-exynos4.c
>>   create mode 100644 drivers/clk/samsung/clk.c
>>   create mode 100644 drivers/clk/samsung/clk.h
> ...
>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>> index 56e4495..456c50b 100644
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -1196,6 +1196,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
>>   int __clk_init(struct device *dev, struct clk *clk)
>>   {
>>       int i, ret = 0;
>> +     u8 index;
>>       struct clk *orphan;
>>       struct hlist_node *tmp, *tmp2;
>>
>> @@ -1259,6 +1260,7 @@ int __clk_init(struct device *dev, struct clk *clk)
>>                                       __clk_lookup(clk->parent_names[i]);
>>       }
>>
>> +
>>       clk->parent = __clk_init_parent(clk);
>>
>>       /*
>> @@ -1298,11 +1300,13 @@ int __clk_init(struct device *dev, struct clk *clk)
>>        * this clock
>>        */
>>       hlist_for_each_entry_safe(orphan, tmp, tmp2,&clk_orphan_list, child_node)
>> -             for (i = 0; i<  orphan->num_parents; i++)
>> -                     if (!strcmp(clk->name, orphan->parent_names[i])) {
>> +             if (orphan->num_parents>  1) {
>> +                     index = orphan->ops->get_parent(orphan->hw);
>> +                     if (!strcmp(clk->name, orphan->parent_names[index]))
>>                               __clk_reparent(orphan, clk);
>> -                             break;
>> -                     }
>> +             } else if (!strcmp(clk->name, orphan->parent_names[0])) {
>> +                     __clk_reparent(orphan, clk);
>> +             }
>
> As this touches generic code it should rather be put into a separate patch,
> along with an explanation why such a change is needed.

There is fix for this in mainline now.

>
>>
>>       /*
>>        * optional platform-specific magic
>> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
>> new file mode 100644
>> index 0000000..69487f7
>> --- /dev/null
>> +++ b/drivers/clk/samsung/Makefile
>> @@ -0,0 +1,6 @@
>> +#
>> +# Samsung Clock specific Makefile
>> +#
>> +
>> +obj-$(CONFIG_PLAT_SAMSUNG)   += clk.o
>> +obj-$(CONFIG_ARCH_EXYNOS4)   += clk-exynos4.o
>> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
>> new file mode 100644
>> index 0000000..74a6f03
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk-exynos4.c
>> @@ -0,0 +1,585 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * Common Clock Framework support for all Exynos4 platforms
>> +*/
>> +
>> +#include<linux/clk.h>
>> +#include<linux/clkdev.h>
>> +#include<linux/io.h>
>> +#include<linux/clk-provider.h>
>> +
>> +#include<plat/pll.h>
>> +#include<plat/cpu.h>
>> +#include<mach/regs-clock.h>
>> +#include<mach/sysmmu.h>
>> +#include<plat/map-s5p.h>
>> +
>> +#include "clk.h"
>> +
>> +#define EXYNOS4_OP_MODE              (S5P_VA_CHIPID + 8)
>> +
>> +static const char *pll_parent_names[] __initdata = { "fin_pll" };
>> +static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
>> +static const char *mout_apll_parents[] __initdata = { "fin_pll", "fout_apll", };
>> +static const char *mout_mpll_parents[] __initdata = { "fin_pll", "fout_mpll", };
>> +static const char *mout_epll_parents[] __initdata = { "fin_pll", "fout_epll", };
>> +
>> +static const char *sclk_ampll_parents[] __initdata = {
>> +             "mout_mpll", "sclk_apll", };
>> +
>> +static const char *sclk_evpll_parents[] __initdata = {
>> +             "mout_epll", "mout_vpll", };
>> +
>> +static const char *mout_core_parents[] __initdata = {
>> +             "mout_apll", "mout_mpll", };
>> +
>> +static const char *mout_mfc_parents[] __initdata = {
>> +             "mout_mfc0", "mout_mfc1", };
>> +
>> +static const char *mout_dac_parents[] __initdata = {
>> +             "mout_vpll", "sclk_hdmiphy", };
>> +
>> +static const char *mout_hdmi_parents[] __initdata = {
>> +             "sclk_pixel", "sclk_hdmiphy", };
>> +
>> +static const char *mout_mixer_parents[] __initdata = {
>> +             "sclk_dac", "sclk_hdmi", };
>> +
>> +static const char *group1_parents[] __initdata = {
>> +             "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
>> +             "none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
>> +             "mout_vpll" };
>> +
>> +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
>> +     FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
>> +     FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
>> +     FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
>> +     FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
>> +     FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
>> +};
>> +
>> +static struct samsung_mux_clock exynos4_mux_clks[] = {
>> +     MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
>> +                     EXYNOS4_OP_MODE, 0, 1, 0),
>> +     MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
>> +                     EXYNOS4_CLKSRC_CPU, 0, 1, 0),
>> +     MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
>> +     MUXCLK(NULL, "mout_core", mout_core_parents, 0,
>> +                     EXYNOS4_CLKSRC_CPU, 16, 1, 0),
>> +     MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
>> +     MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
>> +     MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
>> +     MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
>> +     MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
>> +     MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
>> +     MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
>> +     MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
>> +     MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
>> +     MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
>> +     MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
>> +     MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
>> +     MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
>> +     MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
>> +     MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
>> +     MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
>> +     MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
>> +                     EXYNOS4_CLKSRC_MFC, 0, 1, 0),
>> +     MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
>> +                     EXYNOS4_CLKSRC_MFC, 4, 1, 0),
>> +     MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
>> +                     EXYNOS4_CLKSRC_MFC, 8, 1, 0),
>> +     MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 24, 4, 0),
>> +     MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 28, 4, 0),
>> +     MUXCLK(NULL, "mout_cam0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 16, 4, 0),
>> +     MUXCLK(NULL, "mout_cam1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 20, 4, 0),
>> +     MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 0, 4, 0),
>> +     MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 4, 4, 0),
>> +     MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 8, 4, 0),
>> +     MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_CAM, 12, 4, 0),
>> +     MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
>> +                     EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
>> +     MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
>> +                     EXYNOS4_CLKSRC_TV, 8, 1, 0),
>> +     MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
>> +                     EXYNOS4_CLKSRC_TV, 0, 1, 0),
>> +     MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
>> +                     EXYNOS4_CLKSRC_TV, 4, 1, 0),
>> +};
>> +
>> +static struct samsung_div_clock exynos4_div_clks[] = {
>> +     DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
>> +                     EXYNOS4_CLKDIV_CPU, 24, 3, 0),
>> +     DIVCLK(NULL, "div_core", "mout_core", 0,
>> +                     EXYNOS4_CLKDIV_CPU, 0, 3, 0),
>> +     DIVCLK(NULL, "armclk", "div_core", 0,
>> +                     EXYNOS4_CLKDIV_CPU, 28, 3, 0),
>> +     DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
>> +                     EXYNOS4_CLKDIV_TOP, 0, 3, 0),
>> +     DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
>> +                     EXYNOS4_CLKDIV_TOP, 4, 4, 0),
>> +     DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
>> +                     EXYNOS4_CLKDIV_TOP, 8, 3, 0),
>> +     DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
>> +                     EXYNOS4_CLKDIV_TOP, 12, 3, 0),
>> +     DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
>> +                     EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
>> +     DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
>> +                     EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
>> +     DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
>> +                     EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
>> +     DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
>> +                     EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
>> +     DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
>> +     DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
>> +     DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
>> +     DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
>> +                     EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
>> +     DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
>> +     DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
>> +     DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
>> +     DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
>> +                     EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
>> +     DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
>> +                     EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
>> +     DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
>> +                     EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
>> +     DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
>> +                     EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
>> +     DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
>> +                     EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
>> +     DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
>> +                     EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
>> +     DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
>> +                     EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
>> +     DIVCLK(NULL, "div_sata", "mout_sata", 0,
>> +                     EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
>> +     DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
>> +                     EXYNOS4_CLKDIV_MFC, 0, 4, 0),
>> +     DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 24, 4, 0),
>> +     DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 28, 4, 0),
>> +     DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 16, 4, 0),
>> +     DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 20, 4, 0),
>> +     DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 0, 4, 0),
>> +     DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> +     DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> +     DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
>> +                     EXYNOS4_CLKDIV_CAM, 4, 4, 0),
>> +     DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
>> +                     EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
>> +     DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
>> +                     EXYNOS4_CLKDIV_TV, 0, 4, 0),
>> +};
>> +
>> +struct samsung_gate_clock exynos4_gate_clks[] = {
>> +     GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
>> +     GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
>> +     GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
>> +     GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
>> +     GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
>> +     GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
>> +     GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
>> +     GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
>> +     GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
>> +     GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
>> +     GATECLK(NULL, "timers", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
>> +     GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
>> +     GATECLK(NULL, "jpeg", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
>> +     GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
>> +     GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
>> +     GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
>> +     GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
>> +     GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
>> +     GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
>> +     GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
>> +     GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
>> +     GATECLK(NULL, "dwmmc", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
>> +     GATECLK("s5p-sdo", "dac", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 2, NULL),
>> +     GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 1, NULL),
>> +     GATECLK("s5p-mixer", "vp", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 0, NULL),
>> +     GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 3, NULL),
>> +     GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
>> +                     S5P_HDMI_PHY_CONTROL, 0, NULL),
>> +     GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
>> +                     S5P_DAC_PHY_CONTROL, 0, NULL),
>> +     GATECLK(NULL, "adc", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
>> +     GATECLK(NULL, "keypad", "aclk_100", 0,
>> +                     EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
>> +     GATECLK(NULL, "rtc", "aclk_100", 0,
>> +                     EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
>> +     GATECLK(NULL, "watchdog", "aclk_100", 0,
>> +                     EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
>> +     GATECLK(NULL, "usbhost", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
>> +     GATECLK(NULL, "otg", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
>> +     GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
>> +     GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
>> +     GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
>> +     GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
>> +     GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
>> +     GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
>> +     GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
>> +     GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
>> +     GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
>> +     GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
>> +     GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
>> +     GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
>> +     GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
>> +     GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
>> +     GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
>> +     GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
>> +     GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
>> +                     EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
>> +                     EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
>> +     GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
>> +     GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
>> +     GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
>> +                     EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
>> +     GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
>> +                     EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
>> +     GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
>> +     GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
>> +     GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
>> +     GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
>> +     GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
>> +     GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
>> +     GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
>> +                     EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
>> +     GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
>> +     GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
>> +     GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
>> +     GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
>> +     GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
>> +     GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
>> +     GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
>> +     GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
>> +                     EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
>> +     GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
>> +                     EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
>> +};
>> +
>> +/* register clock common to all Exynos4 platforms */
>> +void __init exynos4_clk_init(void)
>> +{
>> +     samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
>> +                     ARRAY_SIZE(exynos4_fixed_rate_clks));
>> +     samsung_clk_register_mux(exynos4_mux_clks,
>> +                     ARRAY_SIZE(exynos4_mux_clks));
>> +     samsung_clk_register_div(exynos4_div_clks,
>> +                     ARRAY_SIZE(exynos4_div_clks));
>> +     samsung_clk_register_gate(exynos4_gate_clks,
>> +                     ARRAY_SIZE(exynos4_gate_clks));
>> +}
> ...
>> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
>> new file mode 100644
>> index 0000000..65156b9
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk.c
>> @@ -0,0 +1,231 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This file includes utility functions to register clocks to common
>> + * clock framework for Samsung platforms. This includes an implementation
>> + * of Samsung 'pll type' clock to represent the implementation of the
>> + * pll found on Samsung platforms. In addition to that, utility functions
>> + * to register mux, div, gate and fixed rate types of clocks are included.
>> +*/
>> +
>> +#include "clk.h"
>> +
>> +static DEFINE_SPINLOCK(lock);
>> +
>> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
>> +
>> +/* determine the output clock speed of the pll */
>> +static unsigned long samsung_clk_pll_recalc_rate(struct clk_hw *hw,
>> +                             unsigned long parent_rate)
>> +{
>> +     struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
>> +
>> +     if (clk_pll->get_rate)
>> +             return to_clk_pll(hw)->get_rate(parent_rate);
>> +
>> +     return 0;
>> +}
>> +
>> +/* round operation not supported */
>> +static long samsung_clk_pll_round_rate(struct clk_hw *hw, unsigned long drate,
>> +                             unsigned long *prate)
>> +{
>> +     return samsung_clk_pll_recalc_rate(hw, *prate);
>> +}
>> +
>> +/* set the clock output rate of the pll */
>> +static int samsung_clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
>> +                             unsigned long prate)
>> +{
>> +     struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
>> +
>> +     if (clk_pll->set_rate)
>> +             return to_clk_pll(hw)->set_rate(drate);
>> +
>> +     return 0;
>> +}
>> +
>> +/* clock operations for samsung pll clock type */
>> +static const struct clk_ops samsung_clk_pll_ops = {
>> +     .recalc_rate = samsung_clk_pll_recalc_rate,
>> +     .round_rate = samsung_clk_pll_round_rate,
>> +     .set_rate = samsung_clk_pll_set_rate,
>> +};
>> +
>> +/* register a samsung pll type clock */
>> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
>> +                             int (*set_rate)(unsigned long rate),
>> +                             unsigned long (*get_rate)(unsigned long rate))
>> +{
>> +     struct samsung_clk_pll *clk_pll;
>> +     struct clk *clk;
>> +     struct clk_init_data init;
>> +     int ret;
>> +
>> +     clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
>> +     if (!clk_pll) {
>> +             pr_err("%s: could not allocate pll clk %s\n", __func__, name);
>> +             return;
>> +     }
>> +
>> +     init.name = name;
>> +     init.ops =&samsung_clk_pll_ops;
>> +     init.flags = CLK_GET_RATE_NOCACHE;
>> +     init.parent_names = pnames;
>> +     init.num_parents = 1;
>> +
>> +     clk_pll->set_rate = set_rate;
>> +     clk_pll->get_rate = get_rate;
>> +     clk_pll->hw.init =&init;
>> +
>> +     /* register the clock */
>> +     clk = clk_register(NULL,&clk_pll->hw);
>> +     if (IS_ERR(clk)) {
>> +             pr_err("%s: failed to register pll clock %s\n", __func__,
>> +                             name);
>> +             kfree(clk_pll);
>> +             return;
>> +     }
>> +
>> +     ret = clk_register_clkdev(clk, name, NULL);
>> +     if (ret)
>> +             pr_err("%s: failed to register clock lookup for %s", __func__,
>> +                             name);
>> +}
>> +
>> +/* register a list of fixed clocks */
>> +void __init samsung_clk_register_fixed_rate(
>> +             struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx<  nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_fixed_rate(NULL, clk_list->name,
>> +                             clk_list->parent_name, clk_list->flags,
>> +                             clk_list->fixed_rate);
>> +             if (IS_ERR_OR_NULL(clk)) {
>
> clk_register_fixed_rate() always returns an error code (ERR_PTR()), i.e. never
> NULL, thus IS_ERR(clk) is more appropriate here.

Ok. I will change it.

>
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +     }
>> +}
>> +
>> +/* register a list of mux clocks */
>> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx<  nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_mux(NULL, clk_list->name,
>> +                     clk_list->parent_names, clk_list->num_parents,
>> +                     clk_list->flags, clk_list->reg, clk_list->shift,
>> +                     clk_list->width, clk_list->mux_flags,&lock);
>> +             if (IS_ERR_OR_NULL(clk)) {
>
> Ditto.
>
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +
>> +             if (clk_list->alias)
>> +                     clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +     }
>> +}
>> +
>> +/* reguster a list of div clocks */
>> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx<  nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_divider(NULL, clk_list->name,
>> +                     clk_list->parent_name, clk_list->flags, clk_list->reg,
>> +                     clk_list->shift, clk_list->width, clk_list->div_flags,
>> +                     &lock);
>> +             if (IS_ERR_OR_NULL(clk)) {
>
> Ditto.
>
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +
>> +             if (clk_list->alias)
>> +                     clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +     }
>> +}
>> +
>> +/* register a list of gate clocks */
>> +void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
>> +                                             unsigned int nr_clk)
>> +{
>> +     struct clk *clk;
>> +     unsigned int idx, ret;
>> +
>> +     for (idx = 0; idx<  nr_clk; idx++, clk_list++) {
>> +             clk = clk_register_gate(NULL, clk_list->name,
>> +                     clk_list->parent_name, clk_list->flags, clk_list->reg,
>> +                     clk_list->bit_idx, clk_list->gate_flags,&lock);
>> +             if (IS_ERR_OR_NULL(clk)) {
>
> Ditto.
>
>> +                     pr_err("clock: failed to register clock %s\n",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->name,
>> +                                             clk_list->dev_name);
>> +             if (ret) {
>> +                     pr_err("clock: failed to register clock lookup for %s",
>> +                             clk_list->name);
>> +                     continue;
>> +             }
>> +
>> +             ret = clk_register_clkdev(clk, clk_list->alias,
>> +                                             clk_list->dev_name);
>> +             if (ret)
>> +                     pr_err("clock: failed to register alias %s for clock "
>> +                                     " %s", clk_list->alias, clk_list->name);
>> +     }
>> +}
>
>
> Do we really need all these clock lookup entries registered for each clk
> primitive ? There seem to be more struck clk objects than with the original
> samsung clock code, now when each instance of struct clk_clksrc has been
> replaced with a corresponding div and mux clock object. All these are not
> needed to be referenced from drivers, so why do we see so many
> clk_register_clkdev() here ?
>
> Couldn't this be avoided by instantiating all platform clocks first and
> then creating required clock object - device associations by adding the
> clkdev lookup entries ? Something like this is done in case of
> arch/arm/mach-imx for instance. I think this would result in less data
> and more clear implementation.

Ok. But the platform code can lookup these clocks (for displaying the
clock speed on the console) and hence all the clocks are registered.
Anyway, these are required only for non-dt platforms and would go away
after switching over to device tree based clock registration.

Thanks,
Thomas.

>
>
>> +/* utility function to get the rate of a specified clock */
>> +unsigned long _get_rate(const char *clk_name)
>> +{
>> +     struct clk *clk;
>> +     unsigned long rate;
>> +
>> +     clk = clk_get(NULL, clk_name);
>> +     if (IS_ERR(clk))
>> +             return 0;
>> +     rate = clk_get_rate(clk);
>> +     clk_put(clk);
>> +     return rate;
>> +}
>> diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
>> new file mode 100644
>> index 0000000..40bdff9
>> --- /dev/null
>> +++ b/drivers/clk/samsung/clk.h
>> @@ -0,0 +1,190 @@
>> +/*
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + * Copyright (c) 2012 Linaro Ltd.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * Common Clock Framework support for all Samsung platforms
>> +*/
>> +
>> +#ifndef __SAMSUNG_CLK_H
>> +#define __SAMSUNG_CLK_H
>> +
>> +#include<linux/clk.h>
>> +#include<linux/clkdev.h>
>> +#include<linux/io.h>
>> +#include<linux/clk-provider.h>
>> +#include<mach/regs-clock.h>
>> +
>> +/**
>> + * struct samsung_clk_pll: represents a samsung pll type clock
>> + * @hw: connection to struct clk.
>> + * @set_rate: callback for setting the pll clock rate
>> + * @get_rate: callback for determing the pll clock rate
>> + *
>> + * Internal representation of the pll type clock. Platform specific
>> + * implementation can instantiate clocks of this type by calling
>> + * samsung_clk_register_pll() function.
>> + */
>> +struct samsung_clk_pll {
>> +     struct clk_hw           hw;
>> +     int                     (*set_rate)(unsigned long rate);
>> +     unsigned long           (*get_rate)(unsigned long xtal_rate);
>> +};
>> +
>> +/**
>> + * struct samsung_fixed_rate_clock: information about fixed-rate clock
>> + * @dev_name: name of the device to which this clock belongs.
>> + * @name: name of this fixed-rate clock.
>> + * @parent_name: optional parent clock name.
>> + * @flags: optional fixed-rate clock flags.
>> + * @fixed-rate: fixed clock rate of this clock.
>> + */
>> +struct samsung_fixed_rate_clock {
>> +     const char              *dev_name;
>> +     const char              *name;
>> +     const char              *parent_name;
>> +     unsigned long           flags;
>> +     unsigned long           fixed_rate;
>> +};
>> +
>> +#define FRATE_CLK(dname, cname, pname, f, frate)     \
>> +     {                                               \
>> +             .dev_name       = dname,                \
>> +             .name           = cname,                \
>> +             .parent_name    = pname,                \
>> +             .flags          = f,                    \
>> +             .fixed_rate     = frate,                \
>> +     }
>> +
>> +/**
>> + * struct samsung_mux_clock: information about mux clock
>> + * @dev_name: name of the device to which this clock belongs.
>> + * @name: name of this mux clock.
>> + * @parent_names: array of pointer to parent clock names.
>> + * @num_parents: number of parents listed in @parent_names.
>> + * @flags: optional flags for basic clock.
>> + * @reg: address of register for configuring the mux.
>> + * @shift: starting bit location of the mux control bit-field in @reg.
>> + * @width: width of the mux control bit-field in @reg.
>> + * @mux_flags: flags for mux-type clock.
>> + * @alias: optional clock alias name to be assigned to this clock.
>> + */
>> +struct samsung_mux_clock {
>> +     const char              *dev_name;
>> +     const char              *name;
>> +     const char              **parent_names;
>> +     u8                      num_parents;
>> +     unsigned long           flags;
>> +     void __iomem            *reg;
>> +     u8                      shift;
>> +     u8                      width;
>> +     u8                      mux_flags;
>> +     const char              *alias;
>> +};
>> +
>> +#define MUXCLK(dname, cname, pnames, f, r, s, w, mf)         \
>> +     {                                                       \
>> +             .dev_name       = dname,                        \
>> +             .name           = cname,                        \
>> +             .parent_names   = pnames,                       \
>> +             .num_parents    = ARRAY_SIZE(pnames),           \
>> +             .flags          = f,                            \
>> +             .reg            = r,                            \
>> +             .shift          = s,                            \
>> +             .width          = w,                            \
>> +             .mux_flags      = mf,                           \
>> +     }
>> +
>> +/**
>> + * struct samsung_div_clock: information about div clock
>> + * @dev_name: name of the device to which this clock belongs.
>> + * @name: name of this div clock.
>> + * @parent_name: name of the parent clock.
>> + * @flags: optional flags for basic clock.
>> + * @reg: address of register for configuring the div.
>> + * @shift: starting bit location of the div control bit-field in @reg.
>> + * @div_flags: flags for div-type clock.
>> + * @alias: optional clock alias name to be assigned to this clock.
>> + */
>> +struct samsung_div_clock {
>> +     const char              *dev_name;
>> +     const char              *name;
>> +     const char              *parent_name;
>> +     unsigned long           flags;
>> +     void __iomem            *reg;
>> +     u8                      shift;
>> +     u8                      width;
>> +     u8                      div_flags;
>> +     const char              *alias;
>> +};
>> +
>> +#define DIVCLK(dname, cname, pname, f, r, s, w, df)          \
>> +     {                                                       \
>> +             .dev_name       = dname,                        \
>> +             .name           = cname,                        \
>> +             .parent_name    = pname,                        \
>> +             .flags          = f,                            \
>> +             .reg            = r,                            \
>> +             .shift          = s,                            \
>> +             .width          = w,                            \
>> +             .div_flags      = df,                           \
>> +     }
>> +
>> +/**
>> + * struct samsung_gate_clock: information about gate clock
>> + * @dev_name: name of the device to which this clock belongs.
>> + * @name: name of this gate clock.
>> + * @parent_name: name of the parent clock.
>> + * @flags: optional flags for basic clock.
>> + * @reg: address of register for configuring the gate.
>> + * @bit_idx: bit index of the gate control bit-field in @reg.
>> + * @gate_flags: flags for gate-type clock.
>> + * @alias: optional clock alias name to be assigned to this clock.
>> + */
>> +struct samsung_gate_clock {
>> +     const char              *dev_name;
>> +     const char              *name;
>> +     const char              *parent_name;
>> +     unsigned long           flags;
>> +     void __iomem            *reg;
>> +     u8                      bit_idx;
>> +     u8                      gate_flags;
>> +     const char              *alias;
>> +};
>> +
>> +#define GATECLK(dname, cname, pname, f, r, b, a)             \
>> +     {                                                       \
>> +             .dev_name       = dname,                        \
>> +             .name           = cname,                        \
>> +             .parent_name    = pname,                        \
>> +             .flags          = f,                            \
>> +             .reg            = r,                            \
>> +             .bit_idx        = b,                            \
>> +             .alias          = a,                            \
>> +     }
>
> --
>
> Regards,
> Sylwester

^ permalink raw reply


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