Skip to content

Commit

Permalink
mx51: fix usb clock support
Browse files Browse the repository at this point in the history
Current code doesn't really enable the usb clocks so if they're disabled
when booting linux, the kernel/machine will hang as soon as someone is trying
to read a usb register

Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
  • Loading branch information
Arnaud Patard (Rtp) authored and Sascha Hauer committed Jan 3, 2011
1 parent 8305ed7 commit 711669e
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 14 deletions.
45 changes: 43 additions & 2 deletions arch/arm/mach-mx5/clock-mx51-mx53.c
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,41 @@ static struct clk usboh3_clk = {
.parent = &pll2_sw_clk,
.get_rate = clk_usboh3_get_rate,
.set_parent = clk_usboh3_set_parent,
.enable = _clk_ccgr_enable,
.disable = _clk_ccgr_disable,
.enable_reg = MXC_CCM_CCGR2,
.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
};

static struct clk usb_ahb_clk = {
.parent = &ipg_clk,
.enable = _clk_ccgr_enable,
.disable = _clk_ccgr_disable,
.enable_reg = MXC_CCM_CCGR2,
.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
};

static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
{
u32 reg;

reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;

if (parent == &pll3_sw_clk)
reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;

__raw_writel(reg, MXC_CCM_CSCMR1);

return 0;
}

static struct clk usb_phy1_clk = {
.parent = &pll3_sw_clk,
.set_parent = clk_usb_phy1_set_parent,
.enable = _clk_ccgr_enable,
.enable_reg = MXC_CCM_CCGR2,
.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
.disable = _clk_ccgr_disable,
};

/* eCSPI */
Expand Down Expand Up @@ -1094,9 +1129,12 @@ static struct clk_lookup mx51_lookups[] = {
_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
_REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
_REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", ahb_clk)
_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
_REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
_REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", ahb_clk)
_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
_REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
_REGISTER_CLOCK("imx-keypad.0", NULL, kpp_clk)
Expand Down Expand Up @@ -1170,6 +1208,9 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
mx51_revision();
clk_disable(&iim_clk);

/* move usb_phy_clk to 24MHz */
clk_set_parent(&usb_phy1_clk, &osc_clk);

/* set the usboh3_clk parent to pll2_sw_clk */
clk_set_parent(&usboh3_clk, &pll2_sw_clk);

Expand Down
44 changes: 32 additions & 12 deletions drivers/usb/host/ehci-mxc.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#define ULPI_VIEWPORT_OFFSET 0x170

struct ehci_mxc_priv {
struct clk *usbclk, *ahbclk;
struct clk *usbclk, *ahbclk, *phy1clk;
struct usb_hcd *hcd;
};

Expand Down Expand Up @@ -168,17 +168,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
goto err_ioremap;
}

/* call platform specific init function */
if (pdata->init) {
ret = pdata->init(pdev);
if (ret) {
dev_err(dev, "platform init failed\n");
goto err_init;
}
/* platforms need some time to settle changed IO settings */
mdelay(10);
}

/* enable clocks */
priv->usbclk = clk_get(dev, "usb");
if (IS_ERR(priv->usbclk)) {
Expand All @@ -196,6 +185,28 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
clk_enable(priv->ahbclk);
}

/* "dr" device has its own clock */
if (pdev->id == 0) {
priv->phy1clk = clk_get(dev, "usb_phy1");
if (IS_ERR(priv->phy1clk)) {
ret = PTR_ERR(priv->phy1clk);
goto err_clk_phy;
}
clk_enable(priv->phy1clk);
}


/* call platform specific init function */
if (pdata->init) {
ret = pdata->init(pdev);
if (ret) {
dev_err(dev, "platform init failed\n");
goto err_init;
}
/* platforms need some time to settle changed IO settings */
mdelay(10);
}

/* setup specific usb hw */
ret = mxc_initialize_usb_hw(pdev->id, pdata->flags);
if (ret < 0)
Expand Down Expand Up @@ -230,6 +241,11 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
if (pdata && pdata->exit)
pdata->exit(pdev);
err_init:
if (priv->phy1clk) {
clk_disable(priv->phy1clk);
clk_put(priv->phy1clk);
}
err_clk_phy:
if (priv->ahbclk) {
clk_disable(priv->ahbclk);
clk_put(priv->ahbclk);
Expand Down Expand Up @@ -273,6 +289,10 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
clk_disable(priv->ahbclk);
clk_put(priv->ahbclk);
}
if (priv->phy1clk) {
clk_disable(priv->phy1clk);
clk_put(priv->phy1clk);
}

kfree(priv);

Expand Down

0 comments on commit 711669e

Please sign in to comment.