116fa3dc7SKeshava Munegowda /** 216fa3dc7SKeshava Munegowda * omap-usb-tll.c - The USB TLL driver for OMAP EHCI & OHCI 316fa3dc7SKeshava Munegowda * 416fa3dc7SKeshava Munegowda * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com 516fa3dc7SKeshava Munegowda * Author: Keshava Munegowda <keshava_mgowda@ti.com> 616fa3dc7SKeshava Munegowda * 716fa3dc7SKeshava Munegowda * This program is free software: you can redistribute it and/or modify 816fa3dc7SKeshava Munegowda * it under the terms of the GNU General Public License version 2 of 916fa3dc7SKeshava Munegowda * the License as published by the Free Software Foundation. 1016fa3dc7SKeshava Munegowda * 1116fa3dc7SKeshava Munegowda * This program is distributed in the hope that it will be useful, 1216fa3dc7SKeshava Munegowda * but WITHOUT ANY WARRANTY; without even the implied warranty of 1316fa3dc7SKeshava Munegowda * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1416fa3dc7SKeshava Munegowda * GNU General Public License for more details. 1516fa3dc7SKeshava Munegowda * 1616fa3dc7SKeshava Munegowda * You should have received a copy of the GNU General Public License 1716fa3dc7SKeshava Munegowda * along with this program. If not, see <http://www.gnu.org/licenses/>. 1816fa3dc7SKeshava Munegowda */ 1916fa3dc7SKeshava Munegowda #include <linux/kernel.h> 2016fa3dc7SKeshava Munegowda #include <linux/module.h> 2116fa3dc7SKeshava Munegowda #include <linux/types.h> 2216fa3dc7SKeshava Munegowda #include <linux/slab.h> 2316fa3dc7SKeshava Munegowda #include <linux/spinlock.h> 2416fa3dc7SKeshava Munegowda #include <linux/platform_device.h> 2516fa3dc7SKeshava Munegowda #include <linux/clk.h> 2616fa3dc7SKeshava Munegowda #include <linux/io.h> 2716fa3dc7SKeshava Munegowda #include <linux/err.h> 2816fa3dc7SKeshava Munegowda #include <plat/usb.h> 2916fa3dc7SKeshava Munegowda #include <linux/pm_runtime.h> 3016fa3dc7SKeshava Munegowda 3116fa3dc7SKeshava Munegowda #define USBTLL_DRIVER_NAME "usbhs_tll" 3216fa3dc7SKeshava Munegowda 3316fa3dc7SKeshava Munegowda /* TLL Register Set */ 3416fa3dc7SKeshava Munegowda #define OMAP_USBTLL_REVISION (0x00) 3516fa3dc7SKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG (0x10) 3616fa3dc7SKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8) 3716fa3dc7SKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3) 3816fa3dc7SKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2) 3916fa3dc7SKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1) 4016fa3dc7SKeshava Munegowda #define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0) 4116fa3dc7SKeshava Munegowda 4216fa3dc7SKeshava Munegowda #define OMAP_USBTLL_SYSSTATUS (0x14) 4316fa3dc7SKeshava Munegowda #define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0) 4416fa3dc7SKeshava Munegowda 4516fa3dc7SKeshava Munegowda #define OMAP_USBTLL_IRQSTATUS (0x18) 4616fa3dc7SKeshava Munegowda #define OMAP_USBTLL_IRQENABLE (0x1C) 4716fa3dc7SKeshava Munegowda 4816fa3dc7SKeshava Munegowda #define OMAP_TLL_SHARED_CONF (0x30) 4916fa3dc7SKeshava Munegowda #define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6) 5016fa3dc7SKeshava Munegowda #define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5) 5116fa3dc7SKeshava Munegowda #define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2) 5216fa3dc7SKeshava Munegowda #define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1) 5316fa3dc7SKeshava Munegowda #define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) 5416fa3dc7SKeshava Munegowda 5516fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) 5616fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT 24 5716fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) 5816fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) 5916fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) 6016fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) 6116fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS (1 << 1) 6216fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) 6316fa3dc7SKeshava Munegowda 6416fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0 0x0 6516fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM 0x1 6616fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_3PIN_PHY 0x2 6716fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_4PIN_PHY 0x3 6816fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0 0x4 6916fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM 0x5 7016fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_3PIN_TLL 0x6 7116fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_4PIN_TLL 0x7 7216fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0 0xA 7316fa3dc7SKeshava Munegowda #define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM 0xB 7416fa3dc7SKeshava Munegowda 7516fa3dc7SKeshava Munegowda #define OMAP_TLL_ULPI_FUNCTION_CTRL(num) (0x804 + 0x100 * num) 7616fa3dc7SKeshava Munegowda #define OMAP_TLL_ULPI_INTERFACE_CTRL(num) (0x807 + 0x100 * num) 7716fa3dc7SKeshava Munegowda #define OMAP_TLL_ULPI_OTG_CTRL(num) (0x80A + 0x100 * num) 7816fa3dc7SKeshava Munegowda #define OMAP_TLL_ULPI_INT_EN_RISE(num) (0x80D + 0x100 * num) 7916fa3dc7SKeshava Munegowda #define OMAP_TLL_ULPI_INT_EN_FALL(num) (0x810 + 0x100 * num) 8016fa3dc7SKeshava Munegowda #define OMAP_TLL_ULPI_INT_STATUS(num) (0x813 + 0x100 * num) 8116fa3dc7SKeshava Munegowda #define OMAP_TLL_ULPI_INT_LATCH(num) (0x814 + 0x100 * num) 8216fa3dc7SKeshava Munegowda #define OMAP_TLL_ULPI_DEBUG(num) (0x815 + 0x100 * num) 8316fa3dc7SKeshava Munegowda #define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) 8416fa3dc7SKeshava Munegowda 8516fa3dc7SKeshava Munegowda #define OMAP_REV2_TLL_CHANNEL_COUNT 2 8616fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_COUNT 3 8716fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 0) 8816fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 1) 8916fa3dc7SKeshava Munegowda #define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 2) 9016fa3dc7SKeshava Munegowda 9116fa3dc7SKeshava Munegowda /* Values of USBTLL_REVISION - Note: these are not given in the TRM */ 9216fa3dc7SKeshava Munegowda #define OMAP_USBTLL_REV1 0x00000015 /* OMAP3 */ 9316fa3dc7SKeshava Munegowda #define OMAP_USBTLL_REV2 0x00000018 /* OMAP 3630 */ 9416fa3dc7SKeshava Munegowda #define OMAP_USBTLL_REV3 0x00000004 /* OMAP4 */ 9516fa3dc7SKeshava Munegowda 9616fa3dc7SKeshava Munegowda #define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL) 9716fa3dc7SKeshava Munegowda 9816fa3dc7SKeshava Munegowda struct usbtll_omap { 9916fa3dc7SKeshava Munegowda struct clk *usbtll_p1_fck; 10016fa3dc7SKeshava Munegowda struct clk *usbtll_p2_fck; 10116fa3dc7SKeshava Munegowda struct usbtll_omap_platform_data platdata; 10216fa3dc7SKeshava Munegowda /* secure the register updates */ 10316fa3dc7SKeshava Munegowda spinlock_t lock; 10416fa3dc7SKeshava Munegowda }; 10516fa3dc7SKeshava Munegowda 10616fa3dc7SKeshava Munegowda /*-------------------------------------------------------------------------*/ 10716fa3dc7SKeshava Munegowda 10816fa3dc7SKeshava Munegowda const char usbtll_driver_name[] = USBTLL_DRIVER_NAME; 10916fa3dc7SKeshava Munegowda struct platform_device *tll_pdev; 11016fa3dc7SKeshava Munegowda 11116fa3dc7SKeshava Munegowda /*-------------------------------------------------------------------------*/ 11216fa3dc7SKeshava Munegowda 11316fa3dc7SKeshava Munegowda static inline void usbtll_write(void __iomem *base, u32 reg, u32 val) 11416fa3dc7SKeshava Munegowda { 11516fa3dc7SKeshava Munegowda __raw_writel(val, base + reg); 11616fa3dc7SKeshava Munegowda } 11716fa3dc7SKeshava Munegowda 11816fa3dc7SKeshava Munegowda static inline u32 usbtll_read(void __iomem *base, u32 reg) 11916fa3dc7SKeshava Munegowda { 12016fa3dc7SKeshava Munegowda return __raw_readl(base + reg); 12116fa3dc7SKeshava Munegowda } 12216fa3dc7SKeshava Munegowda 12316fa3dc7SKeshava Munegowda static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val) 12416fa3dc7SKeshava Munegowda { 12516fa3dc7SKeshava Munegowda __raw_writeb(val, base + reg); 12616fa3dc7SKeshava Munegowda } 12716fa3dc7SKeshava Munegowda 12816fa3dc7SKeshava Munegowda static inline u8 usbtll_readb(void __iomem *base, u8 reg) 12916fa3dc7SKeshava Munegowda { 13016fa3dc7SKeshava Munegowda return __raw_readb(base + reg); 13116fa3dc7SKeshava Munegowda } 13216fa3dc7SKeshava Munegowda 13316fa3dc7SKeshava Munegowda /*-------------------------------------------------------------------------*/ 13416fa3dc7SKeshava Munegowda 13516fa3dc7SKeshava Munegowda static bool is_ohci_port(enum usbhs_omap_port_mode pmode) 13616fa3dc7SKeshava Munegowda { 13716fa3dc7SKeshava Munegowda switch (pmode) { 13816fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0: 13916fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM: 14016fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0: 14116fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM: 14216fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0: 14316fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM: 14416fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0: 14516fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM: 14616fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0: 14716fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM: 14816fa3dc7SKeshava Munegowda return true; 14916fa3dc7SKeshava Munegowda 15016fa3dc7SKeshava Munegowda default: 15116fa3dc7SKeshava Munegowda return false; 15216fa3dc7SKeshava Munegowda } 15316fa3dc7SKeshava Munegowda } 15416fa3dc7SKeshava Munegowda 15516fa3dc7SKeshava Munegowda /* 15616fa3dc7SKeshava Munegowda * convert the port-mode enum to a value we can use in the FSLSMODE 15716fa3dc7SKeshava Munegowda * field of USBTLL_CHANNEL_CONF 15816fa3dc7SKeshava Munegowda */ 15916fa3dc7SKeshava Munegowda static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode) 16016fa3dc7SKeshava Munegowda { 16116fa3dc7SKeshava Munegowda switch (mode) { 16216fa3dc7SKeshava Munegowda case OMAP_USBHS_PORT_MODE_UNUSED: 16316fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0: 16416fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0; 16516fa3dc7SKeshava Munegowda 16616fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM: 16716fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM; 16816fa3dc7SKeshava Munegowda 16916fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0: 17016fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_3PIN_PHY; 17116fa3dc7SKeshava Munegowda 17216fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM: 17316fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_4PIN_PHY; 17416fa3dc7SKeshava Munegowda 17516fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0: 17616fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0; 17716fa3dc7SKeshava Munegowda 17816fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM: 17916fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM; 18016fa3dc7SKeshava Munegowda 18116fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0: 18216fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_3PIN_TLL; 18316fa3dc7SKeshava Munegowda 18416fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM: 18516fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_4PIN_TLL; 18616fa3dc7SKeshava Munegowda 18716fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0: 18816fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0; 18916fa3dc7SKeshava Munegowda 19016fa3dc7SKeshava Munegowda case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM: 19116fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM; 19216fa3dc7SKeshava Munegowda default: 19316fa3dc7SKeshava Munegowda pr_warn("Invalid port mode, using default\n"); 19416fa3dc7SKeshava Munegowda return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0; 19516fa3dc7SKeshava Munegowda } 19616fa3dc7SKeshava Munegowda } 19716fa3dc7SKeshava Munegowda 19816fa3dc7SKeshava Munegowda /** 19916fa3dc7SKeshava Munegowda * usbtll_omap_probe - initialize TI-based HCDs 20016fa3dc7SKeshava Munegowda * 20116fa3dc7SKeshava Munegowda * Allocates basic resources for this USB host controller. 20216fa3dc7SKeshava Munegowda */ 20316fa3dc7SKeshava Munegowda static int __devinit usbtll_omap_probe(struct platform_device *pdev) 20416fa3dc7SKeshava Munegowda { 20516fa3dc7SKeshava Munegowda struct device *dev = &pdev->dev; 20616fa3dc7SKeshava Munegowda struct usbtll_omap_platform_data *pdata = dev->platform_data; 20716fa3dc7SKeshava Munegowda void __iomem *base; 20816fa3dc7SKeshava Munegowda struct resource *res; 20916fa3dc7SKeshava Munegowda struct usbtll_omap *tll; 21016fa3dc7SKeshava Munegowda unsigned reg; 21116fa3dc7SKeshava Munegowda unsigned long flags; 21216fa3dc7SKeshava Munegowda int ret = 0; 21316fa3dc7SKeshava Munegowda int i, ver, count; 21416fa3dc7SKeshava Munegowda 21516fa3dc7SKeshava Munegowda dev_dbg(dev, "starting TI HSUSB TLL Controller\n"); 21616fa3dc7SKeshava Munegowda 21716fa3dc7SKeshava Munegowda tll = kzalloc(sizeof(struct usbtll_omap), GFP_KERNEL); 21816fa3dc7SKeshava Munegowda if (!tll) { 21916fa3dc7SKeshava Munegowda dev_err(dev, "Memory allocation failed\n"); 22016fa3dc7SKeshava Munegowda ret = -ENOMEM; 22116fa3dc7SKeshava Munegowda goto end; 22216fa3dc7SKeshava Munegowda } 22316fa3dc7SKeshava Munegowda 22416fa3dc7SKeshava Munegowda spin_lock_init(&tll->lock); 22516fa3dc7SKeshava Munegowda 22616fa3dc7SKeshava Munegowda for (i = 0; i < OMAP3_HS_USB_PORTS; i++) 22716fa3dc7SKeshava Munegowda tll->platdata.port_mode[i] = pdata->port_mode[i]; 22816fa3dc7SKeshava Munegowda 22916fa3dc7SKeshava Munegowda tll->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk"); 23016fa3dc7SKeshava Munegowda if (IS_ERR(tll->usbtll_p1_fck)) { 23116fa3dc7SKeshava Munegowda ret = PTR_ERR(tll->usbtll_p1_fck); 23216fa3dc7SKeshava Munegowda dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret); 23316fa3dc7SKeshava Munegowda goto err_tll; 23416fa3dc7SKeshava Munegowda } 23516fa3dc7SKeshava Munegowda 23616fa3dc7SKeshava Munegowda tll->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk"); 23716fa3dc7SKeshava Munegowda if (IS_ERR(tll->usbtll_p2_fck)) { 23816fa3dc7SKeshava Munegowda ret = PTR_ERR(tll->usbtll_p2_fck); 23916fa3dc7SKeshava Munegowda dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret); 24016fa3dc7SKeshava Munegowda goto err_usbtll_p1_fck; 24116fa3dc7SKeshava Munegowda } 24216fa3dc7SKeshava Munegowda 24316fa3dc7SKeshava Munegowda res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 24416fa3dc7SKeshava Munegowda if (!res) { 24516fa3dc7SKeshava Munegowda dev_err(dev, "usb tll get resource failed\n"); 24616fa3dc7SKeshava Munegowda ret = -ENODEV; 24716fa3dc7SKeshava Munegowda goto err_usbtll_p2_fck; 24816fa3dc7SKeshava Munegowda } 24916fa3dc7SKeshava Munegowda 25016fa3dc7SKeshava Munegowda base = ioremap(res->start, resource_size(res)); 25116fa3dc7SKeshava Munegowda if (!base) { 25216fa3dc7SKeshava Munegowda dev_err(dev, "TLL ioremap failed\n"); 25316fa3dc7SKeshava Munegowda ret = -ENOMEM; 25416fa3dc7SKeshava Munegowda goto err_usbtll_p2_fck; 25516fa3dc7SKeshava Munegowda } 25616fa3dc7SKeshava Munegowda 25716fa3dc7SKeshava Munegowda platform_set_drvdata(pdev, tll); 25816fa3dc7SKeshava Munegowda pm_runtime_enable(dev); 25916fa3dc7SKeshava Munegowda pm_runtime_get_sync(dev); 26016fa3dc7SKeshava Munegowda 26116fa3dc7SKeshava Munegowda spin_lock_irqsave(&tll->lock, flags); 26216fa3dc7SKeshava Munegowda 26316fa3dc7SKeshava Munegowda ver = usbtll_read(base, OMAP_USBTLL_REVISION); 26416fa3dc7SKeshava Munegowda switch (ver) { 26516fa3dc7SKeshava Munegowda case OMAP_USBTLL_REV1: 26616fa3dc7SKeshava Munegowda case OMAP_USBTLL_REV2: 26716fa3dc7SKeshava Munegowda count = OMAP_TLL_CHANNEL_COUNT; 26816fa3dc7SKeshava Munegowda break; 26916fa3dc7SKeshava Munegowda case OMAP_USBTLL_REV3: 27016fa3dc7SKeshava Munegowda count = OMAP_REV2_TLL_CHANNEL_COUNT; 27116fa3dc7SKeshava Munegowda break; 27216fa3dc7SKeshava Munegowda default: 27316fa3dc7SKeshava Munegowda dev_err(dev, "TLL version failed\n"); 27416fa3dc7SKeshava Munegowda ret = -ENODEV; 27516fa3dc7SKeshava Munegowda goto err_ioremap; 27616fa3dc7SKeshava Munegowda } 27716fa3dc7SKeshava Munegowda 27816fa3dc7SKeshava Munegowda if (is_ehci_tll_mode(pdata->port_mode[0]) || 27916fa3dc7SKeshava Munegowda is_ehci_tll_mode(pdata->port_mode[1]) || 28016fa3dc7SKeshava Munegowda is_ehci_tll_mode(pdata->port_mode[2]) || 28116fa3dc7SKeshava Munegowda is_ohci_port(pdata->port_mode[0]) || 28216fa3dc7SKeshava Munegowda is_ohci_port(pdata->port_mode[1]) || 28316fa3dc7SKeshava Munegowda is_ohci_port(pdata->port_mode[2])) { 28416fa3dc7SKeshava Munegowda 28516fa3dc7SKeshava Munegowda /* Program Common TLL register */ 28616fa3dc7SKeshava Munegowda reg = usbtll_read(base, OMAP_TLL_SHARED_CONF); 28716fa3dc7SKeshava Munegowda reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON 28816fa3dc7SKeshava Munegowda | OMAP_TLL_SHARED_CONF_USB_DIVRATION); 28916fa3dc7SKeshava Munegowda reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; 29016fa3dc7SKeshava Munegowda reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN; 29116fa3dc7SKeshava Munegowda 29216fa3dc7SKeshava Munegowda usbtll_write(base, OMAP_TLL_SHARED_CONF, reg); 29316fa3dc7SKeshava Munegowda 29416fa3dc7SKeshava Munegowda /* Enable channels now */ 29516fa3dc7SKeshava Munegowda for (i = 0; i < count; i++) { 29616fa3dc7SKeshava Munegowda reg = usbtll_read(base, OMAP_TLL_CHANNEL_CONF(i)); 29716fa3dc7SKeshava Munegowda 29816fa3dc7SKeshava Munegowda if (is_ohci_port(pdata->port_mode[i])) { 29916fa3dc7SKeshava Munegowda reg |= ohci_omap3_fslsmode(pdata->port_mode[i]) 30016fa3dc7SKeshava Munegowda << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT; 30116fa3dc7SKeshava Munegowda reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS; 30216fa3dc7SKeshava Munegowda } else if (pdata->port_mode[i] == 30316fa3dc7SKeshava Munegowda OMAP_EHCI_PORT_MODE_TLL) { 30416fa3dc7SKeshava Munegowda /* 30516fa3dc7SKeshava Munegowda * Disable AutoIdle, BitStuffing 30616fa3dc7SKeshava Munegowda * and use SDR Mode 30716fa3dc7SKeshava Munegowda */ 30816fa3dc7SKeshava Munegowda reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE 30916fa3dc7SKeshava Munegowda | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF 31016fa3dc7SKeshava Munegowda | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); 31116fa3dc7SKeshava Munegowda } else { 31216fa3dc7SKeshava Munegowda continue; 31316fa3dc7SKeshava Munegowda } 31416fa3dc7SKeshava Munegowda reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; 31516fa3dc7SKeshava Munegowda usbtll_write(base, OMAP_TLL_CHANNEL_CONF(i), reg); 31616fa3dc7SKeshava Munegowda 31716fa3dc7SKeshava Munegowda usbtll_writeb(base, 31816fa3dc7SKeshava Munegowda OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 31916fa3dc7SKeshava Munegowda 0xbe); 32016fa3dc7SKeshava Munegowda } 32116fa3dc7SKeshava Munegowda } 32216fa3dc7SKeshava Munegowda 32316fa3dc7SKeshava Munegowda err_ioremap: 32416fa3dc7SKeshava Munegowda spin_unlock_irqrestore(&tll->lock, flags); 32516fa3dc7SKeshava Munegowda iounmap(base); 32616fa3dc7SKeshava Munegowda pm_runtime_put_sync(dev); 32716fa3dc7SKeshava Munegowda tll_pdev = pdev; 32816fa3dc7SKeshava Munegowda if (!ret) 32916fa3dc7SKeshava Munegowda goto end; 33016fa3dc7SKeshava Munegowda pm_runtime_disable(dev); 33116fa3dc7SKeshava Munegowda 33216fa3dc7SKeshava Munegowda err_usbtll_p2_fck: 33316fa3dc7SKeshava Munegowda clk_put(tll->usbtll_p2_fck); 33416fa3dc7SKeshava Munegowda 33516fa3dc7SKeshava Munegowda err_usbtll_p1_fck: 33616fa3dc7SKeshava Munegowda clk_put(tll->usbtll_p1_fck); 33716fa3dc7SKeshava Munegowda 33816fa3dc7SKeshava Munegowda err_tll: 33916fa3dc7SKeshava Munegowda kfree(tll); 34016fa3dc7SKeshava Munegowda 34116fa3dc7SKeshava Munegowda end: 34216fa3dc7SKeshava Munegowda return ret; 34316fa3dc7SKeshava Munegowda } 34416fa3dc7SKeshava Munegowda 34516fa3dc7SKeshava Munegowda /** 34616fa3dc7SKeshava Munegowda * usbtll_omap_remove - shutdown processing for UHH & TLL HCDs 34716fa3dc7SKeshava Munegowda * @pdev: USB Host Controller being removed 34816fa3dc7SKeshava Munegowda * 34916fa3dc7SKeshava Munegowda * Reverses the effect of usbtll_omap_probe(). 35016fa3dc7SKeshava Munegowda */ 35116fa3dc7SKeshava Munegowda static int __devexit usbtll_omap_remove(struct platform_device *pdev) 35216fa3dc7SKeshava Munegowda { 35316fa3dc7SKeshava Munegowda struct usbtll_omap *tll = platform_get_drvdata(pdev); 35416fa3dc7SKeshava Munegowda 35516fa3dc7SKeshava Munegowda clk_put(tll->usbtll_p2_fck); 35616fa3dc7SKeshava Munegowda clk_put(tll->usbtll_p1_fck); 35716fa3dc7SKeshava Munegowda pm_runtime_disable(&pdev->dev); 35816fa3dc7SKeshava Munegowda kfree(tll); 35916fa3dc7SKeshava Munegowda return 0; 36016fa3dc7SKeshava Munegowda } 36116fa3dc7SKeshava Munegowda 36216fa3dc7SKeshava Munegowda static int usbtll_runtime_resume(struct device *dev) 36316fa3dc7SKeshava Munegowda { 36416fa3dc7SKeshava Munegowda struct usbtll_omap *tll = dev_get_drvdata(dev); 36516fa3dc7SKeshava Munegowda struct usbtll_omap_platform_data *pdata = &tll->platdata; 36616fa3dc7SKeshava Munegowda unsigned long flags; 36716fa3dc7SKeshava Munegowda 36816fa3dc7SKeshava Munegowda dev_dbg(dev, "usbtll_runtime_resume\n"); 36916fa3dc7SKeshava Munegowda 37016fa3dc7SKeshava Munegowda if (!pdata) { 37116fa3dc7SKeshava Munegowda dev_dbg(dev, "missing platform_data\n"); 37216fa3dc7SKeshava Munegowda return -ENODEV; 37316fa3dc7SKeshava Munegowda } 37416fa3dc7SKeshava Munegowda 37516fa3dc7SKeshava Munegowda spin_lock_irqsave(&tll->lock, flags); 37616fa3dc7SKeshava Munegowda 37716fa3dc7SKeshava Munegowda if (is_ehci_tll_mode(pdata->port_mode[0])) 37816fa3dc7SKeshava Munegowda clk_enable(tll->usbtll_p1_fck); 37916fa3dc7SKeshava Munegowda 38016fa3dc7SKeshava Munegowda if (is_ehci_tll_mode(pdata->port_mode[1])) 38116fa3dc7SKeshava Munegowda clk_enable(tll->usbtll_p2_fck); 38216fa3dc7SKeshava Munegowda 38316fa3dc7SKeshava Munegowda spin_unlock_irqrestore(&tll->lock, flags); 38416fa3dc7SKeshava Munegowda 38516fa3dc7SKeshava Munegowda return 0; 38616fa3dc7SKeshava Munegowda } 38716fa3dc7SKeshava Munegowda 38816fa3dc7SKeshava Munegowda static int usbtll_runtime_suspend(struct device *dev) 38916fa3dc7SKeshava Munegowda { 39016fa3dc7SKeshava Munegowda struct usbtll_omap *tll = dev_get_drvdata(dev); 39116fa3dc7SKeshava Munegowda struct usbtll_omap_platform_data *pdata = &tll->platdata; 39216fa3dc7SKeshava Munegowda unsigned long flags; 39316fa3dc7SKeshava Munegowda 39416fa3dc7SKeshava Munegowda dev_dbg(dev, "usbtll_runtime_suspend\n"); 39516fa3dc7SKeshava Munegowda 39616fa3dc7SKeshava Munegowda if (!pdata) { 39716fa3dc7SKeshava Munegowda dev_dbg(dev, "missing platform_data\n"); 39816fa3dc7SKeshava Munegowda return -ENODEV; 39916fa3dc7SKeshava Munegowda } 40016fa3dc7SKeshava Munegowda 40116fa3dc7SKeshava Munegowda spin_lock_irqsave(&tll->lock, flags); 40216fa3dc7SKeshava Munegowda 40316fa3dc7SKeshava Munegowda if (is_ehci_tll_mode(pdata->port_mode[0])) 40416fa3dc7SKeshava Munegowda clk_disable(tll->usbtll_p1_fck); 40516fa3dc7SKeshava Munegowda 40616fa3dc7SKeshava Munegowda if (is_ehci_tll_mode(pdata->port_mode[1])) 40716fa3dc7SKeshava Munegowda clk_disable(tll->usbtll_p2_fck); 40816fa3dc7SKeshava Munegowda 40916fa3dc7SKeshava Munegowda spin_unlock_irqrestore(&tll->lock, flags); 41016fa3dc7SKeshava Munegowda 41116fa3dc7SKeshava Munegowda return 0; 41216fa3dc7SKeshava Munegowda } 41316fa3dc7SKeshava Munegowda 41416fa3dc7SKeshava Munegowda static const struct dev_pm_ops usbtllomap_dev_pm_ops = { 41516fa3dc7SKeshava Munegowda SET_RUNTIME_PM_OPS(usbtll_runtime_suspend, 41616fa3dc7SKeshava Munegowda usbtll_runtime_resume, 41716fa3dc7SKeshava Munegowda NULL) 41816fa3dc7SKeshava Munegowda }; 41916fa3dc7SKeshava Munegowda 42016fa3dc7SKeshava Munegowda static struct platform_driver usbtll_omap_driver = { 42116fa3dc7SKeshava Munegowda .driver = { 42216fa3dc7SKeshava Munegowda .name = (char *)usbtll_driver_name, 42316fa3dc7SKeshava Munegowda .owner = THIS_MODULE, 42416fa3dc7SKeshava Munegowda .pm = &usbtllomap_dev_pm_ops, 42516fa3dc7SKeshava Munegowda }, 42616fa3dc7SKeshava Munegowda .probe = usbtll_omap_probe, 42784449216SBill Pemberton .remove = usbtll_omap_remove, 42816fa3dc7SKeshava Munegowda }; 42916fa3dc7SKeshava Munegowda 43016fa3dc7SKeshava Munegowda int omap_tll_enable(void) 43116fa3dc7SKeshava Munegowda { 43216fa3dc7SKeshava Munegowda if (!tll_pdev) { 43316fa3dc7SKeshava Munegowda pr_err("missing omap usbhs tll platform_data\n"); 43416fa3dc7SKeshava Munegowda return -ENODEV; 43516fa3dc7SKeshava Munegowda } 43616fa3dc7SKeshava Munegowda return pm_runtime_get_sync(&tll_pdev->dev); 43716fa3dc7SKeshava Munegowda } 43816fa3dc7SKeshava Munegowda EXPORT_SYMBOL_GPL(omap_tll_enable); 43916fa3dc7SKeshava Munegowda 44016fa3dc7SKeshava Munegowda int omap_tll_disable(void) 44116fa3dc7SKeshava Munegowda { 44216fa3dc7SKeshava Munegowda if (!tll_pdev) { 44316fa3dc7SKeshava Munegowda pr_err("missing omap usbhs tll platform_data\n"); 44416fa3dc7SKeshava Munegowda return -ENODEV; 44516fa3dc7SKeshava Munegowda } 44616fa3dc7SKeshava Munegowda return pm_runtime_put_sync(&tll_pdev->dev); 44716fa3dc7SKeshava Munegowda } 44816fa3dc7SKeshava Munegowda EXPORT_SYMBOL_GPL(omap_tll_disable); 44916fa3dc7SKeshava Munegowda 45016fa3dc7SKeshava Munegowda MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>"); 45116fa3dc7SKeshava Munegowda MODULE_ALIAS("platform:" USBHS_DRIVER_NAME); 45216fa3dc7SKeshava Munegowda MODULE_LICENSE("GPL v2"); 45316fa3dc7SKeshava Munegowda MODULE_DESCRIPTION("usb tll driver for TI OMAP EHCI and OHCI controllers"); 45416fa3dc7SKeshava Munegowda 45516fa3dc7SKeshava Munegowda static int __init omap_usbtll_drvinit(void) 45616fa3dc7SKeshava Munegowda { 45716fa3dc7SKeshava Munegowda return platform_driver_register(&usbtll_omap_driver); 45816fa3dc7SKeshava Munegowda } 45916fa3dc7SKeshava Munegowda 46016fa3dc7SKeshava Munegowda /* 46116fa3dc7SKeshava Munegowda * init before usbhs core driver; 46216fa3dc7SKeshava Munegowda * The usbtll driver should be initialized before 46316fa3dc7SKeshava Munegowda * the usbhs core driver probe function is called. 46416fa3dc7SKeshava Munegowda */ 46516fa3dc7SKeshava Munegowda fs_initcall(omap_usbtll_drvinit); 46616fa3dc7SKeshava Munegowda 46716fa3dc7SKeshava Munegowda static void __exit omap_usbtll_drvexit(void) 46816fa3dc7SKeshava Munegowda { 46916fa3dc7SKeshava Munegowda platform_driver_unregister(&usbtll_omap_driver); 47016fa3dc7SKeshava Munegowda } 47116fa3dc7SKeshava Munegowda module_exit(omap_usbtll_drvexit); 472