All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/35] davinci updates queued for 2.6.34
@ 2010-01-06 18:31 Kevin Hilman
  2010-01-06 18:31 ` [PATCH 01/35] davinci: da8xx/omapl1: add support for the second sysconfig module Kevin Hilman
  2010-01-10 13:59 ` [PATCH 00/35] davinci updates queued for 2.6.34 Russell King - ARM Linux
  0 siblings, 2 replies; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

Here's a set of DaVinci updates for review.

Apologies for the large series, I've been meaning to send these in
smaller batches, but hd lots to queue up from over the holidays.

Pending any review comments, these will be submitted to Linus during
the next merge window.

Kevin

Chaithrika U S (1):
  davinci: clock: Check CLK_PSC flag before disabling PSC

Nageswari Srinivasan (2):
  davinci: add support for CDCE949 clock synthesizer
  davinci: add CDCE949 support on DM6467 EVM

Sandeep Paulraj (1):
  DaVinci: DM365: Changing default queue for DM365.

Sekhar Nori (17):
  davinci: da8xx/omapl1: add support for the second sysconfig module
  davinci: move PLL wait time values to clock.h
  davinci: move DDR2 controller defines to memory.h
  davinci: move PSC register definitions from psc.c to psc.h
  davinci: make it possible to include clock.h and psc.h in assembly
    code
  davinci: cpuidle: move mapping of DDR2 controller registers out of
    driver
  davinci: da850/omap-l138: unlock PLL registers during init
  davinci: da850/omap-l138: create static map for SRAM
  davinci: explain CLOCK_TICK_RATE of 27MHz in include/mach/timex.h
  davinci: board-dm646x-evm.c: arrange related code together
  davinci: add support for DM6467T EVM
  davinci: clock framework: remove spinlock usage
  davinci: make /proc/davinci_clocks display multi-rooted clock tree
  davinci: move /proc/davinci_clocks to debugfs
  davinci: add power management support
  davinci: da850/omap-l138: add support for SoC suspend
  davinci: da850/omap-l138 EVM: register for suspend support

Sriramakrishnan (3):
  TI Davinci EMAC : Re-use driver for other platforms.
  TI Davinci EMAC : add platform specific interrupt enable/disable
    logic.
  TI Davinci EMAC : Abstract Buffer address translation logic.

Sudhakar Rajashekhara (11):
  davinci: da850/omap-l138: Modify NOR partition info
  davinci: da850/omap-l138: Enable 4-bit ecc
  davinci: Correct return value of edma_alloc_channel api
  davinci: Keep count of channel controllers on a platform
  davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case
  davinci: build list of unused EDMA events dynamically
  davinci: support for EDMA resource sharing
  davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138
  davinci: da830/omapl137: Specify reserved channels/slots
  davinci: da850/omapl138: Specify reserved channels/slots
  davinci: dm646x: Specify reserved EDMA channel/slots for DM646x

 arch/arm/mach-davinci/Kconfig                |    4 +
 arch/arm/mach-davinci/Makefile               |    3 +-
 arch/arm/mach-davinci/board-da830-evm.c      |    4 +-
 arch/arm/mach-davinci/board-da850-evm.c      |   34 +++-
 arch/arm/mach-davinci/board-dm646x-evm.c     |  143 +++++++++----
 arch/arm/mach-davinci/cdce949.c              |  289 ++++++++++++++++++++++++++
 arch/arm/mach-davinci/clock.c                |  143 +++++--------
 arch/arm/mach-davinci/clock.h                |   29 ++-
 arch/arm/mach-davinci/common.c               |    2 +-
 arch/arm/mach-davinci/cpuidle.c              |   38 +---
 arch/arm/mach-davinci/da830.c                |   10 +-
 arch/arm/mach-davinci/da850.c                |   86 +++++++--
 arch/arm/mach-davinci/devices-da8xx.c        |  210 +++++++++++++++++--
 arch/arm/mach-davinci/dm355.c                |   12 +-
 arch/arm/mach-davinci/dm365.c                |    6 +-
 arch/arm/mach-davinci/dm644x.c               |   18 +--
 arch/arm/mach-davinci/dm646x.c               |   44 +++--
 arch/arm/mach-davinci/dma.c                  |  101 ++++++++--
 arch/arm/mach-davinci/include/mach/cdce949.h |   19 ++
 arch/arm/mach-davinci/include/mach/cpuidle.h |    1 +
 arch/arm/mach-davinci/include/mach/da8xx.h   |   18 ++-
 arch/arm/mach-davinci/include/mach/dm365.h   |    2 +-
 arch/arm/mach-davinci/include/mach/dm644x.h  |    2 +-
 arch/arm/mach-davinci/include/mach/dm646x.h  |    4 +-
 arch/arm/mach-davinci/include/mach/edma.h    |    4 +-
 arch/arm/mach-davinci/include/mach/emac.h    |   36 ----
 arch/arm/mach-davinci/include/mach/memory.h  |    5 +
 arch/arm/mach-davinci/include/mach/mux.h     |    1 +
 arch/arm/mach-davinci/include/mach/pm.h      |   54 +++++
 arch/arm/mach-davinci/include/mach/psc.h     |   15 ++
 arch/arm/mach-davinci/include/mach/timex.h   |    7 +-
 arch/arm/mach-davinci/pm.c                   |  158 ++++++++++++++
 arch/arm/mach-davinci/psc.c                  |   17 +-
 arch/arm/mach-davinci/sleep.S                |  224 ++++++++++++++++++++
 drivers/net/Kconfig                          |    2 +-
 drivers/net/davinci_emac.c                   |   55 ++++--
 include/linux/davinci_emac.h                 |   39 ++++
 37 files changed, 1494 insertions(+), 345 deletions(-)
 create mode 100644 arch/arm/mach-davinci/cdce949.c
 create mode 100644 arch/arm/mach-davinci/include/mach/cdce949.h
 delete mode 100644 arch/arm/mach-davinci/include/mach/emac.h
 create mode 100644 arch/arm/mach-davinci/include/mach/pm.h
 create mode 100644 arch/arm/mach-davinci/pm.c
 create mode 100644 arch/arm/mach-davinci/sleep.S
 create mode 100644 include/linux/davinci_emac.h

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 01/35] davinci: da8xx/omapl1: add support for the second sysconfig module
  2010-01-06 18:31 [PATCH 00/35] davinci updates queued for 2.6.34 Kevin Hilman
@ 2010-01-06 18:31 ` Kevin Hilman
  2010-01-06 18:31   ` [PATCH 02/35] davinci: move PLL wait time values to clock.h Kevin Hilman
  2010-01-10 13:59 ` [PATCH 00/35] davinci updates queued for 2.6.34 Russell King - ARM Linux
  1 sibling, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

OMAP-L138 adds a second SYSCFG region having useful functionality
like deep sleep, pull up/down control and SATA clock stop.

This patch makes provision for accessing registers from second
SYSCFG region in da8xx code.

Note that OMAP-L137 has a single SYSCFG region.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/board-da830-evm.c    |    4 ++--
 arch/arm/mach-davinci/board-da850-evm.c    |    2 +-
 arch/arm/mach-davinci/da830.c              |    8 ++++----
 arch/arm/mach-davinci/da850.c              |   20 ++++++++++++--------
 arch/arm/mach-davinci/devices-da8xx.c      |    3 ++-
 arch/arm/mach-davinci/include/mach/da8xx.h |   10 +++++++---
 6 files changed, 28 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 31dc990..dc19870 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -112,7 +112,7 @@ static __init void da830_evm_usb_init(void)
 	 * Set up USB clock/mode in the CFGCHIP2 register.
 	 * FYI:  CFGCHIP2 is 0x0000ef00 initially.
 	 */
-	cfgchip2 = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP2_REG));
+	cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 
 	/* USB2.0 PHY reference clock is 24 MHz */
 	cfgchip2 &= ~CFGCHIP2_REFFREQ;
@@ -139,7 +139,7 @@ static __init void da830_evm_usb_init(void)
 	cfgchip2 |=  CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN;
 #endif
 
-	__raw_writel(cfgchip2, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP2_REG));
+	__raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
 
 	/* USB_REFCLKIN is not used. */
 	ret = davinci_cfg_reg(DA830_USB0_DRVVBUS);
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 07de8db..dba2241 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -537,7 +537,7 @@ static int __init da850_evm_config_emac(void)
 	if (!machine_is_davinci_da850_evm())
 		return 0;
 
-	cfg_chip3_base = DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG);
+	cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
 
 	val = __raw_readl(cfg_chip3_base);
 
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index b22b5cf..5479605 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -1208,13 +1208,13 @@ static struct davinci_soc_info davinci_soc_info_da830 = {
 
 void __init da830_init(void)
 {
-	da8xx_syscfg_base = ioremap(DA8XX_SYSCFG_BASE, SZ_4K);
-	if (WARN(!da8xx_syscfg_base, "Unable to map syscfg module"))
+	da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
+	if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module"))
 		return;
 
 	davinci_soc_info_da830.jtag_id_base =
-					DA8XX_SYSCFG_VIRT(DA8XX_JTAG_ID_REG);
-	davinci_soc_info_da830.pinmux_base = DA8XX_SYSCFG_VIRT(0x120);
+					DA8XX_SYSCFG0_VIRT(DA8XX_JTAG_ID_REG);
+	davinci_soc_info_da830.pinmux_base = DA8XX_SYSCFG0_VIRT(0x120);
 
 	davinci_common_init(&davinci_soc_info_da830);
 }
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 717806c..4f84ab4 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -838,12 +838,12 @@ static void da850_set_async3_src(int pllnum)
 		}
        }
 
-	v = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG));
+	v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
 	if (pllnum)
 		v |= CFGCHIP3_ASYNC3_CLKSRC;
 	else
 		v &= ~CFGCHIP3_ASYNC3_CLKSRC;
-	__raw_writel(v, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP3_REG));
+	__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
 }
 
 #ifdef CONFIG_CPU_FREQ
@@ -996,9 +996,9 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)
 	postdiv = opp->postdiv;
 
 	/* Unlock writing to PLL registers */
-	v = __raw_readl(DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP0_REG));
+	v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
 	v &= ~CFGCHIP0_PLL_MASTER_LOCK;
-	__raw_writel(v, DA8XX_SYSCFG_VIRT(DA8XX_CFGCHIP0_REG));
+	__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
 
 	ret = davinci_set_pllrate(pll, prediv, mult, postdiv);
 	if (WARN_ON(ret))
@@ -1053,13 +1053,17 @@ static struct davinci_soc_info davinci_soc_info_da850 = {
 
 void __init da850_init(void)
 {
-	da8xx_syscfg_base = ioremap(DA8XX_SYSCFG_BASE, SZ_4K);
-	if (WARN(!da8xx_syscfg_base, "Unable to map syscfg module"))
+	da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
+	if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module"))
+		return;
+
+	da8xx_syscfg1_base = ioremap(DA8XX_SYSCFG1_BASE, SZ_4K);
+	if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module"))
 		return;
 
 	davinci_soc_info_da850.jtag_id_base =
-					DA8XX_SYSCFG_VIRT(DA8XX_JTAG_ID_REG);
-	davinci_soc_info_da850.pinmux_base = DA8XX_SYSCFG_VIRT(0x120);
+					DA8XX_SYSCFG0_VIRT(DA8XX_JTAG_ID_REG);
+	davinci_soc_info_da850.pinmux_base = DA8XX_SYSCFG0_VIRT(0x120);
 
 	davinci_common_init(&davinci_soc_info_da850);
 
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index dd2d32c..8de5f9f 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -42,7 +42,8 @@
 #define DA8XX_MDIO_REG_OFFSET		0x4000
 #define DA8XX_EMAC_CTRL_RAM_SIZE	SZ_8K
 
-void __iomem *da8xx_syscfg_base;
+void __iomem *da8xx_syscfg0_base;
+void __iomem *da8xx_syscfg1_base;
 
 static struct plat_serial8250_port da8xx_serial_pdata[] = {
 	{
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index 9070491..bddc4d4 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -21,7 +21,8 @@
 #include <mach/mmc.h>
 #include <mach/usb.h>
 
-extern void __iomem *da8xx_syscfg_base;
+extern void __iomem *da8xx_syscfg0_base;
+extern void __iomem *da8xx_syscfg1_base;
 
 /*
  * The cp_intc interrupt controller for the da8xx isn't in the same
@@ -34,13 +35,16 @@ extern void __iomem *da8xx_syscfg_base;
 #define DA8XX_CP_INTC_SIZE	SZ_8K
 #define DA8XX_CP_INTC_VIRT	(IO_VIRT - DA8XX_CP_INTC_SIZE - SZ_4K)
 
-#define DA8XX_SYSCFG_BASE	(IO_PHYS + 0x14000)
-#define DA8XX_SYSCFG_VIRT(x)	(da8xx_syscfg_base + (x))
+#define DA8XX_SYSCFG0_BASE	(IO_PHYS + 0x14000)
+#define DA8XX_SYSCFG0_VIRT(x)	(da8xx_syscfg0_base + (x))
 #define DA8XX_JTAG_ID_REG	0x18
 #define DA8XX_CFGCHIP0_REG	0x17c
 #define DA8XX_CFGCHIP2_REG	0x184
 #define DA8XX_CFGCHIP3_REG	0x188
 
+#define DA8XX_SYSCFG1_BASE	(IO_PHYS + 0x22C000)
+#define DA8XX_SYSCFG1_VIRT(x)	(da8xx_syscfg1_base + (x))
+
 #define DA8XX_PSC0_BASE		0x01c10000
 #define DA8XX_PLL0_BASE		0x01c11000
 #define DA8XX_TIMER64P0_BASE	0x01c20000
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 02/35] davinci: move PLL wait time values to clock.h
  2010-01-06 18:31 ` [PATCH 01/35] davinci: da8xx/omapl1: add support for the second sysconfig module Kevin Hilman
@ 2010-01-06 18:31   ` Kevin Hilman
  2010-01-06 18:31     ` [PATCH 03/35] davinci: move DDR2 controller defines to memory.h Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

As suspend support is added, the code supporting
the suspend operation needs to bypass PLLs and
needs to access the same wait time values as the
PLL code in clock.c.

To facilitate this, move the PLL wait times to
clock.h where they can be accessed by suspend code.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/clock.c |   15 +++------------
 arch/arm/mach-davinci/clock.h |   15 +++++++++++++++
 2 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index baece65..0fa68c5 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -376,7 +376,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
 		locktime = ((2000 * prediv) / 100);
 		prediv = (prediv - 1) | PLLDIV_EN;
 	} else {
-		locktime = 20;
+		locktime = PLL_LOCK_TIME;
 	}
 	if (postdiv)
 		postdiv = (postdiv - 1) | PLLDIV_EN;
@@ -389,12 +389,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
 	ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
 	__raw_writel(ctrl, pll->base + PLLCTL);
 
-	/*
-	 * Wait for 4 OSCIN/CLKIN cycles to ensure that the PLLC has switched
-	 * to bypass mode. Delay of 1us ensures we are good for all > 4MHz
-	 * OSCIN/CLKIN inputs. Typically the input is ~25MHz.
-	 */
-	udelay(1);
+	udelay(PLL_BYPASS_TIME);
 
 	/* Reset and enable PLL */
 	ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS);
@@ -408,11 +403,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
 	if (pll->flags & PLL_HAS_POSTDIV)
 		__raw_writel(postdiv, pll->base + POSTDIV);
 
-	/*
-	 * Wait for PLL to reset properly, OMAP-L138 datasheet says
-	 * 'min' time = 125ns
-	 */
-	udelay(1);
+	udelay(PLL_RESET_TIME);
 
 	/* Bring PLL out of reset */
 	ctrl |= PLLCTL_PLLRST;
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index c92d77a..eca4d99 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -53,6 +53,21 @@
 #define PLLDIV_EN       BIT(15)
 #define PLLDIV_RATIO_MASK 0x1f
 
+/*
+ * OMAP-L138 system reference guide recommends a wait for 4 OSCIN/CLKIN
+ * cycles to ensure that the PLLC has switched to bypass mode. Delay of 1us
+ * ensures we are good for all > 4MHz OSCIN/CLKIN inputs. Typically the input
+ * is ~25MHz. Units are micro seconds.
+ */
+#define PLL_BYPASS_TIME		1
+/* From OMAP-L138 datasheet table 6-4. Units are micro seconds */
+#define PLL_RESET_TIME		1
+/*
+ * From OMAP-L138 datasheet table 6-4; assuming prediv = 1, sqrt(pllm) = 4
+ * Units are micro seconds.
+ */
+#define PLL_LOCK_TIME		20
+
 struct pll_data {
 	u32 phys_base;
 	void __iomem *base;
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 03/35] davinci: move DDR2 controller defines to memory.h
  2010-01-06 18:31   ` [PATCH 02/35] davinci: move PLL wait time values to clock.h Kevin Hilman
@ 2010-01-06 18:31     ` Kevin Hilman
  2010-01-06 18:31       ` [PATCH 04/35] davinci: move PSC register definitions from psc.c to psc.h Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

Move defintions of DDR2 controller registers to memory.h
from cpuidle.c. The motivation behind the change is to be
able to use these defintions in assembly code that puts
DDR2 in self-refresh and enables the SoC to enter suspend
state.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/cpuidle.c             |    5 +----
 arch/arm/mach-davinci/include/mach/memory.h |    4 ++++
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index 97a90f3..beda3b5 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -19,6 +19,7 @@
 #include <asm/proc-fns.h>
 
 #include <mach/cpuidle.h>
+#include <mach/memory.h>
 
 #define DAVINCI_CPUIDLE_MAX_STATES	2
 
@@ -39,10 +40,6 @@ static struct cpuidle_driver davinci_idle_driver = {
 static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device);
 static void __iomem *ddr2_reg_base;
 
-#define DDR2_SDRCR_OFFSET	0xc
-#define DDR2_SRPD_BIT		BIT(23)
-#define DDR2_LPMODEN_BIT	BIT(31)
-
 static void davinci_save_ddr_power(int enter, bool pdown)
 {
 	u32 val;
diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h
index 80309ae..7aeaf46 100644
--- a/arch/arm/mach-davinci/include/mach/memory.h
+++ b/arch/arm/mach-davinci/include/mach/memory.h
@@ -31,6 +31,10 @@
 #define PHYS_OFFSET DAVINCI_DDR_BASE
 #endif
 
+#define DDR2_SDRCR_OFFSET	0xc
+#define DDR2_SRPD_BIT		BIT(23)
+#define DDR2_LPMODEN_BIT	BIT(31)
+
 /*
  * Increase size of DMA-consistent memory region
  */
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 04/35] davinci: move PSC register definitions from psc.c to psc.h
  2010-01-06 18:31     ` [PATCH 03/35] davinci: move DDR2 controller defines to memory.h Kevin Hilman
@ 2010-01-06 18:31       ` Kevin Hilman
  2010-01-06 18:31         ` [PATCH 05/35] davinci: make it possible to include clock.h and psc.h in assembly code Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

The motivation behind the change is to use the same
definitions in the assembly code responsible for
suspending the SoC, a part of which is to clock gate
the DDR2 clock.

Note that the assembly code cannot invoke the C function
meant for this. The main reason being that stack in DDR2
cannot be accessed while DDR2 clock is being clock gated.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/include/mach/psc.h |   11 +++++++++++
 arch/arm/mach-davinci/psc.c              |   11 -----------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h
index 171173c..2776b23 100644
--- a/arch/arm/mach-davinci/include/mach/psc.h
+++ b/arch/arm/mach-davinci/include/mach/psc.h
@@ -180,6 +180,17 @@
 #define DA8XX_LPSC1_CR_P3_SS		26
 #define DA8XX_LPSC1_L3_CBA_RAM		31
 
+/* PSC register offsets */
+#define EPCPR		0x070
+#define PTCMD		0x120
+#define PTSTAT		0x128
+#define PDSTAT		0x200
+#define PDCTL1		0x304
+#define MDSTAT		0x800
+#define MDCTL		0xA00
+
+#define MDSTAT_STATE_MASK 0x1f
+
 extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
 extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 		unsigned int id, char enable);
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index 04a3cb7..adf6b5c 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -25,17 +25,6 @@
 #include <mach/cputype.h>
 #include <mach/psc.h>
 
-/* PSC register offsets */
-#define EPCPR		0x070
-#define PTCMD		0x120
-#define PTSTAT		0x128
-#define PDSTAT		0x200
-#define PDCTL1		0x304
-#define MDSTAT		0x800
-#define MDCTL		0xA00
-
-#define MDSTAT_STATE_MASK 0x1f
-
 /* Return nonzero iff the domain's clock is active */
 int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
 {
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 05/35] davinci: make it possible to include clock.h and psc.h in assembly code
  2010-01-06 18:31       ` [PATCH 04/35] davinci: move PSC register definitions from psc.c to psc.h Kevin Hilman
@ 2010-01-06 18:31         ` Kevin Hilman
  2010-01-06 18:31           ` [PATCH 06/35] davinci: cpuidle: move mapping of DDR2 controller registers out of driver Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

psc.h contains register defines for PSC module which
need to be accessed in assembly code which helps the
DA850/OMAP-L138 SoC go to sleep. Shutting down DDR clock
using PSC is a part of the sleep procedure.

Also, the PLL related hardware definitions in clock.h are
needed in assembly code to bypass the DDR2 PLL.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/clock.h            |   10 +++++++---
 arch/arm/mach-davinci/include/mach/psc.h |    4 ++++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index eca4d99..31fb6ea 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -12,9 +12,6 @@
 #ifndef __ARCH_ARM_DAVINCI_CLOCK_H
 #define __ARCH_ARM_DAVINCI_CLOCK_H
 
-#include <linux/list.h>
-#include <asm/clkdev.h>
-
 #define DAVINCI_PLL1_BASE 0x01c40800
 #define DAVINCI_PLL2_BASE 0x01c40c00
 #define MAX_PLL 2
@@ -68,6 +65,11 @@
  */
 #define PLL_LOCK_TIME		20
 
+#ifndef __ASSEMBLER__
+
+#include <linux/list.h>
+#include <asm/clkdev.h>
+
 struct pll_data {
 	u32 phys_base;
 	void __iomem *base;
@@ -124,3 +126,5 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
 extern struct platform_device davinci_wdt_device;
 
 #endif
+
+#endif
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h
index 2776b23..651f6d8 100644
--- a/arch/arm/mach-davinci/include/mach/psc.h
+++ b/arch/arm/mach-davinci/include/mach/psc.h
@@ -191,8 +191,12 @@
 
 #define MDSTAT_STATE_MASK 0x1f
 
+#ifndef __ASSEMBLER__
+
 extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
 extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 		unsigned int id, char enable);
 
+#endif
+
 #endif /* __ASM_ARCH_PSC_H */
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 06/35] davinci: cpuidle: move mapping of DDR2 controller registers out of driver
  2010-01-06 18:31         ` [PATCH 05/35] davinci: make it possible to include clock.h and psc.h in assembly code Kevin Hilman
