From 0cf0d815ba0d09281c5671b82a83c4220a606dc4 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 8 Feb 2012 21:41:04 +0100 Subject: ARM: LPC32xx: clock.c: warning fix This patch removes the debug warning on local_clk_disable() as done in Kevin Wells' driver update Signed-off-by: Roland Stigge Acked-by: Wolfram Sang Tested-by: Wolfram Sang Acked-by: Kevin Wells Signed-off-by: Olof Johansson --- arch/arm/mach-lpc32xx/clock.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm/mach-lpc32xx/clock.c') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 1e02751..39dcbd0 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -903,8 +903,6 @@ static inline void clk_unlock(void) static void local_clk_disable(struct clk *clk) { - WARN_ON(clk->usecount == 0); - /* Don't attempt to disable clock if it has no users */ if (clk->usecount > 0) { clk->usecount--; -- cgit v1.1 From b84518625183e87c6930b11db0592be786181128 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 8 Feb 2012 21:41:05 +0100 Subject: ARM: LPC32xx: clock.c: Fix mutex lock issues This patch fixes the mutex issue in clock.c, as done in Kevin Wells' original driver update: In some cases, the clock drivers could grab a mutex twice in an improper context. This patch changes the mutex mechanism to a simple irq lock/unlock mechanism and removes un-needed locks from some functions. (See also git.lpclinux.com) Signed-off-by: Roland Stigge Tested-by: Wolfram Sang Acked-by: Kevin Wells Signed-off-by: Olof Johansson --- arch/arm/mach-lpc32xx/clock.c | 41 +++++++++++------------------------------ 1 file changed, 11 insertions(+), 30 deletions(-) (limited to 'arch/arm/mach-lpc32xx/clock.c') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 39dcbd0..fef8630 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -97,9 +97,10 @@ #include "clock.h" #include "common.h" +static DEFINE_SPINLOCK(global_clkregs_lock); + static struct clk clk_armpll; static struct clk clk_usbpll; -static DEFINE_MUTEX(clkm_lock); /* * Post divider values for PLLs based on selected register value @@ -891,16 +892,6 @@ static struct clk clk_lcd = { .enable_mask = LPC32XX_CLKPWR_LCDCTRL_CLK_EN, }; -static inline void clk_lock(void) -{ - mutex_lock(&clkm_lock); -} - -static inline void clk_unlock(void) -{ - mutex_unlock(&clkm_lock); -} - static void local_clk_disable(struct clk *clk) { /* Don't attempt to disable clock if it has no users */ @@ -945,10 +936,11 @@ static int local_clk_enable(struct clk *clk) int clk_enable(struct clk *clk) { int ret; + unsigned long flags; - clk_lock(); + spin_lock_irqsave(&global_clkregs_lock, flags); ret = local_clk_enable(clk); - clk_unlock(); + spin_unlock_irqrestore(&global_clkregs_lock, flags); return ret; } @@ -959,9 +951,11 @@ EXPORT_SYMBOL(clk_enable); */ void clk_disable(struct clk *clk) { - clk_lock(); + unsigned long flags; + + spin_lock_irqsave(&global_clkregs_lock, flags); local_clk_disable(clk); - clk_unlock(); + spin_unlock_irqrestore(&global_clkregs_lock, flags); } EXPORT_SYMBOL(clk_disable); @@ -970,13 +964,7 @@ EXPORT_SYMBOL(clk_disable); */ unsigned long clk_get_rate(struct clk *clk) { - unsigned long rate; - - clk_lock(); - rate = clk->get_rate(clk); - clk_unlock(); - - return rate; + return clk->get_rate(clk); } EXPORT_SYMBOL(clk_get_rate); @@ -992,11 +980,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) * the actual rate set as part of the peripheral dividers * instead of high level clock control */ - if (clk->set_rate) { - clk_lock(); + if (clk->set_rate) ret = clk->set_rate(clk, rate); - clk_unlock(); - } return ret; } @@ -1007,15 +992,11 @@ EXPORT_SYMBOL(clk_set_rate); */ long clk_round_rate(struct clk *clk, unsigned long rate) { - clk_lock(); - if (clk->round_rate) rate = clk->round_rate(clk, rate); else rate = clk->get_rate(clk); - clk_unlock(); - return rate; } EXPORT_SYMBOL(clk_round_rate); -- cgit v1.1 From 8998316c425ed2b36ca3b01a658f08a7d006a4f9 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 8 Feb 2012 21:41:01 +0100 Subject: ARM: LPC32xx: clock.c: Missing header file This patch fixes the compiler warnings regarding the EXPORT_SYMBOL usage Signed-off-by: Roland Stigge Acked-by: Wolfram Sang Acked-by: Kevin Wells Signed-off-by: Olof Johansson --- arch/arm/mach-lpc32xx/clock.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/mach-lpc32xx/clock.c') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index fef8630..09dfa49 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -82,6 +82,7 @@ * will also impact the individual peripheral rates. */ +#include #include #include #include -- cgit v1.1 From f40a6818857e00c1d0ecec9af832f46a83f12f53 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 8 Feb 2012 21:41:02 +0100 Subject: ARM: LPC32xx: clock.c: jiffies wrapping This patch fixes the jiffies wrapping bug in clock.c. It corrects the timeout computation based on jiffies, uses time_before() for correct wrapping handling and replaces a binary "&" which should really be a logical "&&" in a truth expression. Signed-off-by: Roland Stigge Acked-by: Wolfram Sang Tested-by: Wolfram Sang Acked-by: Kevin Wells Signed-off-by: Olof Johansson --- arch/arm/mach-lpc32xx/clock.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/arm/mach-lpc32xx/clock.c') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 09dfa49..6a15e36 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -129,7 +129,7 @@ static struct clk osc_32KHz = { static int local_pll397_enable(struct clk *clk, int enable) { u32 reg; - unsigned long timeout = 1 + msecs_to_jiffies(10); + unsigned long timeout = jiffies + msecs_to_jiffies(10); reg = __raw_readl(LPC32XX_CLKPWR_PLL397_CTRL); @@ -144,7 +144,7 @@ static int local_pll397_enable(struct clk *clk, int enable) /* Wait for PLL397 lock */ while (((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) & LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0) && - (timeout > jiffies)) + time_before(jiffies, timeout)) cpu_relax(); if ((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) & @@ -158,7 +158,7 @@ static int local_pll397_enable(struct clk *clk, int enable) static int local_oscmain_enable(struct clk *clk, int enable) { u32 reg; - unsigned long timeout = 1 + msecs_to_jiffies(10); + unsigned long timeout = jiffies + msecs_to_jiffies(10); reg = __raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL); @@ -173,7 +173,7 @@ static int local_oscmain_enable(struct clk *clk, int enable) /* Wait for main oscillator to start */ while (((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) & LPC32XX_CLKPWR_MOSC_DISABLE) != 0) && - (timeout > jiffies)) + time_before(jiffies, timeout)) cpu_relax(); if ((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) & @@ -385,7 +385,7 @@ static int local_usbpll_enable(struct clk *clk, int enable) { u32 reg; int ret = -ENODEV; - unsigned long timeout = 1 + msecs_to_jiffies(10); + unsigned long timeout = jiffies + msecs_to_jiffies(10); reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); @@ -398,7 +398,7 @@ static int local_usbpll_enable(struct clk *clk, int enable) __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); /* Wait for PLL lock */ - while ((timeout > jiffies) & (ret == -ENODEV)) { + while (time_before(jiffies, timeout) && (ret == -ENODEV)) { reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS) ret = 0; -- cgit v1.1 From d35dfa59a3101095228e0a5ed2dda33fc870b50d Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Wed, 8 Feb 2012 21:41:03 +0100 Subject: ARM: LPC32xx: clock.c: Clock registration fixes This patch adjusts the clock registration list, ported from the latest version of Kevin Wells' latest version of clock.c: i2s0_ck, i2s1_ck and dev:mmc0 have NULL pointers associated as the .dev_id and .con_id, respectively. The old values were not useful. Signed-off-by: Roland Stigge Acked-by: Kevin Wells Signed-off-by: Olof Johansson --- arch/arm/mach-lpc32xx/clock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-lpc32xx/clock.c') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 6a15e36..0e01bf4 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -1055,10 +1055,10 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("dev:ssp1", NULL, clk_ssp1) _REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan) _REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand) - _REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0) - _REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1) + _REGISTER_CLOCK(NULL, "i2s0_ck", clk_i2s0) + _REGISTER_CLOCK(NULL, "i2s1_ck", clk_i2s1) _REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc) - _REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc) + _REGISTER_CLOCK("dev:mmc0", NULL, clk_mmc) _REGISTER_CLOCK("lpc-net.0", NULL, clk_net) _REGISTER_CLOCK("dev:clcd", NULL, clk_lcd) _REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd) -- cgit v1.1 From 48a5dedfa78899dad50b3b4ae30f07e27e6591ab Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 12 Mar 2012 22:23:43 +0100 Subject: ARM: LPC32xx: USB Support This patch adds OHCI support to the LPC32xx ARM platform. Besides the trivial addition of platform "usb-ohci" support, fixes for the USB PLL have been added to arch/arm/mach-lpc32xx/clock.c, ported from NXP's lpclinux.com. (This is the mach-lpc32xx specific part, the USB subsystem specific changes are in a separate patch for the USB maintainers.) Signed-off-by: Roland Stigge --- arch/arm/mach-lpc32xx/clock.c | 87 +++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 24 deletions(-) (limited to 'arch/arm/mach-lpc32xx/clock.c') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index ab8c216..370a547 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -87,6 +87,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,8 @@ static DEFINE_SPINLOCK(global_clkregs_lock); +static int usb_pll_enable, usb_pll_valid; + static struct clk clk_armpll; static struct clk clk_usbpll; @@ -384,30 +387,62 @@ static u32 local_clk_usbpll_setup(struct clk_pll_setup *pHCLKPllSetup) static int local_usbpll_enable(struct clk *clk, int enable) { u32 reg; - int ret = -ENODEV; - unsigned long timeout = jiffies + msecs_to_jiffies(10); + int ret = 0; + unsigned long timeout = jiffies + msecs_to_jiffies(20); reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); - if (enable == 0) { - reg &= ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 | - LPC32XX_CLKPWR_USBCTRL_CLK_EN2); - __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); - } else if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP) { + __raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN2 | + LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP), + LPC32XX_CLKPWR_USB_CTRL); + __raw_writel(reg & ~LPC32XX_CLKPWR_USBCTRL_CLK_EN1, + LPC32XX_CLKPWR_USB_CTRL); + + if (enable && usb_pll_valid && usb_pll_enable) { + ret = -ENODEV; + /* + * If the PLL rate has been previously set, then the rate + * in the PLL register is valid and can be enabled here. + * Otherwise, it needs to be enabled as part of setrate. + */ + + /* + * Gate clock into PLL + */ reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1; __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); - /* Wait for PLL lock */ + /* + * Enable PLL + */ + reg |= LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP; + __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); + + /* + * Wait for PLL to lock + */ while (time_before(jiffies, timeout) && (ret == -ENODEV)) { reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS) ret = 0; + else + udelay(10); } + /* + * Gate clock from PLL if PLL is locked + */ if (ret == 0) { - reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2; - __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); + __raw_writel(reg | LPC32XX_CLKPWR_USBCTRL_CLK_EN2, + LPC32XX_CLKPWR_USB_CTRL); + } else { + __raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 | + LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP), + LPC32XX_CLKPWR_USB_CTRL); } + } else if ((enable == 0) && usb_pll_valid && usb_pll_enable) { + usb_pll_valid = 0; + usb_pll_enable = 0; } return ret; @@ -425,7 +460,7 @@ static unsigned long local_usbpll_round_rate(struct clk *clk, */ rate = rate * 1000; - clkin = clk->parent->rate; + clkin = clk->get_rate(clk); usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) & LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1; clkin = clkin / usbdiv; @@ -439,7 +474,8 @@ static unsigned long local_usbpll_round_rate(struct clk *clk, static int local_usbpll_set_rate(struct clk *clk, unsigned long rate) { - u32 clkin, reg, usbdiv; + int ret = -ENODEV; + u32 clkin, usbdiv; struct clk_pll_setup pllsetup; /* @@ -448,7 +484,7 @@ static int local_usbpll_set_rate(struct clk *clk, unsigned long rate) */ rate = rate * 1000; - clkin = clk->get_rate(clk); + clkin = clk->get_rate(clk->parent); usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) & LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1; clkin = clkin / usbdiv; @@ -457,22 +493,25 @@ static int local_usbpll_set_rate(struct clk *clk, unsigned long rate) if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0) return -EINVAL; + /* + * Disable PLL clocks during PLL change + */ local_usbpll_enable(clk, 0); - - reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); - reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1; - __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); - - pllsetup.analog_on = 1; + pllsetup.analog_on = 0; local_clk_usbpll_setup(&pllsetup); - clk->rate = clk_check_pll_setup(clkin, &pllsetup); + /* + * Start USB PLL and check PLL status + */ + + usb_pll_valid = 1; + usb_pll_enable = 1; - reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); - reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2; - __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); + ret = local_usbpll_enable(clk, 1); + if (ret >= 0) + clk->rate = clk_check_pll_setup(clkin, &pllsetup); - return 0; + return ret; } static struct clk clk_usbpll = { -- cgit v1.1 From c20b909be9ba27173294a52d08cab293ec030a2c Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 12 Mar 2012 22:27:28 +0100 Subject: ARM: LPC32xx: Ethernet support This patch adds ethernet support to the LPC32xx ARM architecture. The actual driver in drivers/net is contained in a separate patch. Signed-off-by: Roland Stigge Acked-by: Arnd Bergmann --- arch/arm/mach-lpc32xx/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-lpc32xx/clock.c') diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index 370a547..47639f3 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c @@ -1134,7 +1134,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("lpc32xx-adc", NULL, clk_adc) _REGISTER_CLOCK("ts-lpc32xx", NULL, clk_tsc) _REGISTER_CLOCK("dev:mmc0", NULL, clk_mmc) - _REGISTER_CLOCK("lpc-net.0", NULL, clk_net) + _REGISTER_CLOCK("lpc-eth.0", NULL, clk_net) _REGISTER_CLOCK("dev:clcd", NULL, clk_lcd) _REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd) _REGISTER_CLOCK("lpc32xx_rtc", NULL, clk_rtc) -- cgit v1.1