diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-lpc32xx/clock.c | 87 | ||||
-rw-r--r-- | arch/arm/mach-lpc32xx/common.c | 26 | ||||
-rw-r--r-- | arch/arm/mach-lpc32xx/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-lpc32xx/phy3250.c | 1 |
4 files changed, 91 insertions, 24 deletions
diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c index ab8c21647422..370a5471798e 100644 --- a/arch/arm/mach-lpc32xx/clock.c +++ b/arch/arm/mach-lpc32xx/clock.c | |||
@@ -87,6 +87,7 @@ | |||
87 | #include <linux/list.h> | 87 | #include <linux/list.h> |
88 | #include <linux/errno.h> | 88 | #include <linux/errno.h> |
89 | #include <linux/device.h> | 89 | #include <linux/device.h> |
90 | #include <linux/delay.h> | ||
90 | #include <linux/err.h> | 91 | #include <linux/err.h> |
91 | #include <linux/clk.h> | 92 | #include <linux/clk.h> |
92 | #include <linux/amba/bus.h> | 93 | #include <linux/amba/bus.h> |
@@ -100,6 +101,8 @@ | |||
100 | 101 | ||
101 | static DEFINE_SPINLOCK(global_clkregs_lock); | 102 | static DEFINE_SPINLOCK(global_clkregs_lock); |
102 | 103 | ||
104 | static int usb_pll_enable, usb_pll_valid; | ||
105 | |||
103 | static struct clk clk_armpll; | 106 | static struct clk clk_armpll; |
104 | static struct clk clk_usbpll; | 107 | static struct clk clk_usbpll; |
105 | 108 | ||
@@ -384,30 +387,62 @@ static u32 local_clk_usbpll_setup(struct clk_pll_setup *pHCLKPllSetup) | |||
384 | static int local_usbpll_enable(struct clk *clk, int enable) | 387 | static int local_usbpll_enable(struct clk *clk, int enable) |
385 | { | 388 | { |
386 | u32 reg; | 389 | u32 reg; |
387 | int ret = -ENODEV; | 390 | int ret = 0; |
388 | unsigned long timeout = jiffies + msecs_to_jiffies(10); | 391 | unsigned long timeout = jiffies + msecs_to_jiffies(20); |
389 | 392 | ||
390 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | 393 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); |
391 | 394 | ||
392 | if (enable == 0) { | 395 | __raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN2 | |
393 | reg &= ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 | | 396 | LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP), |
394 | LPC32XX_CLKPWR_USBCTRL_CLK_EN2); | 397 | LPC32XX_CLKPWR_USB_CTRL); |
395 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | 398 | __raw_writel(reg & ~LPC32XX_CLKPWR_USBCTRL_CLK_EN1, |
396 | } else if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP) { | 399 | LPC32XX_CLKPWR_USB_CTRL); |
400 | |||
401 | if (enable && usb_pll_valid && usb_pll_enable) { | ||
402 | ret = -ENODEV; | ||
403 | /* | ||
404 | * If the PLL rate has been previously set, then the rate | ||
405 | * in the PLL register is valid and can be enabled here. | ||
406 | * Otherwise, it needs to be enabled as part of setrate. | ||
407 | */ | ||
408 | |||
409 | /* | ||
410 | * Gate clock into PLL | ||
411 | */ | ||
397 | reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1; | 412 | reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1; |
398 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | 413 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); |
399 | 414 | ||
400 | /* Wait for PLL lock */ | 415 | /* |
416 | * Enable PLL | ||
417 | */ | ||
418 | reg |= LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP; | ||
419 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | ||
420 | |||
421 | /* | ||
422 | * Wait for PLL to lock | ||
423 | */ | ||
401 | while (time_before(jiffies, timeout) && (ret == -ENODEV)) { | 424 | while (time_before(jiffies, timeout) && (ret == -ENODEV)) { |
402 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | 425 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); |
403 | if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS) | 426 | if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS) |
404 | ret = 0; | 427 | ret = 0; |
428 | else | ||
429 | udelay(10); | ||
405 | } | 430 | } |
406 | 431 | ||
432 | /* | ||
433 | * Gate clock from PLL if PLL is locked | ||
434 | */ | ||
407 | if (ret == 0) { | 435 | if (ret == 0) { |
408 | reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2; | 436 | __raw_writel(reg | LPC32XX_CLKPWR_USBCTRL_CLK_EN2, |
409 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | 437 | LPC32XX_CLKPWR_USB_CTRL); |
438 | } else { | ||
439 | __raw_writel(reg & ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 | | ||
440 | LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP), | ||
441 | LPC32XX_CLKPWR_USB_CTRL); | ||
410 | } | 442 | } |
443 | } else if ((enable == 0) && usb_pll_valid && usb_pll_enable) { | ||
444 | usb_pll_valid = 0; | ||
445 | usb_pll_enable = 0; | ||
411 | } | 446 | } |
412 | 447 | ||
413 | return ret; | 448 | return ret; |
@@ -425,7 +460,7 @@ static unsigned long local_usbpll_round_rate(struct clk *clk, | |||
425 | */ | 460 | */ |
426 | rate = rate * 1000; | 461 | rate = rate * 1000; |
427 | 462 | ||
428 | clkin = clk->parent->rate; | 463 | clkin = clk->get_rate(clk); |
429 | usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) & | 464 | usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) & |
430 | LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1; | 465 | LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1; |
431 | clkin = clkin / usbdiv; | 466 | clkin = clkin / usbdiv; |
@@ -439,7 +474,8 @@ static unsigned long local_usbpll_round_rate(struct clk *clk, | |||
439 | 474 | ||
440 | static int local_usbpll_set_rate(struct clk *clk, unsigned long rate) | 475 | static int local_usbpll_set_rate(struct clk *clk, unsigned long rate) |
441 | { | 476 | { |
442 | u32 clkin, reg, usbdiv; | 477 | int ret = -ENODEV; |
478 | u32 clkin, usbdiv; | ||
443 | struct clk_pll_setup pllsetup; | 479 | struct clk_pll_setup pllsetup; |
444 | 480 | ||
445 | /* | 481 | /* |
@@ -448,7 +484,7 @@ static int local_usbpll_set_rate(struct clk *clk, unsigned long rate) | |||
448 | */ | 484 | */ |
449 | rate = rate * 1000; | 485 | rate = rate * 1000; |
450 | 486 | ||
451 | clkin = clk->get_rate(clk); | 487 | clkin = clk->get_rate(clk->parent); |
452 | usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) & | 488 | usbdiv = (__raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) & |
453 | LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1; | 489 | LPC32XX_CLKPWR_USBPDIV_PLL_MASK) + 1; |
454 | clkin = clkin / usbdiv; | 490 | clkin = clkin / usbdiv; |
@@ -457,22 +493,25 @@ static int local_usbpll_set_rate(struct clk *clk, unsigned long rate) | |||
457 | if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0) | 493 | if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0) |
458 | return -EINVAL; | 494 | return -EINVAL; |
459 | 495 | ||
496 | /* | ||
497 | * Disable PLL clocks during PLL change | ||
498 | */ | ||
460 | local_usbpll_enable(clk, 0); | 499 | local_usbpll_enable(clk, 0); |
461 | 500 | pllsetup.analog_on = 0; | |
462 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | ||
463 | reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1; | ||
464 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | ||
465 | |||
466 | pllsetup.analog_on = 1; | ||
467 | local_clk_usbpll_setup(&pllsetup); | 501 | local_clk_usbpll_setup(&pllsetup); |
468 | 502 | ||
469 | clk->rate = clk_check_pll_setup(clkin, &pllsetup); | 503 | /* |
504 | * Start USB PLL and check PLL status | ||
505 | */ | ||
506 | |||
507 | usb_pll_valid = 1; | ||
508 | usb_pll_enable = 1; | ||
470 | 509 | ||
471 | reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL); | 510 | ret = local_usbpll_enable(clk, 1); |
472 | reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2; | 511 | if (ret >= 0) |
473 | __raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL); | 512 | clk->rate = clk_check_pll_setup(clkin, &pllsetup); |
474 | 513 | ||
475 | return 0; | 514 | return ret; |
476 | } | 515 | } |
477 | 516 | ||
478 | static struct clk clk_usbpll = { | 517 | static struct clk clk_usbpll = { |
diff --git a/arch/arm/mach-lpc32xx/common.c b/arch/arm/mach-lpc32xx/common.c index 6c76bb36559b..11c900857b1b 100644 --- a/arch/arm/mach-lpc32xx/common.c +++ b/arch/arm/mach-lpc32xx/common.c | |||
@@ -160,6 +160,32 @@ struct platform_device lpc32xx_adc_device = { | |||
160 | }; | 160 | }; |
161 | 161 | ||
162 | /* | 162 | /* |
163 | * USB support | ||
164 | */ | ||
165 | /* The dmamask must be set for OHCI to work */ | ||
166 | static u64 ohci_dmamask = ~(u32) 0; | ||
167 | static struct resource ohci_resources[] = { | ||
168 | { | ||
169 | .start = IO_ADDRESS(LPC32XX_USB_BASE), | ||
170 | .end = IO_ADDRESS(LPC32XX_USB_BASE + 0x100 - 1), | ||
171 | .flags = IORESOURCE_MEM, | ||
172 | }, { | ||
173 | .start = IRQ_LPC32XX_USB_HOST, | ||
174 | .flags = IORESOURCE_IRQ, | ||
175 | }, | ||
176 | }; | ||
177 | struct platform_device lpc32xx_ohci_device = { | ||
178 | .name = "usb-ohci", | ||
179 | .id = -1, | ||
180 | .dev = { | ||
181 | .dma_mask = &ohci_dmamask, | ||
182 | .coherent_dma_mask = 0xFFFFFFFF, | ||
183 | }, | ||
184 | .num_resources = ARRAY_SIZE(ohci_resources), | ||
185 | .resource = ohci_resources, | ||
186 | }; | ||
187 | |||
188 | /* | ||
163 | * Returns the unique ID for the device | 189 | * Returns the unique ID for the device |
164 | */ | 190 | */ |
165 | void lpc32xx_get_uid(u32 devid[4]) | 191 | void lpc32xx_get_uid(u32 devid[4]) |
diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h index 68f2e46d98ad..e1880b02b76b 100644 --- a/arch/arm/mach-lpc32xx/common.h +++ b/arch/arm/mach-lpc32xx/common.h | |||
@@ -31,6 +31,7 @@ extern struct platform_device lpc32xx_i2c2_device; | |||
31 | extern struct platform_device lpc32xx_tsc_device; | 31 | extern struct platform_device lpc32xx_tsc_device; |
32 | extern struct platform_device lpc32xx_adc_device; | 32 | extern struct platform_device lpc32xx_adc_device; |
33 | extern struct platform_device lpc32xx_rtc_device; | 33 | extern struct platform_device lpc32xx_rtc_device; |
34 | extern struct platform_device lpc32xx_ohci_device; | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Other arch specific structures and functions | 37 | * Other arch specific structures and functions |
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index 4590a8b52e72..53f12301be8a 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c | |||
@@ -279,6 +279,7 @@ static struct platform_device *phy3250_devs[] __initdata = { | |||
279 | &lpc32xx_watchdog_device, | 279 | &lpc32xx_watchdog_device, |
280 | &lpc32xx_gpio_led_device, | 280 | &lpc32xx_gpio_led_device, |
281 | &lpc32xx_adc_device, | 281 | &lpc32xx_adc_device, |
282 | &lpc32xx_ohci_device, | ||
282 | }; | 283 | }; |
283 | 284 | ||
284 | static struct amba_device *amba_devs[] __initdata = { | 285 | static struct amba_device *amba_devs[] __initdata = { |