From patchwork Thu Aug 19 19:18:07 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Munegowda, Keshava" X-Patchwork-Id: 120478 X-Patchwork-Delegate: me@felipebalbi.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o7K7IApe024548 for ; Fri, 20 Aug 2010 07:18:11 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751829Ab0HTHRm (ORCPT ); Fri, 20 Aug 2010 03:17:42 -0400 Received: from comal.ext.ti.com ([198.47.26.152]:36449 "EHLO comal.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751924Ab0HTHR2 (ORCPT ); Fri, 20 Aug 2010 03:17:28 -0400 Received: from dlep36.itg.ti.com ([157.170.170.91]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id o7K7HRAM028803 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 20 Aug 2010 02:17:27 -0500 Received: from legion.dal.design.ti.com (localhost [127.0.0.1]) by dlep36.itg.ti.com (8.13.8/8.13.8) with ESMTP id o7K7HP4w004863; Fri, 20 Aug 2010 02:17:25 -0500 (CDT) Received: from localhost (a0393220-desktop.apr.dhcp.ti.com [172.24.137.6]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id o7K7HNf00705; Fri, 20 Aug 2010 02:17:23 -0500 (CDT) From: Keshava Munegowda To: linux-usb@vger.kernel.org, linux-omap@vger.kernel.org Cc: Keshava Munegowda , Anand Gadiyar Subject: [RFC] [PATCH 2/5] usb: ohci: omap: Add OMAP4 support Date: Fri, 20 Aug 2010 00:48:07 +0530 Message-Id: <1282245490-24339-3-git-send-email-keshava_mgowda@ti.com> X-Mailer: git-send-email 1.6.0.4 In-Reply-To: <1282245490-24339-2-git-send-email-keshava_mgowda@ti.com> References: <1282245490-24339-1-git-send-email-keshava_mgowda@ti.com> <1282245490-24339-2-git-send-email-keshava_mgowda@ti.com> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 20 Aug 2010 07:18:11 +0000 (UTC) Index: linux-2.6/drivers/usb/host/ohci-omap3.c =================================================================== --- linux-2.6.orig/drivers/usb/host/ohci-omap3.c +++ linux-2.6/drivers/usb/host/ohci-omap3.c @@ -106,6 +106,31 @@ #define OMAP_UHH_DEBUG_CSR (0x44) +/* OMAP4 specific */ +#define OMAP_UHH_SYSCONFIG_IDLEMODE_RESET (~(0xC)) +#define OMAP_UHH_SYSCONFIG_FIDLEMODE_SET (0 << 2) +#define OMAP_UHH_SYSCONFIG_NIDLEMODE_SET (1 << 2) +#define OMAP_UHH_SYSCONFIG_SIDLEMODE_SET (2 << 2) +#define OMAP_UHH_SYSCONFIG_SWIDLMODE_SET (3 << 2) + +#define OMAP_UHH_SYSCONFIG_STDYMODE_RESET (~(3 << 4)) +#define OMAP_UHH_SYSCONFIG_FSTDYMODE_SET (0 << 4) +#define OMAP_UHH_SYSCONFIG_NSTDYMODE_SET (1 << 4) +#define OMAP_UHH_SYSCONFIG_SSTDYMODE_SET (2 << 4) +#define OMAP_UHH_SYSCONFIG_SWSTDMODE_SET (3 << 4) + +#define OMAP_UHH_HOST_PORTS_RESET (~(0xF << 16)) +#define OMAP_UHH_HOST_P1_SET_ULPIPHY (0 << 16) +#define OMAP_UHH_HOST_P1_SET_ULPITLL (1 << 16) +#define OMAP_UHH_HOST_P1_SET_HSIC (3 << 16) + +#define OMAP_UHH_HOST_P2_SET_ULPIPHY (0 << 18) +#define OMAP_UHH_HOST_P2_SET_ULPITLL (1 << 18) +#define OMAP_UHH_HOST_P2_SET_HSIC (3 << 18) +#define OMAP4_UHH_SYSCONFIG_SOFTRESET (1 << 0) + +#define OMAP4_TLL_CHANNEL_COUNT 2 + /*-------------------------------------------------------------------------*/ static inline void ohci_omap_writel(void __iomem *base, u32 reg, u32 val) @@ -128,8 +153,6 @@ static inline u8 ohci_omap_readb(void __ return __raw_readb(base + reg); } -/*-------------------------------------------------------------------------*/ - struct ohci_hcd_omap3 { struct ohci_hcd *ohci; struct device *dev; @@ -139,6 +162,10 @@ struct ohci_hcd_omap3 { struct clk *usbhost_fs_fck; struct clk *usbtll_fck; struct clk *usbtll_ick; + struct clk *xclk60mhsp1_ck; + struct clk *xclk60mhsp2_ck; + struct clk *utmi_p1_fck; + struct clk *utmi_p2_fck; /* port_mode: TLL/PHY, 2/3/4/6-PIN, DP-DM/DAT-SE0 */ enum ohci_omap3_port_mode port_mode[OMAP3_HS_USB_PORTS]; @@ -154,17 +181,36 @@ struct ohci_hcd_omap3 { static void ohci_omap3_clock_power(struct ohci_hcd_omap3 *omap, int on) { if (on) { - clk_enable(omap->usbtll_ick); - clk_enable(omap->usbtll_fck); - clk_enable(omap->usbhost_ick); - clk_enable(omap->usbhost_fs_fck); - clk_enable(omap->usbhost_hs_fck); + if (omap->usbtll_ick != NULL) + clk_enable(omap->usbtll_ick); + if (omap->usbtll_fck != NULL) + clk_enable(omap->usbtll_fck); + if (omap->usbhost_ick != NULL) + clk_enable(omap->usbhost_ick); + if (omap->usbhost_fs_fck != NULL) + clk_enable(omap->usbhost_fs_fck); + if (omap->usbhost_hs_fck != NULL) + clk_enable(omap->usbhost_hs_fck); + if (omap->utmi_p1_fck != NULL) + clk_enable(omap->utmi_p1_fck); + if (omap->utmi_p2_fck != NULL) + clk_enable(omap->utmi_p2_fck); + } else { - clk_disable(omap->usbhost_hs_fck); - clk_disable(omap->usbhost_fs_fck); - clk_disable(omap->usbhost_ick); - clk_disable(omap->usbtll_fck); - clk_disable(omap->usbtll_ick); + if (omap->usbtll_ick != NULL) + clk_disable(omap->usbtll_ick); + if (omap->usbtll_fck != NULL) + clk_disable(omap->usbtll_fck); + if (omap->usbhost_ick != NULL) + clk_disable(omap->usbhost_ick); + if (omap->usbhost_fs_fck != NULL) + clk_disable(omap->usbhost_fs_fck); + if (omap->usbhost_hs_fck != NULL) + clk_disable(omap->usbhost_hs_fck); + if (omap->utmi_p1_fck != NULL) + clk_disable(omap->utmi_p1_fck); + if (omap->utmi_p2_fck != NULL) + clk_disable(omap->utmi_p2_fck); } } @@ -291,14 +337,118 @@ static int omap3_start_ohci(struct ohci_ dev_dbg(omap->dev, "starting TI OHCI USB Controller\n"); if (cpu_is_omap44xx()) { - /* TODO */ + /* Enable clocks for OMAP4 USBHOST */ + omap->usbhost_fs_fck = clk_get(omap->dev, "usb_host_fs_fck"); + if (IS_ERR(omap->usbhost_fs_fck)) { + ret = PTR_ERR(omap->usbhost_fs_fck); + goto err_host; + } + + omap->utmi_p1_fck = clk_get(omap->dev, "utmi_p1_gfclk_ck"); + if (IS_ERR(omap->utmi_p1_fck)) { + ret = PTR_ERR(omap->utmi_p1_fck); + goto err_utmi_p1_ck; + } + + omap->utmi_p2_fck = clk_get(omap->dev, "utmi_p2_gfclk_ck"); + if (IS_ERR(omap->utmi_p2_fck)) { + ret = PTR_ERR(omap->utmi_p2_fck); + goto err_utmi_p2_ck; + } + + omap->usbtll_ick = clk_get(omap->dev, "usb_tll_ick"); + if (IS_ERR(omap->usbtll_ick)) { + ret = PTR_ERR(omap->usbtll_ick); + goto err_44tll_ick; + } + + omap->usbhost_hs_fck = NULL; + omap->xclk60mhsp2_ck = NULL; + omap->xclk60mhsp1_ck = NULL; + omap->usbhost_ick = NULL; + + /* Now enable all the clocks in the correct order */ + ohci_omap3_clock_power(omap, 1); + + /* perform TLL soft reset, and wait + * until reset is complete */ + ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, + OMAP_USBTLL_SYSCONFIG_SOFTRESET); + + /* Wait for TLL reset to complete */ + while (!(ohci_omap_readl(omap->tll_base, + OMAP_USBTLL_SYSSTATUS) & + OMAP_USBTLL_SYSSTATUS_RESETDONE)) { + cpu_relax(); + + if (time_after(jiffies, timeout)) { + dev_dbg(omap->dev, "operation timed out\n"); + ret = -EINVAL; + goto err_44sys_status; + } + } + + dev_dbg(omap->dev, "TLL RESET DONE\n"); + + /* Put UHH in NoIdle/NoStandby mode */ + reg = ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); + reg &= OMAP_UHH_SYSCONFIG_IDLEMODE_RESET; + reg |= OMAP_UHH_SYSCONFIG_NIDLEMODE_SET; + + reg &= OMAP_UHH_SYSCONFIG_STDYMODE_RESET; + reg |= OMAP_UHH_SYSCONFIG_NSTDYMODE_SET; + + ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); + + reg = ohci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); + + /* setup ULPI bypass and burst configurations */ + reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | + OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | + OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); + reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; + + /* set p1 & p2 modes */ + /* OHCI has to go through USBTLL */ + reg &= OMAP_UHH_HOST_PORTS_RESET; + if (omap->port_mode[0] != OMAP_OHCI_PORT_MODE_UNUSED) + reg |= OMAP_UHH_HOST_P1_SET_ULPITLL; + if (omap->port_mode[1] != OMAP_OHCI_PORT_MODE_UNUSED) + reg |= OMAP_UHH_HOST_P2_SET_ULPITLL; + + ohci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); + dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); + + /* (1<<3) = no idle mode only for initial debugging */ + ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, + OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | + OMAP_USBTLL_SYSCONFIG_SIDLEMODE | + OMAP_USBTLL_SYSCONFIG_CACTIVITY); + + ohci_omap3_tll_config(omap, OMAP4_TLL_CHANNEL_COUNT); + + return 0; + +err_44sys_status: + ohci_omap3_clock_power(omap, 0); + clk_put(omap->usbtll_ick); + +err_44tll_ick: + clk_put(omap->utmi_p2_fck); + +err_utmi_p2_ck: + clk_put(omap->utmi_p1_fck); + +err_utmi_p1_ck: + clk_put(omap->usbhost_fs_fck); + } else { /* Get all the clock handles we need */ omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick"); if (IS_ERR(omap->usbhost_ick)) { dev_err(omap->dev, "could not get usbhost_ick\n"); ret = PTR_ERR(omap->usbhost_ick); - goto err_host_ick; + goto err_host; } omap->usbhost_hs_fck = clk_get(omap->dev, "usbhost_120m_fck"); @@ -445,10 +595,10 @@ err_host_fs_fck: err_host_hs_fck: clk_put(omap->usbhost_ick); - -err_host_ick: - return ret; } + +err_host: + return ret; } static void omap3_stop_ohci(struct ohci_hcd_omap3 *omap, struct usb_hcd *hcd) @@ -458,8 +608,13 @@ static void omap3_stop_ohci(struct ohci_ dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n"); /* Reset USBHOST for insmod/rmmod to work */ - ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, - OMAP_UHH_SYSCONFIG_SOFTRESET); + if (cpu_is_omap44xx()) + ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, + OMAP4_UHH_SYSCONFIG_SOFTRESET); + else + ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, + OMAP_UHH_SYSCONFIG_SOFTRESET); + while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) & OMAP_UHH_SYSSTATUS_UHHRESETDONE)) { cpu_relax(); @@ -501,6 +656,26 @@ static void omap3_stop_ohci(struct ohci_ omap->usbtll_fck = NULL; } + if (omap->utmi_p2_fck != NULL) { + clk_put(omap->utmi_p2_fck); + omap->utmi_p2_fck = NULL; + } + + if (omap->utmi_p1_fck != NULL) { + clk_put(omap->utmi_p1_fck); + omap->utmi_p1_fck = NULL; + } + + if (omap->xclk60mhsp2_ck != NULL) { + clk_put(omap->xclk60mhsp2_ck); + omap->xclk60mhsp2_ck = NULL; + } + + if (omap->xclk60mhsp1_ck != NULL) { + clk_put(omap->xclk60mhsp1_ck); + omap->xclk60mhsp1_ck = NULL; + } + if (omap->usbhost_ick != NULL) { clk_put(omap->usbhost_ick); omap->usbhost_ick = NULL;