@ 2010-01-06 18:31           ` Kevin Hilman
  2010-01-06 18:31             ` [PATCH 07/35] davinci: da850/omap-l138: unlock PLL registers during init Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

When suspend is supported, both cpuidle and suspend code
need to work on DDR2 registers. Instead of mapping the
DDR2 registers twice, do it once outside of cpuidle
driver and let cpuidle driver get the virtual base address
of DDR2 registers.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/cpuidle.c              |   33 +++----------------------
 arch/arm/mach-davinci/devices-da8xx.c        |   16 +++++++++++-
 arch/arm/mach-davinci/include/mach/cpuidle.h |    1 +
 arch/arm/mach-davinci/include/mach/da8xx.h   |    1 +
 4 files changed, 21 insertions(+), 30 deletions(-)

diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c
index beda3b5..bd59f31 100644
--- a/arch/arm/mach-davinci/cpuidle.c
+++ b/arch/arm/mach-davinci/cpuidle.c
@@ -106,8 +106,6 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
 	int ret;
 	struct cpuidle_device *device;
 	struct davinci_cpuidle_config *pdata = pdev->dev.platform_data;
-	struct resource *ddr2_regs;
-	resource_size_t len;
 
 	device = &per_cpu(davinci_cpuidle_device, smp_processor_id());
 
@@ -116,28 +114,12 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
-	ddr2_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!ddr2_regs) {
-		dev_err(&pdev->dev, "cannot get DDR2 controller register base");
-		return -ENODEV;
-	}
-
-	len = resource_size(ddr2_regs);
-
-	ddr2_regs = request_mem_region(ddr2_regs->start, len, ddr2_regs->name);
-	if (!ddr2_regs)
-		return -EBUSY;
-
-	ddr2_reg_base = ioremap(ddr2_regs->start, len);
-	if (!ddr2_reg_base) {
-		ret = -ENOMEM;
-		goto ioremap_fail;
-	}
+	ddr2_reg_base = pdata->ddr2_ctlr_base;
 
 	ret = cpuidle_register_driver(&davinci_idle_driver);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register driver\n");
-		goto driver_register_fail;
+		return ret;
 	}
 
 	/* Wait for interrupt state */
@@ -164,18 +146,11 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev)
 	ret = cpuidle_register_device(device);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register device\n");
-		goto device_register_fail;
+		cpuidle_unregister_driver(&davinci_idle_driver);
+		return ret;
 	}
 
 	return 0;
-
-device_register_fail:
-	cpuidle_unregister_driver(&davinci_idle_driver);
-driver_register_fail:
-	iounmap(ddr2_reg_base);
-ioremap_fail:
-	release_mem_region(ddr2_regs->start, len);
-	return ret;
 }
 
 static struct platform_driver davinci_cpuidle_driver = {
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 8de5f9f..5df27f7 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -489,6 +489,19 @@ int da8xx_register_rtc(void)
 	return platform_device_register(&da8xx_rtc_device);
 }
 
+static void __iomem *da8xx_ddr2_ctlr_base;
+void __iomem * __init da8xx_get_mem_ctlr(void)
+{
+	if (da8xx_ddr2_ctlr_base)
+		return da8xx_ddr2_ctlr_base;
+
+	da8xx_ddr2_ctlr_base = ioremap(DA8XX_DDR2_CTL_BASE, SZ_32K);
+	if (!da8xx_ddr2_ctlr_base)
+		pr_warning("%s: Unable to map DDR2 controller",	__func__);
+
+	return da8xx_ddr2_ctlr_base;
+}
+
 static struct resource da8xx_cpuidle_resources[] = {
 	{
 		.start		= DA8XX_DDR2_CTL_BASE,
@@ -514,6 +527,7 @@ static struct platform_device da8xx_cpuidle_device = {
 
 int __init da8xx_register_cpuidle(void)
 {
+	da8xx_cpuidle_pdata.ddr2_ctlr_base = da8xx_get_mem_ctlr();
+
 	return platform_device_register(&da8xx_cpuidle_device);
 }
-
diff --git a/arch/arm/mach-davinci/include/mach/cpuidle.h b/arch/arm/mach-davinci/include/mach/cpuidle.h
index cbfc6a9..74f088b 100644
--- a/arch/arm/mach-davinci/include/mach/cpuidle.h
+++ b/arch/arm/mach-davinci/include/mach/cpuidle.h
@@ -12,6 +12,7 @@
 
 struct davinci_cpuidle_config {
 	u32 ddr2_pdown;
+	void __iomem *ddr2_ctlr_base;
 };
 
 #endif
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index bddc4d4..cab4a25 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -94,6 +94,7 @@ void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata);
 int da8xx_register_rtc(void);
 int da850_register_cpufreq(void);
 int da8xx_register_cpuidle(void);
+void __iomem * __init da8xx_get_mem_ctlr(void);
 
 extern struct platform_device da8xx_serial_device;
 extern struct emac_platform_data da8xx_emac_pdata;
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 07/35] davinci: da850/omap-l138: unlock PLL registers during init
  2010-01-06 18:31           ` [PATCH 06/35] davinci: cpuidle: move mapping of DDR2 controller registers out of driver Kevin Hilman
@ 2010-01-06 18:31             ` Kevin Hilman
  2010-01-06 18:31               ` [PATCH 08/35] davinci: da850/omap-l138: create static map for SRAM Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

On omap-l1 devices the PLL registers can be locked from
writes. Currently the cpufreq rate setting code unlocks
PLL0 before the write actually happens. With suspend
support getting added PLL1 registers need be be unlocked
as well.

To facilitate this, unlock both PLLs during the init time
itself.

This also obviates the need to unlock PLL registers for
each CPUFreq transtition.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/da850.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 4f84ab4..fcfde2a 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -40,6 +40,7 @@
 #define DA850_REF_FREQ		24000000
 
 #define CFGCHIP3_ASYNC3_CLKSRC	BIT(4)
+#define CFGCHIP3_PLL1_MASTER_LOCK	BIT(5)
 #define CFGCHIP0_PLL_MASTER_LOCK	BIT(4)
 
 static int da850_set_armrate(struct clk *clk, unsigned long rate);
@@ -987,7 +988,6 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)
 	unsigned int prediv, mult, postdiv;
 	struct da850_opp *opp;
 	struct pll_data *pll = clk->pll_data;
-	unsigned int v;
 	int ret;
 
 	opp = (struct da850_opp *) da850_freq_table[index].index;
@@ -995,11 +995,6 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)
 	mult = opp->mult;
 	postdiv = opp->postdiv;
 
-	/* Unlock writing to PLL registers */
-	v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
-	v &= ~CFGCHIP0_PLL_MASTER_LOCK;
-	__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
-
 	ret = davinci_set_pllrate(pll, prediv, mult, postdiv);
 	if (WARN_ON(ret))
 		return ret;
@@ -1053,6 +1048,8 @@ static struct davinci_soc_info davinci_soc_info_da850 = {
 
 void __init da850_init(void)
 {
+	unsigned int v;
+
 	da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
 	if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module"))
 		return;
@@ -1075,4 +1072,14 @@ void __init da850_init(void)
 	 * be any noticible change even in non-DVFS use cases.
 	 */
 	da850_set_async3_src(1);
+
+	/* Unlock writing to PLL0 registers */
+	v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
+	v &= ~CFGCHIP0_PLL_MASTER_LOCK;
+	__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
+
+	/* Unlock writing to PLL1 registers */
+	v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
+	v &= ~CFGCHIP3_PLL1_MASTER_LOCK;
+	__raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
 }
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 08/35] davinci: da850/omap-l138: create static map for SRAM
  2010-01-06 18:31             ` [PATCH 07/35] davinci: da850/omap-l138: unlock PLL registers during init Kevin Hilman
@ 2010-01-06 18:31               ` Kevin Hilman
  2010-01-06 18:31                 ` [PATCH 09/35] davinci: explain CLOCK_TICK_RATE of 27MHz in include/mach/timex.h Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

Create static map for internal SRAM and populate SRAM base
and size in soc_info structure to allow SRAM allocation
functions from arch/arm/mach-davinci/sram.c to work.

On DA850 SRAM is used for suspend-to-RAM implementation
in places where DDR2 cannot be accessed as its clocks are
stopped.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/da850.c              |    8 ++++++++
 arch/arm/mach-davinci/include/mach/da8xx.h |    1 +
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index fcfde2a..1ac8f63 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -771,6 +771,12 @@ static struct map_desc da850_io_desc[] = {
 		.length		= DA8XX_CP_INTC_SIZE,
 		.type		= MT_DEVICE
 	},
+	{
+		.virtual	= SRAM_VIRT,
+		.pfn		= __phys_to_pfn(DA8XX_ARM_RAM_BASE),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE
+	},
 };
 
 static void __iomem *da850_psc_bases[] = {
@@ -1044,6 +1050,8 @@ static struct davinci_soc_info davinci_soc_info_da850 = {
 	.gpio_irq		= IRQ_DA8XX_GPIO0,
 	.serial_dev		= &da8xx_serial_device,
 	.emac_pdata		= &da8xx_emac_pdata,
+	.sram_dma		= DA8XX_ARM_RAM_BASE,
+	.sram_len		= SZ_8K,
 };
 
 void __init da850_init(void)
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index cab4a25..d43a4b6 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -57,6 +57,7 @@ extern void __iomem *da8xx_syscfg1_base;
 #define DA8XX_AEMIF_CS3_BASE	0x62000000
 #define DA8XX_AEMIF_CTL_BASE	0x68000000
 #define DA8XX_DDR2_CTL_BASE	0xb0000000
+#define DA8XX_ARM_RAM_BASE	0xffff0000
 
 #define PINMUX0			0x00
 #define PINMUX1			0x04
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 09/35] davinci: explain CLOCK_TICK_RATE of 27MHz in include/mach/timex.h
  2010-01-06 18:31               ` [PATCH 08/35] davinci: da850/omap-l138: create static map for SRAM Kevin Hilman
@ 2010-01-06 18:31                 ` Kevin Hilman
  2010-01-06 18:31                   ` [PATCH 10/35] davinci: board-dm646x-evm.c: arrange related code together Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

Leave a comment explaining the constant value of 27Mhz used
in include/mach/timex.h for all DaVinci platforms. Many of
the platforms actually run at 24MHz timer frequency (Eg.
EVMs of DM355, DM365 and OMAP-L1).

The comment also serves as a porting alert.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/include/mach/timex.h |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/include/mach/timex.h b/arch/arm/mach-davinci/include/mach/timex.h
index 5282756..9b88529 100644
--- a/arch/arm/mach-davinci/include/mach/timex.h
+++ b/arch/arm/mach-davinci/include/mach/timex.h
@@ -11,7 +11,12 @@
 #ifndef __ASM_ARCH_TIMEX_H
 #define __ASM_ARCH_TIMEX_H
 
-/* The source frequency for the timers is the 27MHz clock */
+/*
+ * Alert: Not all timers of the DaVinci family run at a frequency of 27MHz,
+ * but we should be fine as long as CLOCK_TICK_RATE or LATCH (see include/
+ * linux/jiffies.h) are not used directly in code. Currently none of the
+ * code relevant to DaVinci platform depends on these values directly.
+ */
 #define CLOCK_TICK_RATE 27000000
 
 #endif /* __ASM_ARCH_TIMEX_H__ */
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 10/35] davinci: board-dm646x-evm.c: arrange related code together
  2010-01-06 18:31                 ` [PATCH 09/35] davinci: explain CLOCK_TICK_RATE of 27MHz in include/mach/timex.h Kevin Hilman
@ 2010-01-06 18:31                   ` Kevin Hilman
  2010-01-06 18:31                     ` [PATCH 11/35] davinci: add support for DM6467T EVM Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

Currently all the #defines and static variables in the
board-dm646x-evm.c file are located right at the start
of the file because of which the related code is not
together - making reading the code difficult.

This patch moves around the code keeping related code
together.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/board-dm646x-evm.c |   90 +++++++++++++++---------------
 1 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 8d0b0e0..8c05343 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -40,53 +40,8 @@
 #include <mach/i2c.h>
 #include <mach/nand.h>
 
-#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
-    defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
-#define HAS_ATA 1
-#else
-#define HAS_ATA 0
-#endif
-
-#define DAVINCI_ASYNC_EMIF_CONTROL_BASE		0x20008000
-#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE	0x42000000
-
 #define NAND_BLOCK_SIZE		SZ_128K
 
-/* CPLD Register 0 bits to control ATA */
-#define DM646X_EVM_ATA_RST		BIT(0)
-#define DM646X_EVM_ATA_PWD		BIT(1)
-
-#define DM646X_EVM_PHY_MASK		(0x2)
-#define DM646X_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
-#define VIDCLKCTL_OFFSET	(DAVINCI_SYSTEM_MODULE_BASE + 0x38)
-#define VSCLKDIS_OFFSET		(DAVINCI_SYSTEM_MODULE_BASE + 0x6c)
-#define VCH2CLK_MASK		(BIT_MASK(10) | BIT_MASK(9) | BIT_MASK(8))
-#define VCH2CLK_SYSCLK8		(BIT(9))
-#define VCH2CLK_AUXCLK		(BIT(9) | BIT(8))
-#define VCH3CLK_MASK		(BIT_MASK(14) | BIT_MASK(13) | BIT_MASK(12))
-#define VCH3CLK_SYSCLK8		(BIT(13))
-#define VCH3CLK_AUXCLK		(BIT(14) | BIT(13))
-
-#define VIDCH2CLK		(BIT(10))
-#define VIDCH3CLK		(BIT(11))
-#define VIDCH1CLK		(BIT(4))
-#define TVP7002_INPUT		(BIT(4))
-#define TVP5147_INPUT		(~BIT(4))
-#define VPIF_INPUT_ONE_CHANNEL	(BIT(5))
-#define VPIF_INPUT_TWO_CHANNEL	(~BIT(5))
-#define TVP5147_CH0		"tvp514x-0"
-#define TVP5147_CH1		"tvp514x-1"
-
-static void __iomem *vpif_vidclkctl_reg;
-static void __iomem *vpif_vsclkdis_reg;
-/* spin lock for updating above registers */
-static spinlock_t vpif_reg_lock;
-
-static struct davinci_uart_config uart_config __initdata = {
-	.enabled_uarts = (1 << 0),
-};
-
 /* Note: We are setting first partition as 'bootloader' constituting UBL, U-Boot
  * and U-Boot environment this avoids dependency on any particular combination
  * of UBL, U-Boot or flashing tools etc.
@@ -120,6 +75,9 @@ static struct davinci_nand_pdata davinci_nand_data = {
 	.options		= 0,
 };
 
+#define DAVINCI_ASYNC_EMIF_CONTROL_BASE		0x20008000
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE	0x42000000
+
 static struct resource davinci_nand_resources[] = {
 	{
 		.start		= DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
@@ -144,6 +102,17 @@ static struct platform_device davinci_nand_device = {
 	},
 };
 
+#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
+    defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
+#define HAS_ATA 1
+#else
+#define HAS_ATA 0
+#endif
+
+/* CPLD Register 0 bits to control ATA */
+#define DM646X_EVM_ATA_RST		BIT(0)
+#define DM646X_EVM_ATA_PWD		BIT(1)
+
 /* CPLD Register 0 Client: used for I/O Control */
 static int cpld_reg0_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
@@ -424,6 +393,30 @@ static struct davinci_i2c_platform_data i2c_pdata = {
 	.bus_delay      = 0 /* usec */,
 };
 
+#define VIDCLKCTL_OFFSET	(DAVINCI_SYSTEM_MODULE_BASE + 0x38)
+#define VSCLKDIS_OFFSET		(DAVINCI_SYSTEM_MODULE_BASE + 0x6c)
+#define VCH2CLK_MASK		(BIT_MASK(10) | BIT_MASK(9) | BIT_MASK(8))
+#define VCH2CLK_SYSCLK8		(BIT(9))
+#define VCH2CLK_AUXCLK		(BIT(9) | BIT(8))
+#define VCH3CLK_MASK		(BIT_MASK(14) | BIT_MASK(13) | BIT_MASK(12))
+#define VCH3CLK_SYSCLK8		(BIT(13))
+#define VCH3CLK_AUXCLK		(BIT(14) | BIT(13))
+
+#define VIDCH2CLK		(BIT(10))
+#define VIDCH3CLK		(BIT(11))
+#define VIDCH1CLK		(BIT(4))
+#define TVP7002_INPUT		(BIT(4))
+#define TVP5147_INPUT		(~BIT(4))
+#define VPIF_INPUT_ONE_CHANNEL	(BIT(5))
+#define VPIF_INPUT_TWO_CHANNEL	(~BIT(5))
+#define TVP5147_CH0		"tvp514x-0"
+#define TVP5147_CH1		"tvp514x-1"
+
+static void __iomem *vpif_vidclkctl_reg;
+static void __iomem *vpif_vsclkdis_reg;
+/* spin lock for updating above registers */
+static spinlock_t vpif_reg_lock;
+
 static int set_vpif_clock(int mux_mode, int hd)
 {
 	unsigned long flags;
@@ -690,6 +683,13 @@ static void __init davinci_map_io(void)
 	dm646x_init();
 }
 
+static struct davinci_uart_config uart_config __initdata = {
+	.enabled_uarts = (1 << 0),
+};
+
+#define DM646X_EVM_PHY_MASK		(0x2)
+#define DM646X_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
+
 static __init void evm_init(void)
 {
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 11/35] davinci: add support for DM6467T EVM
  2010-01-06 18:31                   ` [PATCH 10/35] davinci: board-dm646x-evm.c: arrange related code together Kevin Hilman
@ 2010-01-06 18:31                     ` Kevin Hilman
  2010-01-06 18:31                       ` [PATCH 12/35] davinci: clock framework: remove spinlock usage Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

DM6467T (T for Turbo) is a newer and faster DM6467
part from TI. The new part supports 1080p video and
has the ARM running at 495MHz. More SoC information:

http://focus.ti.com/docs/prod/folders/print/tms320dm6467t.html

Spectrum Digital, Inc has a new EVM for this part.
It is _mostly_ same as the older DM6467 EVM except
for a 33MHz crystal input and THS8200 video encoder
for 1080p support.

The meat of this patch is dedicated to initializing
the crystal frequency from EVM board file.

Additional notes:
I did consider some alternative ways to make the crystal
input board specific including - (1) having board code
initialize the crystal frequency using the first member
of soc_info->cpu_clks array (2) introducing a new ref_clk_rate
member in soc_info structure.

But, the current way seems to be the simplest and least
intruding considering that both the clock array and SoC
info structure are actually private to the SoC file. Also
the fact that davinci_common_init() initializes both the
soc_info and clocks in one go.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/Kconfig               |    4 ++++
 arch/arm/mach-davinci/board-dm646x-evm.c    |   24 ++++++++++++++++++++++++
 arch/arm/mach-davinci/dm646x.c              |    3 +--
 arch/arm/mach-davinci/include/mach/dm646x.h |    2 ++
 4 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index 033bfed..0ebe185 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -91,10 +91,14 @@ config MACH_DAVINCI_DM6467_EVM
 	bool "TI DM6467 EVM"
 	default ARCH_DAVINCI_DM646x
 	depends on ARCH_DAVINCI_DM646x
+	select MACH_DAVINCI_DM6467TEVM
 	help
 	  Configure this option to specify the whether the board used
 	  for development is a DM6467 EVM
 
+config MACH_DAVINCI_DM6467TEVM
+	bool
+
 config MACH_DAVINCI_DM365_EVM
 	bool "TI DM365 EVM"
 	default ARCH_DAVINCI_DM365
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 8c05343..542bfdb 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -30,6 +30,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/clk.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -40,6 +41,8 @@
 #include <mach/i2c.h>
 #include <mach/nand.h>
 
+#include "clock.h"
+
 #define NAND_BLOCK_SIZE		SZ_128K
 
 /* Note: We are setting first partition as 'bootloader' constituting UBL, U-Boot
@@ -713,6 +716,17 @@ static __init void davinci_dm646x_evm_irq_init(void)
 	davinci_irq_init();
 }
 
+#define DM646X_EVM_REF_FREQ		27000000
+#define DM6467T_EVM_REF_FREQ		33000000
+
+void __init dm646x_board_setup_refclk(struct clk *clk)
+{
+	if (machine_is_davinci_dm6467tevm())
+		clk->rate = DM6467T_EVM_REF_FREQ;
+	else
+		clk->rate = DM646X_EVM_REF_FREQ;
+}
+
 MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
 	.phys_io      = IO_PHYS,
 	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
@@ -723,3 +737,13 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
 	.init_machine = evm_init,
 MACHINE_END
 
+MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM")
+	.phys_io      = IO_PHYS,
+	.io_pg_offst  = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
+	.boot_params  = (0x80000100),
+	.map_io       = davinci_map_io,
+	.init_irq     = davinci_dm646x_evm_irq_init,
+	.timer        = &davinci_timer,
+	.init_machine = evm_init,
+MACHINE_END
+
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 829a44b..515d3ed 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -42,7 +42,6 @@
 /*
  * Device specific clocks
  */
-#define DM646X_REF_FREQ		27000000
 #define DM646X_AUX_FREQ		24000000
 
 static struct pll_data pll1_data = {
@@ -57,7 +56,6 @@ static struct pll_data pll2_data = {
 
 static struct clk ref_clk = {
 	.name = "ref_clk",
-	.rate = DM646X_REF_FREQ,
 };
 
 static struct clk aux_clkin = {
@@ -925,6 +923,7 @@ void dm646x_setup_vpif(struct vpif_display_config *display_config,
 
 void __init dm646x_init(void)
 {
+	dm646x_board_setup_refclk(&ref_clk);
 	davinci_common_init(&davinci_soc_info_dm646x);
 }
 
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h
index 8cec746..8221153 100644
--- a/arch/arm/mach-davinci/include/mach/dm646x.h
+++ b/arch/arm/mach-davinci/include/mach/dm646x.h
@@ -16,6 +16,7 @@
 #include <mach/asp.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
+#include <linux/clk.h>
 
 #define DM646X_EMAC_BASE		(0x01C80000)
 #define DM646X_EMAC_CNTRL_OFFSET	(0x0000)
@@ -30,6 +31,7 @@ void __init dm646x_init(void);
 void __init dm646x_init_ide(void);
 void __init dm646x_init_mcasp0(struct snd_platform_data *pdata);
 void __init dm646x_init_mcasp1(struct snd_platform_data *pdata);
+void __init dm646x_board_setup_refclk(struct clk *clk);
 
 void dm646x_video_init(void);
 
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 12/35] davinci: clock framework: remove spinlock usage
  2010-01-06 18:31                     ` [PATCH 11/35] davinci: add support for DM6467T EVM Kevin Hilman
