Skip to content

Commit

Permalink
usb: ehci: omap: add support for TLL mode on OMAP4
Browse files Browse the repository at this point in the history
The EHCI controller in OMAP4 supports a transceiver-less link
mode (TLL mode), similar to the one in OMAP3. On the OMAP4
however, there are an additional set of clocks that need
to be turned on to get this working.

Request and configure these for each port if that port
is connected in TLL mode.

Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Anand Gadiyar authored and Felipe Balbi committed Mar 1, 2011
1 parent c88ba39 commit 87ecc73
Showing 1 changed file with 134 additions and 0 deletions.
134 changes: 134 additions & 0 deletions drivers/usb/host/ehci-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,11 @@ struct ehci_hcd_omap {
struct clk *xclk60mhsp1_ck;
struct clk *xclk60mhsp2_ck;
struct clk *utmi_p1_fck;
struct clk *usbhost_p1_fck;
struct clk *usbtll_p1_fck;
struct clk *utmi_p2_fck;
struct clk *usbhost_p2_fck;
struct clk *usbtll_p2_fck;

/* FIXME the following two workarounds are
* board specific not silicon-specific so these
Expand Down Expand Up @@ -410,6 +414,50 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
}
break;
case EHCI_HCD_OMAP_MODE_TLL:
omap->xclk60mhsp1_ck = clk_get(omap->dev,
"init_60m_fclk");
if (IS_ERR(omap->xclk60mhsp1_ck)) {
ret = PTR_ERR(omap->xclk60mhsp1_ck);
dev_err(omap->dev,
"Unable to get Port1 ULPI clock\n");
}

omap->utmi_p1_fck = clk_get(omap->dev,
"utmi_p1_gfclk");
if (IS_ERR(omap->utmi_p1_fck)) {
ret = PTR_ERR(omap->utmi_p1_fck);
dev_err(omap->dev,
"Unable to get utmi_p1_fck\n");
}

ret = clk_set_parent(omap->utmi_p1_fck,
omap->xclk60mhsp1_ck);
if (ret != 0) {
dev_err(omap->dev,
"Unable to set P1 f-clock\n");
}

omap->usbhost_p1_fck = clk_get(omap->dev,
"usb_host_hs_utmi_p1_clk");
if (IS_ERR(omap->usbhost_p1_fck)) {
ret = PTR_ERR(omap->usbhost_p1_fck);
dev_err(omap->dev,
"Unable to get HOST PORT 1 clk\n");
} else {
clk_enable(omap->usbhost_p1_fck);
}

omap->usbtll_p1_fck = clk_get(omap->dev,
"usb_tll_hs_usb_ch0_clk");

if (IS_ERR(omap->usbtll_p1_fck)) {
ret = PTR_ERR(omap->usbtll_p1_fck);
dev_err(omap->dev,
"Unable to get TLL CH0 clk\n");
} else {
clk_enable(omap->usbtll_p1_fck);
}
break;
/* TODO */
default:
break;
Expand Down Expand Up @@ -440,6 +488,50 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
}
break;
case EHCI_HCD_OMAP_MODE_TLL:
omap->xclk60mhsp2_ck = clk_get(omap->dev,
"init_60m_fclk");
if (IS_ERR(omap->xclk60mhsp2_ck)) {
ret = PTR_ERR(omap->xclk60mhsp2_ck);
dev_err(omap->dev,
"Unable to get Port2 ULPI clock\n");
}

omap->utmi_p2_fck = clk_get(omap->dev,
"utmi_p2_gfclk");
if (IS_ERR(omap->utmi_p2_fck)) {
ret = PTR_ERR(omap->utmi_p2_fck);
dev_err(omap->dev,
"Unable to get utmi_p2_fck\n");
}

ret = clk_set_parent(omap->utmi_p2_fck,
omap->xclk60mhsp2_ck);
if (ret != 0) {
dev_err(omap->dev,
"Unable to set P2 f-clock\n");
}

omap->usbhost_p2_fck = clk_get(omap->dev,
"usb_host_hs_utmi_p2_clk");
if (IS_ERR(omap->usbhost_p2_fck)) {
ret = PTR_ERR(omap->usbhost_p2_fck);
dev_err(omap->dev,
"Unable to get HOST PORT 2 clk\n");
} else {
clk_enable(omap->usbhost_p2_fck);
}

omap->usbtll_p2_fck = clk_get(omap->dev,
"usb_tll_hs_usb_ch1_clk");

if (IS_ERR(omap->usbtll_p2_fck)) {
ret = PTR_ERR(omap->usbtll_p2_fck);
dev_err(omap->dev,
"Unable to get TLL CH1 clk\n");
} else {
clk_enable(omap->usbtll_p2_fck);
}
break;
/* TODO */
default:
break;
Expand Down Expand Up @@ -602,6 +694,24 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
return 0;

err_sys_status:

if (omap->usbtll_p2_fck != NULL) {
clk_disable(omap->usbtll_p2_fck);
clk_put(omap->usbtll_p2_fck);
}
if (omap->usbhost_p2_fck != NULL) {
clk_disable(omap->usbhost_p2_fck);
clk_put(omap->usbhost_p2_fck);
}
if (omap->usbtll_p1_fck != NULL) {
clk_disable(omap->usbtll_p1_fck);
clk_put(omap->usbtll_p1_fck);
}
if (omap->usbhost_p1_fck != NULL) {
clk_disable(omap->usbhost_p1_fck);
clk_put(omap->usbhost_p1_fck);
}

clk_disable(omap->utmi_p2_fck);
clk_put(omap->utmi_p2_fck);
clk_disable(omap->xclk60mhsp2_ck);
Expand Down Expand Up @@ -740,6 +850,30 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
clk_put(omap->utmi_p2_fck);
omap->utmi_p2_fck = NULL;
}

if (omap->usbtll_p2_fck != NULL) {
clk_disable(omap->usbtll_p2_fck);
clk_put(omap->usbtll_p2_fck);
omap->usbtll_p2_fck = NULL;
}

if (omap->usbhost_p2_fck != NULL) {
clk_disable(omap->usbhost_p2_fck);
clk_put(omap->usbhost_p2_fck);
omap->usbhost_p2_fck = NULL;
}

if (omap->usbtll_p1_fck != NULL) {
clk_disable(omap->usbtll_p1_fck);
clk_put(omap->usbtll_p1_fck);
omap->usbtll_p1_fck = NULL;
}

if (omap->usbhost_p1_fck != NULL) {
clk_disable(omap->usbhost_p1_fck);
clk_put(omap->usbhost_p1_fck);
omap->usbhost_p1_fck = NULL;
}
}

if (omap->phy_reset) {
Expand Down

0 comments on commit 87ecc73

Please sign in to comment.