117cdd29dSKeshava Munegowda /** 217cdd29dSKeshava Munegowda * omap-usb-host.c - The USBHS core driver for OMAP EHCI & OHCI 317cdd29dSKeshava Munegowda * 417cdd29dSKeshava Munegowda * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com 517cdd29dSKeshava Munegowda * Author: Keshava Munegowda <keshava_mgowda@ti.com> 617cdd29dSKeshava Munegowda * 717cdd29dSKeshava Munegowda * This program is free software: you can redistribute it and/or modify 817cdd29dSKeshava Munegowda * it under the terms of the GNU General Public License version 2 of 917cdd29dSKeshava Munegowda * the License as published by the Free Software Foundation. 1017cdd29dSKeshava Munegowda * 1117cdd29dSKeshava Munegowda * This program is distributed in the hope that it will be useful, 1217cdd29dSKeshava Munegowda * but WITHOUT ANY WARRANTY; without even the implied warranty of 1317cdd29dSKeshava Munegowda * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1417cdd29dSKeshava Munegowda * GNU General Public License for more details. 1517cdd29dSKeshava Munegowda * 1617cdd29dSKeshava Munegowda * You should have received a copy of the GNU General Public License 1717cdd29dSKeshava Munegowda * along with this program. If not, see <http://www.gnu.org/licenses/>. 1817cdd29dSKeshava Munegowda */ 1917cdd29dSKeshava Munegowda #include <linux/kernel.h> 2017cdd29dSKeshava Munegowda #include <linux/types.h> 2117cdd29dSKeshava Munegowda #include <linux/slab.h> 2217cdd29dSKeshava Munegowda #include <linux/delay.h> 2317cdd29dSKeshava Munegowda #include <linux/platform_device.h> 2417cdd29dSKeshava Munegowda #include <linux/clk.h> 2517cdd29dSKeshava Munegowda #include <linux/dma-mapping.h> 2617cdd29dSKeshava Munegowda #include <linux/spinlock.h> 2717cdd29dSKeshava Munegowda #include <linux/gpio.h> 2817cdd29dSKeshava Munegowda #include <linux/regulator/consumer.h> 2917cdd29dSKeshava Munegowda #include <plat/usb.h> 3017cdd29dSKeshava Munegowda 3117cdd29dSKeshava Munegowda #define USBHS_DRIVER_NAME "usbhs-omap" 3217cdd29dSKeshava Munegowda #define OMAP_EHCI_DEVICE "ehci-omap" 3317cdd29dSKeshava Munegowda #define OMAP_OHCI_DEVICE "ohci-omap3" 3417cdd29dSKeshava Munegowda 3517cdd29dSKeshava Munegowda /* OMAP USBHOST Register addresses */ 3617cdd29dSKeshava Munegowda 3717cdd29dSKeshava Munegowda /* TLL Register Set */ 3817cdd29dSKeshava Munegowda #define OMAP_USBTLL_REVISION (0x00) 3917cdd29dSKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG (0x10) 4017cdd29dSKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8) 4117cdd29dSKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3) 4217cdd29dSKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2) 4317cdd29dSKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1) 4417cdd29dSKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0) 4517cdd29dSKeshava Munegowda 4617cdd29dSKeshava Munegowda #define OMAP_USBTLL_SYSSTATUS (0x14) 4717cdd29dSKeshava Munegowda #define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0) 4817cdd29dSKeshava Munegowda 4917cdd29dSKeshava Munegowda #define OMAP_USBTLL_IRQSTATUS (0x18) 5017cdd29dSKeshava Munegowda #define OMAP_USBTLL_IRQENABLE (0x1C) 5117cdd29dSKeshava Munegowda 5217cdd29dSKeshava Munegowda #define OMAP_TLL_SHARED_CONF (0x30) 5317cdd29dSKeshava Munegowda #define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6) 5417cdd29dSKeshava Munegowda #define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5) 5517cdd29dSKeshava Munegowda #define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2) 5617cdd29dSKeshava Munegowda #define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1) 5717cdd29dSKeshava Munegowda #define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) 5817cdd29dSKeshava Munegowda 5917cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) 6017cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT 24 6117cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) 6217cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) 6317cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) 6417cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) 6517cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS (1 << 1) 6617cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) 6717cdd29dSKeshava Munegowda 6817cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0 0x0 6917cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM 0x1 7017cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_3PIN_PHY 0x2 7117cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_4PIN_PHY 0x3 7217cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0 0x4 7317cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM 0x5 7417cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_3PIN_TLL 0x6 7517cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_4PIN_TLL 0x7 7617cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0 0xA 7717cdd29dSKeshava Munegowda #define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM 0xB 7817cdd29dSKeshava Munegowda 7917cdd29dSKeshava Munegowda #define OMAP_TLL_ULPI_FUNCTION_CTRL(num) (0x804 + 0x100 * num) 8017cdd29dSKeshava Munegowda #define OMAP_TLL_ULPI_INTERFACE_CTRL(num) (0x807 + 0x100 * num) 8117cdd29dSKeshava Munegowda #define OMAP_TLL_ULPI_OTG_CTRL(num) (0x80A + 0x100 * num) 8217cdd29dSKeshava Munegowda #define OMAP_TLL_ULPI_INT_EN_RISE(num) (0x80D + 0x100 * num) 8317cdd29dSKeshava Munegowda #define OMAP_TLL_ULPI_INT_EN_FALL(num) (0x810 + 0x100 * num) 8417cdd29dSKeshava Munegowda #define OMAP_TLL_ULPI_INT_STATUS(num) (0x813 + 0x100 * num) 8517cdd29dSKeshava Munegowda #define OMAP_TLL_ULPI_INT_LATCH(num) (0x814 + 0x100 * num) 8617cdd29dSKeshava Munegowda #define OMAP_TLL_ULPI_DEBUG(num) (0x815 + 0x100 * num) 8717cdd29dSKeshava Munegowda #define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) 8817cdd29dSKeshava Munegowda 8917cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_COUNT 3 9017cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 0) 9117cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 1) 9217cdd29dSKeshava Munegowda #define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 2) 9317cdd29dSKeshava Munegowda 9417cdd29dSKeshava Munegowda /* UHH Register Set */ 9517cdd29dSKeshava Munegowda #define OMAP_UHH_REVISION (0x00) 9617cdd29dSKeshava Munegowda #define OMAP_UHH_SYSCONFIG (0x10) 9717cdd29dSKeshava Munegowda #define OMAP_UHH_SYSCONFIG_MIDLEMODE (1 << 12) 9817cdd29dSKeshava Munegowda #define OMAP_UHH_SYSCONFIG_CACTIVITY (1 << 8) 9917cdd29dSKeshava Munegowda #define OMAP_UHH_SYSCONFIG_SIDLEMODE (1 << 3) 10017cdd29dSKeshava Munegowda #define OMAP_UHH_SYSCONFIG_ENAWAKEUP (1 << 2) 10117cdd29dSKeshava Munegowda #define OMAP_UHH_SYSCONFIG_SOFTRESET (1 << 1) 10217cdd29dSKeshava Munegowda #define OMAP_UHH_SYSCONFIG_AUTOIDLE (1 << 0) 10317cdd29dSKeshava Munegowda 10417cdd29dSKeshava Munegowda #define OMAP_UHH_SYSSTATUS (0x14) 10517cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG (0x40) 10617cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS (1 << 0) 10717cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS (1 << 0) 10817cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS (1 << 11) 10917cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS (1 << 12) 11017cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN (1 << 2) 11117cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN (1 << 3) 11217cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN (1 << 4) 11317cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN (1 << 5) 11417cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS (1 << 8) 11517cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) 11617cdd29dSKeshava Munegowda #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) 11717cdd29dSKeshava Munegowda #define OMAP4_UHH_HOSTCONFIG_APP_START_CLK (1 << 31) 11817cdd29dSKeshava Munegowda 11917cdd29dSKeshava Munegowda /* OMAP4-specific defines */ 12017cdd29dSKeshava Munegowda #define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR (3 << 2) 12117cdd29dSKeshava Munegowda #define OMAP4_UHH_SYSCONFIG_NOIDLE (1 << 2) 12217cdd29dSKeshava Munegowda #define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR (3 << 4) 12317cdd29dSKeshava Munegowda #define OMAP4_UHH_SYSCONFIG_NOSTDBY (1 << 4) 12417cdd29dSKeshava Munegowda #define OMAP4_UHH_SYSCONFIG_SOFTRESET (1 << 0) 12517cdd29dSKeshava Munegowda 12617cdd29dSKeshava Munegowda #define OMAP4_P1_MODE_CLEAR (3 << 16) 12717cdd29dSKeshava Munegowda #define OMAP4_P1_MODE_TLL (1 << 16) 12817cdd29dSKeshava Munegowda #define OMAP4_P1_MODE_HSIC (3 << 16) 12917cdd29dSKeshava Munegowda #define OMAP4_P2_MODE_CLEAR (3 << 18) 13017cdd29dSKeshava Munegowda #define OMAP4_P2_MODE_TLL (1 << 18) 13117cdd29dSKeshava Munegowda #define OMAP4_P2_MODE_HSIC (3 << 18) 13217cdd29dSKeshava Munegowda 13317cdd29dSKeshava Munegowda #define OMAP_REV2_TLL_CHANNEL_COUNT 2 13417cdd29dSKeshava Munegowda 13517cdd29dSKeshava Munegowda #define OMAP_UHH_DEBUG_CSR (0x44) 13617cdd29dSKeshava Munegowda 13717cdd29dSKeshava Munegowda /* Values of UHH_REVISION - Note: these are not given in the TRM */ 13817cdd29dSKeshava Munegowda #define OMAP_USBHS_REV1 0x00000010 /* OMAP3 */ 13917cdd29dSKeshava Munegowda #define OMAP_USBHS_REV2 0x50700100 /* OMAP4 */ 14017cdd29dSKeshava Munegowda 14117cdd29dSKeshava Munegowda #define is_omap_usbhs_rev1(x) (x->usbhs_rev == OMAP_USBHS_REV1) 14217cdd29dSKeshava Munegowda #define is_omap_usbhs_rev2(x) (x->usbhs_rev == OMAP_USBHS_REV2) 14317cdd29dSKeshava Munegowda 14417cdd29dSKeshava Munegowda #define is_ehci_phy_mode(x) (x == OMAP_EHCI_PORT_MODE_PHY) 14517cdd29dSKeshava Munegowda #define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL) 14617cdd29dSKeshava Munegowda #define is_ehci_hsic_mode(x) (x == OMAP_EHCI_PORT_MODE_HSIC) 14717cdd29dSKeshava Munegowda 14817cdd29dSKeshava Munegowda 14917cdd29dSKeshava Munegowda struct usbhs_hcd_omap { 15017cdd29dSKeshava Munegowda struct clk *usbhost_ick; 15117cdd29dSKeshava Munegowda struct clk *usbhost_hs_fck; 15217cdd29dSKeshava Munegowda struct clk *usbhost_fs_fck; 15317cdd29dSKeshava Munegowda struct clk *xclk60mhsp1_ck; 15417cdd29dSKeshava Munegowda struct clk *xclk60mhsp2_ck; 15517cdd29dSKeshava Munegowda struct clk *utmi_p1_fck; 15617cdd29dSKeshava Munegowda struct clk *usbhost_p1_fck; 15717cdd29dSKeshava Munegowda struct clk *usbtll_p1_fck; 15817cdd29dSKeshava Munegowda struct clk *utmi_p2_fck; 15917cdd29dSKeshava Munegowda struct clk *usbhost_p2_fck; 16017cdd29dSKeshava Munegowda struct clk *usbtll_p2_fck; 16117cdd29dSKeshava Munegowda struct clk *init_60m_fclk; 16217cdd29dSKeshava Munegowda struct clk *usbtll_fck; 16317cdd29dSKeshava Munegowda struct clk *usbtll_ick; 16417cdd29dSKeshava Munegowda 16517cdd29dSKeshava Munegowda void __iomem *uhh_base; 16617cdd29dSKeshava Munegowda void __iomem *tll_base; 16717cdd29dSKeshava Munegowda 16817cdd29dSKeshava Munegowda struct usbhs_omap_platform_data platdata; 16917cdd29dSKeshava Munegowda 17017cdd29dSKeshava Munegowda u32 usbhs_rev; 17117cdd29dSKeshava Munegowda spinlock_t lock; 17217cdd29dSKeshava Munegowda int count; 17317cdd29dSKeshava Munegowda }; 17417cdd29dSKeshava Munegowda /*-------------------------------------------------------------------------*/ 17517cdd29dSKeshava Munegowda 17617cdd29dSKeshava Munegowda const char usbhs_driver_name[] = USBHS_DRIVER_NAME; 17717cdd29dSKeshava Munegowda static u64 usbhs_dmamask = ~(u32)0; 17817cdd29dSKeshava Munegowda 17917cdd29dSKeshava Munegowda /*-------------------------------------------------------------------------*/ 18017cdd29dSKeshava Munegowda 18117cdd29dSKeshava Munegowda static inline void usbhs_write(void __iomem *base, u32 reg, u32 val) 18217cdd29dSKeshava Munegowda { 18317cdd29dSKeshava Munegowda __raw_writel(val, base + reg); 18417cdd29dSKeshava Munegowda } 18517cdd29dSKeshava Munegowda 18617cdd29dSKeshava Munegowda static inline u32 usbhs_read(void __iomem *base, u32 reg) 18717cdd29dSKeshava Munegowda { 18817cdd29dSKeshava Munegowda return __raw_readl(base + reg); 18917cdd29dSKeshava Munegowda } 19017cdd29dSKeshava Munegowda 19117cdd29dSKeshava Munegowda static inline void usbhs_writeb(void __iomem *base, u8 reg, u8 val) 19217cdd29dSKeshava Munegowda { 19317cdd29dSKeshava Munegowda __raw_writeb(val, base + reg); 19417cdd29dSKeshava Munegowda } 19517cdd29dSKeshava Munegowda 19617cdd29dSKeshava Munegowda static inline u8 usbhs_readb(void __iomem *base, u8 reg) 19717cdd29dSKeshava Munegowda { 19817cdd29dSKeshava Munegowda return __raw_readb(base + reg); 19917cdd29dSKeshava Munegowda } 20017cdd29dSKeshava Munegowda 20117cdd29dSKeshava Munegowda /*-------------------------------------------------------------------------*/ 20217cdd29dSKeshava Munegowda 20317cdd29dSKeshava Munegowda static struct platform_device *omap_usbhs_alloc_child(const char *name, 20417cdd29dSKeshava Munegowda struct resource *res, int num_resources, void *pdata, 20517cdd29dSKeshava Munegowda size_t pdata_size, struct device *dev) 20617cdd29dSKeshava Munegowda { 20717cdd29dSKeshava Munegowda struct platform_device *child; 20817cdd29dSKeshava Munegowda int ret; 20917cdd29dSKeshava Munegowda 21017cdd29dSKeshava Munegowda child = platform_device_alloc(name, 0); 21117cdd29dSKeshava Munegowda 21217cdd29dSKeshava Munegowda if (!child) { 21317cdd29dSKeshava Munegowda dev_err(dev, "platform_device_alloc %s failed\n", name); 21417cdd29dSKeshava Munegowda goto err_end; 21517cdd29dSKeshava Munegowda } 21617cdd29dSKeshava Munegowda 21717cdd29dSKeshava Munegowda ret = platform_device_add_resources(child, res, num_resources); 21817cdd29dSKeshava Munegowda if (ret) { 21917cdd29dSKeshava Munegowda dev_err(dev, "platform_device_add_resources failed\n"); 22017cdd29dSKeshava Munegowda goto err_alloc; 22117cdd29dSKeshava Munegowda } 22217cdd29dSKeshava Munegowda 22317cdd29dSKeshava Munegowda ret = platform_device_add_data(child, pdata, pdata_size); 22417cdd29dSKeshava Munegowda if (ret) { 22517cdd29dSKeshava Munegowda dev_err(dev, "platform_device_add_data failed\n"); 22617cdd29dSKeshava Munegowda goto err_alloc; 22717cdd29dSKeshava Munegowda } 22817cdd29dSKeshava Munegowda 22917cdd29dSKeshava Munegowda child->dev.dma_mask = &usbhs_dmamask; 23017cdd29dSKeshava Munegowda child->dev.coherent_dma_mask = 0xffffffff; 23117cdd29dSKeshava Munegowda child->dev.parent = dev; 23217cdd29dSKeshava Munegowda 23317cdd29dSKeshava Munegowda ret = platform_device_add(child); 23417cdd29dSKeshava Munegowda if (ret) { 23517cdd29dSKeshava Munegowda dev_err(dev, "platform_device_add failed\n"); 23617cdd29dSKeshava Munegowda goto err_alloc; 23717cdd29dSKeshava Munegowda } 23817cdd29dSKeshava Munegowda 23917cdd29dSKeshava Munegowda return child; 24017cdd29dSKeshava Munegowda 24117cdd29dSKeshava Munegowda err_alloc: 24217cdd29dSKeshava Munegowda platform_device_put(child); 24317cdd29dSKeshava Munegowda 24417cdd29dSKeshava Munegowda err_end: 24517cdd29dSKeshava Munegowda return NULL; 24617cdd29dSKeshava Munegowda } 24717cdd29dSKeshava Munegowda 24817cdd29dSKeshava Munegowda static int omap_usbhs_alloc_children(struct platform_device *pdev) 24917cdd29dSKeshava Munegowda { 25017cdd29dSKeshava Munegowda struct device *dev = &pdev->dev; 25117cdd29dSKeshava Munegowda struct usbhs_hcd_omap *omap; 25217cdd29dSKeshava Munegowda struct ehci_hcd_omap_platform_data *ehci_data; 25317cdd29dSKeshava Munegowda struct ohci_hcd_omap_platform_data *ohci_data; 25417cdd29dSKeshava Munegowda struct platform_device *ehci; 25517cdd29dSKeshava Munegowda struct platform_device *ohci; 25617cdd29dSKeshava Munegowda struct resource *res; 25717cdd29dSKeshava Munegowda struct resource resources[2]; 25817cdd29dSKeshava Munegowda int ret; 25917cdd29dSKeshava Munegowda 26017cdd29dSKeshava Munegowda omap = platform_get_drvdata(pdev); 26117cdd29dSKeshava Munegowda ehci_data = omap->platdata.ehci_data; 26217cdd29dSKeshava Munegowda ohci_data = omap->platdata.ohci_data; 26317cdd29dSKeshava Munegowda 26417cdd29dSKeshava Munegowda res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci"); 26517cdd29dSKeshava Munegowda if (!res) { 26617cdd29dSKeshava Munegowda dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n"); 26717cdd29dSKeshava Munegowda ret = -ENODEV; 26817cdd29dSKeshava Munegowda goto err_end; 26917cdd29dSKeshava Munegowda } 27017cdd29dSKeshava Munegowda resources[0] = *res; 27117cdd29dSKeshava Munegowda 27217cdd29dSKeshava Munegowda res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ehci-irq"); 27317cdd29dSKeshava Munegowda if (!res) { 27417cdd29dSKeshava Munegowda dev_err(dev, " EHCI get resource IORESOURCE_IRQ failed\n"); 27517cdd29dSKeshava Munegowda ret = -ENODEV; 27617cdd29dSKeshava Munegowda goto err_end; 27717cdd29dSKeshava Munegowda } 27817cdd29dSKeshava Munegowda resources[1] = *res; 27917cdd29dSKeshava Munegowda 28017cdd29dSKeshava Munegowda ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, ehci_data, 28117cdd29dSKeshava Munegowda sizeof(*ehci_data), dev); 28217cdd29dSKeshava Munegowda 28317cdd29dSKeshava Munegowda if (!ehci) { 28417cdd29dSKeshava Munegowda dev_err(dev, "omap_usbhs_alloc_child failed\n"); 28517cdd29dSKeshava Munegowda goto err_end; 28617cdd29dSKeshava Munegowda } 28717cdd29dSKeshava Munegowda 28817cdd29dSKeshava Munegowda res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci"); 28917cdd29dSKeshava Munegowda if (!res) { 29017cdd29dSKeshava Munegowda dev_err(dev, "OHCI get resource IORESOURCE_MEM failed\n"); 29117cdd29dSKeshava Munegowda ret = -ENODEV; 29217cdd29dSKeshava Munegowda goto err_ehci; 29317cdd29dSKeshava Munegowda } 29417cdd29dSKeshava Munegowda resources[0] = *res; 29517cdd29dSKeshava Munegowda 29617cdd29dSKeshava Munegowda res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ohci-irq"); 29717cdd29dSKeshava Munegowda if (!res) { 29817cdd29dSKeshava Munegowda dev_err(dev, "OHCI get resource IORESOURCE_IRQ failed\n"); 29917cdd29dSKeshava Munegowda ret = -ENODEV; 30017cdd29dSKeshava Munegowda goto err_ehci; 30117cdd29dSKeshava Munegowda } 30217cdd29dSKeshava Munegowda resources[1] = *res; 30317cdd29dSKeshava Munegowda 30417cdd29dSKeshava Munegowda ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, ohci_data, 30517cdd29dSKeshava Munegowda sizeof(*ohci_data), dev); 30617cdd29dSKeshava Munegowda if (!ohci) { 30717cdd29dSKeshava Munegowda dev_err(dev, "omap_usbhs_alloc_child failed\n"); 30817cdd29dSKeshava Munegowda goto err_ehci; 30917cdd29dSKeshava Munegowda } 31017cdd29dSKeshava Munegowda 31117cdd29dSKeshava Munegowda return 0; 31217cdd29dSKeshava Munegowda 31317cdd29dSKeshava Munegowda err_ehci: 31417cdd29dSKeshava Munegowda platform_device_put(ehci); 31517cdd29dSKeshava Munegowda 31617cdd29dSKeshava Munegowda err_end: 31717cdd29dSKeshava Munegowda return ret; 31817cdd29dSKeshava Munegowda } 31917cdd29dSKeshava Munegowda 32017cdd29dSKeshava Munegowda /** 32117cdd29dSKeshava Munegowda * usbhs_omap_probe - initialize TI-based HCDs 32217cdd29dSKeshava Munegowda * 32317cdd29dSKeshava Munegowda * Allocates basic resources for this USB host controller. 32417cdd29dSKeshava Munegowda */ 32517cdd29dSKeshava Munegowda static int __devinit usbhs_omap_probe(struct platform_device *pdev) 32617cdd29dSKeshava Munegowda { 32717cdd29dSKeshava Munegowda struct device *dev = &pdev->dev; 32817cdd29dSKeshava Munegowda struct usbhs_omap_platform_data *pdata = dev->platform_data; 32917cdd29dSKeshava Munegowda struct usbhs_hcd_omap *omap; 33017cdd29dSKeshava Munegowda struct resource *res; 33117cdd29dSKeshava Munegowda int ret = 0; 33217cdd29dSKeshava Munegowda int i; 33317cdd29dSKeshava Munegowda 33417cdd29dSKeshava Munegowda if (!pdata) { 33517cdd29dSKeshava Munegowda dev_err(dev, "Missing platfrom data\n"); 33617cdd29dSKeshava Munegowda ret = -ENOMEM; 33717cdd29dSKeshava Munegowda goto end_probe; 33817cdd29dSKeshava Munegowda } 33917cdd29dSKeshava Munegowda 34017cdd29dSKeshava Munegowda omap = kzalloc(sizeof(*omap), GFP_KERNEL); 34117cdd29dSKeshava Munegowda if (!omap) { 34217cdd29dSKeshava Munegowda dev_err(dev, "Memory allocation failed\n"); 34317cdd29dSKeshava Munegowda ret = -ENOMEM; 34417cdd29dSKeshava Munegowda goto end_probe; 34517cdd29dSKeshava Munegowda } 34617cdd29dSKeshava Munegowda 34717cdd29dSKeshava Munegowda spin_lock_init(&omap->lock); 34817cdd29dSKeshava Munegowda 34917cdd29dSKeshava Munegowda for (i = 0; i < OMAP3_HS_USB_PORTS; i++) 35017cdd29dSKeshava Munegowda omap->platdata.port_mode[i] = pdata->port_mode[i]; 35117cdd29dSKeshava Munegowda 35217cdd29dSKeshava Munegowda omap->platdata.ehci_data = pdata->ehci_data; 35317cdd29dSKeshava Munegowda omap->platdata.ohci_data = pdata->ohci_data; 35417cdd29dSKeshava Munegowda 35517cdd29dSKeshava Munegowda omap->usbhost_ick = clk_get(dev, "usbhost_ick"); 35617cdd29dSKeshava Munegowda if (IS_ERR(omap->usbhost_ick)) { 35717cdd29dSKeshava Munegowda ret = PTR_ERR(omap->usbhost_ick); 35817cdd29dSKeshava Munegowda dev_err(dev, "usbhost_ick failed error:%d\n", ret); 35917cdd29dSKeshava Munegowda goto err_end; 36017cdd29dSKeshava Munegowda } 36117cdd29dSKeshava Munegowda 36217cdd29dSKeshava Munegowda omap->usbhost_hs_fck = clk_get(dev, "hs_fck"); 36317cdd29dSKeshava Munegowda if (IS_ERR(omap->usbhost_hs_fck)) { 36417cdd29dSKeshava Munegowda ret = PTR_ERR(omap->usbhost_hs_fck); 36517cdd29dSKeshava Munegowda dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret); 36617cdd29dSKeshava Munegowda goto err_usbhost_ick; 36717cdd29dSKeshava Munegowda } 36817cdd29dSKeshava Munegowda 36917cdd29dSKeshava Munegowda omap->usbhost_fs_fck = clk_get(dev, "fs_fck"); 37017cdd29dSKeshava Munegowda if (IS_ERR(omap->usbhost_fs_fck)) { 37117cdd29dSKeshava Munegowda ret = PTR_ERR(omap->usbhost_fs_fck); 37217cdd29dSKeshava Munegowda dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret); 37317cdd29dSKeshava Munegowda goto err_usbhost_hs_fck; 37417cdd29dSKeshava Munegowda } 37517cdd29dSKeshava Munegowda 37617cdd29dSKeshava Munegowda omap->usbtll_fck = clk_get(dev, "usbtll_fck"); 37717cdd29dSKeshava Munegowda if (IS_ERR(omap->usbtll_fck)) { 37817cdd29dSKeshava Munegowda ret = PTR_ERR(omap->usbtll_fck); 37917cdd29dSKeshava Munegowda dev_err(dev, "usbtll_fck failed error:%d\n", ret); 38017cdd29dSKeshava Munegowda goto err_usbhost_fs_fck; 38117cdd29dSKeshava Munegowda } 38217cdd29dSKeshava Munegowda 38317cdd29dSKeshava Munegowda omap->usbtll_ick = clk_get(dev, "usbtll_ick"); 38417cdd29dSKeshava Munegowda if (IS_ERR(omap->usbtll_ick)) { 38517cdd29dSKeshava Munegowda ret = PTR_ERR(omap->usbtll_ick); 38617cdd29dSKeshava Munegowda dev_err(dev, "usbtll_ick failed error:%d\n", ret); 38717cdd29dSKeshava Munegowda goto err_usbtll_fck; 38817cdd29dSKeshava Munegowda } 38917cdd29dSKeshava Munegowda 39017cdd29dSKeshava Munegowda omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk"); 39117cdd29dSKeshava Munegowda if (IS_ERR(omap->utmi_p1_fck)) { 39217cdd29dSKeshava Munegowda ret = PTR_ERR(omap->utmi_p1_fck); 39317cdd29dSKeshava Munegowda dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret); 39417cdd29dSKeshava Munegowda goto err_usbtll_ick; 39517cdd29dSKeshava Munegowda } 39617cdd29dSKeshava Munegowda 39717cdd29dSKeshava Munegowda omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck"); 39817cdd29dSKeshava Munegowda if (IS_ERR(omap->xclk60mhsp1_ck)) { 39917cdd29dSKeshava Munegowda ret = PTR_ERR(omap->xclk60mhsp1_ck); 40017cdd29dSKeshava Munegowda dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret); 40117cdd29dSKeshava Munegowda goto err_utmi_p1_fck; 40217cdd29dSKeshava Munegowda } 40317cdd29dSKeshava Munegowda 40417cdd29dSKeshava Munegowda omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk"); 40517cdd29dSKeshava Munegowda if (IS_ERR(omap->utmi_p2_fck)) { 40617cdd29dSKeshava Munegowda ret = PTR_ERR(omap->utmi_p2_fck); 40717cdd29dSKeshava Munegowda dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret); 40817cdd29dSKeshava Munegowda goto err_xclk60mhsp1_ck; 40917cdd29dSKeshava Munegowda } 41017cdd29dSKeshava Munegowda 41117cdd29dSKeshava Munegowda omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck"); 41217cdd29dSKeshava Munegowda if (IS_ERR(omap->xclk60mhsp2_ck)) { 41317cdd29dSKeshava Munegowda ret = PTR_ERR(omap->xclk60mhsp2_ck); 41417cdd29dSKeshava Munegowda dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret); 41517cdd29dSKeshava Munegowda goto err_utmi_p2_fck; 41617cdd29dSKeshava Munegowda } 41717cdd29dSKeshava Munegowda 41817cdd29dSKeshava Munegowda omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk"); 41917cdd29dSKeshava Munegowda if (IS_ERR(omap->usbhost_p1_fck)) { 42017cdd29dSKeshava Munegowda ret = PTR_ERR(omap->usbhost_p1_fck); 42117cdd29dSKeshava Munegowda dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret); 42217cdd29dSKeshava Munegowda goto err_xclk60mhsp2_ck; 42317cdd29dSKeshava Munegowda } 42417cdd29dSKeshava Munegowda 42517cdd29dSKeshava Munegowda omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk"); 42617cdd29dSKeshava Munegowda if (IS_ERR(omap->usbtll_p1_fck)) { 42717cdd29dSKeshava Munegowda ret = PTR_ERR(omap->usbtll_p1_fck); 42817cdd29dSKeshava Munegowda dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret); 42917cdd29dSKeshava Munegowda goto err_usbhost_p1_fck; 43017cdd29dSKeshava Munegowda } 43117cdd29dSKeshava Munegowda 43217cdd29dSKeshava Munegowda omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk"); 43317cdd29dSKeshava Munegowda if (IS_ERR(omap->usbhost_p2_fck)) { 43417cdd29dSKeshava Munegowda ret = PTR_ERR(omap->usbhost_p2_fck); 43517cdd29dSKeshava Munegowda dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret); 43617cdd29dSKeshava Munegowda goto err_usbtll_p1_fck; 43717cdd29dSKeshava Munegowda } 43817cdd29dSKeshava Munegowda 43917cdd29dSKeshava Munegowda omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk"); 44017cdd29dSKeshava Munegowda if (IS_ERR(omap->usbtll_p2_fck)) { 44117cdd29dSKeshava Munegowda ret = PTR_ERR(omap->usbtll_p2_fck); 44217cdd29dSKeshava Munegowda dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret); 44317cdd29dSKeshava Munegowda goto err_usbhost_p2_fck; 44417cdd29dSKeshava Munegowda } 44517cdd29dSKeshava Munegowda 44617cdd29dSKeshava Munegowda omap->init_60m_fclk = clk_get(dev, "init_60m_fclk"); 44717cdd29dSKeshava Munegowda if (IS_ERR(omap->init_60m_fclk)) { 44817cdd29dSKeshava Munegowda ret = PTR_ERR(omap->init_60m_fclk); 44917cdd29dSKeshava Munegowda dev_err(dev, "init_60m_fclk failed error:%d\n", ret); 45017cdd29dSKeshava Munegowda goto err_usbtll_p2_fck; 45117cdd29dSKeshava Munegowda } 45217cdd29dSKeshava Munegowda 45317cdd29dSKeshava Munegowda res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); 45417cdd29dSKeshava Munegowda if (!res) { 45517cdd29dSKeshava Munegowda dev_err(dev, "UHH EHCI get resource failed\n"); 45617cdd29dSKeshava Munegowda ret = -ENODEV; 45717cdd29dSKeshava Munegowda goto err_init_60m_fclk; 45817cdd29dSKeshava Munegowda } 45917cdd29dSKeshava Munegowda 46017cdd29dSKeshava Munegowda omap->uhh_base = ioremap(res->start, resource_size(res)); 46117cdd29dSKeshava Munegowda if (!omap->uhh_base) { 46217cdd29dSKeshava Munegowda dev_err(dev, "UHH ioremap failed\n"); 46317cdd29dSKeshava Munegowda ret = -ENOMEM; 46417cdd29dSKeshava Munegowda goto err_init_60m_fclk; 46517cdd29dSKeshava Munegowda } 46617cdd29dSKeshava Munegowda 46717cdd29dSKeshava Munegowda res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll"); 46817cdd29dSKeshava Munegowda if (!res) { 46917cdd29dSKeshava Munegowda dev_err(dev, "UHH EHCI get resource failed\n"); 47017cdd29dSKeshava Munegowda ret = -ENODEV; 47117cdd29dSKeshava Munegowda goto err_tll; 47217cdd29dSKeshava Munegowda } 47317cdd29dSKeshava Munegowda 47417cdd29dSKeshava Munegowda omap->tll_base = ioremap(res->start, resource_size(res)); 47517cdd29dSKeshava Munegowda if (!omap->tll_base) { 47617cdd29dSKeshava Munegowda dev_err(dev, "TLL ioremap failed\n"); 47717cdd29dSKeshava Munegowda ret = -ENOMEM; 47817cdd29dSKeshava Munegowda goto err_tll; 47917cdd29dSKeshava Munegowda } 48017cdd29dSKeshava Munegowda 48117cdd29dSKeshava Munegowda platform_set_drvdata(pdev, omap); 48217cdd29dSKeshava Munegowda 48317cdd29dSKeshava Munegowda ret = omap_usbhs_alloc_children(pdev); 48417cdd29dSKeshava Munegowda if (ret) { 48517cdd29dSKeshava Munegowda dev_err(dev, "omap_usbhs_alloc_children failed\n"); 48617cdd29dSKeshava Munegowda goto err_alloc; 48717cdd29dSKeshava Munegowda } 48817cdd29dSKeshava Munegowda 48917cdd29dSKeshava Munegowda goto end_probe; 49017cdd29dSKeshava Munegowda 49117cdd29dSKeshava Munegowda err_alloc: 49217cdd29dSKeshava Munegowda iounmap(omap->tll_base); 49317cdd29dSKeshava Munegowda 49417cdd29dSKeshava Munegowda err_tll: 49517cdd29dSKeshava Munegowda iounmap(omap->uhh_base); 49617cdd29dSKeshava Munegowda 49717cdd29dSKeshava Munegowda err_init_60m_fclk: 49817cdd29dSKeshava Munegowda clk_put(omap->init_60m_fclk); 49917cdd29dSKeshava Munegowda 50017cdd29dSKeshava Munegowda err_usbtll_p2_fck: 50117cdd29dSKeshava Munegowda clk_put(omap->usbtll_p2_fck); 50217cdd29dSKeshava Munegowda 50317cdd29dSKeshava Munegowda err_usbhost_p2_fck: 50417cdd29dSKeshava Munegowda clk_put(omap->usbhost_p2_fck); 50517cdd29dSKeshava Munegowda 50617cdd29dSKeshava Munegowda err_usbtll_p1_fck: 50717cdd29dSKeshava Munegowda clk_put(omap->usbtll_p1_fck); 50817cdd29dSKeshava Munegowda 50917cdd29dSKeshava Munegowda err_usbhost_p1_fck: 51017cdd29dSKeshava Munegowda clk_put(omap->usbhost_p1_fck); 51117cdd29dSKeshava Munegowda 51217cdd29dSKeshava Munegowda err_xclk60mhsp2_ck: 51317cdd29dSKeshava Munegowda clk_put(omap->xclk60mhsp2_ck); 51417cdd29dSKeshava Munegowda 51517cdd29dSKeshava Munegowda err_utmi_p2_fck: 51617cdd29dSKeshava Munegowda clk_put(omap->utmi_p2_fck); 51717cdd29dSKeshava Munegowda 51817cdd29dSKeshava Munegowda err_xclk60mhsp1_ck: 51917cdd29dSKeshava Munegowda clk_put(omap->xclk60mhsp1_ck); 52017cdd29dSKeshava Munegowda 52117cdd29dSKeshava Munegowda err_utmi_p1_fck: 52217cdd29dSKeshava Munegowda clk_put(omap->utmi_p1_fck); 52317cdd29dSKeshava Munegowda 52417cdd29dSKeshava Munegowda err_usbtll_ick: 52517cdd29dSKeshava Munegowda clk_put(omap->usbtll_ick); 52617cdd29dSKeshava Munegowda 52717cdd29dSKeshava Munegowda err_usbtll_fck: 52817cdd29dSKeshava Munegowda clk_put(omap->usbtll_fck); 52917cdd29dSKeshava Munegowda 53017cdd29dSKeshava Munegowda err_usbhost_fs_fck: 53117cdd29dSKeshava Munegowda clk_put(omap->usbhost_fs_fck); 53217cdd29dSKeshava Munegowda 53317cdd29dSKeshava Munegowda err_usbhost_hs_fck: 53417cdd29dSKeshava Munegowda clk_put(omap->usbhost_hs_fck); 53517cdd29dSKeshava Munegowda 53617cdd29dSKeshava Munegowda err_usbhost_ick: 53717cdd29dSKeshava Munegowda clk_put(omap->usbhost_ick); 53817cdd29dSKeshava Munegowda 53917cdd29dSKeshava Munegowda err_end: 54017cdd29dSKeshava Munegowda kfree(omap); 54117cdd29dSKeshava Munegowda 54217cdd29dSKeshava Munegowda end_probe: 54317cdd29dSKeshava Munegowda return ret; 54417cdd29dSKeshava Munegowda } 54517cdd29dSKeshava Munegowda 54617cdd29dSKeshava Munegowda /** 54717cdd29dSKeshava Munegowda * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs 54817cdd29dSKeshava Munegowda * @pdev: USB Host Controller being removed 54917cdd29dSKeshava Munegowda * 55017cdd29dSKeshava Munegowda * Reverses the effect of usbhs_omap_probe(). 55117cdd29dSKeshava Munegowda */ 55217cdd29dSKeshava Munegowda static int __devexit usbhs_omap_remove(struct platform_device *pdev) 55317cdd29dSKeshava Munegowda { 55417cdd29dSKeshava Munegowda struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev); 55517cdd29dSKeshava Munegowda 55617cdd29dSKeshava Munegowda if (omap->count != 0) { 55717cdd29dSKeshava Munegowda dev_err(&pdev->dev, 55817cdd29dSKeshava Munegowda "Either EHCI or OHCI is still using usbhs core\n"); 55917cdd29dSKeshava Munegowda return -EBUSY; 56017cdd29dSKeshava Munegowda } 56117cdd29dSKeshava Munegowda 56217cdd29dSKeshava Munegowda iounmap(omap->tll_base); 56317cdd29dSKeshava Munegowda iounmap(omap->uhh_base); 56417cdd29dSKeshava Munegowda clk_put(omap->init_60m_fclk); 56517cdd29dSKeshava Munegowda clk_put(omap->usbtll_p2_fck); 56617cdd29dSKeshava Munegowda clk_put(omap->usbhost_p2_fck); 56717cdd29dSKeshava Munegowda clk_put(omap->usbtll_p1_fck); 56817cdd29dSKeshava Munegowda clk_put(omap->usbhost_p1_fck); 56917cdd29dSKeshava Munegowda clk_put(omap->xclk60mhsp2_ck); 57017cdd29dSKeshava Munegowda clk_put(omap->utmi_p2_fck); 57117cdd29dSKeshava Munegowda clk_put(omap->xclk60mhsp1_ck); 57217cdd29dSKeshava Munegowda clk_put(omap->utmi_p1_fck); 57317cdd29dSKeshava Munegowda clk_put(omap->usbtll_ick); 57417cdd29dSKeshava Munegowda clk_put(omap->usbtll_fck); 57517cdd29dSKeshava Munegowda clk_put(omap->usbhost_fs_fck); 57617cdd29dSKeshava Munegowda clk_put(omap->usbhost_hs_fck); 57717cdd29dSKeshava Munegowda clk_put(omap->usbhost_ick); 57817cdd29dSKeshava Munegowda kfree(omap); 57917cdd29dSKeshava Munegowda 58017cdd29dSKeshava Munegowda return 0; 58117cdd29dSKeshava Munegowda } 58217cdd29dSKeshava Munegowda 58317cdd29dSKeshava Munegowda static bool is_ohci_port(enum usbhs_omap_port_mode pmode) 58417cdd29dSKeshava Munegowda { 58517cdd29dSKeshava Munegowda switch (pmode) { 58617cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0: 58717cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM: 58817cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0: 58917cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM: 59017cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0: 59117cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM: 59217cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0: 59317cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM: 59417cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0: 59517cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM: 59617cdd29dSKeshava Munegowda return true; 59717cdd29dSKeshava Munegowda 59817cdd29dSKeshava Munegowda default: 59917cdd29dSKeshava Munegowda return false; 60017cdd29dSKeshava Munegowda } 60117cdd29dSKeshava Munegowda } 60217cdd29dSKeshava Munegowda 60317cdd29dSKeshava Munegowda /* 60417cdd29dSKeshava Munegowda * convert the port-mode enum to a value we can use in the FSLSMODE 60517cdd29dSKeshava Munegowda * field of USBTLL_CHANNEL_CONF 60617cdd29dSKeshava Munegowda */ 60717cdd29dSKeshava Munegowda static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode) 60817cdd29dSKeshava Munegowda { 60917cdd29dSKeshava Munegowda switch (mode) { 61017cdd29dSKeshava Munegowda case OMAP_USBHS_PORT_MODE_UNUSED: 61117cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0: 61217cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0; 61317cdd29dSKeshava Munegowda 61417cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM: 61517cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM; 61617cdd29dSKeshava Munegowda 61717cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0: 61817cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_3PIN_PHY; 61917cdd29dSKeshava Munegowda 62017cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM: 62117cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_4PIN_PHY; 62217cdd29dSKeshava Munegowda 62317cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0: 62417cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0; 62517cdd29dSKeshava Munegowda 62617cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM: 62717cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM; 62817cdd29dSKeshava Munegowda 62917cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0: 63017cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_3PIN_TLL; 63117cdd29dSKeshava Munegowda 63217cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM: 63317cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_4PIN_TLL; 63417cdd29dSKeshava Munegowda 63517cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0: 63617cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0; 63717cdd29dSKeshava Munegowda 63817cdd29dSKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM: 63917cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM; 64017cdd29dSKeshava Munegowda default: 64117cdd29dSKeshava Munegowda pr_warning("Invalid port mode, using default\n"); 64217cdd29dSKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0; 64317cdd29dSKeshava Munegowda } 64417cdd29dSKeshava Munegowda } 64517cdd29dSKeshava Munegowda 64617cdd29dSKeshava Munegowda static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count) 64717cdd29dSKeshava Munegowda { 64817cdd29dSKeshava Munegowda struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); 64917cdd29dSKeshava Munegowda struct usbhs_omap_platform_data *pdata = dev->platform_data; 65017cdd29dSKeshava Munegowda unsigned reg; 65117cdd29dSKeshava Munegowda int i; 65217cdd29dSKeshava Munegowda 65317cdd29dSKeshava Munegowda /* Program Common TLL register */ 65417cdd29dSKeshava Munegowda reg = usbhs_read(omap->tll_base, OMAP_TLL_SHARED_CONF); 65517cdd29dSKeshava Munegowda reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON 65617cdd29dSKeshava Munegowda | OMAP_TLL_SHARED_CONF_USB_DIVRATION); 65717cdd29dSKeshava Munegowda reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; 65817cdd29dSKeshava Munegowda reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN; 65917cdd29dSKeshava Munegowda 66017cdd29dSKeshava Munegowda usbhs_write(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); 66117cdd29dSKeshava Munegowda 66217cdd29dSKeshava Munegowda /* Enable channels now */ 66317cdd29dSKeshava Munegowda for (i = 0; i < tll_channel_count; i++) { 66417cdd29dSKeshava Munegowda reg = usbhs_read(omap->tll_base, 66517cdd29dSKeshava Munegowda OMAP_TLL_CHANNEL_CONF(i)); 66617cdd29dSKeshava Munegowda 66717cdd29dSKeshava Munegowda if (is_ohci_port(pdata->port_mode[i])) { 66817cdd29dSKeshava Munegowda reg |= ohci_omap3_fslsmode(pdata->port_mode[i]) 66917cdd29dSKeshava Munegowda << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT; 67017cdd29dSKeshava Munegowda reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS; 67117cdd29dSKeshava Munegowda } else if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_TLL) { 67217cdd29dSKeshava Munegowda 67317cdd29dSKeshava Munegowda /* Disable AutoIdle, BitStuffing and use SDR Mode */ 67417cdd29dSKeshava Munegowda reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE 67517cdd29dSKeshava Munegowda | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF 67617cdd29dSKeshava Munegowda | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); 67717cdd29dSKeshava Munegowda 67817cdd29dSKeshava Munegowda reg |= (1 << (i + 1)); 67917cdd29dSKeshava Munegowda } else 68017cdd29dSKeshava Munegowda continue; 68117cdd29dSKeshava Munegowda 68217cdd29dSKeshava Munegowda reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; 68317cdd29dSKeshava Munegowda usbhs_write(omap->tll_base, 68417cdd29dSKeshava Munegowda OMAP_TLL_CHANNEL_CONF(i), reg); 68517cdd29dSKeshava Munegowda 68617cdd29dSKeshava Munegowda usbhs_writeb(omap->tll_base, 68717cdd29dSKeshava Munegowda OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe); 68817cdd29dSKeshava Munegowda } 68917cdd29dSKeshava Munegowda } 69017cdd29dSKeshava Munegowda 69117cdd29dSKeshava Munegowda static int usbhs_enable(struct device *dev) 69217cdd29dSKeshava Munegowda { 69317cdd29dSKeshava Munegowda struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); 69417cdd29dSKeshava Munegowda struct usbhs_omap_platform_data *pdata = &omap->platdata; 69517cdd29dSKeshava Munegowda unsigned long flags = 0; 69617cdd29dSKeshava Munegowda int ret = 0; 69717cdd29dSKeshava Munegowda unsigned long timeout; 69817cdd29dSKeshava Munegowda unsigned reg; 69917cdd29dSKeshava Munegowda 70017cdd29dSKeshava Munegowda dev_dbg(dev, "starting TI HSUSB Controller\n"); 70117cdd29dSKeshava Munegowda if (!pdata) { 70217cdd29dSKeshava Munegowda dev_dbg(dev, "missing platform_data\n"); 70317cdd29dSKeshava Munegowda ret = -ENODEV; 70417cdd29dSKeshava Munegowda goto end_enable; 70517cdd29dSKeshava Munegowda } 70617cdd29dSKeshava Munegowda 70717cdd29dSKeshava Munegowda spin_lock_irqsave(&omap->lock, flags); 70817cdd29dSKeshava Munegowda if (omap->count > 0) 70917cdd29dSKeshava Munegowda goto end_count; 71017cdd29dSKeshava Munegowda 71117cdd29dSKeshava Munegowda clk_enable(omap->usbhost_ick); 71217cdd29dSKeshava Munegowda clk_enable(omap->usbhost_hs_fck); 71317cdd29dSKeshava Munegowda clk_enable(omap->usbhost_fs_fck); 71417cdd29dSKeshava Munegowda clk_enable(omap->usbtll_fck); 71517cdd29dSKeshava Munegowda clk_enable(omap->usbtll_ick); 71617cdd29dSKeshava Munegowda 71717cdd29dSKeshava Munegowda if (pdata->ehci_data->phy_reset) { 71817cdd29dSKeshava Munegowda if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) { 71917cdd29dSKeshava Munegowda gpio_request(pdata->ehci_data->reset_gpio_port[0], 72017cdd29dSKeshava Munegowda "USB1 PHY reset"); 72117cdd29dSKeshava Munegowda gpio_direction_output 72217cdd29dSKeshava Munegowda (pdata->ehci_data->reset_gpio_port[0], 1); 72317cdd29dSKeshava Munegowda } 72417cdd29dSKeshava Munegowda 72517cdd29dSKeshava Munegowda if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) { 72617cdd29dSKeshava Munegowda gpio_request(pdata->ehci_data->reset_gpio_port[1], 72717cdd29dSKeshava Munegowda "USB2 PHY reset"); 72817cdd29dSKeshava Munegowda gpio_direction_output 72917cdd29dSKeshava Munegowda (pdata->ehci_data->reset_gpio_port[1], 1); 73017cdd29dSKeshava Munegowda } 73117cdd29dSKeshava Munegowda 73217cdd29dSKeshava Munegowda /* Hold the PHY in RESET for enough time till DIR is high */ 73317cdd29dSKeshava Munegowda udelay(10); 73417cdd29dSKeshava Munegowda } 73517cdd29dSKeshava Munegowda 73617cdd29dSKeshava Munegowda omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION); 73717cdd29dSKeshava Munegowda dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev); 73817cdd29dSKeshava Munegowda 73917cdd29dSKeshava Munegowda /* perform TLL soft reset, and wait until reset is complete */ 74017cdd29dSKeshava Munegowda usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, 74117cdd29dSKeshava Munegowda OMAP_USBTLL_SYSCONFIG_SOFTRESET); 74217cdd29dSKeshava Munegowda 74317cdd29dSKeshava Munegowda /* Wait for TLL reset to complete */ 74417cdd29dSKeshava Munegowda timeout = jiffies + msecs_to_jiffies(1000); 74517cdd29dSKeshava Munegowda while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) 74617cdd29dSKeshava Munegowda & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { 74717cdd29dSKeshava Munegowda cpu_relax(); 74817cdd29dSKeshava Munegowda 74917cdd29dSKeshava Munegowda if (time_after(jiffies, timeout)) { 75017cdd29dSKeshava Munegowda dev_dbg(dev, "operation timed out\n"); 75117cdd29dSKeshava Munegowda ret = -EINVAL; 75217cdd29dSKeshava Munegowda goto err_tll; 75317cdd29dSKeshava Munegowda } 75417cdd29dSKeshava Munegowda } 75517cdd29dSKeshava Munegowda 75617cdd29dSKeshava Munegowda dev_dbg(dev, "TLL RESET DONE\n"); 75717cdd29dSKeshava Munegowda 75817cdd29dSKeshava Munegowda /* (1<<3) = no idle mode only for initial debugging */ 75917cdd29dSKeshava Munegowda usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, 76017cdd29dSKeshava Munegowda OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | 76117cdd29dSKeshava Munegowda OMAP_USBTLL_SYSCONFIG_SIDLEMODE | 76217cdd29dSKeshava Munegowda OMAP_USBTLL_SYSCONFIG_AUTOIDLE); 76317cdd29dSKeshava Munegowda 76417cdd29dSKeshava Munegowda /* Put UHH in NoIdle/NoStandby mode */ 76517cdd29dSKeshava Munegowda reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG); 76617cdd29dSKeshava Munegowda if (is_omap_usbhs_rev1(omap)) { 76717cdd29dSKeshava Munegowda reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP 76817cdd29dSKeshava Munegowda | OMAP_UHH_SYSCONFIG_SIDLEMODE 76917cdd29dSKeshava Munegowda | OMAP_UHH_SYSCONFIG_CACTIVITY 77017cdd29dSKeshava Munegowda | OMAP_UHH_SYSCONFIG_MIDLEMODE); 77117cdd29dSKeshava Munegowda reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; 77217cdd29dSKeshava Munegowda 77317cdd29dSKeshava Munegowda 77417cdd29dSKeshava Munegowda } else if (is_omap_usbhs_rev2(omap)) { 77517cdd29dSKeshava Munegowda reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; 77617cdd29dSKeshava Munegowda reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; 77717cdd29dSKeshava Munegowda reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; 77817cdd29dSKeshava Munegowda reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; 77917cdd29dSKeshava Munegowda } 78017cdd29dSKeshava Munegowda 78117cdd29dSKeshava Munegowda usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); 78217cdd29dSKeshava Munegowda 78317cdd29dSKeshava Munegowda reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG); 78417cdd29dSKeshava Munegowda /* setup ULPI bypass and burst configurations */ 78517cdd29dSKeshava Munegowda reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN 78617cdd29dSKeshava Munegowda | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN 78717cdd29dSKeshava Munegowda | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); 78817cdd29dSKeshava Munegowda reg |= OMAP4_UHH_HOSTCONFIG_APP_START_CLK; 78917cdd29dSKeshava Munegowda reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; 79017cdd29dSKeshava Munegowda 79117cdd29dSKeshava Munegowda if (is_omap_usbhs_rev1(omap)) { 79217cdd29dSKeshava Munegowda if (pdata->port_mode[0] == OMAP_USBHS_PORT_MODE_UNUSED) 79317cdd29dSKeshava Munegowda reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; 79417cdd29dSKeshava Munegowda if (pdata->port_mode[1] == OMAP_USBHS_PORT_MODE_UNUSED) 79517cdd29dSKeshava Munegowda reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; 79617cdd29dSKeshava Munegowda if (pdata->port_mode[2] == OMAP_USBHS_PORT_MODE_UNUSED) 79717cdd29dSKeshava Munegowda reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; 79817cdd29dSKeshava Munegowda 79917cdd29dSKeshava Munegowda /* Bypass the TLL module for PHY mode operation */ 80017cdd29dSKeshava Munegowda if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { 80117cdd29dSKeshava Munegowda dev_dbg(dev, "OMAP3 ES version <= ES2.1\n"); 80217cdd29dSKeshava Munegowda if (is_ehci_phy_mode(pdata->port_mode[0]) || 80317cdd29dSKeshava Munegowda is_ehci_phy_mode(pdata->port_mode[1]) || 80417cdd29dSKeshava Munegowda is_ehci_phy_mode(pdata->port_mode[2])) 80517cdd29dSKeshava Munegowda reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; 80617cdd29dSKeshava Munegowda else 80717cdd29dSKeshava Munegowda reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; 80817cdd29dSKeshava Munegowda } else { 80917cdd29dSKeshava Munegowda dev_dbg(dev, "OMAP3 ES version > ES2.1\n"); 81017cdd29dSKeshava Munegowda if (is_ehci_phy_mode(pdata->port_mode[0])) 81117cdd29dSKeshava Munegowda reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; 81217cdd29dSKeshava Munegowda else 81317cdd29dSKeshava Munegowda reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; 81417cdd29dSKeshava Munegowda if (is_ehci_phy_mode(pdata->port_mode[1])) 81517cdd29dSKeshava Munegowda reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; 81617cdd29dSKeshava Munegowda else 81717cdd29dSKeshava Munegowda reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; 81817cdd29dSKeshava Munegowda if (is_ehci_phy_mode(pdata->port_mode[2])) 81917cdd29dSKeshava Munegowda reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; 82017cdd29dSKeshava Munegowda else 82117cdd29dSKeshava Munegowda reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; 82217cdd29dSKeshava Munegowda } 82317cdd29dSKeshava Munegowda } else if (is_omap_usbhs_rev2(omap)) { 82417cdd29dSKeshava Munegowda /* Clear port mode fields for PHY mode*/ 82517cdd29dSKeshava Munegowda reg &= ~OMAP4_P1_MODE_CLEAR; 82617cdd29dSKeshava Munegowda reg &= ~OMAP4_P2_MODE_CLEAR; 82717cdd29dSKeshava Munegowda 82817cdd29dSKeshava Munegowda if (is_ehci_phy_mode(pdata->port_mode[0])) { 82917cdd29dSKeshava Munegowda ret = clk_set_parent(omap->utmi_p1_fck, 83017cdd29dSKeshava Munegowda omap->xclk60mhsp1_ck); 83117cdd29dSKeshava Munegowda if (ret != 0) { 83217cdd29dSKeshava Munegowda dev_err(dev, "xclk60mhsp1_ck set parent" 83317cdd29dSKeshava Munegowda "failed error:%d\n", ret); 83417cdd29dSKeshava Munegowda goto err_tll; 83517cdd29dSKeshava Munegowda } 83617cdd29dSKeshava Munegowda } else if (is_ehci_tll_mode(pdata->port_mode[0])) { 83717cdd29dSKeshava Munegowda ret = clk_set_parent(omap->utmi_p1_fck, 83817cdd29dSKeshava Munegowda omap->init_60m_fclk); 83917cdd29dSKeshava Munegowda if (ret != 0) { 84017cdd29dSKeshava Munegowda dev_err(dev, "init_60m_fclk set parent" 84117cdd29dSKeshava Munegowda "failed error:%d\n", ret); 84217cdd29dSKeshava Munegowda goto err_tll; 84317cdd29dSKeshava Munegowda } 84417cdd29dSKeshava Munegowda clk_enable(omap->usbhost_p1_fck); 84517cdd29dSKeshava Munegowda clk_enable(omap->usbtll_p1_fck); 84617cdd29dSKeshava Munegowda } 84717cdd29dSKeshava Munegowda 84817cdd29dSKeshava Munegowda if (is_ehci_phy_mode(pdata->port_mode[1])) { 84917cdd29dSKeshava Munegowda ret = clk_set_parent(omap->utmi_p2_fck, 85017cdd29dSKeshava Munegowda omap->xclk60mhsp2_ck); 85117cdd29dSKeshava Munegowda if (ret != 0) { 85217cdd29dSKeshava Munegowda dev_err(dev, "xclk60mhsp1_ck set parent" 85317cdd29dSKeshava Munegowda "failed error:%d\n", ret); 85417cdd29dSKeshava Munegowda goto err_tll; 85517cdd29dSKeshava Munegowda } 85617cdd29dSKeshava Munegowda } else if (is_ehci_tll_mode(pdata->port_mode[1])) { 85717cdd29dSKeshava Munegowda ret = clk_set_parent(omap->utmi_p2_fck, 85817cdd29dSKeshava Munegowda omap->init_60m_fclk); 85917cdd29dSKeshava Munegowda if (ret != 0) { 86017cdd29dSKeshava Munegowda dev_err(dev, "init_60m_fclk set parent" 86117cdd29dSKeshava Munegowda "failed error:%d\n", ret); 86217cdd29dSKeshava Munegowda goto err_tll; 86317cdd29dSKeshava Munegowda } 86417cdd29dSKeshava Munegowda clk_enable(omap->usbhost_p2_fck); 86517cdd29dSKeshava Munegowda clk_enable(omap->usbtll_p2_fck); 86617cdd29dSKeshava Munegowda } 86717cdd29dSKeshava Munegowda 86817cdd29dSKeshava Munegowda clk_enable(omap->utmi_p1_fck); 86917cdd29dSKeshava Munegowda clk_enable(omap->utmi_p2_fck); 87017cdd29dSKeshava Munegowda 87117cdd29dSKeshava Munegowda if (is_ehci_tll_mode(pdata->port_mode[0]) || 87217cdd29dSKeshava Munegowda (is_ohci_port(pdata->port_mode[0]))) 87317cdd29dSKeshava Munegowda reg |= OMAP4_P1_MODE_TLL; 87417cdd29dSKeshava Munegowda else if (is_ehci_hsic_mode(pdata->port_mode[0])) 87517cdd29dSKeshava Munegowda reg |= OMAP4_P1_MODE_HSIC; 87617cdd29dSKeshava Munegowda 87717cdd29dSKeshava Munegowda if (is_ehci_tll_mode(pdata->port_mode[1]) || 87817cdd29dSKeshava Munegowda (is_ohci_port(pdata->port_mode[1]))) 87917cdd29dSKeshava Munegowda reg |= OMAP4_P2_MODE_TLL; 88017cdd29dSKeshava Munegowda else if (is_ehci_hsic_mode(pdata->port_mode[1])) 88117cdd29dSKeshava Munegowda reg |= OMAP4_P2_MODE_HSIC; 88217cdd29dSKeshava Munegowda } 88317cdd29dSKeshava Munegowda 88417cdd29dSKeshava Munegowda usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); 88517cdd29dSKeshava Munegowda dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg); 88617cdd29dSKeshava Munegowda 88717cdd29dSKeshava Munegowda if (is_ehci_tll_mode(pdata->port_mode[0]) || 88817cdd29dSKeshava Munegowda is_ehci_tll_mode(pdata->port_mode[1]) || 88917cdd29dSKeshava Munegowda is_ehci_tll_mode(pdata->port_mode[2]) || 89017cdd29dSKeshava Munegowda (is_ohci_port(pdata->port_mode[0])) || 89117cdd29dSKeshava Munegowda (is_ohci_port(pdata->port_mode[1])) || 89217cdd29dSKeshava Munegowda (is_ohci_port(pdata->port_mode[2]))) { 89317cdd29dSKeshava Munegowda 89417cdd29dSKeshava Munegowda /* Enable UTMI mode for required TLL channels */ 89517cdd29dSKeshava Munegowda if (is_omap_usbhs_rev2(omap)) 89617cdd29dSKeshava Munegowda usbhs_omap_tll_init(dev, OMAP_REV2_TLL_CHANNEL_COUNT); 89717cdd29dSKeshava Munegowda else 89817cdd29dSKeshava Munegowda usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT); 89917cdd29dSKeshava Munegowda } 90017cdd29dSKeshava Munegowda 90117cdd29dSKeshava Munegowda if (pdata->ehci_data->phy_reset) { 90217cdd29dSKeshava Munegowda /* Hold the PHY in RESET for enough time till 90317cdd29dSKeshava Munegowda * PHY is settled and ready 90417cdd29dSKeshava Munegowda */ 90517cdd29dSKeshava Munegowda udelay(10); 90617cdd29dSKeshava Munegowda 90717cdd29dSKeshava Munegowda if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) 90817cdd29dSKeshava Munegowda gpio_set_value 90917cdd29dSKeshava Munegowda (pdata->ehci_data->reset_gpio_port[0], 0); 91017cdd29dSKeshava Munegowda 91117cdd29dSKeshava Munegowda if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) 91217cdd29dSKeshava Munegowda gpio_set_value 91317cdd29dSKeshava Munegowda (pdata->ehci_data->reset_gpio_port[1], 0); 91417cdd29dSKeshava Munegowda } 91517cdd29dSKeshava Munegowda 91617cdd29dSKeshava Munegowda end_count: 91717cdd29dSKeshava Munegowda omap->count++; 91817cdd29dSKeshava Munegowda goto end_enable; 91917cdd29dSKeshava Munegowda 92017cdd29dSKeshava Munegowda err_tll: 92117cdd29dSKeshava Munegowda if (pdata->ehci_data->phy_reset) { 92217cdd29dSKeshava Munegowda if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) 92317cdd29dSKeshava Munegowda gpio_free(pdata->ehci_data->reset_gpio_port[0]); 92417cdd29dSKeshava Munegowda 92517cdd29dSKeshava Munegowda if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) 92617cdd29dSKeshava Munegowda gpio_free(pdata->ehci_data->reset_gpio_port[1]); 92717cdd29dSKeshava Munegowda } 92817cdd29dSKeshava Munegowda 92917cdd29dSKeshava Munegowda clk_disable(omap->usbtll_ick); 93017cdd29dSKeshava Munegowda clk_disable(omap->usbtll_fck); 93117cdd29dSKeshava Munegowda clk_disable(omap->usbhost_fs_fck); 93217cdd29dSKeshava Munegowda clk_disable(omap->usbhost_hs_fck); 93317cdd29dSKeshava Munegowda clk_disable(omap->usbhost_ick); 93417cdd29dSKeshava Munegowda 93517cdd29dSKeshava Munegowda end_enable: 93617cdd29dSKeshava Munegowda spin_unlock_irqrestore(&omap->lock, flags); 93717cdd29dSKeshava Munegowda return ret; 93817cdd29dSKeshava Munegowda } 93917cdd29dSKeshava Munegowda 94017cdd29dSKeshava Munegowda static void usbhs_disable(struct device *dev) 94117cdd29dSKeshava Munegowda { 94217cdd29dSKeshava Munegowda struct usbhs_hcd_omap *omap = dev_get_drvdata(dev); 94317cdd29dSKeshava Munegowda struct usbhs_omap_platform_data *pdata = &omap->platdata; 94417cdd29dSKeshava Munegowda unsigned long flags = 0; 94517cdd29dSKeshava Munegowda unsigned long timeout; 94617cdd29dSKeshava Munegowda 94717cdd29dSKeshava Munegowda dev_dbg(dev, "stopping TI HSUSB Controller\n"); 94817cdd29dSKeshava Munegowda 94917cdd29dSKeshava Munegowda spin_lock_irqsave(&omap->lock, flags); 95017cdd29dSKeshava Munegowda 95117cdd29dSKeshava Munegowda if (omap->count == 0) 95217cdd29dSKeshava Munegowda goto end_disble; 95317cdd29dSKeshava Munegowda 95417cdd29dSKeshava Munegowda omap->count--; 95517cdd29dSKeshava Munegowda 95617cdd29dSKeshava Munegowda if (omap->count != 0) 95717cdd29dSKeshava Munegowda goto end_disble; 95817cdd29dSKeshava Munegowda 95917cdd29dSKeshava Munegowda /* Reset OMAP modules for insmod/rmmod to work */ 96017cdd29dSKeshava Munegowda usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, 96117cdd29dSKeshava Munegowda is_omap_usbhs_rev2(omap) ? 96217cdd29dSKeshava Munegowda OMAP4_UHH_SYSCONFIG_SOFTRESET : 96317cdd29dSKeshava Munegowda OMAP_UHH_SYSCONFIG_SOFTRESET); 96417cdd29dSKeshava Munegowda 96517cdd29dSKeshava Munegowda timeout = jiffies + msecs_to_jiffies(100); 96617cdd29dSKeshava Munegowda while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS) 96717cdd29dSKeshava Munegowda & (1 << 0))) { 96817cdd29dSKeshava Munegowda cpu_relax(); 96917cdd29dSKeshava Munegowda 97017cdd29dSKeshava Munegowda if (time_after(jiffies, timeout)) 97117cdd29dSKeshava Munegowda dev_dbg(dev, "operation timed out\n"); 97217cdd29dSKeshava Munegowda } 97317cdd29dSKeshava Munegowda 97417cdd29dSKeshava Munegowda while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS) 97517cdd29dSKeshava Munegowda & (1 << 1))) { 97617cdd29dSKeshava Munegowda cpu_relax(); 97717cdd29dSKeshava Munegowda 97817cdd29dSKeshava Munegowda if (time_after(jiffies, timeout)) 97917cdd29dSKeshava Munegowda dev_dbg(dev, "operation timed out\n"); 98017cdd29dSKeshava Munegowda } 98117cdd29dSKeshava Munegowda 98217cdd29dSKeshava Munegowda while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS) 98317cdd29dSKeshava Munegowda & (1 << 2))) { 98417cdd29dSKeshava Munegowda cpu_relax(); 98517cdd29dSKeshava Munegowda 98617cdd29dSKeshava Munegowda if (time_after(jiffies, timeout)) 98717cdd29dSKeshava Munegowda dev_dbg(dev, "operation timed out\n"); 98817cdd29dSKeshava Munegowda } 98917cdd29dSKeshava Munegowda 99017cdd29dSKeshava Munegowda usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1)); 99117cdd29dSKeshava Munegowda 99217cdd29dSKeshava Munegowda while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS) 99317cdd29dSKeshava Munegowda & (1 << 0))) { 99417cdd29dSKeshava Munegowda cpu_relax(); 99517cdd29dSKeshava Munegowda 99617cdd29dSKeshava Munegowda if (time_after(jiffies, timeout)) 99717cdd29dSKeshava Munegowda dev_dbg(dev, "operation timed out\n"); 99817cdd29dSKeshava Munegowda } 99917cdd29dSKeshava Munegowda 100017cdd29dSKeshava Munegowda if (pdata->ehci_data->phy_reset) { 100117cdd29dSKeshava Munegowda if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) 100217cdd29dSKeshava Munegowda gpio_free(pdata->ehci_data->reset_gpio_port[0]); 100317cdd29dSKeshava Munegowda 100417cdd29dSKeshava Munegowda if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) 100517cdd29dSKeshava Munegowda gpio_free(pdata->ehci_data->reset_gpio_port[1]); 100617cdd29dSKeshava Munegowda } 100717cdd29dSKeshava Munegowda 100817cdd29dSKeshava Munegowda clk_disable(omap->utmi_p2_fck); 100917cdd29dSKeshava Munegowda clk_disable(omap->utmi_p1_fck); 101017cdd29dSKeshava Munegowda clk_disable(omap->usbtll_ick); 101117cdd29dSKeshava Munegowda clk_disable(omap->usbtll_fck); 101217cdd29dSKeshava Munegowda clk_disable(omap->usbhost_fs_fck); 101317cdd29dSKeshava Munegowda clk_disable(omap->usbhost_hs_fck); 101417cdd29dSKeshava Munegowda clk_disable(omap->usbhost_ick); 101517cdd29dSKeshava Munegowda 101617cdd29dSKeshava Munegowda end_disble: 101717cdd29dSKeshava Munegowda spin_unlock_irqrestore(&omap->lock, flags); 101817cdd29dSKeshava Munegowda } 101917cdd29dSKeshava Munegowda 102017cdd29dSKeshava Munegowda int omap_usbhs_enable(struct device *dev) 102117cdd29dSKeshava Munegowda { 102217cdd29dSKeshava Munegowda return usbhs_enable(dev->parent); 102317cdd29dSKeshava Munegowda } 102417cdd29dSKeshava Munegowda EXPORT_SYMBOL_GPL(omap_usbhs_enable); 102517cdd29dSKeshava Munegowda 102617cdd29dSKeshava Munegowda void omap_usbhs_disable(struct device *dev) 102717cdd29dSKeshava Munegowda { 102817cdd29dSKeshava Munegowda usbhs_disable(dev->parent); 102917cdd29dSKeshava Munegowda } 103017cdd29dSKeshava Munegowda EXPORT_SYMBOL_GPL(omap_usbhs_disable); 103117cdd29dSKeshava Munegowda 103217cdd29dSKeshava Munegowda static struct platform_driver usbhs_omap_driver = { 103317cdd29dSKeshava Munegowda .driver = { 103417cdd29dSKeshava Munegowda .name = (char *)usbhs_driver_name, 103517cdd29dSKeshava Munegowda .owner = THIS_MODULE, 103617cdd29dSKeshava Munegowda }, 103717cdd29dSKeshava Munegowda .remove = __exit_p(usbhs_omap_remove), 103817cdd29dSKeshava Munegowda }; 103917cdd29dSKeshava Munegowda 104017cdd29dSKeshava Munegowda MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>"); 104117cdd29dSKeshava Munegowda MODULE_ALIAS("platform:" USBHS_DRIVER_NAME); 104217cdd29dSKeshava Munegowda MODULE_LICENSE("GPL v2"); 104317cdd29dSKeshava Munegowda MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI"); 104417cdd29dSKeshava Munegowda 104517cdd29dSKeshava Munegowda static int __init omap_usbhs_drvinit(void) 104617cdd29dSKeshava Munegowda { 104717cdd29dSKeshava Munegowda return platform_driver_probe(&usbhs_omap_driver, usbhs_omap_probe); 104817cdd29dSKeshava Munegowda } 104917cdd29dSKeshava Munegowda 105017cdd29dSKeshava Munegowda /* 105117cdd29dSKeshava Munegowda * init before ehci and ohci drivers; 105217cdd29dSKeshava Munegowda * The usbhs core driver should be initialized much before 105317cdd29dSKeshava Munegowda * the omap ehci and ohci probe functions are called. 105417cdd29dSKeshava Munegowda */ 105517cdd29dSKeshava Munegowda fs_initcall(omap_usbhs_drvinit); 105617cdd29dSKeshava Munegowda 105717cdd29dSKeshava Munegowda static void __exit omap_usbhs_drvexit(void) 105817cdd29dSKeshava Munegowda { 105917cdd29dSKeshava Munegowda platform_driver_unregister(&usbhs_omap_driver); 106017cdd29dSKeshava Munegowda } 106117cdd29dSKeshava Munegowda module_exit(omap_usbhs_drvexit); 1062