@ 2010-01-06 18:31                       ` Kevin Hilman
  2010-01-06 18:31                         ` [PATCH 13/35] davinci: make /proc/davinci_clocks display multi-rooted clock tree Kevin Hilman
  2010-01-08 17:06                         ` [PATCH 12/35] davinci: clock framework: remove spinlock usage Russell King - ARM Linux
  0 siblings, 2 replies; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

Currently, the spinlock in DaVinci clock framework is being
used to:

1) Protect clock structure variables usecount and rate against
concurrent modification.

2) Protect against simultaneous PSC enables/disables ie.
serialize davinci_psc_config().

3) Serialize clk_set_rate():
	i.	Prevent simultaneous setting of clock rates
	ii.	Ensure clock list remains sane during rate
		propagation (also in clk_set_parent).

Remove the spinlock usage in clock framework by:

1) Making clock rate and usecount as atomic variables.

2) Making davinci_psc_config() protect itself instead of
relying on serialization by caller.

3) (i) Allowing the clk->set_rate to serialize itself. There
should be no need to serialize all clock rate settings.
Currently the only user of rate setting is cpufreq driver on
DA850. cpufreq naturally serializes the calls to set CPU rate.
Also, there appears no need to lock IRQs during CPU rate
transtitions. If required, IRQs can be locked in the actual
set_rate function.

3) (ii) Use the mutex already in place for serialzing clock list
manipulation for serializing clock rate propagation as well.

Apart from the general benefit of reducing locking granurlarity,
the main motivation behind this change is to enable usage of
clock framework for off-chip clock synthesizers. One such
synthesizer, CDCE949, is present on DM6467 EVM. Access to the
synthesizer happens through I2C bus - accessing which can lead to
CPU sleep. Having IRQs locked in clk_set_rate prevents the
clk->set_rate function from sleeping.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/board-dm646x-evm.c |    4 +-
 arch/arm/mach-davinci/clock.c            |   74 ++++++++++++-----------------
 arch/arm/mach-davinci/clock.h            |    4 +-
 arch/arm/mach-davinci/da830.c            |    2 +-
 arch/arm/mach-davinci/da850.c            |    4 +-
 arch/arm/mach-davinci/dm355.c            |    4 +-
 arch/arm/mach-davinci/dm365.c            |    4 +-
 arch/arm/mach-davinci/dm644x.c           |    8 ++--
 arch/arm/mach-davinci/dm646x.c           |    8 ++--
 arch/arm/mach-davinci/psc.c              |    6 ++
 10 files changed, 56 insertions(+), 62 deletions(-)

diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 542bfdb..6ff3411 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -722,9 +722,9 @@ static __init void davinci_dm646x_evm_irq_init(void)
 void __init dm646x_board_setup_refclk(struct clk *clk)
 {
 	if (machine_is_davinci_dm6467tevm())
-		clk->rate = DM6467T_EVM_REF_FREQ;
+		atomic_set(&clk->rate, DM6467T_EVM_REF_FREQ);
 	else
-		clk->rate = DM646X_EVM_REF_FREQ;
+		atomic_set(&clk->rate, DM646X_EVM_REF_FREQ);
 }
 
 MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM")
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 0fa68c5..46c95e0 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -28,7 +28,6 @@
 
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clockfw_lock);
 
 static unsigned psc_domain(struct clk *clk)
 {
@@ -41,15 +40,16 @@ static void __clk_enable(struct clk *clk)
 {
 	if (clk->parent)
 		__clk_enable(clk->parent);
-	if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
+	if (atomic_read(&clk->usecount) == 0 && (clk->flags & CLK_PSC))
 		davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 1);
+	atomic_inc(&clk->usecount);
 }
 
 static void __clk_disable(struct clk *clk)
 {
-	if (WARN_ON(clk->usecount == 0))
+	if (WARN_ON(atomic_read(&clk->usecount) == 0))
 		return;
-	if (--clk->usecount == 0 && !(clk->flags & CLK_PLL))
+	if (atomic_dec_and_test(&clk->usecount) && !(clk->flags & CLK_PLL))
 		davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0);
 	if (clk->parent)
 		__clk_disable(clk->parent);
@@ -57,14 +57,10 @@ static void __clk_disable(struct clk *clk)
 
 int clk_enable(struct clk *clk)
 {
-	unsigned long flags;
-
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
 
-	spin_lock_irqsave(&clockfw_lock, flags);
 	__clk_enable(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return 0;
 }
@@ -72,14 +68,10 @@ EXPORT_SYMBOL(clk_enable);
 
 void clk_disable(struct clk *clk)
 {
-	unsigned long flags;
-
 	if (clk == NULL || IS_ERR(clk))
 		return;
 
-	spin_lock_irqsave(&clockfw_lock, flags);
 	__clk_disable(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
@@ -88,7 +80,7 @@ unsigned long clk_get_rate(struct clk *clk)
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
 
-	return clk->rate;
+	return atomic_read(&clk->rate);
 }
 EXPORT_SYMBOL(clk_get_rate);
 
@@ -100,7 +92,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 	if (clk->round_rate)
 		return clk->round_rate(clk, rate);
 
-	return clk->rate;
+	return atomic_read(&clk->rate);
 }
 EXPORT_SYMBOL(clk_round_rate);
 
@@ -111,28 +103,27 @@ static void propagate_rate(struct clk *root)
 
 	list_for_each_entry(clk, &root->children, childnode) {
 		if (clk->recalc)
-			clk->rate = clk->recalc(clk);
+			atomic_set(&clk->rate, clk->recalc(clk));
 		propagate_rate(clk);
 	}
 }
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	unsigned long flags;
 	int ret = -EINVAL;
 
 	if (clk == NULL || IS_ERR(clk))
 		return ret;
 
-	spin_lock_irqsave(&clockfw_lock, flags);
 	if (clk->set_rate)
 		ret = clk->set_rate(clk, rate);
 	if (ret == 0) {
 		if (clk->recalc)
-			clk->rate = clk->recalc(clk);
+			atomic_set(&clk->rate, clk->recalc(clk));
+		mutex_lock(&clocks_mutex);
 		propagate_rate(clk);
+		mutex_unlock(&clocks_mutex);
 	}
-	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
 }
@@ -140,26 +131,22 @@ EXPORT_SYMBOL(clk_set_rate);
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
-	unsigned long flags;
-
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
 
 	/* Cannot change parent on enabled clock */
-	if (WARN_ON(clk->usecount))
+	if (WARN_ON(atomic_read(&clk->usecount)))
 		return -EINVAL;
 
 	mutex_lock(&clocks_mutex);
 	clk->parent = parent;
 	list_del_init(&clk->childnode);
 	list_add(&clk->childnode, &clk->parent->children);
-	mutex_unlock(&clocks_mutex);
 
-	spin_lock_irqsave(&clockfw_lock, flags);
 	if (clk->recalc)
-		clk->rate = clk->recalc(clk);
+		atomic_set(&clk->rate, clk->recalc(clk));
 	propagate_rate(clk);
-	spin_unlock_irqrestore(&clockfw_lock, flags);
+	mutex_unlock(&clocks_mutex);
 
 	return 0;
 }
@@ -170,7 +157,7 @@ int clk_register(struct clk *clk)
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
 
-	if (WARN(clk->parent && !clk->parent->rate,
+	if (WARN(clk->parent && !atomic_read(&clk->parent->rate),
 			"CLK: %s parent %s has no rate!\n",
 			clk->name, clk->parent->name))
 		return -EINVAL;
@@ -184,16 +171,16 @@ int clk_register(struct clk *clk)
 	mutex_unlock(&clocks_mutex);
 
 	/* If rate is already set, use it */
-	if (clk->rate)
+	if (atomic_read(&clk->rate))
 		return 0;
 
 	/* Else, see if there is a way to calculate it */
 	if (clk->recalc)
-		clk->rate = clk->recalc(clk);
+		atomic_set(&clk->rate, clk->recalc(clk));
 
 	/* Otherwise, default to parent rate */
 	else if (clk->parent)
-		clk->rate = clk->parent->rate;
+		atomic_set(&clk->rate, atomic_read(&clk->parent->rate));
 
 	return 0;
 }
@@ -219,9 +206,9 @@ static int __init clk_disable_unused(void)
 {
 	struct clk *ck;
 
-	spin_lock_irq(&clockfw_lock);
+	mutex_lock(&clocks_mutex);
 	list_for_each_entry(ck, &clocks, node) {
-		if (ck->usecount > 0)
+		if (atomic_read(&ck->usecount) > 0)
 			continue;
 		if (!(ck->flags & CLK_PSC))
 			continue;
@@ -233,7 +220,7 @@ static int __init clk_disable_unused(void)
 		pr_info("Clocks: disable unused %s\n", ck->name);
 		davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, 0);
 	}
-	spin_unlock_irq(&clockfw_lock);
+	mutex_unlock(&clocks_mutex);
 
 	return 0;
 }
@@ -244,7 +231,7 @@ static unsigned long clk_sysclk_recalc(struct clk *clk)
 {
 	u32 v, plldiv;
 	struct pll_data *pll;
-	unsigned long rate = clk->rate;
+	unsigned long rate = atomic_read(&clk->rate);
 
 	/* If this is the PLL base clock, no more calculations needed */
 	if (clk->pll_data)
@@ -253,7 +240,7 @@ static unsigned long clk_sysclk_recalc(struct clk *clk)
 	if (WARN_ON(!clk->parent))
 		return rate;
 
-	rate = clk->parent->rate;
+	rate = atomic_read(&clk->parent->rate);
 
 	/* Otherwise, the parent must be a PLL */
 	if (WARN_ON(!clk->parent->pll_data))
@@ -281,9 +268,9 @@ static unsigned long clk_sysclk_recalc(struct clk *clk)
 static unsigned long clk_leafclk_recalc(struct clk *clk)
 {
 	if (WARN_ON(!clk->parent))
-		return clk->rate;
+		return atomic_read(&clk->rate);
 
-	return clk->parent->rate;
+	return atomic_read(&clk->parent->rate);
 }
 
 static unsigned long clk_pllclk_recalc(struct clk *clk)
@@ -291,11 +278,11 @@ static unsigned long clk_pllclk_recalc(struct clk *clk)
 	u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
 	u8 bypass;
 	struct pll_data *pll = clk->pll_data;
-	unsigned long rate = clk->rate;
+	unsigned long rate = atomic_read(&clk->rate);
 
 	pll->base = IO_ADDRESS(pll->phys_base);
 	ctrl = __raw_readl(pll->base + PLLCTL);
-	rate = pll->input_rate = clk->parent->rate;
+	rate = pll->input_rate = atomic_read(&clk->parent->rate);
 
 	if (ctrl & PLLCTL_PLLEN) {
 		bypass = 0;
@@ -333,8 +320,8 @@ static unsigned long clk_pllclk_recalc(struct clk *clk)
 		rate /= postdiv;
 	}
 
-	pr_debug("PLL%d: input = %lu MHz [ ",
-		 pll->num, clk->parent->rate / 1000000);
+	pr_debug("PLL%d: input = %u MHz [ ",
+		 pll->num, atomic_read(&clk->parent->rate) / 1000000);
 	if (bypass)
 		pr_debug("bypass ");
 	if (prediv > 1)
@@ -443,7 +430,7 @@ int __init davinci_clk_init(struct davinci_clk *clocks)
 		}
 
 		if (clk->recalc)
-			clk->rate = clk->recalc(clk);
+			atomic_set(&clk->rate, clk->recalc(clk));
 
 		if (clk->lpsc)
 			clk->flags |= CLK_PSC;
@@ -505,7 +492,8 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
 			min(i, (unsigned)(sizeof(buf) - 1 - nest)));
 
 	seq_printf(s, "%s users=%2d %-3s %9ld Hz\n",
-		   buf, parent->usecount, state, clk_get_rate(parent));
+			buf, atomic_read(&parent->usecount), state,
+			clk_get_rate(parent));
 	/* REVISIT show device associations too */
 
 	/* cost is now small, but not linear... */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index 31fb6ea..fa3e373 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -84,8 +84,8 @@ struct clk {
 	struct list_head	node;
 	struct module		*owner;
 	const char		*name;
-	unsigned long		rate;
-	u8			usecount;
+	atomic_t		rate;
+	atomic_t		usecount;
 	u8			lpsc;
 	u8			gpsc;
 	u32			flags;
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index 5479605..7a7895d 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -43,7 +43,7 @@ static struct pll_data pll0_data = {
 
 static struct clk ref_clk = {
 	.name		= "ref_clk",
-	.rate		= DA830_REF_FREQ,
+	.rate		= ATOMIC_INIT(DA830_REF_FREQ),
 };
 
 static struct clk pll0_clk = {
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 1ac8f63..5c6dd97 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -55,7 +55,7 @@ static struct pll_data pll0_data = {
 
 static struct clk ref_clk = {
 	.name		= "ref_clk",
-	.rate		= DA850_REF_FREQ,
+	.rate		= ATOMIC_INIT(DA850_REF_FREQ),
 };
 
 static struct clk pll0_clk = {
@@ -1025,7 +1025,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long armrate)
 
 static int da850_round_armrate(struct clk *clk, unsigned long rate)
 {
-	return clk->rate;
+	return atomic_read(&clk->rate);
 }
 #endif
 
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index dedf4d4..2244e8c 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -55,7 +55,7 @@ static struct pll_data pll2_data = {
 static struct clk ref_clk = {
 	.name = "ref_clk",
 	/* FIXME -- crystal rate is board-specific */
-	.rate = DM355_REF_FREQ,
+	.rate = ATOMIC_INIT(DM355_REF_FREQ),
 };
 
 static struct clk pll1_clk = {
@@ -314,7 +314,7 @@ static struct clk timer2_clk = {
 	.name = "timer2",
 	.parent = &pll1_aux_clk,
 	.lpsc = DAVINCI_LPSC_TIMER2,
-	.usecount = 1,              /* REVISIT: why cant' this be disabled? */
+	.usecount = ATOMIC_INIT(1), /* REVISIT: why cant' this be disabled? */
 };
 
 static struct clk timer3_clk = {
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 2ec619e..cc3bae4 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -52,7 +52,7 @@ static struct pll_data pll2_data = {
 
 static struct clk ref_clk = {
 	.name		= "ref_clk",
-	.rate		= DM365_REF_FREQ,
+	.rate		= ATOMIC_INIT(DM365_REF_FREQ),
 };
 
 static struct clk pll1_clk = {
@@ -358,7 +358,7 @@ static struct clk timer2_clk = {
 	.name		= "timer2",
 	.parent		= &pll1_aux_clk,
 	.lpsc		= DAVINCI_LPSC_TIMER2,
-	.usecount	= 1,
+	.usecount	= ATOMIC_INIT(1),
 };
 
 static struct clk timer3_clk = {
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index 2cd0081..e65e29e 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -47,7 +47,7 @@ static struct pll_data pll2_data = {
 
 static struct clk ref_clk = {
 	.name = "ref_clk",
-	.rate = DM644X_REF_FREQ,
+	.rate = ATOMIC_INIT(DM644X_REF_FREQ),
 };
 
 static struct clk pll1_clk = {
@@ -131,7 +131,7 @@ static struct clk dsp_clk = {
 	.parent = &pll1_sysclk1,
 	.lpsc = DAVINCI_LPSC_GEM,
 	.flags = PSC_DSP,
-	.usecount = 1,			/* REVISIT how to disable? */
+	.usecount = ATOMIC_INIT(1),	/* REVISIT how to disable? */
 };
 
 static struct clk arm_clk = {
@@ -146,7 +146,7 @@ static struct clk vicp_clk = {
 	.parent = &pll1_sysclk2,
 	.lpsc = DAVINCI_LPSC_IMCOP,
 	.flags = PSC_DSP,
-	.usecount = 1,			/* REVISIT how to disable? */
+	.usecount = ATOMIC_INIT(1),	/* REVISIT how to disable? */
 };
 
 static struct clk vpss_master_clk = {
@@ -274,7 +274,7 @@ static struct clk timer2_clk = {
 	.name = "timer2",
 	.parent = &pll1_aux_clk,
 	.lpsc = DAVINCI_LPSC_TIMER2,
-	.usecount = 1,              /* REVISIT: why cant' this be disabled? */
+	.usecount = ATOMIC_INIT(1), /* REVISIT: why cant' this be disabled? */
 };
 
 struct davinci_clk dm644x_clks[] = {
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 515d3ed..6f80616 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -60,7 +60,7 @@ static struct clk ref_clk = {
 
 static struct clk aux_clkin = {
 	.name = "aux_clkin",
-	.rate = DM646X_AUX_FREQ,
+	.rate = ATOMIC_INIT(DM646X_AUX_FREQ),
 };
 
 static struct clk pll1_clk = {
@@ -158,7 +158,7 @@ static struct clk dsp_clk = {
 	.parent = &pll1_sysclk1,
 	.lpsc = DM646X_LPSC_C64X_CPU,
 	.flags = PSC_DSP,
-	.usecount = 1,			/* REVISIT how to disable? */
+	.usecount = ATOMIC_INIT(1),		/* REVISIT how to disable? */
 };
 
 static struct clk arm_clk = {
@@ -262,14 +262,14 @@ static struct clk pwm0_clk = {
 	.name = "pwm0",
 	.parent = &pll1_sysclk3,
 	.lpsc = DM646X_LPSC_PWM0,
-	.usecount = 1,            /* REVIST: disabling hangs system */
+	.usecount = ATOMIC_INIT(1),	/* REVIST: disabling hangs system */
 };
 
 static struct clk pwm1_clk = {
 	.name = "pwm1",
 	.parent = &pll1_sysclk3,
 	.lpsc = DM646X_LPSC_PWM1,
-	.usecount = 1,            /* REVIST: disabling hangs system */
+	.usecount = ATOMIC_INIT(1),	/* REVIST: disabling hangs system */
 };
 
 static struct clk timer0_clk = {
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index adf6b5c..06130df 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/spinlock.h>
 
 #include <mach/cputype.h>
 #include <mach/psc.h>
@@ -53,6 +54,9 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 	void __iomem *psc_base;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 	u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */
+	/* Protect against simultaneous enable/disable of PSCs */
+	DEFINE_SPINLOCK(lock);
+	unsigned long flags;
 
 	if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
 		pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
@@ -62,6 +66,7 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 
 	psc_base = soc_info->psc_bases[ctlr];
 
+	spin_lock_irqsave(&lock, flags);
 	mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
 	mdctl &= ~MDSTAT_STATE_MASK;
 	mdctl |= next_state;
@@ -100,4 +105,5 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 	do {
 		mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
 	} while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
+	spin_unlock_irqrestore(&lock, flags);
 }
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 13/35] davinci: make /proc/davinci_clocks display multi-rooted clock tree
  2010-01-06 18:31                       ` [PATCH 12/35] davinci: clock framework: remove spinlock usage Kevin Hilman
@ 2010-01-06 18:31                         ` Kevin Hilman
  2010-01-06 18:31                           ` [PATCH 14/35] davinci: move /proc/davinci_clocks to debugfs Kevin Hilman
  2010-01-08 17:06                         ` [PATCH 12/35] davinci: clock framework: remove spinlock usage Russell King - ARM Linux
  1 sibling, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

This patch modifies clock dump to take care of
clock tress rooted at multiple oscillators.
Current code assumes the entire tree is rooted
on a single oscillator. When using off-chip
clock synthesizers, some of the clocks can
be obtained from a different on-board oscillator.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/clock.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 46c95e0..f7a04c2 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -504,12 +504,15 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
 
 static int davinci_ck_show(struct seq_file *m, void *v)
 {
-	/* Show clock tree; we know the main oscillator is first.
-	 * We trust nonzero usecounts equate to PSC enables...
+	struct clk *clk;
+
+	/*
+	 * Show clock tree; We trust nonzero usecounts equate to PSC enables...
 	 */
 	mutex_lock(&clocks_mutex);
-	if (!list_empty(&clocks))
-		dump_clock(m, 0, list_first_entry(&clocks, struct clk, node));
+	list_for_each_entry(clk, &clocks, node)
+		if (!clk->parent)
+			dump_clock(m, 0, clk);
 	mutex_unlock(&clocks_mutex);
 
 	return 0;
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 14/35] davinci: move /proc/davinci_clocks to debugfs
  2010-01-06 18:31                         ` [PATCH 13/35] davinci: make /proc/davinci_clocks display multi-rooted clock tree Kevin Hilman
