Skip to content

Commit

Permalink
USB: at91-ohci, handle extra at91sam9261 ahb clock
Browse files Browse the repository at this point in the history
The AT91SAM9261 needs to activate an AHB clock (HCK0) to use the USB Host
controller. Previously clock.c would just enable it at startup, but now
all the unused clocks are automatically disabled.

Based on patch from Nicolas Ferre.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Andrew Victor authored and Greg Kroah-Hartman committed Feb 16, 2007
1 parent ebaf494 commit ed077bb
Showing 1 changed file with 33 additions and 17 deletions.
50 changes: 33 additions & 17 deletions drivers/usb/host/ohci-at91.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,38 @@
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/arch/board.h>
#include <asm/arch/cpu.h>

#ifndef CONFIG_ARCH_AT91
#error "CONFIG_ARCH_AT91 must be defined."
#endif

/* interface and function clocks */
static struct clk *iclk, *fclk;
/* interface and function clocks; sometimes also an AHB clock */
static struct clk *iclk, *fclk, *hclk;
static int clocked;

extern int usb_disabled(void);

/*-------------------------------------------------------------------------*/

static void at91_start_clock(void)
{
if (cpu_is_at91sam9261())
clk_enable(hclk);
clk_enable(iclk);
clk_enable(fclk);
clocked = 1;
}

static void at91_stop_clock(void)
{
clk_disable(fclk);
clk_disable(iclk);
if (cpu_is_at91sam9261())
clk_disable(hclk);
clocked = 0;
}

static void at91_start_hc(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
Expand All @@ -41,9 +60,7 @@ static void at91_start_hc(struct platform_device *pdev)
/*
* Start the USB clocks.
*/
clk_enable(iclk);
clk_enable(fclk);
clocked = 1;
at91_start_clock();

/*
* The USB host controller must remain in reset.
Expand All @@ -66,9 +83,7 @@ static void at91_stop_hc(struct platform_device *pdev)
/*
* Stop the USB clocks.
*/
clk_disable(fclk);
clk_disable(iclk);
clocked = 0;
at91_stop_clock();
}


Expand Down Expand Up @@ -126,6 +141,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,

iclk = clk_get(&pdev->dev, "ohci_clk");
fclk = clk_get(&pdev->dev, "uhpck");
if (cpu_is_at91sam9261())
hclk = clk_get(&pdev->dev, "hck0");

at91_start_hc(pdev);
ohci_hcd_init(hcd_to_ohci(hcd));
Expand All @@ -137,6 +154,8 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver,
/* Error handling */
at91_stop_hc(pdev);

if (cpu_is_at91sam9261())
clk_put(hclk);
clk_put(fclk);
clk_put(iclk);

Expand Down Expand Up @@ -171,9 +190,11 @@ static int usb_hcd_at91_remove(struct usb_hcd *hcd,
iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);

if (cpu_is_at91sam9261())
clk_put(hclk);
clk_put(fclk);
clk_put(iclk);
fclk = iclk = NULL;
fclk = iclk = hclk = NULL;

dev_set_drvdata(&pdev->dev, NULL);
return 0;
Expand Down Expand Up @@ -280,9 +301,7 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg)
*/
if (at91_suspend_entering_slow_clock()) {
ohci_usb_reset (ohci);
clk_disable(fclk);
clk_disable(iclk);
clocked = 0;
at91_stop_clock();
}

return 0;
Expand All @@ -295,11 +314,8 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
if (device_may_wakeup(&pdev->dev))
disable_irq_wake(hcd->irq);

if (!clocked) {
clk_enable(iclk);
clk_enable(fclk);
clocked = 1;
}
if (!clocked)
at91_start_clock();

return 0;
}
Expand Down

0 comments on commit ed077bb

Please sign in to comment.