@ 2010-01-06 18:31                           ` Kevin Hilman
  2010-01-06 18:31                             ` [PATCH 15/35] davinci: da850/omap-l138: Modify NOR partition info Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

Move /proc/davinci_clocks to /sys/kernel/debug/davinci_clocks
(debugfs).

debugfs is more suited for this since the clock dump is
debug information.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/clock.c |   42 ++++++++++------------------------------
 1 files changed, 11 insertions(+), 31 deletions(-)

diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index f7a04c2..e46a643 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -446,24 +446,10 @@ int __init davinci_clk_init(struct davinci_clk *clocks)
 	return 0;
 }
 
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
-{
-	return *pos < 1 ? (void *)1 : NULL;
-}
-
-static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	++*pos;
-	return NULL;
-}
+#ifdef CONFIG_DEBUG_FS
 
-static void davinci_ck_stop(struct seq_file *m, void *v)
-{
-}
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #define CLKNAME_MAX	10		/* longest clock name */
 #define NEST_DELTA	2
@@ -518,30 +504,24 @@ static int davinci_ck_show(struct seq_file *m, void *v)
 	return 0;
 }
 
-static const struct seq_operations davinci_ck_op = {
-	.start	= davinci_ck_start,
-	.next	= davinci_ck_next,
-	.stop	= davinci_ck_stop,
-	.show	= davinci_ck_show
-};
-
 static int davinci_ck_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &davinci_ck_op);
+	return single_open(file, davinci_ck_show, NULL);
 }
 
-static const struct file_operations proc_davinci_ck_operations = {
+static const struct file_operations davinci_ck_operations = {
 	.open		= davinci_ck_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= seq_release,
+	.release	= single_release,
 };
 
-static int __init davinci_ck_proc_init(void)
+static int __init davinci_clk_debugfs_init(void)
 {
-	proc_create("davinci_clocks", 0, NULL, &proc_davinci_ck_operations);
+	debugfs_create_file("davinci_clocks", S_IFREG | S_IRUGO, NULL, NULL,
+						&davinci_ck_operations);
 	return 0;
 
 }
-__initcall(davinci_ck_proc_init);
-#endif /* CONFIG_DEBUG_PROC_FS */
+device_initcall(davinci_clk_debugfs_init);
+#endif /* CONFIG_DEBUG_FS */
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 15/35] davinci: da850/omap-l138: Modify NOR partition info
  2010-01-06 18:31                           ` [PATCH 14/35] davinci: move /proc/davinci_clocks to debugfs Kevin Hilman
@ 2010-01-06 18:31                             ` Kevin Hilman
  2010-01-06 18:31                               ` [PATCH 16/35] davinci: da850/omap-l138: Enable 4-bit ecc Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

On DA850/OMAP-L138, NOR flash partition was starting from offset
ZERO erasing the UBL and u-boot when the complete NOR is erased.
This patch moves the start of the partition to 512K, after the
bootloaders and u-boot env variables.

This patch also creates a new partition on NOR Flash to store
Linux kernel image.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/board-da850-evm.c |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index dba2241..ac3b5a3 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -46,8 +46,20 @@
 
 static struct mtd_partition da850_evm_norflash_partition[] = {
 	{
-		.name           = "NOR filesystem",
+		.name           = "bootloaders + env",
 		.offset         = 0,
+		.size           = SZ_512K,
+		.mask_flags     = MTD_WRITEABLE,
+	},
+	{
+		.name           = "kernel",
+		.offset         = MTDPART_OFS_APPEND,
+		.size           = SZ_2M,
+		.mask_flags     = 0,
+	},
+	{
+		.name           = "filesystem",
+		.offset         = MTDPART_OFS_APPEND,
 		.size           = MTDPART_SIZ_FULL,
 		.mask_flags     = 0,
 	},
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 16/35] davinci: da850/omap-l138: Enable 4-bit ecc
  2010-01-06 18:31                             ` [PATCH 15/35] davinci: da850/omap-l138: Modify NOR partition info Kevin Hilman
@ 2010-01-06 18:31                               ` Kevin Hilman
  2010-01-06 18:31                                 ` [PATCH 17/35] TI Davinci EMAC : Re-use driver for other platforms Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

This patch initializes the platform data to enable 4-bit
ecc support on DA850/OMAP-L138.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/board-da850-evm.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index ac3b5a3..76e4347 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -131,6 +131,7 @@ static struct davinci_nand_pdata da850_evm_nandflash_data = {
 	.parts		= da850_evm_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(da850_evm_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
+	.ecc_bits	= 4,
 	.options	= NAND_USE_FLASH_BBT,
 };
 
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 17/35] TI Davinci EMAC : Re-use driver for other platforms.
  2010-01-06 18:31                               ` [PATCH 16/35] davinci: da850/omap-l138: Enable 4-bit ecc Kevin Hilman
@ 2010-01-06 18:31                                 ` Kevin Hilman
  2010-01-06 18:32                                   ` [PATCH 18/35] TI Davinci EMAC : add platform specific interrupt enable/disable logic Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sriramakrishnan <srk@ti.com>

The davinci EMAC peripheral is also available on other TI
platforms -notably TI AM3517 SoC. This patch modifies the
config option and the platform structure header files so that
the driver can be reused on non-davinci platforms as well.

Signed-off-by: Sriramakrishnan <srk@ti.com>
Acked-by: Chaithrika U S <chaithrika@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/common.c              |    2 +-
 arch/arm/mach-davinci/include/mach/da8xx.h  |    2 +-
 arch/arm/mach-davinci/include/mach/dm365.h  |    2 +-
 arch/arm/mach-davinci/include/mach/dm644x.h |    2 +-
 arch/arm/mach-davinci/include/mach/dm646x.h |    2 +-
 arch/arm/mach-davinci/include/mach/emac.h   |   36 ---------------------------
 drivers/net/Kconfig                         |    2 +-
 drivers/net/davinci_emac.c                  |    3 +-
 include/linux/davinci_emac.h                |   36 +++++++++++++++++++++++++++
 9 files changed, 43 insertions(+), 44 deletions(-)
 delete mode 100644 arch/arm/mach-davinci/include/mach/emac.h
 create mode 100644 include/linux/davinci_emac.h

diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c
index c2de94c..94f27cb 100644
--- a/arch/arm/mach-davinci/common.c
+++ b/arch/arm/mach-davinci/common.c
@@ -11,13 +11,13 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/etherdevice.h>
+#include <linux/davinci_emac.h>
 
 #include <asm/tlb.h>
 #include <asm/mach/map.h>
 
 #include <mach/common.h>
 #include <mach/cputype.h>
-#include <mach/emac.h>
 
 #include "clock.h"
 
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index d43a4b6..d9a7f11 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -13,10 +13,10 @@
 
 #include <video/da8xx-fb.h>
 
+#include <linux/davinci_emac.h>
 #include <mach/serial.h>
 #include <mach/edma.h>
 #include <mach/i2c.h>
-#include <mach/emac.h>
 #include <mach/asp.h>
 #include <mach/mmc.h>
 #include <mach/usb.h>
diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h
index f1710a3..3c07a88 100644
--- a/arch/arm/mach-davinci/include/mach/dm365.h
+++ b/arch/arm/mach-davinci/include/mach/dm365.h
@@ -14,8 +14,8 @@
 #define __ASM_ARCH_DM665_H
 
 #include <linux/platform_device.h>
+#include <linux/davinci_emac.h>
 #include <mach/hardware.h>
-#include <mach/emac.h>
 #include <mach/asp.h>
 #include <mach/keyscan.h>
 
diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h
index 44e8f0f..1a8b09c 100644
--- a/arch/arm/mach-davinci/include/mach/dm644x.h
+++ b/arch/arm/mach-davinci/include/mach/dm644x.h
@@ -22,8 +22,8 @@
 #ifndef __ASM_ARCH_DM644X_H
 #define __ASM_ARCH_DM644X_H
 
+#include <linux/davinci_emac.h>
 #include <mach/hardware.h>
-#include <mach/emac.h>
 #include <mach/asp.h>
 #include <media/davinci/vpfe_capture.h>
 
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h
index 8221153..846da98 100644
--- a/arch/arm/mach-davinci/include/mach/dm646x.h
+++ b/arch/arm/mach-davinci/include/mach/dm646x.h
@@ -12,11 +12,11 @@
 #define __ASM_ARCH_DM646X_H
 
 #include <mach/hardware.h>
-#include <mach/emac.h>
 #include <mach/asp.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <linux/clk.h>
+#include <linux/davinci_emac.h>
 
 #define DM646X_EMAC_BASE		(0x01C80000)
 #define DM646X_EMAC_CNTRL_OFFSET	(0x0000)
diff --git a/arch/arm/mach-davinci/include/mach/emac.h b/arch/arm/mach-davinci/include/mach/emac.h
deleted file mode 100644
index beff4fb..0000000
--- a/arch/arm/mach-davinci/include/mach/emac.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * TI DaVinci EMAC platform support
- *
- * Author: Kevin Hilman, Deep Root Systems, LLC
- *
- * 2007 (c) Deep Root Systems, LLC. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef _MACH_DAVINCI_EMAC_H
-#define _MACH_DAVINCI_EMAC_H
-
-#include <linux/if_ether.h>
-#include <linux/memory.h>
-
-struct emac_platform_data {
-	char mac_addr[ETH_ALEN];
-	u32 ctrl_reg_offset;
-	u32 ctrl_mod_reg_offset;
-	u32 ctrl_ram_offset;
-	u32 mdio_reg_offset;
-	u32 ctrl_ram_size;
-	u32 phy_mask;
-	u32 mdio_max_freq;
-	u8 rmii_en;
-	u8 version;
-};
-
-enum {
-	EMAC_VERSION_1,	/* DM644x */
-	EMAC_VERSION_2,	/* DM646x */
-};
-
-void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context);
-#endif
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index dd9a09c..1830062 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -920,7 +920,7 @@ config NET_NETX
 
 config TI_DAVINCI_EMAC
 	tristate "TI DaVinci EMAC Support"
-	depends on ARM && ARCH_DAVINCI
+	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
 	select PHYLIB
 	help
 	  This driver supports TI's DaVinci Ethernet .
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 34e0310..d4e72c0 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -62,12 +62,11 @@
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
+#include <linux/davinci_emac.h>
 
 #include <asm/irq.h>
 #include <asm/page.h>
 
-#include <mach/emac.h>
-
 static int debug_level;
 module_param(debug_level, int, 0);
 MODULE_PARM_DESC(debug_level, "DaVinci EMAC debug level (NETIF_MSG bits)");
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
new file mode 100644
index 0000000..ff55487
--- /dev/null
+++ b/include/linux/davinci_emac.h
@@ -0,0 +1,36 @@
+/*
+ * TI DaVinci EMAC platform support
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef _LINUX_DAVINCI_EMAC_H
+#define _LINUX_DAVINCI_EMAC_H
+
+#include <linux/if_ether.h>
+#include <linux/memory.h>
+
+struct emac_platform_data {
+	char mac_addr[ETH_ALEN];
+	u32 ctrl_reg_offset;
+	u32 ctrl_mod_reg_offset;
+	u32 ctrl_ram_offset;
+	u32 mdio_reg_offset;
+	u32 ctrl_ram_size;
+	u32 phy_mask;
+	u32 mdio_max_freq;
+	u8 rmii_en;
+	u8 version;
+};
+
+enum {
+	EMAC_VERSION_1,	/* DM644x */
+	EMAC_VERSION_2,	/* DM646x */
+};
+
+void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context);
+#endif
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 18/35] TI Davinci EMAC : add platform specific interrupt enable/disable logic.
  2010-01-06 18:31                                 ` [PATCH 17/35] TI Davinci EMAC : Re-use driver for other platforms Kevin Hilman
@ 2010-01-06 18:32                                   ` Kevin Hilman
  2010-01-06 18:32                                     ` [PATCH 19/35] TI Davinci EMAC : Abstract Buffer address translation logic Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sriramakrishnan <srk@ti.com>

On certain SOCs, the EMAC controller is interfaced with a wrapper logic
for handling interrupts. This  patch implements a platform
specific hook to cater to platforms that require custom interrupt
handling logic

Signed-off-by: Sriramakrishnan <srk@ti.com>
Acked-by: Chaithrika U S <chaithrika@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 drivers/net/davinci_emac.c   |   11 +++++++++++
 include/linux/davinci_emac.h |    2 ++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index d4e72c0..8c356b5 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -487,6 +487,9 @@ struct emac_priv {
 	struct mii_bus *mii_bus;
 	struct phy_device *phydev;
 	spinlock_t lock;
+	/*platform specific members*/
+	void (*int_enable) (void);
+	void (*int_disable) (void);
 };
 
 /* clock frequency for EMAC */
@@ -1001,6 +1004,8 @@ static void emac_int_disable(struct emac_priv *priv)
 		emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0x0);
 		emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0x0);
 		/* NOTE: Rx Threshold and Misc interrupts are not disabled */
+		if (priv->int_disable)
+			priv->int_disable();
 
 		local_irq_restore(flags);
 
@@ -1020,6 +1025,9 @@ static void emac_int_disable(struct emac_priv *priv)
 static void emac_int_enable(struct emac_priv *priv)
 {
 	if (priv->version == EMAC_VERSION_2) {
+		if (priv->int_enable)
+			priv->int_enable();
+
 		emac_ctrl_write(EMAC_DM646X_CMRXINTEN, 0xff);
 		emac_ctrl_write(EMAC_DM646X_CMTXINTEN, 0xff);
 
@@ -2659,6 +2667,9 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 	priv->phy_mask = pdata->phy_mask;
 	priv->rmii_en = pdata->rmii_en;
 	priv->version = pdata->version;
+	priv->int_enable = pdata->interrupt_enable;
+	priv->int_disable = pdata->interrupt_disable;
+
 	emac_dev = &ndev->dev;
 	/* Get EMAC platform data */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
index ff55487..6d894ef 100644
--- a/include/linux/davinci_emac.h
+++ b/include/linux/davinci_emac.h
@@ -25,6 +25,8 @@ struct emac_platform_data {
 	u32 mdio_max_freq;
 	u8 rmii_en;
 	u8 version;
+	void (*interrupt_enable) (void);
+	void (*interrupt_disable) (void);
 };
 
 enum {
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 19/35] TI Davinci EMAC : Abstract Buffer address translation logic.
  2010-01-06 18:32                                   ` [PATCH 18/35] TI Davinci EMAC : add platform specific interrupt enable/disable logic Kevin Hilman
@ 2010-01-06 18:32                                     ` Kevin Hilman
  2010-01-06 18:32                                       ` [PATCH 20/35] davinci: clock: Check CLK_PSC flag before disabling PSC Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sriramakrishnan <srk@ti.com>

When programming the DMA engine, the next pointers must be
programmed with physical address as seen from the DMA master
address space. This address may be different from physical
address of the buffer RAM area. This patch abstracts the
buffer address translation logic.

Signed-off-by: Sriramakrishnan <srk@ti.com>
Acked-by: Chaithrika U S <chaithrika@ti.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 drivers/net/davinci_emac.c   |   41 ++++++++++++++++++++++++-----------------
 include/linux/davinci_emac.h |    1 +
 2 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 8c356b5..a46286e 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -464,6 +464,7 @@ struct emac_priv {
 	void __iomem *ctrl_base;
 	void __iomem *emac_ctrl_ram;
 	u32 ctrl_ram_size;
+	u32 hw_ram_addr;
 	struct emac_txch *txch[EMAC_DEF_MAX_TX_CH];
 	struct emac_rxch *rxch[EMAC_DEF_MAX_RX_CH];
 	u32 link; /* 1=link on, 0=link off */
@@ -497,11 +498,9 @@ static struct clk *emac_clk;
 static unsigned long emac_bus_frequency;
 static unsigned long mdio_max_freq;
 
-/* EMAC internal utility function */
-static inline u32 emac_virt_to_phys(void __iomem *addr)
-{
-	return (u32 __force) io_v2p(addr);
-}
+#define emac_virt_to_phys(addr, priv) \
+	(((u32 __force)(addr) - (u32 __force)(priv->emac_ctrl_ram)) \
+	+ priv->hw_ram_addr)
 
 /* Cache macros - Packet buffers would be from skb pool which is cached */
 #define EMAC_VIRT_NOCACHE(addr) (addr)
@@ -1309,7 +1308,7 @@ static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
 	curr_bd = txch->active_queue_head;
 	if (NULL == curr_bd) {
 		emac_write(EMAC_TXCP(ch),
-			   emac_virt_to_phys(txch->last_hw_bdprocessed));
+			   emac_virt_to_phys(txch->last_hw_bdprocessed, priv));
 		txch->no_active_pkts++;
 		spin_unlock_irqrestore(&priv->tx_lock, flags);
 		return 0;
@@ -1319,7 +1318,7 @@ static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
 	while ((curr_bd) &&
 	      ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
 	      (pkts_processed < budget)) {
-		emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd));
+		emac_write(EMAC_TXCP(ch), emac_virt_to_phys(curr_bd, priv));
 		txch->active_queue_head = curr_bd->next;
 		if (frame_status & EMAC_CPPI_EOQ_BIT) {
 			if (curr_bd->next) {	/* misqueued packet */
@@ -1406,7 +1405,7 @@ static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch)
 		txch->active_queue_tail = curr_bd;
 		if (1 != txch->queue_active) {
 			emac_write(EMAC_TXHDP(ch),
-					emac_virt_to_phys(curr_bd));
+					emac_virt_to_phys(curr_bd, priv));
 			txch->queue_active = 1;
 		}
 		++txch->queue_reinit;
@@ -1418,10 +1417,11 @@ static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch)
 		tail_bd->next = curr_bd;
 		txch->active_queue_tail = curr_bd;
 		tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
-		tail_bd->h_next = (int)emac_virt_to_phys(curr_bd);
+		tail_bd->h_next = (int)emac_virt_to_phys(curr_bd, priv);
 		frame_status = tail_bd->mode;
 		if (frame_status & EMAC_CPPI_EOQ_BIT) {
-			emac_write(EMAC_TXHDP(ch), emac_virt_to_phys(curr_bd));
+			emac_write(EMAC_TXHDP(ch),
+				emac_virt_to_phys(curr_bd, priv));
 			frame_status &= ~(EMAC_CPPI_EOQ_BIT);
 			tail_bd->mode = frame_status;
 			++txch->end_of_queue_add;
@@ -1611,7 +1611,8 @@ static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param)
 		}
 
 		/* populate the hardware descriptor */
-		curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head);
+		curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head,
+				priv);
 		/* FIXME buff_ptr = dma_map_single(... data_ptr ...) */
 		curr_bd->buff_ptr = virt_to_phys(curr_bd->data_ptr);
 		curr_bd->off_b_len = rxch->buf_size;
@@ -1886,7 +1887,7 @@ static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch,
 		rxch->active_queue_tail = curr_bd;
 		if (0 != rxch->queue_active) {
 			emac_write(EMAC_RXHDP(ch),
-				   emac_virt_to_phys(rxch->active_queue_head));
+			   emac_virt_to_phys(rxch->active_queue_head, priv));
 			rxch->queue_active = 1;
 		}
 	} else {
@@ -1897,11 +1898,11 @@ static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch,
 		rxch->active_queue_tail = curr_bd;
 		tail_bd->next = curr_bd;
 		tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
-		tail_bd->h_next = emac_virt_to_phys(curr_bd);
+		tail_bd->h_next = emac_virt_to_phys(curr_bd, priv);
 		frame_status = tail_bd->mode;
 		if (frame_status & EMAC_CPPI_EOQ_BIT) {
 			emac_write(EMAC_RXHDP(ch),
-					emac_virt_to_phys(curr_bd));
+					emac_virt_to_phys(curr_bd, priv));
 			frame_status &= ~(EMAC_CPPI_EOQ_BIT);
 			tail_bd->mode = frame_status;
 			++rxch->end_of_queue_add;
@@ -1994,7 +1995,7 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
 		curr_pkt->num_bufs = 1;
 		curr_pkt->pkt_length =
 			(frame_status & EMAC_RX_BD_PKT_LENGTH_MASK);
-		emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd));
+		emac_write(EMAC_RXCP(ch), emac_virt_to_phys(curr_bd, priv));
 		++rxch->processed_bd;
 		last_bd = curr_bd;
 		curr_bd = last_bd->next;
@@ -2005,7 +2006,7 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
 			if (curr_bd) {
 				++rxch->mis_queued_packets;
 				emac_write(EMAC_RXHDP(ch),
-					   emac_virt_to_phys(curr_bd));
+					   emac_virt_to_phys(curr_bd, priv));
 			} else {
 				++rxch->end_of_queue;
 				rxch->queue_active = 0;
@@ -2106,7 +2107,7 @@ static int emac_hw_enable(struct emac_priv *priv)
 		emac_write(EMAC_RXINTMASKSET, BIT(ch));
 		rxch->queue_active = 1;
 		emac_write(EMAC_RXHDP(ch),
-			   emac_virt_to_phys(rxch->active_queue_head));
+			   emac_virt_to_phys(rxch->active_queue_head, priv));
 	}
 
 	/* Enable MII */
@@ -2702,6 +2703,12 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
 	priv->ctrl_ram_size = pdata->ctrl_ram_size;
 	priv->emac_ctrl_ram = priv->remap_addr + pdata->ctrl_ram_offset;
 
+	if (pdata->hw_ram_addr)
+		priv->hw_ram_addr = pdata->hw_ram_addr;
+	else
+		priv->hw_ram_addr = (u32 __force)res->start +
+					pdata->ctrl_ram_offset;
+
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
 		dev_err(emac_dev, "DaVinci EMAC: Error getting irq res\n");
diff --git a/include/linux/davinci_emac.h b/include/linux/davinci_emac.h
index 6d894ef..7c930db 100644
--- a/include/linux/davinci_emac.h
+++ b/include/linux/davinci_emac.h
@@ -19,6 +19,7 @@ struct emac_platform_data {
 	u32 ctrl_reg_offset;
 	u32 ctrl_mod_reg_offset;
 	u32 ctrl_ram_offset;
+	u32 hw_ram_addr;
 	u32 mdio_reg_offset;
 	u32 ctrl_ram_size;
 	u32 phy_mask;
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 20/35] davinci: clock: Check CLK_PSC flag before disabling PSC
  2010-01-06 18:32                                     ` [PATCH 19/35] TI Davinci EMAC : Abstract Buffer address translation logic Kevin Hilman
@ 2010-01-06 18:32                                       ` Kevin Hilman
  2010-01-06 18:32                                         ` [PATCH 21/35] DaVinci: DM365: Changing default queue for DM365 Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Chaithrika U S <chaithrika@ti.com>

Some modules do not have PSC to control their clocks.
The 'lpsc' field in the clk structure is 0 for such clocks.

In the clock disable function check for CLK PSC flag before
disabling the PSC. If this is not taken care of then it may
so happen that module controlled by LPSC 0 is erroneously disabled.

Signed-off-by: Chaithrika U S <chaithrika@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/clock.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index e46a643..f097f8d 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -49,7 +49,8 @@ static void __clk_disable(struct clk *clk)
 {
 	if (WARN_ON(atomic_read(&clk->usecount) == 0))
 		return;
-	if (atomic_dec_and_test(&clk->usecount) && !(clk->flags & CLK_PLL))
+	if (atomic_dec_and_test(&clk->usecount) && !(clk->flags & CLK_PLL)
+						&& (clk->flags & CLK_PSC))
 		davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0);
 	if (clk->parent)
 		__clk_disable(clk->parent);
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 21/35] DaVinci: DM365: Changing default queue for DM365.
  2010-01-06 18:32                                       ` [PATCH 20/35] davinci: clock: Check CLK_PSC flag before disabling PSC Kevin Hilman
@ 2010-01-06 18:32                                         ` Kevin Hilman
  2010-01-06 18:32                                           ` [PATCH 22/35] davinci: add power management support Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sandeep Paulraj <s-paulraj@ti.com>

In DM365 Q0, Q1 and Q2 are used by codecs.
LSP drivers should use Q3.
This patch changes the default queue for DM365.

Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/dm365.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index cc3bae4..62cec33 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -754,7 +754,7 @@ static struct edma_soc_info dm365_edma_info[] = {
 		.n_cc			= 1,
 		.queue_tc_mapping	= dm365_queue_tc_mapping,
 		.queue_priority_mapping	= dm365_queue_priority_mapping,
-		.default_queue		= EVENTQ_2,
+		.default_queue		= EVENTQ_3,
 	},
 };
 
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 22/35] davinci: add power management support
  2010-01-06 18:32                                         ` [PATCH 21/35] DaVinci: DM365: Changing default queue for DM365 Kevin Hilman
@ 2010-01-06 18:32                                           ` Kevin Hilman
  2010-01-06 18:32                                             ` [PATCH 23/35] davinci: da850/omap-l138: add support for SoC suspend Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

This patch adds core power management (suspend-to-RAM)
support for DaVinci SoCs.

The code depends on the the "deepsleep" feature to suspend
the SoC and saves power by gating the input clock.

The wakeup can be based on an external event as supported
by the SoC.

Assembly code (in sleep.S) is added to aid gating DDR2
clocks. Code doing this work should not be accessing DDR2.
The assembly code is relocated to SRAM by the code in pm.c

The support has been validated on DA850/OMAP-L138 only
though the code is (hopefully) generic enough that other
SoCs supporting deepsleep feature simply requires SoC
specific code to start using this driver.

Note that all the device drivers don't support suspend/resume
still and are being worked on.

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/Makefile              |    1 +
 arch/arm/mach-davinci/include/mach/memory.h |    1 +
 arch/arm/mach-davinci/include/mach/pm.h     |   54 +++++++
 arch/arm/mach-davinci/pm.c                  |  158 +++++++++++++++++++
 arch/arm/mach-davinci/sleep.S               |  224 +++++++++++++++++++++++++++
 5 files changed, 438 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-davinci/include/mach/pm.h
 create mode 100644 arch/arm/mach-davinci/pm.c
 create mode 100644 arch/arm/mach-davinci/sleep.S

diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index eeb9230..d0fed3a 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_MACH_DAVINCI_DA850_EVM)	+= board-da850-evm.o
 # Power Management
 obj-$(CONFIG_CPU_FREQ)			+= cpufreq.o
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
+obj-$(CONFIG_SUSPEND)			+= pm.o sleep.o
diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h
index 7aeaf46..a91edfb 100644
--- a/arch/arm/mach-davinci/include/mach/memory.h
+++ b/arch/arm/mach-davinci/include/mach/memory.h
@@ -33,6 +33,7 @@
 
 #define DDR2_SDRCR_OFFSET	0xc
 #define DDR2_SRPD_BIT		BIT(23)
+#define DDR2_MCLKSTOPEN_BIT	BIT(30)
 #define DDR2_LPMODEN_BIT	BIT(31)
 
 /*
diff --git a/arch/arm/mach-davinci/include/mach/pm.h b/arch/arm/mach-davinci/include/mach/pm.h
new file mode 100644
index 0000000..37b19bf
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/pm.h
@@ -0,0 +1,54 @@
+/*
+ * TI DaVinci platform support for power management.
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc. 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef _MACH_DAVINCI_PM_H
+#define _MACH_DAVINCI_PM_H
+
+/*
+ * Caution: Assembly code in sleep.S makes assumtion on the order
+ * of the members of this structure.
+ */
+struct davinci_pm_config {
+	void __iomem *ddr2_ctlr_base;
+	void __iomem *ddrpsc_reg_base;
+	int ddrpsc_num;
+	void __iomem *ddrpll_reg_base;
+	void __iomem *deepsleep_reg;
+	void __iomem *cpupll_reg_base;
+	/*
+	 * Note on SLEEPCOUNT:
+	 * The SLEEPCOUNT feature is mainly intended for cases in which
+	 * the internal oscillator is used. The internal oscillator is
+	 * fully disabled in deep sleep mode.  When you exist deep sleep
+	 * mode, the oscillator will be turned on and will generate very
+	 * small oscillations which will not be detected by the deep sleep
+	 * counter.  Eventually those oscillations will grow to an amplitude
+	 * large enough to start incrementing the deep sleep counter.
+	 * In this case recommendation from hardware engineers is that the
+	 * SLEEPCOUNT be set to 4096.  This means that 4096 valid clock cycles
+	 * must be detected before the clock is passed to the rest of the
+	 * system.
+	 * In the case that the internal oscillator is not used and the
+	 * clock is generated externally, the SLEEPCOUNT value can be very
+	 * small since the clock input is assumed to be stable before SoC
+	 * is taken out of deepsleep mode.  A value of 128 would be more than
+	 * adequate.
+	 */
+	int sleepcount;
+};
+
+extern unsigned int davinci_cpu_suspend_sz;
+extern void davinci_cpu_suspend(struct davinci_pm_config *);
+
+#endif
diff --git a/arch/arm/mach-davinci/pm.c b/arch/arm/mach-davinci/pm.c
new file mode 100644
index 0000000..fab953b
--- /dev/null
+++ b/arch/arm/mach-davinci/pm.c
@@ -0,0 +1,158 @@
+/*
+ * DaVinci Power Management Routines
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc. 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+
+#include <asm/cacheflush.h>
+#include <asm/delay.h>
+
+#include <mach/da8xx.h>
+#include <mach/sram.h>
+#include <mach/pm.h>
+
+#include "clock.h"
+
+#define DEEPSLEEP_SLEEPCOUNT_MASK	0xFFFF
+
+static void (*davinci_sram_suspend) (struct davinci_pm_config *);
+static struct davinci_pm_config *pdata;
+
+static void davinci_sram_push(void *dest, void *src, unsigned int size)
+{
+	memcpy(dest, src, size);
+	flush_icache_range((unsigned long)dest, (unsigned long)(dest + size));
+}
+
+static void davinci_pm_suspend(void)
+{
+	unsigned val;
+
+	if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
+
+		/* Switch CPU PLL to bypass mode */
+		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
+		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+
+		udelay(PLL_BYPASS_TIME);
+
+		/* Powerdown CPU PLL */
+		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val |= PLLCTL_PLLPWRDN;
+		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+	}
+
+	/* Configure sleep count in deep sleep register */
+	val = __raw_readl(pdata->deepsleep_reg);
+	val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
+	val |= pdata->sleepcount;
+	__raw_writel(val, pdata->deepsleep_reg);
+
+	/* System goes to sleep in this call */
+	davinci_sram_suspend(pdata);
+
+	if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
+
+		/* put CPU PLL in reset */
+		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val &= ~PLLCTL_PLLRST;
+		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+
+		/* put CPU PLL in power down */
+		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val &= ~PLLCTL_PLLPWRDN;
+		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+
+		/* wait for CPU PLL reset */
+		udelay(PLL_RESET_TIME);
+
+		/* bring CPU PLL out of reset */
+		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val |= PLLCTL_PLLRST;
+		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+
+		/* Wait for CPU PLL to lock */
+		udelay(PLL_LOCK_TIME);
+
+		/* Remove CPU PLL from bypass mode */
+		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val &= ~PLLCTL_PLLENSRC;
+		val |= PLLCTL_PLLEN;
+		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+	}
+}
+
+static int davinci_pm_enter(suspend_state_t state)
+{
+	int ret = 0;
+
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		davinci_pm_suspend();
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static struct platform_suspend_ops davinci_pm_ops = {
+	.enter		= davinci_pm_enter,
+	.valid		= suspend_valid_only_mem,
+};
+
+static int __init davinci_pm_probe(struct platform_device *pdev)
+{
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "cannot get platform data\n");
+		return -ENOENT;
+	}
+
+	davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL);
+	if (!davinci_sram_suspend) {
+		dev_err(&pdev->dev, "cannot allocate SRAM memory\n");
+		return -ENOMEM;
+	}
+
+	davinci_sram_push(davinci_sram_suspend, davinci_cpu_suspend,
+						davinci_cpu_suspend_sz);
+
+	suspend_set_ops(&davinci_pm_ops);
+
+	return 0;
+}
+
+static int __exit davinci_pm_remove(struct platform_device *pdev)
+{
+	sram_free(davinci_sram_suspend, davinci_cpu_suspend_sz);
+	return 0;
+}
+
+static struct platform_driver davinci_pm_driver = {
+	.driver = {
+		.name	 = "pm-davinci",
+		.owner	 = THIS_MODULE,
+	},
+	.remove = __exit_p(davinci_pm_remove),
+};
+
+static int __init davinci_pm_init(void)
+{
+	return platform_driver_probe(&davinci_pm_driver, davinci_pm_probe);
+}
+late_initcall(davinci_pm_init);
diff --git a/arch/arm/mach-davinci/sleep.S b/arch/arm/mach-davinci/sleep.S
new file mode 100644
index 0000000..fb5e72b
--- /dev/null
+++ b/arch/arm/mach-davinci/sleep.S
@@ -0,0 +1,224 @@
+/*
+ * (C) Copyright 2009, Texas Instruments, Inc. 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
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* replicated define because linux/bitops.h cannot be included in assembly */
+#define BIT(nr)			(1 << (nr))
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/psc.h>
+#include <mach/memory.h>
+
+#include "clock.h"
+
+/* Arbitrary, hardware currently does not update PHYRDY correctly */
+#define PHYRDY_CYCLES		0x1000
+
+/* Assume 25 MHz speed for the cycle conversions since PLLs are bypassed */
+#define PLL_BYPASS_CYCLES	(PLL_BYPASS_TIME * 25)
+#define PLL_RESET_CYCLES	(PLL_RESET_TIME	* 25)
+#define PLL_LOCK_CYCLES		(PLL_LOCK_TIME * 25)
+
+#define DEEPSLEEP_SLEEPENABLE_BIT	BIT(31)
+
+	.text
+/*
+ * Move DaVinci into deep sleep state
+ *
+ * Note: This code is copied to internal SRAM by PM code. When the DaVinci
+ *	 wakes up it continues execution at the point it went to sleep.
+ * Register Usage:
+ * 	r0: contains virtual base for DDR2 controller
+ * 	r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
+ * 	r2: contains PSC number for DDR2
+ * 	r3: contains virtual base DDR2 PLL controller
+ * 	r4: contains virtual address of the DEEPSLEEP register
+ */
+ENTRY(davinci_cpu_suspend)
+	stmfd	sp!, {r0-r12, lr}		@ save registers on stack
+
+	ldr 	ip, CACHE_FLUSH
+	blx	ip
+
+	ldmia	r0, {r0-r4}
+
+	/*
+	 * Switch DDR to self-refresh mode.
+	 */
+
+	/* calculate SDRCR address */
+	ldr	ip, [r0, #DDR2_SDRCR_OFFSET]
+	bic	ip, ip, #DDR2_SRPD_BIT
+	orr	ip, ip, #DDR2_LPMODEN_BIT
+	str	ip, [r0, #DDR2_SDRCR_OFFSET]
+
+	ldr	ip, [r0, #DDR2_SDRCR_OFFSET]
+	orr	ip, ip, #DDR2_MCLKSTOPEN_BIT
+	str	ip, [r0, #DDR2_SDRCR_OFFSET]
+
+       mov	ip, #PHYRDY_CYCLES
+1:     subs	ip, ip, #0x1
+       bne	1b
+
+       /* Disable DDR2 LPSC */
+	mov	r7, r0
+	mov	r0, #0x2
+	bl davinci_ddr_psc_config
+	mov	r0, r7
+
+	/* Disable clock to DDR PHY */
+	ldr	ip, [r3, #PLLDIV1]
+	bic	ip, ip, #PLLDIV_EN
+	str	ip, [r3, #PLLDIV1]
+
+	/* Put the DDR PLL in bypass and power down */
+	ldr	ip, [r3, #PLLCTL]
+	bic	ip, ip, #PLLCTL_PLLENSRC
+	bic	ip, ip, #PLLCTL_PLLEN
+	str	ip, [r3, #PLLCTL]
+
+	/* Wait for PLL to switch to bypass */
+       mov	ip, #PLL_BYPASS_CYCLES
+2:     subs	ip, ip, #0x1
+       bne	2b
+
+       /* Power down the PLL */
+	ldr	ip, [r3, #PLLCTL]
+	orr	ip, ip, #PLLCTL_PLLPWRDN
+	str	ip, [r3, #PLLCTL]
+
+	/* Go to deep sleep */
+	ldr	ip, [r4]
+	orr	ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
+	/* System goes to sleep beyond after this instruction */
+	str	ip, [r4]
+
+	/* Wake up from sleep */
+
+	/* Clear sleep enable */
+	ldr	ip, [r4]
+	bic	ip, ip, #DEEPSLEEP_SLEEPENABLE_BIT
+	str	ip, [r4]
+
+	/* initialize the DDR PLL controller */
+
+	/* Put PLL in reset */
+	ldr	ip, [r3, #PLLCTL]
+	bic	ip, ip, #PLLCTL_PLLRST
+	str	ip, [r3, #PLLCTL]
+
+	/* Clear PLL power down */
+	ldr	ip, [r3, #PLLCTL]
+	bic	ip, ip, #PLLCTL_PLLPWRDN
+	str	ip, [r3, #PLLCTL]
+
+       mov	ip, #PLL_RESET_CYCLES
+3:     subs	ip, ip, #0x1
+       bne	3b
+
+       /* Bring PLL out of reset */
+	ldr	ip, [r3, #PLLCTL]
+	orr	ip, ip, #PLLCTL_PLLRST
+	str	ip, [r3, #PLLCTL]
+
+	/* Wait for PLL to lock (assume prediv = 1, 25MHz OSCIN) */
+       mov	ip, #PLL_LOCK_CYCLES
+4:     subs	ip, ip, #0x1
+       bne	4b
+
+       /* Remove PLL from bypass mode */
+	ldr	ip, [r3, #PLLCTL]
+	bic	ip, ip, #PLLCTL_PLLENSRC
+	orr	ip, ip, #PLLCTL_PLLEN
+	str	ip, [r3, #PLLCTL]
+
+	/* Start 2x clock to DDR2 */
+
+	ldr	ip, [r3, #PLLDIV1]
+	orr	ip, ip, #PLLDIV_EN
+	str	ip, [r3, #PLLDIV1]
+
+	/* Enable VCLK */
+
+       /* Enable DDR2 LPSC */
+	mov	r7, r0
+	mov	r0, #0x3
+	bl davinci_ddr_psc_config
+	mov	r0, r7
+
+	/* clear  MCLKSTOPEN */
+
+	ldr	ip, [r0, #DDR2_SDRCR_OFFSET]
+	bic	ip, ip, #DDR2_MCLKSTOPEN_BIT
+	str	ip, [r0, #DDR2_SDRCR_OFFSET]
+
+	ldr	ip, [r0, #DDR2_SDRCR_OFFSET]
+	bic	ip, ip, #DDR2_LPMODEN_BIT
+	str	ip, [r0, #DDR2_SDRCR_OFFSET]
+
+	/* Restore registers and return */
+	ldmfd   sp!, {r0-r12, pc}
+
+ENDPROC(davinci_cpu_suspend)
+
+/*
+ * Disables or Enables DDR2 LPSC
+ * Register Usage:
+ * 	r0: Enable or Disable LPSC r0 = 0x3 => Enable, r0 = 0x2 => Disable LPSC
+ * 	r1: contains virtual base for DDR2 Power and Sleep controller (PSC)
+ * 	r2: contains PSC number for DDR2
+ */
+ENTRY(davinci_ddr_psc_config)
+	/* Set next state in mdctl for DDR2 */
+	mov	r6, #MDCTL
+	add	r6, r6, r2, lsl #2
+	ldr	ip, [r1, r6]
+	bic	ip, ip, #MDSTAT_STATE_MASK
+	orr	ip, ip, r0
+	str	ip, [r1, r6]
+
+	/* Enable the Power Domain Transition Command */
+	ldr	ip, [r1, #PTCMD]
+	orr	ip, ip, #0x1
+	str	ip, [r1, #PTCMD]
+
+	/* Check for Transition Complete (PTSTAT) */
+ptstat_done:
+	ldr	ip, [r1, #PTSTAT]
+	and	ip, ip, #0x1
+	cmp 	ip, #0x0
+	bne	ptstat_done
+
+	/* Check for DDR2 clock disable completion; */
+	mov	r6, #MDSTAT
+	add	r6, r6, r2, lsl #2
+ddr2clk_stop_done:
+	ldr	ip, [r1, r6]
+	and	ip, ip, #MDSTAT_STATE_MASK
+	cmp	ip, r0
+	bne	ddr2clk_stop_done
+
+	mov	pc, lr
+ENDPROC(davinci_ddr_psc_config)
+
+CACHE_FLUSH:
+	.word	arm926_flush_kern_cache_all
+
+ENTRY(davinci_cpu_suspend_sz)
+	.word	. - davinci_cpu_suspend
+ENDPROC(davinci_cpu_suspend_sz)
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 23/35] davinci: da850/omap-l138: add support for SoC suspend
  2010-01-06 18:32                                           ` [PATCH 22/35] davinci: add power management support Kevin Hilman
@ 2010-01-06 18:32                                             ` Kevin Hilman
  2010-01-06 18:32                                               ` [PATCH 24/35] davinci: da850/omap-l138 EVM: register for suspend support Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

This patch adds support for registering for suspend-to-RAM
functionality on da850/omap-l138 SoCs.

da850 supports wakeup based on external event and RTC
alarm.

Currently only RTC alarm based wakeup is supported.
Support for wakeup based on external event will be
added as later improvements.

For scheduling an alarm event on RTC some useful code
is present in Documentation/rtc.txt

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/da850.c              |   39 ++++++++++++++++++++++++++++
 arch/arm/mach-davinci/include/mach/da8xx.h |    4 +++
 arch/arm/mach-davinci/include/mach/mux.h   |    1 +
 3 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 5c6dd97..f4d4da5 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -26,6 +26,7 @@
 #include <mach/time.h>
 #include <mach/da8xx.h>
 #include <mach/cpufreq.h>
+#include <mach/pm.h>
 
 #include "clock.h"
 #include "mux.h"
@@ -536,6 +537,7 @@ static const struct mux_config da850_pins[] = {
 	MUX_CFG(DA850, GPIO2_15,	5,	0,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_0,		10,	28,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_1,		10,	24,	15,	8,	false)
+	MUX_CFG(DA850, RTC_ALARM,	0,	28,	15,	2,	false)
 #endif
 };
 
@@ -1029,6 +1031,43 @@ static int da850_round_armrate(struct clk *clk, unsigned long rate)
 }
 #endif
 
+int da850_register_pm(struct platform_device *pdev)
+{
+	int ret;
+	struct davinci_pm_config *pdata = pdev->dev.platform_data;
+
+	ret = davinci_cfg_reg(DA850_RTC_ALARM);
+	if (ret)
+		return ret;
+
+	pdata->ddr2_ctlr_base = da8xx_get_mem_ctlr();
+	pdata->deepsleep_reg = DA8XX_SYSCFG1_VIRT(DA8XX_DEEPSLEEP_REG);
+	pdata->ddrpsc_num = DA8XX_LPSC1_EMIF3C;
+
+	pdata->cpupll_reg_base = ioremap(DA8XX_PLL0_BASE, SZ_4K);
+	if (!pdata->cpupll_reg_base)
+		return -ENOMEM;
+
+	pdata->ddrpll_reg_base = ioremap(DA8XX_PLL1_BASE, SZ_4K);
+	if (!pdata->ddrpll_reg_base) {
+		ret = -ENOMEM;
+		goto no_ddrpll_mem;
+	}
+
+	pdata->ddrpsc_reg_base = ioremap(DA8XX_PSC1_BASE, SZ_4K);
+	if (!pdata->ddrpsc_reg_base) {
+		ret = -ENOMEM;
+		goto no_ddrpsc_mem;
+	}
+
+	return platform_device_register(pdev);
+
+no_ddrpsc_mem:
+	iounmap(pdata->ddrpll_reg_base);
+no_ddrpll_mem:
+	iounmap(pdata->cpupll_reg_base);
+	return ret;
+}
 
 static struct davinci_soc_info davinci_soc_info_da850 = {
 	.io_desc		= da850_io_desc,
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index d9a7f11..cc9be7f 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -20,6 +20,7 @@
 #include <mach/asp.h>
 #include <mach/mmc.h>
 #include <mach/usb.h>
+#include <mach/pm.h>
 
 extern void __iomem *da8xx_syscfg0_base;
 extern void __iomem *da8xx_syscfg1_base;
@@ -44,6 +45,7 @@ extern void __iomem *da8xx_syscfg1_base;
 
 #define DA8XX_SYSCFG1_BASE	(IO_PHYS + 0x22C000)
 #define DA8XX_SYSCFG1_VIRT(x)	(da8xx_syscfg1_base + (x))
+#define DA8XX_DEEPSLEEP_REG	0x8
 
 #define DA8XX_PSC0_BASE		0x01c10000
 #define DA8XX_PLL0_BASE		0x01c11000
@@ -52,6 +54,7 @@ extern void __iomem *da8xx_syscfg1_base;
 #define DA8XX_GPIO_BASE		0x01e26000
 #define DA8XX_PSC1_BASE		0x01e27000
 #define DA8XX_LCD_CNTRL_BASE	0x01e13000
+#define DA8XX_PLL1_BASE		0x01e1a000
 #define DA8XX_MMCSD0_BASE	0x01c40000
 #define DA8XX_AEMIF_CS2_BASE	0x60000000
 #define DA8XX_AEMIF_CS3_BASE	0x62000000
@@ -96,6 +99,7 @@ int da8xx_register_rtc(void);
 int da850_register_cpufreq(void);
 int da8xx_register_cpuidle(void);
 void __iomem * __init da8xx_get_mem_ctlr(void);
+int da850_register_pm(struct platform_device *pdev);
 
 extern struct platform_device da8xx_serial_device;
 extern struct emac_platform_data da8xx_emac_pdata;
diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
index b60c693..137bfba 100644
--- a/arch/arm/mach-davinci/include/mach/mux.h
+++ b/arch/arm/mach-davinci/include/mach/mux.h
@@ -899,6 +899,7 @@ enum davinci_da850_index {
 	DA850_GPIO2_15,
 	DA850_GPIO4_0,
 	DA850_GPIO4_1,
+	DA850_RTC_ALARM,
 };
 
 #ifdef CONFIG_DAVINCI_MUX
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 24/35] davinci: da850/omap-l138 EVM: register for suspend support
  2010-01-06 18:32                                             ` [PATCH 23/35] davinci: da850/omap-l138: add support for SoC suspend Kevin Hilman
@ 2010-01-06 18:32                                               ` Kevin Hilman
  2010-01-06 18:32                                                 ` [PATCH 25/35] davinci: add support for CDCE949 clock synthesizer Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sekhar Nori <nsekhar@ti.com>

Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/board-da850-evm.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 76e4347..411284d 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -89,6 +89,18 @@ static struct platform_device da850_evm_norflash_device = {
 	.resource	= da850_evm_norflash_resource,
 };
 
+static struct davinci_pm_config da850_pm_pdata = {
+	.sleepcount = 128,
+};
+
+static struct platform_device da850_pm_device = {
+	.name           = "pm-davinci",
+	.dev = {
+		.platform_data	= &da850_pm_pdata,
+	},
+	.id             = -1,
+};
+
 /* DA850/OMAP-L138 EVM includes a 512 MByte large-page NAND flash
  * (128K blocks). It may be used instead of the (default) SPI flash
  * to boot, using TI's tools to install the secondary boot loader
@@ -709,6 +721,11 @@ static __init void da850_evm_init(void)
 	if (ret)
 		pr_warning("da850_evm_init: cpuidle registration failed: %d\n",
 				ret);
+
+	ret = da850_register_pm(&da850_pm_device);
+	if (ret)
+		pr_warning("da850_evm_init: suspend registration failed: %d\n",
+				ret);
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 25/35] davinci: add support for CDCE949 clock synthesizer
  2010-01-06 18:32                                               ` [PATCH 24/35] davinci: da850/omap-l138 EVM: register for suspend support Kevin Hilman
@ 2010-01-06 18:32                                                 ` Kevin Hilman
  2010-01-06 18:32                                                   ` [PATCH 26/35] davinci: add CDCE949 support on DM6467 EVM Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Nageswari Srinivasan <nageswari@ti.com>

This patch adds support for TI's CDCE949 - a clock
synthesizer with 4 PLLs and 9 outputs.

It is used on DM6467 EVM. On the EVM, it generates
clocks required for VPIF, TSIF and Audio modules.

This patch adds it as part of the DaVinci clock framework.

Testing:
The various frequency outputs on Y1 have been tested using
a out-of-tree VPIF video driver supporting HD video.
The register values for Y5 frequency outputs have been
derived from TSIF driver sources in MontaVista LSP kernel,
but actual output has not been tested for lack of TSIF
driver which actually works on the latest kernel.

Signed-off-by: Nageswari Srinivasan <nageswari@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/cdce949.c              |  289 ++++++++++++++++++++++++++
 arch/arm/mach-davinci/include/mach/cdce949.h |   19 ++
 2 files changed, 308 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-davinci/cdce949.c
 create mode 100644 arch/arm/mach-davinci/include/mach/cdce949.h

diff --git a/arch/arm/mach-davinci/cdce949.c b/arch/arm/mach-davinci/cdce949.c
new file mode 100644
index 0000000..5a08283
--- /dev/null
+++ b/arch/arm/mach-davinci/cdce949.c
@@ -0,0 +1,289 @@
+/*
+ * TI CDCE949 clock synthesizer driver
+ *
+ * Note: This implementation assumes an input of 27MHz to the CDCE.
+ * This is by no means constrained by CDCE hardware although the datasheet
+ * does use this as an example for all illustrations and more importantly:
+ * that is the crystal input on boards it is currently used on.
+ *
+ * Copyright (C) 2009 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+#include <mach/clock.h>
+
+#include "clock.h"
+
+static struct i2c_client *cdce_i2c_client;
+
+/* CDCE register descriptor */
+struct cdce_reg {
+	u8	addr;
+	u8	val;
+};
+
+/* Per-Output (Y1, Y2 etc.) frequency descriptor */
+struct cdce_freq {
+	/* Frequency in KHz */
+	unsigned long frequency;
+	/*
+	 * List of registers to program to obtain a particular frequency.
+	 * 0x0 in register address and value is the end of list marker.
+	 */
+	struct cdce_reg *reglist;
+};
+
+#define CDCE_FREQ_TABLE_ENTRY(line, out)		\
+{							\
+	.reglist	= cdce_y ##line## _ ##out,		\
+	.frequency	= out,				\
+}
+
+/* List of CDCE outputs  */
+struct cdce_output {
+	/* List of frequencies on this output */
+	struct cdce_freq *freq_table;
+	/* Number of possible frequencies */
+	int size;
+};
+
+/*
+ * Finding out the values to program into CDCE949 registers for a particular
+ * frequency output is not a simple calculation. Have a look at the datasheet
+ * for the details. There is desktop software available to help users with
+ * the calculations. Here, we just depend on the output of that software
+ * (or hand calculations) instead trying to runtime calculate the register
+ * values and inflicting misery on ourselves.
+ */
+static struct cdce_reg cdce_y1_148500[] = {
+	{ 0x13, 0x00 },
+	/* program PLL1_0 multiplier */
+	{ 0x18, 0xaf },
+	{ 0x19, 0x50 },
+	{ 0x1a, 0x02 },
+	{ 0x1b, 0xc9 },
+	/* program PLL1_11 multiplier */
+	{ 0x1c, 0x00 },
+	{ 0x1d, 0x40 },
+	{ 0x1e, 0x02 },
+	{ 0x1f, 0xc9 },
+	/* output state selection */
+	{ 0x15, 0x00 },
+	{ 0x14, 0xef },
+	/* switch MUX to PLL1 output */
+	{ 0x14, 0x6f },
+	{ 0x16, 0x06 },
+	/* set P2DIV divider, P3DIV and input crystal */
+	{ 0x17, 0x06 },
+	{ 0x01, 0x00 },
+	{ 0x05, 0x48 },
+	{ 0x02, 0x80 },
+	/* enable and disable PLL */
+	{ 0x02, 0xbc },
+	{ 0x03, 0x01 },
+	{ },
+};
+
+static struct cdce_reg cdce_y1_74250[] = {
+	{ 0x13, 0x00 },
+	{ 0x18, 0xaf },
+	{ 0x19, 0x50 },
+	{ 0x1a, 0x02 },
+	{ 0x1b, 0xc9 },
+	{ 0x1c, 0x00 },
+	{ 0x1d, 0x40 },
+	{ 0x1e, 0x02 },
+	{ 0x1f, 0xc9 },
+	/* output state selection */
+	{ 0x15, 0x00 },
+	{ 0x14, 0xef },
+	/* switch MUX to PLL1 output */
+	{ 0x14, 0x6f },
+	{ 0x16, 0x06 },
+	/* set P2DIV divider, P3DIV and input crystal */
+	{ 0x17, 0x06 },
+	{ 0x01, 0x00 },
+	{ 0x05, 0x48 },
+	{ 0x02, 0x80 },
+	/* enable and disable PLL */
+	{ 0x02, 0xbc },
+	{ 0x03, 0x02 },
+	{ },
+};
+
+static struct cdce_reg cdce_y1_27000[] = {
+	{ 0x13, 0x00 },
+	{ 0x18, 0x00 },
+	{ 0x19, 0x40 },
+	{ 0x1a, 0x02 },
+	{ 0x1b, 0x08 },
+	{ 0x1c, 0x00 },
+	{ 0x1d, 0x40 },
+	{ 0x1e, 0x02 },
+	{ 0x1f, 0x08 },
+	{ 0x15, 0x02 },
+	{ 0x14, 0xed },
+	{ 0x16, 0x01 },
+	{ 0x17, 0x01 },
+	{ 0x01, 0x00 },
+	{ 0x05, 0x50 },
+	{ 0x02, 0xb4 },
+	{ 0x03, 0x01 },
+	{ },
+};
+
+static struct cdce_freq cdce_y1_freqs[] = {
+	CDCE_FREQ_TABLE_ENTRY(1, 148500),
+	CDCE_FREQ_TABLE_ENTRY(1, 74250),
+	CDCE_FREQ_TABLE_ENTRY(1, 27000),
+};
+
+static struct cdce_reg cdce_y5_13500[] = {
+	{ 0x27, 0x08 },
+	{ 0x28, 0x00 },
+	{ 0x29, 0x40 },
+	{ 0x2a, 0x02 },
+	{ 0x2b, 0x08 },
+	{ 0x24, 0x6f },
+	{ },
+};
+
+static struct cdce_reg cdce_y5_16875[] = {
+	{ 0x27, 0x08 },
+	{ 0x28, 0x9f },
+	{ 0x29, 0xb0 },
+	{ 0x2a, 0x02 },
+	{ 0x2b, 0x89 },
+	{ 0x24, 0x6f },
+	{ },
+};
+
+static struct cdce_reg cdce_y5_27000[] = {
+	{ 0x27, 0x04 },
+	{ 0x28, 0x00 },
+	{ 0x29, 0x40 },
+	{ 0x2a, 0x02 },
+	{ 0x2b, 0x08 },
+	{ 0x24, 0x6f },
+	{ },
+};
+static struct cdce_reg cdce_y5_54000[] = {
+	{ 0x27, 0x04 },
+	{ 0x28, 0xff },
+	{ 0x29, 0x80 },
+	{ 0x2a, 0x02 },
+	{ 0x2b, 0x07 },
+	{ 0x24, 0x6f },
+	{ },
+};
+
+static struct cdce_reg cdce_y5_81000[] = {
+	{ 0x27, 0x02 },
+	{ 0x28, 0xbf },
+	{ 0x29, 0xa0 },
+	{ 0x2a, 0x03 },
+	{ 0x2b, 0x0a },
+	{ 0x24, 0x6f },
+	{ },
+};
+
+static struct cdce_freq cdce_y5_freqs[] = {
+	CDCE_FREQ_TABLE_ENTRY(5, 13500),
+	CDCE_FREQ_TABLE_ENTRY(5, 16875),
+	CDCE_FREQ_TABLE_ENTRY(5, 27000),
+	CDCE_FREQ_TABLE_ENTRY(5, 54000),
+	CDCE_FREQ_TABLE_ENTRY(5, 81000),
+};
+
+
+static struct cdce_output output_list[] = {
+	[1]	= { cdce_y1_freqs, ARRAY_SIZE(cdce_y1_freqs) },
+	[5]	= { cdce_y5_freqs, ARRAY_SIZE(cdce_y5_freqs) },
+};
+
+int cdce_set_rate(struct clk *clk, unsigned long rate)
+{
+	int i, ret = 0;
+	struct cdce_freq *freq_table = output_list[clk->lpsc].freq_table;
+	struct cdce_reg  *regs = NULL;
+
+	if (!cdce_i2c_client)
+		return -ENODEV;
+
+	if (!freq_table)
+		return -EINVAL;
+
+	for (i = 0; i < output_list[clk->lpsc].size; i++) {
+		if (freq_table[i].frequency == rate / 1000) {
+			regs = freq_table[i].reglist;
+			break;
+		}
+	}
+
+	if (!regs)
+		return -EINVAL;
+
+	for (i = 0; regs[i].addr; i++) {
+		ret = i2c_smbus_write_byte_data(cdce_i2c_client,
+					regs[i].addr | 0x80, regs[i].val);
+		if (ret)
+			return ret;
+	}
+
+	atomic_set(&clk->rate, rate);
+
+	return 0;
+}
+
+static int cdce_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	cdce_i2c_client = client;
+	return 0;
+}
+
+static int __devexit cdce_remove(struct i2c_client *client)
+{
+	cdce_i2c_client = NULL;
+	return 0;
+}
+
+static const struct i2c_device_id cdce_id[] = {
+	{"cdce949", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, cdce_id);
+
+static struct i2c_driver cdce_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "cdce949",
+	},
+	.probe		= cdce_probe,
+	.remove		= __devexit_p(cdce_remove),
+	.id_table	= cdce_id,
+};
+
+static int __init cdce_init(void)
+{
+	return i2c_add_driver(&cdce_driver);
+}
+subsys_initcall(cdce_init);
+
+static void __exit cdce_exit(void)
+{
+	i2c_del_driver(&cdce_driver);
+}
+module_exit(cdce_exit);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("CDCE949 clock synthesizer driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-davinci/include/mach/cdce949.h b/arch/arm/mach-davinci/include/mach/cdce949.h
new file mode 100644
index 0000000..c73331f
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/cdce949.h
@@ -0,0 +1,19 @@
+/*
+ * TI CDCE949 off-chip clock synthesizer support
+ *
+ * 2009 (C) Texas Instruments, Inc. http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+#ifndef _MACH_DAVINCI_CDCE949_H
+#define _MACH_DAVINCI_CDCE949_H
+
+#include <linux/clk.h>
+
+#include <mach/clock.h>
+
+int cdce_set_rate(struct clk *clk, unsigned long rate);
+
+#endif
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 26/35] davinci: add CDCE949 support on DM6467 EVM
  2010-01-06 18:32                                                 ` [PATCH 25/35] davinci: add support for CDCE949 clock synthesizer Kevin Hilman
@ 2010-01-06 18:32                                                   ` Kevin Hilman
  2010-01-06 18:32                                                     ` [PATCH 27/35] davinci: Correct return value of edma_alloc_channel api Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Nageswari Srinivasan <nageswari@ti.com>

This patch adds the CDCE949 reference oscillator to
the davinci clock list.

On the DM6467T EVM, the CDCE949 is responsible for
generating the pixel clock for display. On the DM6467
EVM, this pixel clock was being obtained from an
internal source. This is not possible on the DM6467T
EVM because of the presence of a 33MHz oscillator.

The TSIF module also requires the CDCE949 to generate
the data clocks.

The actual clock definitions will be added by patches
adding support for DM6467T VPIF and TSIF. This patch
mearly lays the foundation for that work.

Signed-off-by: Nageswari Srinivasan <nageswari@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/Makefile           |    2 +-
 arch/arm/mach-davinci/board-dm646x-evm.c |   31 ++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index d0fed3a..6aac880 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -26,7 +26,7 @@ obj-$(CONFIG_MACH_SFFSDR)		+= board-sffsdr.o
 obj-$(CONFIG_MACH_NEUROS_OSD2)		+= board-neuros-osd2.o
 obj-$(CONFIG_MACH_DAVINCI_DM355_EVM)	+= board-dm355-evm.o
 obj-$(CONFIG_MACH_DM355_LEOPARD)	+= board-dm355-leopard.o
-obj-$(CONFIG_MACH_DAVINCI_DM6467_EVM)	+= board-dm646x-evm.o
+obj-$(CONFIG_MACH_DAVINCI_DM6467_EVM)	+= board-dm646x-evm.o cdce949.o
 obj-$(CONFIG_MACH_DAVINCI_DM365_EVM)	+= board-dm365-evm.o
 obj-$(CONFIG_MACH_DAVINCI_DA830_EVM)	+= board-da830-evm.o
 obj-$(CONFIG_MACH_DAVINCI_DA850_EVM)	+= board-da850-evm.o
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 6ff3411..6c7c604 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -40,6 +40,8 @@
 #include <mach/serial.h>
 #include <mach/i2c.h>
 #include <mach/nand.h>
+#include <mach/clock.h>
+#include <mach/cdce949.h>
 
 #include "clock.h"
 
@@ -389,6 +391,9 @@ static struct i2c_board_info __initdata i2c_info[] =  {
 	{
 		I2C_BOARD_INFO("cpld_video", 0x3b),
 	},
+	{
+		I2C_BOARD_INFO("cdce949", 0x6c),
+	},
 };
 
 static struct davinci_i2c_platform_data i2c_pdata = {
@@ -681,9 +686,35 @@ static void __init evm_init_i2c(void)
 	evm_init_video();
 }
 
+#define CDCE949_XIN_RATE	27000000
+
+/* CDCE949 support - "lpsc" field is overridden to work as clock number */
+static struct clk cdce_clk_in = {
+	.name	= "cdce_xin",
+	.rate	= ATOMIC_INIT(CDCE949_XIN_RATE),
+};
+
+static struct davinci_clk cdce_clks[] = {
+	CLK(NULL, "xin", &cdce_clk_in),
+	CLK(NULL, NULL, NULL),
+};
+
+static void __init cdce_clk_init(void)
+{
+	struct davinci_clk *c;
+	struct clk *clk;
+
+	for (c = cdce_clks; c->lk.clk; c++) {
+		clk = c->lk.clk;
+		clkdev_add(&c->lk);
+		clk_register(clk);
+	}
+}
+
 static void __init davinci_map_io(void)
 {
 	dm646x_init();
+	cdce_clk_init();
 }
 
 static struct davinci_uart_config uart_config __initdata = {
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 27/35] davinci: Correct return value of edma_alloc_channel api
  2010-01-06 18:32                                                   ` [PATCH 26/35] davinci: add CDCE949 support on DM6467 EVM Kevin Hilman
@ 2010-01-06 18:32                                                     ` Kevin Hilman
  2010-01-06 18:32                                                       ` [PATCH 28/35] davinci: Keep count of channel controllers on a platform Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Currently, edma_alloc_channel api is returning the channel
number without prepending the controller on which the
channel was allocated. So, if a channel is allocated on
2nd controller, calls subsequent to edma_alloc_channel would
never know that channel was allocated on the 2nd controller,
and continue to operate on 1st controller, resulting in edma
failure. This patch fixes this issue.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/dma.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 648fbb7..5a71f4d 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -642,7 +642,7 @@ int edma_alloc_channel(int channel,
 
 	map_dmach_queue(ctlr, channel, eventq_no);
 
-	return channel;
+	return EDMA_CTLR_CHAN(ctlr, channel);
 }
 EXPORT_SYMBOL(edma_alloc_channel);
 
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 28/35] davinci: Keep count of channel controllers on a platform
  2010-01-06 18:32                                                     ` [PATCH 27/35] davinci: Correct return value of edma_alloc_channel api Kevin Hilman
@ 2010-01-06 18:32                                                       ` Kevin Hilman
  2010-01-06 18:32                                                         ` [PATCH 29/35] davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Some architectures have only one channel controller, but the
edma_alloc_channel api loops twice to findout the free channel
available in EDMA_CHANNEL_ANY case. A new variable has been
introduced to keep count of number of channel controllers being
used on a particular architecture.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/dma.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 5a71f4d..97a49f9 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -243,6 +243,7 @@ struct edma {
 };
 
 static struct edma *edma_info[EDMA_MAX_CC];
+static int arch_num_cc;
 
 /* dummy param set used to (re)initialize parameter RAM slots */
 static const struct edmacc_param dummy_paramset = {
@@ -602,7 +603,7 @@ int edma_alloc_channel(int channel,
 	}
 
 	if (channel < 0) {
-		for (i = 0; i < EDMA_MAX_CC; i++) {
+		for (i = 0; i < arch_num_cc; i++) {
 			channel = 0;
 			for (;;) {
 				channel = find_next_bit(edma_info[i]->
@@ -1467,6 +1468,7 @@ static int __init edma_probe(struct platform_device *pdev)
 			edma_write_array2(j, EDMA_DRAE, i, 1, 0x0);
 			edma_write_array(j, EDMA_QRAE, i, 0x0);
 		}
+		arch_num_cc++;
 	}
 
 	if (tc_errs_handled) {
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 29/35] davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case
  2010-01-06 18:32                                                       ` [PATCH 28/35] davinci: Keep count of channel controllers on a platform Kevin Hilman
@ 2010-01-06 18:32                                                         ` Kevin Hilman
  2010-01-06 18:32                                                           ` [PATCH 30/35] davinci: build list of unused EDMA events dynamically Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Though edma_alloc_channel api was looping through the available
channel controllers in EDMA_CHANNEL_ANY case, it was never
returning the channel for 2nd channel controller, if 1st
channel controller had no free channels. This issue has
been fixed with this patch.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/dma.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 97a49f9..89a3dcc 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -595,7 +595,7 @@ int edma_alloc_channel(int channel,
 		void *data,
 		enum dma_event_q eventq_no)
 {
-	unsigned i, done, ctlr = 0;
+	unsigned i, done = 0, ctlr = 0;
 
 	if (channel >= 0) {
 		ctlr = EDMA_CTLR(channel);
@@ -611,7 +611,7 @@ int edma_alloc_channel(int channel,
 						edma_info[i]->num_channels,
 						channel);
 				if (channel == edma_info[i]->num_channels)
-					return -ENOMEM;
+					break;
 				if (!test_and_set_bit(channel,
 						edma_info[i]->edma_inuse)) {
 					done = 1;
@@ -623,6 +623,8 @@ int edma_alloc_channel(int channel,
 			if (done)
 				break;
 		}
+		if (!done)
+			return -ENOMEM;
 	} else if (channel >= edma_info[ctlr]->num_channels) {
 		return -EINVAL;
 	} else if (test_and_set_bit(channel, edma_info[ctlr]->edma_inuse)) {
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 30/35] davinci: build list of unused EDMA events dynamically
  2010-01-06 18:32                                                         ` [PATCH 29/35] davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case Kevin Hilman
@ 2010-01-06 18:32                                                           ` Kevin Hilman
  2010-01-06 18:32                                                             ` [PATCH 31/35] davinci: support for EDMA resource sharing Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Currently, the edma_noevent list is passed from platform data.
But on some architectures, there will be many EDMA channels
which will not be used at all. This patch scans all the
platform devices and then builds a list of events which are
not being used. The unused event list will be used to allocate
EDMA channels in case of EDMA_CHANNEL_ANY usage instead of the
edma_noevent being used earlier for this purpose.

This patch is based on David Brownells's suggestion at
http://article.gmane.org/gmane.linux.davinci/15176.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/devices-da8xx.c     |    6 ---
 arch/arm/mach-davinci/dm355.c             |    8 ----
 arch/arm/mach-davinci/dm644x.c            |   10 -----
 arch/arm/mach-davinci/dm646x.c            |    9 -----
 arch/arm/mach-davinci/dma.c               |   55 ++++++++++++++++++++++------
 arch/arm/mach-davinci/include/mach/edma.h |    2 -
 6 files changed, 43 insertions(+), 47 deletions(-)

diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 5df27f7..40647c4 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -83,11 +83,6 @@ struct platform_device da8xx_serial_device = {
 	},
 };
 
-static const s8 da8xx_dma_chan_no_event[] = {
-	20, 21,
-	-1
-};
-
 static const s8 da8xx_queue_tc_mapping[][2] = {
 	/* {event queue no, TC no} */
 	{0, 0},
@@ -109,7 +104,6 @@ static struct edma_soc_info da8xx_edma_info[] = {
 		.n_slot			= 128,
 		.n_tc			= 2,
 		.n_cc			= 1,
-		.noevent		= da8xx_dma_chan_no_event,
 		.queue_tc_mapping	= da8xx_queue_tc_mapping,
 		.queue_priority_mapping	= da8xx_queue_priority_mapping,
 	},
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 2244e8c..9b2c40e 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -564,13 +564,6 @@ static u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
 
 /*----------------------------------------------------------------------*/
 
-static const s8 dma_chan_dm355_no_event[] = {
-	12, 13, 24, 56, 57,
-	58, 59, 60, 61, 62,
-	63,
-	-1
-};
-
 static const s8
 queue_tc_mapping[][2] = {
 	/* {event queue no, TC no} */
@@ -594,7 +587,6 @@ static struct edma_soc_info dm355_edma_info[] = {
 		.n_slot			= 128,
 		.n_tc			= 2,
 		.n_cc			= 1,
-		.noevent		= dma_chan_dm355_no_event,
 		.queue_tc_mapping	= queue_tc_mapping,
 		.queue_priority_mapping	= queue_priority_mapping,
 	},
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index e65e29e..61856f8 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -479,15 +479,6 @@ static u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
 
 /*----------------------------------------------------------------------*/
 
-static const s8 dma_chan_dm644x_no_event[] = {
-	 0,  1, 12, 13, 14,
-	15, 25, 30, 31, 45,
-	46, 47, 55, 56, 57,
-	58, 59, 60, 61, 62,
-	63,
-	-1
-};
-
 static const s8
 queue_tc_mapping[][2] = {
 	/* {event queue no, TC no} */
@@ -511,7 +502,6 @@ static struct edma_soc_info dm644x_edma_info[] = {
 		.n_slot			= 128,
 		.n_tc			= 2,
 		.n_cc			= 1,
-		.noevent		= dma_chan_dm644x_no_event,
 		.queue_tc_mapping	= queue_tc_mapping,
 		.queue_priority_mapping	= queue_priority_mapping,
 	},
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 6f80616..de306ca 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -511,14 +511,6 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
 
 /*----------------------------------------------------------------------*/
 
-static const s8 dma_chan_dm646x_no_event[] = {
-	 0,  1,  2,  3, 13,
-	14, 15, 24, 25, 26,
-	27, 30, 31, 54, 55,
-	56,
-	-1
-};
-
 /* Four Transfer Controllers on DM646x */
 static const s8
 dm646x_queue_tc_mapping[][2] = {
@@ -547,7 +539,6 @@ static struct edma_soc_info dm646x_edma_info[] = {
 		.n_slot			= 512,
 		.n_tc			= 4,
 		.n_cc			= 1,
-		.noevent		= dma_chan_dm646x_no_event,
 		.queue_tc_mapping	= dm646x_queue_tc_mapping,
 		.queue_priority_mapping	= dm646x_queue_priority_mapping,
 	},
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 89a3dcc..15dd886 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -226,11 +226,11 @@ struct edma {
 	 */
 	DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
 
-	/* The edma_noevent bit for each channel is clear unless
-	 * it doesn't trigger DMA events on this platform.  It uses a
-	 * bit of SOC-specific initialization code.
+	/* The edma_unused bit for each channel is clear unless
+	 * it is not being used on this platform. It uses a bit
+	 * of SOC-specific initialization code.
 	 */
-	DECLARE_BITMAP(edma_noevent, EDMA_MAX_DMACH);
+	DECLARE_BITMAP(edma_unused, EDMA_MAX_DMACH);
 
 	unsigned	irq_res_start;
 	unsigned	irq_res_end;
@@ -556,8 +556,27 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id,
 	return EDMA_CTLR_CHAN(ctlr, i - num_slots + 1);
 }
 
+static int prepare_unused_channel_list(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int i, ctlr;
+
+	for (i = 0; i < pdev->num_resources; i++) {
+		if ((pdev->resource[i].flags & IORESOURCE_DMA) &&
+				(int)pdev->resource[i].start >= 0) {
+			ctlr = EDMA_CTLR(pdev->resource[i].start);
+			clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start),
+					edma_info[ctlr]->edma_unused);
+		}
+	}
+
+	return 0;
+}
+
 /*-----------------------------------------------------------------------*/
 
+static bool unused_chan_list_done;
+
 /* Resource alloc/free:  dma channels, parameter RAM slots */
 
 /**
@@ -596,6 +615,21 @@ int edma_alloc_channel(int channel,
 		enum dma_event_q eventq_no)
 {
 	unsigned i, done = 0, ctlr = 0;
+	int ret = 0;
+
+	if (!unused_chan_list_done) {
+		/*
+		 * Scan all the platform devices to find out the EDMA channels
+		 * used and clear them in the unused list, making the rest
+		 * available for ARM usage.
+		 */
+		ret = bus_for_each_dev(&platform_bus_type, NULL, NULL,
+				prepare_unused_channel_list);
+		if (ret < 0)
+			return ret;
+
+		unused_chan_list_done = true;
+	}
 
 	if (channel >= 0) {
 		ctlr = EDMA_CTLR(channel);
@@ -607,7 +641,7 @@ int edma_alloc_channel(int channel,
 			channel = 0;
 			for (;;) {
 				channel = find_next_bit(edma_info[i]->
-						edma_noevent,
+						edma_unused,
 						edma_info[i]->num_channels,
 						channel);
 				if (channel == edma_info[i]->num_channels)
@@ -1222,7 +1256,7 @@ int edma_start(unsigned channel)
 		unsigned int mask = (1 << (channel & 0x1f));
 
 		/* EDMA channels without event association */
-		if (test_bit(channel, edma_info[ctlr]->edma_noevent)) {
+		if (test_bit(channel, edma_info[ctlr]->edma_unused)) {
 			pr_debug("EDMA: ESR%d %08x\n", j,
 				edma_shadow0_read_array(ctlr, SH_ESR, j));
 			edma_shadow0_write_array(ctlr, SH_ESR, j, mask);
@@ -1347,7 +1381,6 @@ static int __init edma_probe(struct platform_device *pdev)
 	const s8		(*queue_tc_mapping)[2];
 	int			i, j, found = 0;
 	int			status = -1;
-	const s8		*noevent;
 	int			irq[EDMA_MAX_CC] = {0, 0};
 	int			err_irq[EDMA_MAX_CC] = {0, 0};
 	struct resource		*r[EDMA_MAX_CC] = {NULL};
@@ -1410,11 +1443,9 @@ static int __init edma_probe(struct platform_device *pdev)
 			memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i),
 					&dummy_paramset, PARM_SIZE);
 
-		noevent = info[j].noevent;
-		if (noevent) {
-			while (*noevent != -1)
-				set_bit(*noevent++, edma_info[j]->edma_noevent);
-		}
+		/* Mark all channels as unused */
+		memset(edma_info[j]->edma_unused, 0xff,
+			sizeof(edma_info[j]->edma_unused));
 
 		sprintf(irq_name, "edma%d", j);
 		irq[j] = platform_get_irq_byname(pdev, irq_name);
diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
index eb8bfd7..ced3092 100644
--- a/arch/arm/mach-davinci/include/mach/edma.h
+++ b/arch/arm/mach-davinci/include/mach/edma.h
@@ -280,8 +280,6 @@ struct edma_soc_info {
 	unsigned	n_cc;
 	enum dma_event_q	default_queue;
 
-	/* list of channels with no even trigger; terminated by "-1" */
-	const s8	*noevent;
 	const s8	(*queue_tc_mapping)[2];
 	const s8	(*queue_priority_mapping)[2];
 };
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 31/35] davinci: support for EDMA resource sharing
  2010-01-06 18:32                                                           ` [PATCH 30/35] davinci: build list of unused EDMA events dynamically Kevin Hilman
@ 2010-01-06 18:32                                                             ` Kevin Hilman
  2010-01-06 18:32                                                               ` [PATCH 32/35] davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138 Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Current EDMA driver is not taking care of EDMA channels/slots
which are allocated from other processor, say DSP. If a
channel/slot is allocated from DSP, the existing EDMA driver
can still allocate the same resource on ARM.

This patch enables the user to pass the channel/slots reserved
for DSP as platform data. EDMA driver scans this list during
probe and prepares a bitmap of channel/slots which can be used
on ARM side.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/dma.c               |   36 ++++++++++++++++++++++++++++-
 arch/arm/mach-davinci/include/mach/edma.h |    2 +
 2 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
index 15dd886..d3e1702 100644
--- a/arch/arm/mach-davinci/dma.c
+++ b/arch/arm/mach-davinci/dma.c
@@ -206,6 +206,18 @@ static inline void edma_parm_or(unsigned ctlr, int offset, int param_no,
 	edma_or(ctlr, EDMA_PARM + offset + (param_no << 5), or);
 }
 
+static inline void set_bits(int offset, int len, unsigned long *p)
+{
+	for (; len > 0; len--)
+		set_bit(offset + (len - 1), p);
+}
+
+static inline void clear_bits(int offset, int len, unsigned long *p)
+{
+	for (; len > 0; len--)
+		clear_bit(offset + (len - 1), p);
+}
+
 /*****************************************************************************/
 
 /* actual number of DMA channels and slots on this silicon */
@@ -1379,8 +1391,10 @@ static int __init edma_probe(struct platform_device *pdev)
 	struct edma_soc_info	*info = pdev->dev.platform_data;
 	const s8		(*queue_priority_mapping)[2];
 	const s8		(*queue_tc_mapping)[2];
-	int			i, j, found = 0;
+	int			i, j, off, ln, found = 0;
 	int			status = -1;
+	const s16		(*rsv_chans)[2];
+	const s16		(*rsv_slots)[2];
 	int			irq[EDMA_MAX_CC] = {0, 0};
 	int			err_irq[EDMA_MAX_CC] = {0, 0};
 	struct resource		*r[EDMA_MAX_CC] = {NULL};
@@ -1447,6 +1461,26 @@ static int __init edma_probe(struct platform_device *pdev)
 		memset(edma_info[j]->edma_unused, 0xff,
 			sizeof(edma_info[j]->edma_unused));
 
+		/* Clear the reserved channels in unused list */
+		rsv_chans = info[j].rsv_chans;
+		if (rsv_chans) {
+			for (i = 0; rsv_chans[i][0] != -1; i++) {
+				off = rsv_chans[i][0];
+				ln = rsv_chans[i][1];
+				clear_bits(off, ln, edma_info[j]->edma_unused);
+			}
+		}
+
+		/* Set the reserved channels/slots in inuse list */
+		rsv_slots = info[j].rsv_slots;
+		if (rsv_slots) {
+			for (i = 0; rsv_slots[i][0] != -1; i++) {
+				off = rsv_slots[i][0];
+				ln = rsv_slots[i][1];
+				set_bits(off, ln, edma_info[j]->edma_inuse);
+			}
+		}
+
 		sprintf(irq_name, "edma%d", j);
 		irq[j] = platform_get_irq_byname(pdev, irq_name);
 		edma_info[j]->irq_res_start = irq[j];
diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
index ced3092..55e217e 100644
--- a/arch/arm/mach-davinci/include/mach/edma.h
+++ b/arch/arm/mach-davinci/include/mach/edma.h
@@ -280,6 +280,8 @@ struct edma_soc_info {
 	unsigned	n_cc;
 	enum dma_event_q	default_queue;
 
+	const s16	(*rsv_chans)[2];
+	const s16	(*rsv_slots)[2];
 	const s8	(*queue_tc_mapping)[2];
 	const s8	(*queue_priority_mapping)[2];
 };
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 32/35] davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138
  2010-01-06 18:32                                                             ` [PATCH 31/35] davinci: support for EDMA resource sharing Kevin Hilman
@ 2010-01-06 18:32                                                               ` Kevin Hilman
  2010-01-06 18:32                                                                 ` [PATCH 33/35] davinci: da830/omapl137: Specify reserved channels/slots Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Currently da850/omap-l138 supports only one channel controller
instance of EDMA though EDMA driver as such supports multiple
channel controller instances. This patch adds platform data
for the 2nd EDMA channel controller. As, the platform data
differ between da830/omap-l137 and da850/omap-l138, existing
code has been re-shuffled to accommodate this.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/devices-da8xx.c |  121 +++++++++++++++++++++++++++++++--
 1 files changed, 114 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 40647c4..63c330c 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -24,8 +24,10 @@
 #include "clock.h"
 
 #define DA8XX_TPCC_BASE			0x01c00000
+#define DA850_TPCC1_BASE		0x01e30000
 #define DA8XX_TPTC0_BASE		0x01c08000
 #define DA8XX_TPTC1_BASE		0x01c08400
+#define DA850_TPTC2_BASE		0x01e38000
 #define DA8XX_WDOG_BASE			0x01c21000 /* DA8XX_TIMER64P1_BASE */
 #define DA8XX_I2C0_BASE			0x01c22000
 #define DA8XX_RTC_BASE			0x01C23000
@@ -97,7 +99,31 @@ static const s8 da8xx_queue_priority_mapping[][2] = {
 	{-1, -1}
 };
 
-static struct edma_soc_info da8xx_edma_info[] = {
+static const s8 da850_queue_tc_mapping[][2] = {
+	/* {event queue no, TC no} */
+	{0, 0},
+	{-1, -1}
+};
+
+static const s8 da850_queue_priority_mapping[][2] = {
+	/* {event queue no, Priority} */
+	{0, 3},
+	{-1, -1}
+};
+
+static struct edma_soc_info da830_edma_info[] = {
+	{
+		.n_channel		= 32,
+		.n_region		= 4,
+		.n_slot			= 128,
+		.n_tc			= 2,
+		.n_cc			= 1,
+		.queue_tc_mapping	= da8xx_queue_tc_mapping,
+		.queue_priority_mapping	= da8xx_queue_priority_mapping,
+	},
+};
+
+static struct edma_soc_info da850_edma_info[] = {
 	{
 		.n_channel		= 32,
 		.n_region		= 4,
@@ -107,9 +133,49 @@ static struct edma_soc_info da8xx_edma_info[] = {
 		.queue_tc_mapping	= da8xx_queue_tc_mapping,
 		.queue_priority_mapping	= da8xx_queue_priority_mapping,
 	},
+	{
+		.n_channel		= 32,
+		.n_region		= 4,
+		.n_slot			= 128,
+		.n_tc			= 1,
+		.n_cc			= 1,
+		.queue_tc_mapping	= da850_queue_tc_mapping,
+		.queue_priority_mapping	= da850_queue_priority_mapping,
+	},
+};
+
+static struct resource da830_edma_resources[] = {
+	{
+		.name	= "edma_cc0",
+		.start	= DA8XX_TPCC_BASE,
+		.end	= DA8XX_TPCC_BASE + SZ_32K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma_tc0",
+		.start	= DA8XX_TPTC0_BASE,
+		.end	= DA8XX_TPTC0_BASE + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma_tc1",
+		.start	= DA8XX_TPTC1_BASE,
+		.end	= DA8XX_TPTC1_BASE + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma0",
+		.start	= IRQ_DA8XX_CCINT0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "edma0_err",
+		.start	= IRQ_DA8XX_CCERRINT,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
-static struct resource da8xx_edma_resources[] = {
+static struct resource da850_edma_resources[] = {
 	{
 		.name	= "edma_cc0",
 		.start	= DA8XX_TPCC_BASE,
@@ -129,6 +195,18 @@ static struct resource da8xx_edma_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	{
+		.name	= "edma_cc1",
+		.start	= DA850_TPCC1_BASE,
+		.end	= DA850_TPCC1_BASE + SZ_32K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "edma_tc2",
+		.start	= DA850_TPTC2_BASE,
+		.end	= DA850_TPTC2_BASE + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
 		.name	= "edma0",
 		.start	= IRQ_DA8XX_CCINT0,
 		.flags	= IORESOURCE_IRQ,
@@ -138,21 +216,50 @@ static struct resource da8xx_edma_resources[] = {
 		.start	= IRQ_DA8XX_CCERRINT,
 		.flags	= IORESOURCE_IRQ,
 	},
+	{
+		.name	= "edma1",
+		.start	= IRQ_DA850_CCINT1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "edma1_err",
+		.start	= IRQ_DA850_CCERRINT1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device da830_edma_device = {
+	.name		= "edma",
+	.id		= -1,
+	.dev = {
+		.platform_data = da830_edma_info,
+	},
+	.num_resources	= ARRAY_SIZE(da830_edma_resources),
+	.resource	= da830_edma_resources,
 };
 
-static struct platform_device da8xx_edma_device = {
+static struct platform_device da850_edma_device = {
 	.name		= "edma",
 	.id		= -1,
 	.dev = {
-		.platform_data	= da8xx_edma_info,
+		.platform_data = da850_edma_info,
 	},
-	.num_resources	= ARRAY_SIZE(da8xx_edma_resources),
-	.resource	= da8xx_edma_resources,
+	.num_resources	= ARRAY_SIZE(da850_edma_resources),
+	.resource	= da850_edma_resources,
 };
 
 int __init da8xx_register_edma(void)
 {
-	return platform_device_register(&da8xx_edma_device);
+	struct platform_device *pdev;
+
+	if (cpu_is_davinci_da830())
+		pdev = &da830_edma_device;
+	else if (cpu_is_davinci_da850())
+		pdev = &da850_edma_device;
+	else
+		return -ENODEV;
+
+	return platform_device_register(pdev);
 }
 
 static struct resource da8xx_i2c_resources0[] = {
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 33/35] davinci: da830/omapl137: Specify reserved channels/slots
  2010-01-06 18:32                                                               ` [PATCH 32/35] davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138 Kevin Hilman
@ 2010-01-06 18:32                                                                 ` Kevin Hilman
  2010-01-06 18:32                                                                   ` [PATCH 34/35] davinci: da850/omapl138: " Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Pass reserved EDMA channel/slots as platform data for da830/omap-l137.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/devices-da8xx.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 63c330c..9a5342b 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -111,6 +111,29 @@ static const s8 da850_queue_priority_mapping[][2] = {
 	{-1, -1}
 };
 
+/*
+ * The following EDMA channels/slots are not being used by drivers (for
+ * example: Timer, GPIO, UART events etc) on da830/omap-l137, hence they
+ * are being reserved for codecs on the DSP side.
+ */
+static const s16 da830_dma_rsv_chans[][2] = {
+	/* (offset, number) */
+	{ 8,  2},
+	{12,  2},
+	{24,  4},
+	{30,  2},
+	{-1, -1}
+};
+
+static const s16 da830_dma_rsv_slots[][2] = {
+	/* (offset, number) */
+	{ 8,  2},
+	{12,  2},
+	{24,  4},
+	{30, 26},
+	{-1, -1}
+};
+
 static struct edma_soc_info da830_edma_info[] = {
 	{
 		.n_channel		= 32,
@@ -118,6 +141,8 @@ static struct edma_soc_info da830_edma_info[] = {
 		.n_slot			= 128,
 		.n_tc			= 2,
 		.n_cc			= 1,
+		.rsv_chans		= da830_dma_rsv_chans,
+		.rsv_slots		= da830_dma_rsv_slots,
 		.queue_tc_mapping	= da8xx_queue_tc_mapping,
 		.queue_priority_mapping	= da8xx_queue_priority_mapping,
 	},
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 34/35] davinci: da850/omapl138: Specify reserved channels/slots
  2010-01-06 18:32                                                                 ` [PATCH 33/35] davinci: da830/omapl137: Specify reserved channels/slots Kevin Hilman
@ 2010-01-06 18:32                                                                   ` Kevin Hilman
  2010-01-06 18:32                                                                     ` [PATCH 35/35] davinci: dm646x: Specify reserved EDMA channel/slots for DM646x Kevin Hilman
  0 siblings, 1 reply; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Pass reserved EDMA channel/slots as platform data for da850/omap-l138.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/devices-da8xx.c |   39 +++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 9a5342b..7e0789f 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -134,6 +134,41 @@ static const s16 da830_dma_rsv_slots[][2] = {
 	{-1, -1}
 };
 
+/*
+ * The following EDMA channels/slots are not being used by drivers (for
+ * example: Timer, GPIO, UART events etc) on da850/omap-l138, hence they
+ * are being reserved for codecs on the DSP side.
+ */
+static const s16 da850_dma0_rsv_chans[][2] = {
+	/* (offset, number) */
+	{ 8,  6},
+	{24,  4},
+	{30,  2},
+	{-1, -1}
+};
+
+static const s16 da850_dma0_rsv_slots[][2] = {
+	/* (offset, number) */
+	{ 8,  6},
+	{24,  4},
+	{30, 50},
+	{-1, -1}
+};
+
+static const s16 da850_dma1_rsv_chans[][2] = {
+	/* (offset, number) */
+	{ 0, 28},
+	{30,  2},
+	{-1, -1}
+};
+
+static const s16 da850_dma1_rsv_slots[][2] = {
+	/* (offset, number) */
+	{ 0, 28},
+	{30, 90},
+	{-1, -1}
+};
+
 static struct edma_soc_info da830_edma_info[] = {
 	{
 		.n_channel		= 32,
@@ -155,6 +190,8 @@ static struct edma_soc_info da850_edma_info[] = {
 		.n_slot			= 128,
 		.n_tc			= 2,
 		.n_cc			= 1,
+		.rsv_chans		= da850_dma0_rsv_chans,
+		.rsv_slots		= da850_dma0_rsv_slots,
 		.queue_tc_mapping	= da8xx_queue_tc_mapping,
 		.queue_priority_mapping	= da8xx_queue_priority_mapping,
 	},
@@ -164,6 +201,8 @@ static struct edma_soc_info da850_edma_info[] = {
 		.n_slot			= 128,
 		.n_tc			= 1,
 		.n_cc			= 1,
+		.rsv_chans		= da850_dma1_rsv_chans,
+		.rsv_slots		= da850_dma1_rsv_slots,
 		.queue_tc_mapping	= da850_queue_tc_mapping,
 		.queue_priority_mapping	= da850_queue_priority_mapping,
 	},
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 35/35] davinci: dm646x: Specify reserved EDMA channel/slots for DM646x
  2010-01-06 18:32                                                                   ` [PATCH 34/35] davinci: da850/omapl138: " Kevin Hilman
@ 2010-01-06 18:32                                                                     ` Kevin Hilman
  0 siblings, 0 replies; 40+ messages in thread
From: Kevin Hilman @ 2010-01-06 18:32 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sudhakar Rajashekhara <sudhakar.raj@ti.com>

Pass reserved EDMA channel/slots as platform data for dm646x.

Signed-off-by: Sudhakar Rajashekhara <sudhakar.raj@ti.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 arch/arm/mach-davinci/dm646x.c |   28 ++++++++++++++++++++++++++++
 1 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index de306ca..99224ec 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -511,6 +511,32 @@ static u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
 
 /*----------------------------------------------------------------------*/
 
+/*
+ * The following EDMA channels/slots are not being used by drivers (for
+ * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
+ * reserved for codecs on the DSP side.
+ */
+static const s16 dm646x_dma_rsv_chans[][2] = {
+	/* (offset, number) */
+	{ 0,  4},
+	{13,  3},
+	{24,  4},
+	{30,  2},
+	{54,  3},
+	{-1, -1}
+};
+
+static const s16 dm646x_dma_rsv_slots[][2] = {
+	/* (offset, number) */
+	{ 0,  4},
+	{13,  3},
+	{24,  4},
+	{30,  2},
+	{54,  3},
+	{128, 384},
+	{-1, -1}
+};
+
 /* Four Transfer Controllers on DM646x */
 static const s8
 dm646x_queue_tc_mapping[][2] = {
@@ -539,6 +565,8 @@ static struct edma_soc_info dm646x_edma_info[] = {
 		.n_slot			= 512,
 		.n_tc			= 4,
 		.n_cc			= 1,
+		.rsv_chans		= dm646x_dma_rsv_chans,
+		.rsv_slots		= dm646x_dma_rsv_slots,
 		.queue_tc_mapping	= dm646x_queue_tc_mapping,
 		.queue_priority_mapping	= dm646x_queue_priority_mapping,
 	},
-- 
1.6.6.rc2.1.g42108

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH 12/35] davinci: clock framework: remove spinlock usage
  2010-01-06 18:31                       ` [PATCH 12/35] davinci: clock framework: remove spinlock usage Kevin Hilman
  2010-01-06 18:31                         ` [PATCH 13/35] davinci: make /proc/davinci_clocks display multi-rooted clock tree Kevin Hilman
@ 2010-01-08 17:06                         ` Russell King - ARM Linux
  2010-01-11 15:27                           ` Kevin Hilman
  1 sibling, 1 reply; 40+ messages in thread
From: Russell King - ARM Linux @ 2010-01-08 17:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 06, 2010 at 10:31:54AM -0800, Kevin Hilman wrote:
> From: Sekhar Nori <nsekhar@ti.com>
> 
> Currently, the spinlock in DaVinci clock framework is being
> used to:
> 
> 1) Protect clock structure variables usecount and rate against
> concurrent modification.
> 
> 2) Protect against simultaneous PSC enables/disables ie.
> serialize davinci_psc_config().
> 
> 3) Serialize clk_set_rate():
> 	i.	Prevent simultaneous setting of clock rates
> 	ii.	Ensure clock list remains sane during rate
> 		propagation (also in clk_set_parent).
> 
> Remove the spinlock usage in clock framework by:
> 
> 1) Making clock rate and usecount as atomic variables.
> 
> 2) Making davinci_psc_config() protect itself instead of
> relying on serialization by caller.
> 
> 3) (i) Allowing the clk->set_rate to serialize itself. There
> should be no need to serialize all clock rate settings.
> Currently the only user of rate setting is cpufreq driver on
> DA850. cpufreq naturally serializes the calls to set CPU rate.
> Also, there appears no need to lock IRQs during CPU rate
> transtitions. If required, IRQs can be locked in the actual
> set_rate function.
> 
> 3) (ii) Use the mutex already in place for serialzing clock list
> manipulation for serializing clock rate propagation as well.
> 
> Apart from the general benefit of reducing locking granurlarity,
> the main motivation behind this change is to enable usage of
> clock framework for off-chip clock synthesizers. One such
> synthesizer, CDCE949, is present on DM6467 EVM. Access to the
> synthesizer happens through I2C bus - accessing which can lead to
> CPU sleep. Having IRQs locked in clk_set_rate prevents the
> clk->set_rate function from sleeping.

This patch is extremely bogus.  Just because something is called 'atomic'
does not make it so.

atomic_set()..atomic_read() are NOT atomic.  They are just plain write
and read of the underlying atomic value - the former is intended for
one-time initialization, and the latter is intended for debugging.

> @@ -41,15 +40,16 @@ static void __clk_enable(struct clk *clk)
>  {
>  	if (clk->parent)
>  		__clk_enable(clk->parent);
> -	if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
> +	if (atomic_read(&clk->usecount) == 0 && (clk->flags & CLK_PSC))
>  		davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 1);
> +	atomic_inc(&clk->usecount);

This is wrong on two levels.  Firstly, consider a simultaneous clk_enable
and clk_disable.

CPU0						CPU1
__clk_disable

atomic_dec_and_test(&clk->usecount) -> true

						__clk_enable
						atomic_read(&clk->usecount) returns zero
						davinci_psc_config(..., 1);
						atomic_inc(&clk->usecount);
davinci_psc_config(..., 0);

The result is that we now have the situation where the usecount is nonzero
but the clock is disabled.

Similar bogosities can arise when an already enabled clock tries to be
simultaneously enabled for a second time and disabled.

Secondly, davinci_psc_config() does a lot of read-modify-writing.  With
the spinlock gone, what's the protection against simultaneous r-m-w on
these registers?

> @@ -88,7 +80,7 @@ unsigned long clk_get_rate(struct clk *clk)
>  	if (clk == NULL || IS_ERR(clk))
>  		return -EINVAL;
>  
> -	return clk->rate;
> +	return atomic_read(&clk->rate);

atomic here doesn't make clk->rate magically right.  This is precisely
equivalent to reading clk->rate directly.

>  int clk_set_rate(struct clk *clk, unsigned long rate)
>  {
> -	unsigned long flags;
>  	int ret = -EINVAL;
>  
>  	if (clk == NULL || IS_ERR(clk))
>  		return ret;
>  
> -	spin_lock_irqsave(&clockfw_lock, flags);
>  	if (clk->set_rate)
>  		ret = clk->set_rate(clk, rate);
>  	if (ret == 0) {
>  		if (clk->recalc)
> -			clk->rate = clk->recalc(clk);
> +			atomic_set(&clk->rate, clk->recalc(clk));

This atomic_set does nothing to protect you from races.  You might as
well be writing directly to clk->rate.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 00/35] davinci updates queued for 2.6.34
  2010-01-06 18:31 [PATCH 00/35] davinci updates queued for 2.6.34 Kevin Hilman
  2010-01-06 18:31 ` [PATCH 01/35] davinci: da8xx/omapl1: add support for the second sysconfig module Kevin Hilman
@ 2010-01-10 13:59 ` Russell King - ARM Linux
  2010-01-11 15:31   ` Kevin Hilman
  1 sibling, 1 reply; 40+ messages in thread
From: Russell King - ARM Linux @ 2010-01-10 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 06, 2010 at 10:31:42AM -0800, Kevin Hilman wrote:
> Apologies for the large series, I've been meaning to send these in
> smaller batches, but hd lots to queue up from over the holidays.
> 
> Pending any review comments, these will be submitted to Linus during
> the next merge window.

Nothing specific on this series.

However, while looking at adding a standard clkdev_add_table() to replace
all those clks_register() implementations found in various machine files
(and open-coded versions of the same) I'm wondering why davinci wraps
the clk_lookup structure without adding anything to it.

Could davinci get rid of this seemingly useless wrapping (presumably
copied from OMAP) and so be able to switch over to use clkdev_add_table()
instead?

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 12/35] davinci: clock framework: remove spinlock usage
  2010-01-08 17:06                         ` [PATCH 12/35] davinci: clock framework: remove spinlock usage Russell King - ARM Linux
@ 2010-01-11 15:27                           ` Kevin Hilman
  0 siblings, 0 replies; 40+ messages in thread
From: Kevin Hilman @ 2010-01-11 15:27 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King - ARM Linux <linux@arm.linux.org.uk> writes:

> On Wed, Jan 06, 2010 at 10:31:54AM -0800, Kevin Hilman wrote:
>> From: Sekhar Nori <nsekhar@ti.com>
>> 
>> Currently, the spinlock in DaVinci clock framework is being
>> used to:
>> 
>> 1) Protect clock structure variables usecount and rate against
>> concurrent modification.
>> 
>> 2) Protect against simultaneous PSC enables/disables ie.
>> serialize davinci_psc_config().
>> 
>> 3) Serialize clk_set_rate():
>> 	i.	Prevent simultaneous setting of clock rates
>> 	ii.	Ensure clock list remains sane during rate
>> 		propagation (also in clk_set_parent).
>> 
>> Remove the spinlock usage in clock framework by:
>> 
>> 1) Making clock rate and usecount as atomic variables.
>> 
>> 2) Making davinci_psc_config() protect itself instead of
>> relying on serialization by caller.
>> 
>> 3) (i) Allowing the clk->set_rate to serialize itself. There
>> should be no need to serialize all clock rate settings.
>> Currently the only user of rate setting is cpufreq driver on
>> DA850. cpufreq naturally serializes the calls to set CPU rate.
>> Also, there appears no need to lock IRQs during CPU rate
>> transtitions. If required, IRQs can be locked in the actual
>> set_rate function.
>> 
>> 3) (ii) Use the mutex already in place for serialzing clock list
>> manipulation for serializing clock rate propagation as well.
>> 
>> Apart from the general benefit of reducing locking granurlarity,
>> the main motivation behind this change is to enable usage of
>> clock framework for off-chip clock synthesizers. One such
>> synthesizer, CDCE949, is present on DM6467 EVM. Access to the
>> synthesizer happens through I2C bus - accessing which can lead to
>> CPU sleep. Having IRQs locked in clk_set_rate prevents the
>> clk->set_rate function from sleeping.
>
> This patch is extremely bogus.  Just because something is called 'atomic'
> does not make it so.

Russell,

Thanks for the feedback.  I'll drop this patch while we rework this in
a different way.

Thanks,

Kevin

> atomic_set()..atomic_read() are NOT atomic.  They are just plain write
> and read of the underlying atomic value - the former is intended for
> one-time initialization, and the latter is intended for debugging.
>
>> @@ -41,15 +40,16 @@ static void __clk_enable(struct clk *clk)
>>  {
>>  	if (clk->parent)
>>  		__clk_enable(clk->parent);
>> -	if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
>> +	if (atomic_read(&clk->usecount) == 0 && (clk->flags & CLK_PSC))
>>  		davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 1);
>> +	atomic_inc(&clk->usecount);
>
> This is wrong on two levels.  Firstly, consider a simultaneous clk_enable
> and clk_disable.
>
> CPU0						CPU1
> __clk_disable
>
> atomic_dec_and_test(&clk->usecount) -> true
>
> 						__clk_enable
> 						atomic_read(&clk->usecount) returns zero
> 						davinci_psc_config(..., 1);
> 						atomic_inc(&clk->usecount);
> davinci_psc_config(..., 0);
>
> The result is that we now have the situation where the usecount is nonzero
> but the clock is disabled.
>
> Similar bogosities can arise when an already enabled clock tries to be
> simultaneously enabled for a second time and disabled.
>
> Secondly, davinci_psc_config() does a lot of read-modify-writing.  With
> the spinlock gone, what's the protection against simultaneous r-m-w on
> these registers?
>
>> @@ -88,7 +80,7 @@ unsigned long clk_get_rate(struct clk *clk)
>>  	if (clk == NULL || IS_ERR(clk))
>>  		return -EINVAL;
>>  
>> -	return clk->rate;
>> +	return atomic_read(&clk->rate);
>
> atomic here doesn't make clk->rate magically right.  This is precisely
> equivalent to reading clk->rate directly.
>
>>  int clk_set_rate(struct clk *clk, unsigned long rate)
>>  {
>> -	unsigned long flags;
>>  	int ret = -EINVAL;
>>  
>>  	if (clk == NULL || IS_ERR(clk))
>>  		return ret;
>>  
>> -	spin_lock_irqsave(&clockfw_lock, flags);
>>  	if (clk->set_rate)
>>  		ret = clk->set_rate(clk, rate);
>>  	if (ret == 0) {
>>  		if (clk->recalc)
>> -			clk->rate = clk->recalc(clk);
>> +			atomic_set(&clk->rate, clk->recalc(clk));
>
> This atomic_set does nothing to protect you from races.  You might as
> well be writing directly to clk->rate.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH 00/35] davinci updates queued for 2.6.34
  2010-01-10 13:59 ` [PATCH 00/35] davinci updates queued for 2.6.34 Russell King - ARM Linux
@ 2010-01-11 15:31   ` Kevin Hilman
  0 siblings, 0 replies; 40+ messages in thread
From: Kevin Hilman @ 2010-01-11 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

Russell King - ARM Linux <linux@arm.linux.org.uk> writes:

> On Wed, Jan 06, 2010 at 10:31:42AM -0800, Kevin Hilman wrote:
>> Apologies for the large series, I've been meaning to send these in
>> smaller batches, but hd lots to queue up from over the holidays.
>> 
>> Pending any review comments, these will be submitted to Linus during
>> the next merge window.
>
> Nothing specific on this series.
>
> However, while looking at adding a standard clkdev_add_table() to replace
> all those clks_register() implementations found in various machine files
> (and open-coded versions of the same) I'm wondering why davinci wraps
> the clk_lookup structure without adding anything to it.

It's no longer needed.  In initial implementation, I had some extra
fields like in OMAP, but then dropped them. 

> Could davinci get rid of this seemingly useless wrapping (presumably
> copied from OMAP) and so be able to switch over to use clkdev_add_table()
> instead?

Yes, I'll drop the wrapping.

Thanks for the reviews,

Kevin

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2010-01-11 15:31 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-01-06 18:31 [PATCH 00/35] davinci updates queued for 2.6.34 Kevin Hilman
2010-01-06 18:31 ` [PATCH 01/35] davinci: da8xx/omapl1: add support for the second sysconfig module Kevin Hilman
2010-01-06 18:31   ` [PATCH 02/35] davinci: move PLL wait time values to clock.h Kevin Hilman
2010-01-06 18:31     ` [PATCH 03/35] davinci: move DDR2 controller defines to memory.h Kevin Hilman
2010-01-06 18:31       ` [PATCH 04/35] davinci: move PSC register definitions from psc.c to psc.h Kevin Hilman
2010-01-06 18:31         ` [PATCH 05/35] davinci: make it possible to include clock.h and psc.h in assembly code Kevin Hilman
2010-01-06 18:31           ` [PATCH 06/35] davinci: cpuidle: move mapping of DDR2 controller registers out of driver Kevin Hilman
2010-01-06 18:31             ` [PATCH 07/35] davinci: da850/omap-l138: unlock PLL registers during init Kevin Hilman
2010-01-06 18:31               ` [PATCH 08/35] davinci: da850/omap-l138: create static map for SRAM Kevin Hilman
2010-01-06 18:31                 ` [PATCH 09/35] davinci: explain CLOCK_TICK_RATE of 27MHz in include/mach/timex.h Kevin Hilman
2010-01-06 18:31                   ` [PATCH 10/35] davinci: board-dm646x-evm.c: arrange related code together Kevin Hilman
2010-01-06 18:31                     ` [PATCH 11/35] davinci: add support for DM6467T EVM Kevin Hilman
2010-01-06 18:31                       ` [PATCH 12/35] davinci: clock framework: remove spinlock usage Kevin Hilman
2010-01-06 18:31                         ` [PATCH 13/35] davinci: make /proc/davinci_clocks display multi-rooted clock tree Kevin Hilman
2010-01-06 18:31                           ` [PATCH 14/35] davinci: move /proc/davinci_clocks to debugfs Kevin Hilman
2010-01-06 18:31                             ` [PATCH 15/35] davinci: da850/omap-l138: Modify NOR partition info Kevin Hilman
2010-01-06 18:31                               ` [PATCH 16/35] davinci: da850/omap-l138: Enable 4-bit ecc Kevin Hilman
2010-01-06 18:31                                 ` [PATCH 17/35] TI Davinci EMAC : Re-use driver for other platforms Kevin Hilman
2010-01-06 18:32                                   ` [PATCH 18/35] TI Davinci EMAC : add platform specific interrupt enable/disable logic Kevin Hilman
2010-01-06 18:32                                     ` [PATCH 19/35] TI Davinci EMAC : Abstract Buffer address translation logic Kevin Hilman
2010-01-06 18:32                                       ` [PATCH 20/35] davinci: clock: Check CLK_PSC flag before disabling PSC Kevin Hilman
2010-01-06 18:32                                         ` [PATCH 21/35] DaVinci: DM365: Changing default queue for DM365 Kevin Hilman
2010-01-06 18:32                                           ` [PATCH 22/35] davinci: add power management support Kevin Hilman
2010-01-06 18:32                                             ` [PATCH 23/35] davinci: da850/omap-l138: add support for SoC suspend Kevin Hilman
2010-01-06 18:32                                               ` [PATCH 24/35] davinci: da850/omap-l138 EVM: register for suspend support Kevin Hilman
2010-01-06 18:32                                                 ` [PATCH 25/35] davinci: add support for CDCE949 clock synthesizer Kevin Hilman
2010-01-06 18:32                                                   ` [PATCH 26/35] davinci: add CDCE949 support on DM6467 EVM Kevin Hilman
2010-01-06 18:32                                                     ` [PATCH 27/35] davinci: Correct return value of edma_alloc_channel api Kevin Hilman
2010-01-06 18:32                                                       ` [PATCH 28/35] davinci: Keep count of channel controllers on a platform Kevin Hilman
2010-01-06 18:32                                                         ` [PATCH 29/35] davinci: Fix edma_alloc_channel api for EDMA_CHANNEL_ANY case Kevin Hilman
2010-01-06 18:32                                                           ` [PATCH 30/35] davinci: build list of unused EDMA events dynamically Kevin Hilman
2010-01-06 18:32                                                             ` [PATCH 31/35] davinci: support for EDMA resource sharing Kevin Hilman
2010-01-06 18:32                                                               ` [PATCH 32/35] davinci: da8xx/omap-l1xx: Add EDMA platform data for da850/omap-l138 Kevin Hilman
2010-01-06 18:32                                                                 ` [PATCH 33/35] davinci: da830/omapl137: Specify reserved channels/slots Kevin Hilman
2010-01-06 18:32                                                                   ` [PATCH 34/35] davinci: da850/omapl138: " Kevin Hilman
2010-01-06 18:32                                                                     ` [PATCH 35/35] davinci: dm646x: Specify reserved EDMA channel/slots for DM646x Kevin Hilman
2010-01-08 17:06                         ` [PATCH 12/35] davinci: clock framework: remove spinlock usage Russell King - ARM Linux
2010-01-11 15:27                           ` Kevin Hilman
2010-01-10 13:59 ` [PATCH 00/35] davinci updates queued for 2.6.34 Russell King - ARM Linux
2010-01-11 15:31   ` Kevin Hilman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.