1550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 2550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * TUSB6010 USB 2.0 OTG Dual Role controller 3550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 4550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Copyright (C) 2006 Nokia Corporation 5550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Tony Lindgren <tony@atomide.com> 6550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 7550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * This program is free software; you can redistribute it and/or modify 8550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * it under the terms of the GNU General Public License version 2 as 9550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * published by the Free Software Foundation. 10550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 11550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Notes: 12550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * - Driver assumes that interface to external host (main CPU) is 13550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * configured for NOR FLASH interface instead of VLYNQ serial 14550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * interface. 15550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 16550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 17550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#include <linux/module.h> 18550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#include <linux/kernel.h> 19550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#include <linux/errno.h> 20550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#include <linux/init.h> 21240a16e2cd831cb25361b1d1797bd04e8faf8b4fFelipe Balbi#include <linux/prefetch.h> 22550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#include <linux/usb.h> 23550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#include <linux/irq.h> 24550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#include <linux/platform_device.h> 2518688fbeb09665725c842291bbadd88295a359e1Felipe Balbi#include <linux/dma-mapping.h> 26550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 27550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#include "musb_core.h" 28550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 291add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbistruct tusb6010_glue { 301add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi struct device *dev; 311add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi struct platform_device *musb; 321add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi}; 331add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi 34743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic void tusb_musb_set_vbus(struct musb *musb, int is_on); 35550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 36550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#define TUSB_REV_MAJOR(reg_val) ((reg_val >> 4) & 0xf) 37550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#define TUSB_REV_MINOR(reg_val) (reg_val & 0xf) 38550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 39550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 40550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Checks the revision. We need to use the DMA register as 3.0 does not 41550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV. 42550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 43550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbiu8 tusb_get_revision(struct musb *musb) 44550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 45550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 46550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 die_id; 47550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u8 rev; 48550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 49550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi rev = musb_readl(tbase, TUSB_DMA_CTRL_REV) & 0xff; 50550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (TUSB_REV_MAJOR(rev) == 3) { 51550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi die_id = TUSB_DIDR1_HI_CHIP_REV(musb_readl(tbase, 52550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_DIDR1_HI)); 53550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (die_id >= TUSB_DIDR1_HI_REV_31) 54550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi rev |= 1; 55550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 56550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 57550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return rev; 58550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 599a35f8767a568bdbb21ba7c3276fdc5321e3960dArnd BergmannEXPORT_SYMBOL_GPL(tusb_get_revision); 60550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 61743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic int tusb_print_revision(struct musb *musb) 62550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 63550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 64550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u8 rev; 65550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 66550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi rev = tusb_get_revision(musb); 67550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 68550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi pr_info("tusb: %s%i.%i %s%i.%i %s%i.%i %s%i.%i %s%i %s%i.%i\n", 69550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi "prcm", 70550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_REV_MAJOR(musb_readl(tbase, TUSB_PRCM_REV)), 71550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_REV_MINOR(musb_readl(tbase, TUSB_PRCM_REV)), 72550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi "int", 73550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_REV_MAJOR(musb_readl(tbase, TUSB_INT_CTRL_REV)), 74550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_REV_MINOR(musb_readl(tbase, TUSB_INT_CTRL_REV)), 75550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi "gpio", 76550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_REV_MAJOR(musb_readl(tbase, TUSB_GPIO_REV)), 77550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_REV_MINOR(musb_readl(tbase, TUSB_GPIO_REV)), 78550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi "dma", 79550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_REV_MAJOR(musb_readl(tbase, TUSB_DMA_CTRL_REV)), 80550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_REV_MINOR(musb_readl(tbase, TUSB_DMA_CTRL_REV)), 81550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi "dieid", 82550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_DIDR1_HI_CHIP_REV(musb_readl(tbase, TUSB_DIDR1_HI)), 83550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi "rev", 84550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_REV_MAJOR(rev), TUSB_REV_MINOR(rev)); 85550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 86550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return tusb_get_revision(musb); 87550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 88550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 89550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#define WBUS_QUIRK_MASK (TUSB_PHY_OTG_CTRL_TESTM2 | TUSB_PHY_OTG_CTRL_TESTM1 \ 90550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | TUSB_PHY_OTG_CTRL_TESTM0) 91550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 92550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 93550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Workaround for spontaneous WBUS wake-up issue #2 for tusb3.0. 94550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Disables power detection in PHY for the duration of idle. 95550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 96550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbistatic void tusb_wbus_quirk(struct musb *musb, int enabled) 97550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 98550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 99550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi static u32 phy_otg_ctrl, phy_otg_ena; 100550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 tmp; 101550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 102550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (enabled) { 103550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ctrl = musb_readl(tbase, TUSB_PHY_OTG_CTRL); 104550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ena = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE); 105550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tmp = TUSB_PHY_OTG_CTRL_WRPROTECT 106550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | phy_otg_ena | WBUS_QUIRK_MASK; 107550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PHY_OTG_CTRL, tmp); 108550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tmp = phy_otg_ena & ~WBUS_QUIRK_MASK; 109550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tmp |= TUSB_PHY_OTG_CTRL_WRPROTECT | TUSB_PHY_OTG_CTRL_TESTM2; 110550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PHY_OTG_CTRL_ENABLE, tmp); 1115c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "Enabled tusb wbus quirk ctrl %08x ena %08x\n", 112550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_readl(tbase, TUSB_PHY_OTG_CTRL), 113550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE)); 114550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else if (musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE) 115550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi & TUSB_PHY_OTG_CTRL_TESTM2) { 116550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tmp = TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ctrl; 117550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PHY_OTG_CTRL, tmp); 118550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tmp = TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ena; 119550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PHY_OTG_CTRL_ENABLE, tmp); 1205c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "Disabled tusb wbus quirk ctrl %08x ena %08x\n", 121550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_readl(tbase, TUSB_PHY_OTG_CTRL), 122550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE)); 123550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ctrl = 0; 124550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ena = 0; 125550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 126550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 127550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 128550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 129550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * TUSB 6010 may use a parallel bus that doesn't support byte ops; 130550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * so both loading and unloading FIFOs need explicit byte counts. 131550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 132550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 133550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbistatic inline void 134550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbitusb_fifo_write_unaligned(void __iomem *fifo, const u8 *buf, u16 len) 135550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 136550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 val; 137550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int i; 138550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 139550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len > 4) { 140550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi for (i = 0; i < (len >> 2); i++) { 141550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi memcpy(&val, buf, 4); 142550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(fifo, 0, val); 143550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi buf += 4; 144550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 145550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi len %= 4; 146550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 147550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len > 0) { 148550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Write the rest 1 - 3 bytes to FIFO */ 149550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi memcpy(&val, buf, len); 150550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(fifo, 0, val); 151550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 152550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 153550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 154550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbistatic inline void tusb_fifo_read_unaligned(void __iomem *fifo, 155550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *buf, u16 len) 156550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 157550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 val; 158550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int i; 159550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 160550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len > 4) { 161550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi for (i = 0; i < (len >> 2); i++) { 162550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi val = musb_readl(fifo, 0); 163550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi memcpy(buf, &val, 4); 164550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi buf += 4; 165550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 166550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi len %= 4; 167550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 168550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len > 0) { 169550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Read the rest 1 - 3 bytes from FIFO */ 170550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi val = musb_readl(fifo, 0); 171550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi memcpy(buf, &val, len); 172550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 173550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 174550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 175550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbivoid musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf) 176550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 17728e4970555554d12eed286cb47763d1949b931fbFelipe Balbi struct musb *musb = hw_ep->musb; 178550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *ep_conf = hw_ep->conf; 179550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *fifo = hw_ep->fifo; 180550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u8 epnum = hw_ep->epnum; 181550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 182550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi prefetch(buf); 183550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1845c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", 185550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 'T', epnum, fifo, len, buf); 186550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 187550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (epnum) 188550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(ep_conf, TUSB_EP_TX_OFFSET, 189550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_EP_CONFIG_XFR_SIZE(len)); 190550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi else 191550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(ep_conf, 0, TUSB_EP0_CONFIG_DIR_TX | 192550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_EP0_CONFIG_XFR_SIZE(len)); 193550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 194550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (likely((0x01 & (unsigned long) buf) == 0)) { 195550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 196550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Best case is 32bit-aligned destination address */ 197550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if ((0x02 & (unsigned long) buf) == 0) { 198550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len >= 4) { 199550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi writesl(fifo, buf, len >> 2); 200550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi buf += (len & ~0x03); 201550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi len &= 0x03; 202550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 203550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else { 204550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len >= 2) { 205550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 val; 206550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int i; 207550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 208550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Cannot use writesw, fifo is 32-bit */ 209550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi for (i = 0; i < (len >> 2); i++) { 210550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi val = (u32)(*(u16 *)buf); 211550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi buf += 2; 212550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi val |= (*(u16 *)buf) << 16; 213550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi buf += 2; 214550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(fifo, 0, val); 215550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 216550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi len &= 0x03; 217550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 218550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 219550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 220550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 221550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len > 0) 222550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tusb_fifo_write_unaligned(fifo, buf, len); 223550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 224550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 225550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbivoid musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) 226550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 22728e4970555554d12eed286cb47763d1949b931fbFelipe Balbi struct musb *musb = hw_ep->musb; 228550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *ep_conf = hw_ep->conf; 229550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *fifo = hw_ep->fifo; 230550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u8 epnum = hw_ep->epnum; 231550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 2325c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", 233550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 'R', epnum, fifo, len, buf); 234550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 235550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (epnum) 236550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(ep_conf, TUSB_EP_RX_OFFSET, 237550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_EP_CONFIG_XFR_SIZE(len)); 238550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi else 239550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(ep_conf, 0, TUSB_EP0_CONFIG_XFR_SIZE(len)); 240550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 241550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (likely((0x01 & (unsigned long) buf) == 0)) { 242550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 243550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Best case is 32bit-aligned destination address */ 244550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if ((0x02 & (unsigned long) buf) == 0) { 245550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len >= 4) { 246550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi readsl(fifo, buf, len >> 2); 247550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi buf += (len & ~0x03); 248550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi len &= 0x03; 249550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 250550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else { 251550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len >= 2) { 252550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 val; 253550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int i; 254550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 255550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Cannot use readsw, fifo is 32-bit */ 256550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi for (i = 0; i < (len >> 2); i++) { 257550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi val = musb_readl(fifo, 0); 258550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi *(u16 *)buf = (u16)(val & 0xffff); 259550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi buf += 2; 260550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi *(u16 *)buf = (u16)(val >> 16); 261550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi buf += 2; 262550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 263550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi len &= 0x03; 264550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 265550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 266550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 267550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 268550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (len > 0) 269550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tusb_fifo_read_unaligned(fifo, buf, len); 270550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 271550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 27284e250ffa76dddc1bad84e04248a27f442c25986David Brownellstatic struct musb *the_musb; 27384e250ffa76dddc1bad84e04248a27f442c25986David Brownell 274550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* This is used by gadget drivers, and OTG transceiver logic, allowing 275550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * at most mA current to be drawn from VBUS during a Default-B session 276550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * (that is, while VBUS exceeds 4.4V). In Default-A (including pure host 277550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * mode), or low power Default-B sessions, something else supplies power. 278550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Caller must take care of locking. 279550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 2808675381109b0eb1c948a423c2b35e3f4509cb25eHeikki Krogerusstatic int tusb_draw_power(struct usb_phy *x, unsigned mA) 281550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 28284e250ffa76dddc1bad84e04248a27f442c25986David Brownell struct musb *musb = the_musb; 283550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 284550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 reg; 285550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 286550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* tps65030 seems to consume max 100mA, with maybe 60mA available 287550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * (measured on one board) for things other than tps and tusb. 288550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 289550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Boards sharing the CPU clock with CLKIN will need to prevent 290550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * certain idle sleep states while the USB link is active. 291550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 292550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * REVISIT we could use VBUS to supply only _one_ of { 1.5V, 3.3V }. 293550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * The actual current usage would be very board-specific. For now, 294550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * it's simpler to just use an aggregate (also board-specific). 295550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 296d445b6da8da491e025eb60576ce959f6a3a56a4fHeikki Krogerus if (x->otg->default_a || mA < (musb->min_power << 1)) 297550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi mA = 0; 298550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 299550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg = musb_readl(tbase, TUSB_PRCM_MNGMT); 300550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (mA) { 301550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_bus_powered = 1; 302550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg |= TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN; 303550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else { 304550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_bus_powered = 0; 305550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg &= ~(TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN); 306550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 307550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PRCM_MNGMT, reg); 308550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 3095c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "draw max %d mA VBUS\n", mA); 310550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return 0; 311550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 312550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 313550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* workaround for issue 13: change clock during chip idle 314550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * (to be fixed in rev3 silicon) ... symptoms include disconnect 315550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * or looping suspend/resume cycles 316550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 317550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbistatic void tusb_set_clock_source(struct musb *musb, unsigned mode) 318550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 319550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 320550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 reg; 321550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 322550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg = musb_readl(tbase, TUSB_PRCM_CONF); 323550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg &= ~TUSB_PRCM_CONF_SYS_CLKSEL(0x3); 324550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 325550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* 0 = refclk (clkin, XI) 326550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 1 = PHY 60 MHz (internal PLL) 327550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 2 = not supported 328550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 3 = what? 329550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 330550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (mode > 0) 331550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg |= TUSB_PRCM_CONF_SYS_CLKSEL(mode & 0x3); 332550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 333550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PRCM_CONF, reg); 334550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 335550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* FIXME tusb6010_platform_retime(mode == 0); */ 336550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 337550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 338550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 339550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Idle TUSB6010 until next wake-up event; NOR access always wakes. 340550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Other code ensures that we idle unless we're connected _and_ the 341550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * USB link is not suspended ... and tells us the relevant wakeup 342550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * events. SW_EN for voltage is handled separately. 343550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 344743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic void tusb_allow_idle(struct musb *musb, u32 wakeup_enables) 345550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 346550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 347550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 reg; 348550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 349550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if ((wakeup_enables & TUSB_PRCM_WBUS) 350550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi && (tusb_get_revision(musb) == TUSB_REV_30)) 351550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tusb_wbus_quirk(musb, 1); 352550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 353550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tusb_set_clock_source(musb, 0); 354550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 355550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi wakeup_enables |= TUSB_PRCM_WNORCS; 356550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PRCM_WAKEUP_MASK, ~wakeup_enables); 357550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 358550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* REVISIT writeup of WID implies that if WID set and ID is grounded, 359550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * TUSB_PHY_OTG_CTRL.TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP must be cleared. 360550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Presumably that's mostly to save power, hence WID is immaterial ... 361550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 362550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 363550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg = musb_readl(tbase, TUSB_PRCM_MNGMT); 364550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* issue 4: when driving vbus, use hipower (vbus_det) comparator */ 365550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (is_host_active(musb)) { 366550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg |= TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN; 367550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg &= ~TUSB_PRCM_MNGMT_OTG_SESS_END_EN; 368550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else { 369550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg |= TUSB_PRCM_MNGMT_OTG_SESS_END_EN; 370550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg &= ~TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN; 371550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 372550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg |= TUSB_PRCM_MNGMT_PM_IDLE | TUSB_PRCM_MNGMT_DEV_IDLE; 373550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PRCM_MNGMT, reg); 374550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 3755c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "idle, wake on %02x\n", wakeup_enables); 376550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 377550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 378550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 379550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Updates cable VBUS status. Caller must take care of locking. 380550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 381743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic int tusb_musb_vbus_status(struct musb *musb) 382550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 383550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 384550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 otg_stat, prcm_mngmt; 385550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int ret = 0; 386550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 387550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); 388550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi prcm_mngmt = musb_readl(tbase, TUSB_PRCM_MNGMT); 389550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 390550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Temporarily enable VBUS detection if it was disabled for 391550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * suspend mode. Unless it's enabled otg_stat and devctl will 392550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * not show correct VBUS state. 393550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 394550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (!(prcm_mngmt & TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN)) { 395550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 tmp = prcm_mngmt; 396550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tmp |= TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN; 397550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PRCM_MNGMT, tmp); 398550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); 399550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PRCM_MNGMT, prcm_mngmt); 400550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 401550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 402550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (otg_stat & TUSB_DEV_OTG_STAT_VBUS_VALID) 403550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ret = 1; 404550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 405550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return ret; 406550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 407550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 408550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbistatic struct timer_list musb_idle_timer; 409550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 410550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbistatic void musb_do_idle(unsigned long _musb) 411550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 412550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi struct musb *musb = (void *)_musb; 413550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi unsigned long flags; 414550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 415550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi spin_lock_irqsave(&musb->lock, flags); 416550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 41784e250ffa76dddc1bad84e04248a27f442c25986David Brownell switch (musb->xceiv->state) { 418550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_WAIT_BCON: 419550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if ((musb->a_wait_bcon != 0) 420550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi && (musb->idle_timeout == 0 421550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi || time_after(jiffies, musb->idle_timeout))) { 4225c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n", 4233df004532582d0cc721da0df28311bcedd639724Anatolij Gustschin otg_state_string(musb->xceiv->state)); 424550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 425550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* FALLTHROUGH */ 426550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_IDLE: 427743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi tusb_musb_set_vbus(musb, 0); 428550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi default: 429550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 430550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 431550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 432550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (!musb->is_active) { 433550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 wakeups; 434550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 435550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* wait until khubd handles port change status */ 436550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (is_host_active(musb) && (musb->port1_status >> 16)) 437550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi goto done; 438550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 439622859634a663c5e55d0e2a2cdbb55ac058d97b3Felipe Balbi if (is_peripheral_enabled(musb) && !musb->gadget_driver) { 440550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi wakeups = 0; 441622859634a663c5e55d0e2a2cdbb55ac058d97b3Felipe Balbi } else { 442550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi wakeups = TUSB_PRCM_WHOSTDISCON 443622859634a663c5e55d0e2a2cdbb55ac058d97b3Felipe Balbi | TUSB_PRCM_WBUS 444550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | TUSB_PRCM_WVBUS; 445550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (is_otg_enabled(musb)) 446550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi wakeups |= TUSB_PRCM_WID; 447550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 448550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tusb_allow_idle(musb, wakeups); 449550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 450550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbidone: 451550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi spin_unlock_irqrestore(&musb->lock, flags); 452550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 453550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 454550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 455550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Maybe put TUSB6010 into idle mode mode depending on USB link status, 456550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * like "disconnected" or "suspended". We'll be woken out of it by 457550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * connect, resume, or disconnect. 458550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 459550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Needs to be called as the last function everywhere where there is 460550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * register access to TUSB6010 because of NOR flash wake-up. 461550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Caller should own controller spinlock. 462550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 463550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Delay because peripheral enables D+ pullup 3msec after SE0, and 464550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * we don't want to treat that full speed J as a wakeup event. 465550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * ... peripherals must draw only suspend current after 10 msec. 466550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 467743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic void tusb_musb_try_idle(struct musb *musb, unsigned long timeout) 468550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 469550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi unsigned long default_timeout = jiffies + msecs_to_jiffies(3); 470550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi static unsigned long last_timer; 471550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 472550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (timeout == 0) 473550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi timeout = default_timeout; 474550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 475550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Never idle if active, or when VBUS timeout is not set as host */ 476550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (musb->is_active || ((musb->a_wait_bcon == 0) 47784e250ffa76dddc1bad84e04248a27f442c25986David Brownell && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { 4785c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "%s active, deleting timer\n", 4793df004532582d0cc721da0df28311bcedd639724Anatolij Gustschin otg_state_string(musb->xceiv->state)); 480550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi del_timer(&musb_idle_timer); 481550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi last_timer = jiffies; 482550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return; 483550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 484550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 485550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (time_after(last_timer, timeout)) { 486550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (!timer_pending(&musb_idle_timer)) 487550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi last_timer = timeout; 488550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi else { 4895c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "Longer idle timer already pending, ignoring\n"); 490550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return; 491550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 492550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 493550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi last_timer = timeout; 494550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 4955c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", 4963df004532582d0cc721da0df28311bcedd639724Anatolij Gustschin otg_state_string(musb->xceiv->state), 497550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi (unsigned long)jiffies_to_msecs(timeout - jiffies)); 498550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi mod_timer(&musb_idle_timer, timeout); 499550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 500550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 501550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* ticks of 60 MHz clock */ 502550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#define DEVCLOCK 60000000 503550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi#define OTG_TIMER_MS(msecs) ((msecs) \ 504550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ? (TUSB_DEV_OTG_TIMER_VAL((DEVCLOCK/1000)*(msecs)) \ 505550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | TUSB_DEV_OTG_TIMER_ENABLE) \ 506550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi : 0) 507550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 508743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic void tusb_musb_set_vbus(struct musb *musb, int is_on) 509550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 510550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 511550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 conf, prcm, timer; 512550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u8 devctl; 513d445b6da8da491e025eb60576ce959f6a3a56a4fHeikki Krogerus struct usb_otg *otg = musb->xceiv->otg; 514550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 515550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* HDRC controls CPEN, but beware current surges during device 516550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * connect. They can trigger transient overcurrent conditions 517550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * that must be ignored. 518550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 519550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 520550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi prcm = musb_readl(tbase, TUSB_PRCM_MNGMT); 521550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi conf = musb_readl(tbase, TUSB_DEV_CONF); 522550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi devctl = musb_readb(musb->mregs, MUSB_DEVCTL); 523550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 524550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (is_on) { 525550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); 526d445b6da8da491e025eb60576ce959f6a3a56a4fHeikki Krogerus otg->default_a = 1; 52784e250ffa76dddc1bad84e04248a27f442c25986David Brownell musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; 528550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi devctl |= MUSB_DEVCTL_SESSION; 529550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 530550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi conf |= TUSB_DEV_CONF_USB_HOST_MODE; 531550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi MUSB_HST_MODE(musb); 532550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else { 533550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 otg_stat; 534550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 535550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi timer = 0; 536550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 537550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* If ID pin is grounded, we want to be a_idle */ 538550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); 539550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) { 54084e250ffa76dddc1bad84e04248a27f442c25986David Brownell switch (musb->xceiv->state) { 541550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_WAIT_VRISE: 542550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_WAIT_BCON: 54384e250ffa76dddc1bad84e04248a27f442c25986David Brownell musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; 544550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 545550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_WAIT_VFALL: 54684e250ffa76dddc1bad84e04248a27f442c25986David Brownell musb->xceiv->state = OTG_STATE_A_IDLE; 547550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 548550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi default: 54984e250ffa76dddc1bad84e04248a27f442c25986David Brownell musb->xceiv->state = OTG_STATE_A_IDLE; 550550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 551550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_active = 0; 552d445b6da8da491e025eb60576ce959f6a3a56a4fHeikki Krogerus otg->default_a = 1; 553550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi MUSB_HST_MODE(musb); 554550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else { 555550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_active = 0; 556d445b6da8da491e025eb60576ce959f6a3a56a4fHeikki Krogerus otg->default_a = 0; 55784e250ffa76dddc1bad84e04248a27f442c25986David Brownell musb->xceiv->state = OTG_STATE_B_IDLE; 558550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi MUSB_DEV_MODE(musb); 559550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 560550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 561550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi devctl &= ~MUSB_DEVCTL_SESSION; 562550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi conf &= ~TUSB_DEV_CONF_USB_HOST_MODE; 563550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 564550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi prcm &= ~(TUSB_PRCM_MNGMT_15_SW_EN | TUSB_PRCM_MNGMT_33_SW_EN); 565550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 566550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PRCM_MNGMT, prcm); 567550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_DEV_OTG_TIMER, timer); 568550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_DEV_CONF, conf); 569550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); 570550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 5715c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "VBUS %s, devctl %02x otg %3x conf %08x prcm %08x\n", 5723df004532582d0cc721da0df28311bcedd639724Anatolij Gustschin otg_state_string(musb->xceiv->state), 573550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_readb(musb->mregs, MUSB_DEVCTL), 574550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_readl(tbase, TUSB_DEV_OTG_STAT), 575550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi conf, prcm); 576550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 577550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 578550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 579550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Sets the mode to OTG, peripheral or host by changing the ID detection. 580550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Caller must take care of locking. 581550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 582550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Note that if a mini-A cable is plugged in the ID line will stay down as 583550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * the weak ID pull-up is not able to pull the ID up. 584550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * 585550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * REVISIT: It would be possible to add support for changing between host 586550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * and peripheral modes in non-OTG configurations by reconfiguring hardware 587550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * and then setting musb->board_mode. For now, only support OTG mode. 588550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 589743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic int tusb_musb_set_mode(struct musb *musb, u8 musb_mode) 590550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 591550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 592550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf; 593550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 594550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (musb->board_mode != MUSB_OTG) { 595550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ERR("Changing mode currently only supported in OTG mode\n"); 59614a2c96f72e0939cb817b6624346b0161b5603dbFelipe Balbi return -EINVAL; 597550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 598550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 599550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); 600550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ctrl = musb_readl(tbase, TUSB_PHY_OTG_CTRL); 601550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ena = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE); 602550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi dev_conf = musb_readl(tbase, TUSB_DEV_CONF); 603550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 604550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi switch (musb_mode) { 605550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 606550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case MUSB_HOST: /* Disable PHY ID detect, ground ID */ 607550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ctrl &= ~TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP; 608550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP; 609550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi dev_conf |= TUSB_DEV_CONF_ID_SEL; 610550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi dev_conf &= ~TUSB_DEV_CONF_SOFT_ID; 611550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 612550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case MUSB_PERIPHERAL: /* Disable PHY ID detect, keep ID pull-up on */ 613550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ctrl |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP; 614550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP; 615550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi dev_conf |= (TUSB_DEV_CONF_ID_SEL | TUSB_DEV_CONF_SOFT_ID); 616550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 617550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case MUSB_OTG: /* Use PHY ID detection */ 618550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ctrl |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP; 619550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi phy_otg_ena |= TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP; 620550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi dev_conf &= ~(TUSB_DEV_CONF_ID_SEL | TUSB_DEV_CONF_SOFT_ID); 621550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 622550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 623550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi default: 6245c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "Trying to set mode %i\n", musb_mode); 62596a274d1da950a96cb31ac1bed044e049d770980David Brownell return -EINVAL; 626550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 627550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 628550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PHY_OTG_CTRL, 629550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ctrl); 630550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PHY_OTG_CTRL_ENABLE, 631550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_PHY_OTG_CTRL_WRPROTECT | phy_otg_ena); 632550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_DEV_CONF, dev_conf); 633550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 634550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); 635550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if ((musb_mode == MUSB_PERIPHERAL) && 636550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) 637550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi INFO("Cannot be peripheral with mini-A cable " 638550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi "otg_stat: %08x\n", otg_stat); 63996a274d1da950a96cb31ac1bed044e049d770980David Brownell 64096a274d1da950a96cb31ac1bed044e049d770980David Brownell return 0; 641550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 642550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 643550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbistatic inline unsigned long 644550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbitusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) 645550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 646550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); 647550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi unsigned long idle_timeout = 0; 648d445b6da8da491e025eb60576ce959f6a3a56a4fHeikki Krogerus struct usb_otg *otg = musb->xceiv->otg; 649550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 650550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* ID pin */ 651550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) { 652550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int default_a; 653550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 654550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (is_otg_enabled(musb)) 655550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi default_a = !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS); 656550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi else 657550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi default_a = is_host_enabled(musb); 6585c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "Default-%c\n", default_a ? 'A' : 'B'); 659d445b6da8da491e025eb60576ce959f6a3a56a4fHeikki Krogerus otg->default_a = default_a; 660743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi tusb_musb_set_vbus(musb, default_a); 661550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 662550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Don't allow idling immediately */ 663550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (default_a) 664550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi idle_timeout = jiffies + (HZ * 3); 665550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 666550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 667550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* VBUS state change */ 668550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { 669550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 670550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* B-dev state machine: no vbus ~= disconnect */ 671d445b6da8da491e025eb60576ce959f6a3a56a4fHeikki Krogerus if ((is_otg_enabled(musb) && !otg->default_a) 672550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi || !is_host_enabled(musb)) { 673550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* ? musb_root_disconnect(musb); */ 674550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->port1_status &= 675550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ~(USB_PORT_STAT_CONNECTION 676550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | USB_PORT_STAT_ENABLE 677550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | USB_PORT_STAT_LOW_SPEED 678550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | USB_PORT_STAT_HIGH_SPEED 679550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | USB_PORT_STAT_TEST 680550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ); 681550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 682550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) { 6835c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "Forcing disconnect (no interrupt)\n"); 68484e250ffa76dddc1bad84e04248a27f442c25986David Brownell if (musb->xceiv->state != OTG_STATE_B_IDLE) { 685550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* INTR_DISCONNECT can hide... */ 68684e250ffa76dddc1bad84e04248a27f442c25986David Brownell musb->xceiv->state = OTG_STATE_B_IDLE; 687550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->int_usb |= MUSB_INTR_DISCONNECT; 688550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 689550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_active = 0; 690550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 6915c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "vbus change, %s, otg %03x\n", 6923df004532582d0cc721da0df28311bcedd639724Anatolij Gustschin otg_state_string(musb->xceiv->state), otg_stat); 693550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi idle_timeout = jiffies + (1 * HZ); 694550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi schedule_work(&musb->irq_work); 695550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 696550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else /* A-dev state machine */ { 6975c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "vbus change, %s, otg %03x\n", 6983df004532582d0cc721da0df28311bcedd639724Anatolij Gustschin otg_state_string(musb->xceiv->state), otg_stat); 699550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 70084e250ffa76dddc1bad84e04248a27f442c25986David Brownell switch (musb->xceiv->state) { 701550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_IDLE: 7025c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "Got SRP, turning on VBUS\n"); 703743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi musb_platform_set_vbus(musb, 1); 704550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 705550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* CONNECT can wake if a_wait_bcon is set */ 706550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (musb->a_wait_bcon != 0) 707550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_active = 0; 708550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi else 709550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_active = 1; 710550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 711550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* 712550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * OPT FS A TD.4.6 needs few seconds for 713550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * A_WAIT_VRISE 714550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 715550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi idle_timeout = jiffies + (2 * HZ); 716550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 717550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 718550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_WAIT_VRISE: 719550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* ignore; A-session-valid < VBUS_VALID/2, 720550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * we monitor this with the timer 721550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 722550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 723550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_WAIT_VFALL: 724550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* REVISIT this irq triggers during short 725550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * spikes caused by enumeration ... 726550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 727550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (musb->vbuserr_retry) { 728550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->vbuserr_retry--; 729743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi tusb_musb_set_vbus(musb, 1); 730550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else { 731550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->vbuserr_retry 732550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi = VBUSERR_RETRY_COUNT; 733743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi tusb_musb_set_vbus(musb, 0); 734550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 735550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 736550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi default: 737550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 738550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 739550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 740550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 741550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 742550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* OTG timer expiration */ 743550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (int_src & TUSB_INT_SRC_OTG_TIMEOUT) { 744550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u8 devctl; 745550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 7465c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "%s timer, %03x\n", 7473df004532582d0cc721da0df28311bcedd639724Anatolij Gustschin otg_state_string(musb->xceiv->state), otg_stat); 748550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 74984e250ffa76dddc1bad84e04248a27f442c25986David Brownell switch (musb->xceiv->state) { 750550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_WAIT_VRISE: 751550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* VBUS has probably been valid for a while now, 752550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * but may well have bounced out of range a bit 753550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 754550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi devctl = musb_readb(musb->mregs, MUSB_DEVCTL); 755550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (otg_stat & TUSB_DEV_OTG_STAT_VBUS_VALID) { 756550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if ((devctl & MUSB_DEVCTL_VBUS) 757550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi != MUSB_DEVCTL_VBUS) { 7585c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "devctl %02x\n", devctl); 759550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 760550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 76184e250ffa76dddc1bad84e04248a27f442c25986David Brownell musb->xceiv->state = OTG_STATE_A_WAIT_BCON; 762550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_active = 0; 763550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi idle_timeout = jiffies 764550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi + msecs_to_jiffies(musb->a_wait_bcon); 765550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else { 766550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* REVISIT report overcurrent to hub? */ 767550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ERR("vbus too slow, devctl %02x\n", devctl); 768743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi tusb_musb_set_vbus(musb, 0); 769550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 770550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 771550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_WAIT_BCON: 772550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (musb->a_wait_bcon != 0) 773550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi idle_timeout = jiffies 774550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi + msecs_to_jiffies(musb->a_wait_bcon); 775550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 776550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_A_SUSPEND: 777550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 778550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi case OTG_STATE_B_WAIT_ACON: 779550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 780550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi default: 781550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 782550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 783550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 784550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi schedule_work(&musb->irq_work); 785550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 786550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return idle_timeout; 787550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 788550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 789743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic irqreturn_t tusb_musb_interrupt(int irq, void *__hci) 790550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 791550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi struct musb *musb = __hci; 792550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 793550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi unsigned long flags, idle_timeout = 0; 794550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 int_mask, int_src; 795550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 796550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi spin_lock_irqsave(&musb->lock, flags); 797550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 798550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Mask all interrupts to allow using both edge and level GPIO irq */ 799550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int_mask = musb_readl(tbase, TUSB_INT_MASK); 800550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_INT_MASK, ~TUSB_INT_MASK_RESERVED_BITS); 801550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 802550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int_src = musb_readl(tbase, TUSB_INT_SRC) & ~TUSB_INT_SRC_RESERVED_BITS; 8035c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "TUSB IRQ %08x\n", int_src); 804550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 805550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->int_usb = (u8) int_src; 806550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 807550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Acknowledge wake-up source interrupts */ 808550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (int_src & TUSB_INT_SRC_DEV_WAKEUP) { 809550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 reg; 810550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 i; 811550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 812550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (tusb_get_revision(musb) == TUSB_REV_30) 813550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tusb_wbus_quirk(musb, 0); 814550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 815550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* there are issues re-locking the PLL on wakeup ... */ 816550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 817550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* work around issue 8 */ 818550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi for (i = 0xf7f7f7; i > 0xf7f7f7 - 1000; i--) { 819550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_SCRATCH_PAD, 0); 820550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_SCRATCH_PAD, i); 821550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg = musb_readl(tbase, TUSB_SCRATCH_PAD); 822550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (reg == i) 823550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi break; 8245c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "TUSB NOR not ready\n"); 825550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 826550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 827550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* work around issue 13 (2nd half) */ 828550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tusb_set_clock_source(musb, 1); 829550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 830550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg = musb_readl(tbase, TUSB_PRCM_WAKEUP_SOURCE); 831550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PRCM_WAKEUP_CLEAR, reg); 832550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (reg & ~TUSB_PRCM_WNORCS) { 833550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_active = 1; 834550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi schedule_work(&musb->irq_work); 835550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 8365c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "wake %sactive %02x\n", 837550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->is_active ? "" : "in", reg); 838550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 839550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* REVISIT host side TUSB_PRCM_WHOSTDISCON, TUSB_PRCM_WBUS */ 840550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 841550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 842550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (int_src & TUSB_INT_SRC_USB_IP_CONN) 843550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi del_timer(&musb_idle_timer); 844550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 845550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* OTG state change reports (annoyingly) not issued by Mentor core */ 846550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (int_src & (TUSB_INT_SRC_VBUS_SENSE_CHNG 847550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | TUSB_INT_SRC_OTG_TIMEOUT 848550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi | TUSB_INT_SRC_ID_STATUS_CHNG)) 849550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi idle_timeout = tusb_otg_ints(musb, int_src, tbase); 850550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 851550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* TX dma callback must be handled here, RX dma callback is 852550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * handled in tusb_omap_dma_cb. 853550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 854550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if ((int_src & TUSB_INT_SRC_TXRX_DMA_DONE)) { 855550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 dma_src = musb_readl(tbase, TUSB_DMA_INT_SRC); 856550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 real_dma_src = musb_readl(tbase, TUSB_DMA_INT_MASK); 857550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 8585c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "DMA IRQ %08x\n", dma_src); 859550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi real_dma_src = ~real_dma_src & dma_src; 860550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (tusb_dma_omap() && real_dma_src) { 861550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int tx_source = (real_dma_src & 0xffff); 862550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int i; 863550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 864550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi for (i = 1; i <= 15; i++) { 865550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (tx_source & (1 << i)) { 8665c8a86e10a7c164f44537fabdc169fd8b4e7a440Felipe Balbi dev_dbg(musb->controller, "completing ep%i %s\n", i, "tx"); 867550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_dma_completion(musb, i, 1); 868550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 869550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 870550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 871550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_DMA_INT_CLEAR, dma_src); 872550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 873550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 874550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* EP interrupts. In OCP mode tusb6010 mirrors the MUSB interrupts */ 875550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (int_src & (TUSB_INT_SRC_USB_IP_TX | TUSB_INT_SRC_USB_IP_RX)) { 876550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 musb_src = musb_readl(tbase, TUSB_USBIP_INT_SRC); 877550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 878550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_USBIP_INT_CLEAR, musb_src); 879550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->int_rx = (((musb_src >> 16) & 0xffff) << 1); 880550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->int_tx = (musb_src & 0xffff); 881550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } else { 882550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->int_rx = 0; 883550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->int_tx = 0; 884550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 885550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 886550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (int_src & (TUSB_INT_SRC_USB_IP_TX | TUSB_INT_SRC_USB_IP_RX | 0xff)) 887550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_interrupt(musb); 888550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 889550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Acknowledge TUSB interrupts. Clear only non-reserved bits */ 890550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_INT_SRC_CLEAR, 891550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int_src & ~TUSB_INT_MASK_RESERVED_BITS); 892550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 893743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi tusb_musb_try_idle(musb, idle_timeout); 894550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 895550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_INT_MASK, int_mask); 896550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi spin_unlock_irqrestore(&musb->lock, flags); 897550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 898550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return IRQ_HANDLED; 899550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 900550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 901550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbistatic int dma_off; 902550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 903550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 904550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Enables TUSB6010. Caller must take care of locking. 905550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * REVISIT: 906550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * - Check what is unnecessary in MGC_HdrcStart() 907550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 908743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic void tusb_musb_enable(struct musb *musb) 909550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 910550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 911550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 912550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Setup TUSB6010 main interrupt mask. Enable all interrupts except SOF. 913550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * REVISIT: Enable and deal with TUSB_INT_SRC_USB_IP_SOF */ 914550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_INT_MASK, TUSB_INT_SRC_USB_IP_SOF); 915550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 916550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Setup TUSB interrupt, disable DMA and GPIO interrupts */ 917550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_USBIP_INT_MASK, 0); 918550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_DMA_INT_MASK, 0x7fffffff); 919550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_GPIO_INT_MASK, 0x1ff); 920550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 921550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Clear all subsystem interrups */ 922550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_USBIP_INT_CLEAR, 0x7fffffff); 923550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_DMA_INT_CLEAR, 0x7fffffff); 924550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_GPIO_INT_CLEAR, 0x1ff); 925550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 926550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Acknowledge pending interrupt(s) */ 927550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_INT_SRC_CLEAR, ~TUSB_INT_MASK_RESERVED_BITS); 928550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 929550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Only 0 clock cycles for minimum interrupt de-assertion time and 930550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * interrupt polarity active low seems to work reliably here */ 931550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_INT_CTRL_CONF, 932550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_INT_CTRL_CONF_INT_RELCYC(0)); 933550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 934dced35aeb0367dda2636ee9ee914bda14510dcc9Thomas Gleixner irq_set_irq_type(musb->nIrq, IRQ_TYPE_LEVEL_LOW); 935550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 936550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* maybe force into the Default-A OTG state machine */ 937550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (!(musb_readl(tbase, TUSB_DEV_OTG_STAT) 938550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi & TUSB_DEV_OTG_STAT_ID_STATUS)) 939550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_INT_SRC_SET, 940550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_INT_SRC_ID_STATUS_CHNG); 941550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 942550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (is_dma_capable() && dma_off) 943550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi printk(KERN_WARNING "%s %s: dma not reactivated\n", 944550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi __FILE__, __func__); 945550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi else 946550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi dma_off = 1; 947550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 948550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 949550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 950550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Disables TUSB6010. Caller must take care of locking. 951550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 952743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic void tusb_musb_disable(struct musb *musb) 953550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 954550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 955550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 956550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* FIXME stop DMA, IRQs, timers, ... */ 957550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 958550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* disable all IRQs */ 959550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_INT_MASK, ~TUSB_INT_MASK_RESERVED_BITS); 960550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_USBIP_INT_MASK, 0x7fffffff); 961550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_DMA_INT_MASK, 0x7fffffff); 962550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_GPIO_INT_MASK, 0x1ff); 963550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 964550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi del_timer(&musb_idle_timer); 965550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 966550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (is_dma_capable() && !dma_off) { 967550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi printk(KERN_WARNING "%s %s: dma still active\n", 968550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi __FILE__, __func__); 969550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi dma_off = 1; 970550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 971550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 972550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 973550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi/* 974550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Sets up TUSB6010 CPU interface specific signals and registers 975550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Note: Settings optimized for OMAP24xx 976550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 977743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic void tusb_setup_cpu_interface(struct musb *musb) 978550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 979550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 980550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 981550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* 982550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Disable GPIO[5:0] pullups (used as output DMA requests) 983550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * Don't disable GPIO[7:6] as they are needed for wake-up. 984550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 985550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PULLUP_1_CTRL, 0x0000003F); 986550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 987550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Disable all pullups on NOR IF, DMAREQ0 and DMAREQ1 */ 988550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PULLUP_2_CTRL, 0x01FFFFFF); 989550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 990550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Turn GPIO[5:0] to DMAREQ[5:0] signals */ 991550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_GPIO_CONF, TUSB_GPIO_CONF_DMAREQ(0x3f)); 992550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 993550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Burst size 16x16 bits, all six DMA requests enabled, DMA request 994550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * de-assertion time 2 system clocks p 62 */ 995550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_DMA_REQ_CONF, 996550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_DMA_REQ_CONF_BURST_SIZE(2) | 997550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_DMA_REQ_CONF_DMA_REQ_EN(0x3f) | 998550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_DMA_REQ_CONF_DMA_REQ_ASSER(2)); 999550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1000550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Set 0 wait count for synchronous burst access */ 1001550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_WAIT_COUNT, 1); 1002550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 1003550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1004743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic int tusb_musb_start(struct musb *musb) 1005550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 1006550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi void __iomem *tbase = musb->ctrl_base; 1007550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int ret = 0; 1008550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi unsigned long flags; 1009550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi u32 reg; 1010550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1011550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (musb->board_set_power) 1012550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ret = musb->board_set_power(1); 1013550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (ret != 0) { 1014550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi printk(KERN_ERR "tusb: Cannot enable TUSB6010\n"); 1015550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return ret; 1016550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 1017550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1018550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi spin_lock_irqsave(&musb->lock, flags); 1019550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1020550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (musb_readl(tbase, TUSB_PROD_TEST_RESET) != 1021550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_PROD_TEST_RESET_VAL) { 1022550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi printk(KERN_ERR "tusb: Unable to detect TUSB6010\n"); 1023550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi goto err; 1024550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 1025550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1026550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ret = tusb_print_revision(musb); 1027550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (ret < 2) { 1028550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi printk(KERN_ERR "tusb: Unsupported TUSB6010 revision %i\n", 1029550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ret); 1030550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi goto err; 1031550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 1032550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1033550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* The uint bit for "USB non-PDR interrupt enable" has to be 1 when 1034550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * NOR FLASH interface is used */ 1035550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_VLYNQ_CTRL, 8); 1036550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1037550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Select PHY free running 60MHz as a system clock */ 1038550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tusb_set_clock_source(musb, 1); 1039550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1040550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* VBus valid timer 1us, disable DFT/Debug and VLYNQ clocks for 1041550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * power saving, enable VBus detect and session end comparators, 1042550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * enable IDpullup, enable VBus charging */ 1043550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PRCM_MNGMT, 1044550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_PRCM_MNGMT_VBUS_VALID_TIMER(0xa) | 1045550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_PRCM_MNGMT_VBUS_VALID_FLT_EN | 1046550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_PRCM_MNGMT_OTG_SESS_END_EN | 1047550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN | 1048550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi TUSB_PRCM_MNGMT_OTG_ID_PULLUP); 1049550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi tusb_setup_cpu_interface(musb); 1050550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1051550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* simplify: always sense/pullup ID pins, as if in OTG mode */ 1052550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE); 1053550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg |= TUSB_PHY_OTG_CTRL_WRPROTECT | TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP; 1054550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PHY_OTG_CTRL_ENABLE, reg); 1055550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1056550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg = musb_readl(tbase, TUSB_PHY_OTG_CTRL); 1057550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi reg |= TUSB_PHY_OTG_CTRL_WRPROTECT | TUSB_PHY_OTG_CTRL_OTG_ID_PULLUP; 1058550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb_writel(tbase, TUSB_PHY_OTG_CTRL, reg); 1059550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1060550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi spin_unlock_irqrestore(&musb->lock, flags); 1061550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1062550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return 0; 1063550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1064550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbierr: 1065550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi spin_unlock_irqrestore(&musb->lock, flags); 1066550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1067550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (musb->board_set_power) 1068550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->board_set_power(0); 1069550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1070550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return -ENODEV; 1071550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 1072550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1073743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic int tusb_musb_init(struct musb *musb) 1074550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 1075550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi struct platform_device *pdev; 1076550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi struct resource *mem; 107784e250ffa76dddc1bad84e04248a27f442c25986David Brownell void __iomem *sync = NULL; 1078550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi int ret; 1079550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 108084e250ffa76dddc1bad84e04248a27f442c25986David Brownell usb_nop_xceiv_register(); 1081b96d3b08365f5a9603f50f3aadca6012f7eaffa1Heikki Krogerus musb->xceiv = usb_get_transceiver(); 108284e250ffa76dddc1bad84e04248a27f442c25986David Brownell if (!musb->xceiv) 108384e250ffa76dddc1bad84e04248a27f442c25986David Brownell return -ENODEV; 108484e250ffa76dddc1bad84e04248a27f442c25986David Brownell 1085550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi pdev = to_platform_device(musb->controller); 1086550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1087550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* dma address for async dma */ 1088550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1089550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->async = mem->start; 1090550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1091550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* dma address for sync dma */ 1092550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1093550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (!mem) { 1094550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi pr_debug("no sync dma resource?\n"); 109584e250ffa76dddc1bad84e04248a27f442c25986David Brownell ret = -ENODEV; 109684e250ffa76dddc1bad84e04248a27f442c25986David Brownell goto done; 1097550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 1098550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->sync = mem->start; 1099550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 11003d268645d50989bc874fadf20db6fd6d17b380dcFelipe Balbi sync = ioremap(mem->start, resource_size(mem)); 1101550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (!sync) { 1102550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi pr_debug("ioremap for sync failed\n"); 110384e250ffa76dddc1bad84e04248a27f442c25986David Brownell ret = -ENOMEM; 110484e250ffa76dddc1bad84e04248a27f442c25986David Brownell goto done; 1105550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 1106550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->sync_va = sync; 1107550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1108550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi /* Offsets from base: VLYNQ at 0x000, MUSB regs at 0x400, 1109550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi * FIFOs at 0x600, TUSB at 0x800 1110550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi */ 1111550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->mregs += TUSB_BASE_OFFSET; 1112550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1113743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi ret = tusb_musb_start(musb); 1114550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (ret) { 1115550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi printk(KERN_ERR "Could not start tusb6010 (%d)\n", 1116550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi ret); 111784e250ffa76dddc1bad84e04248a27f442c25986David Brownell goto done; 1118550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi } 1119743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi musb->isr = tusb_musb_interrupt; 1120550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 112184e250ffa76dddc1bad84e04248a27f442c25986David Brownell if (is_peripheral_enabled(musb)) { 112284e250ffa76dddc1bad84e04248a27f442c25986David Brownell musb->xceiv->set_power = tusb_draw_power; 112384e250ffa76dddc1bad84e04248a27f442c25986David Brownell the_musb = musb; 112484e250ffa76dddc1bad84e04248a27f442c25986David Brownell } 1125550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1126550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); 1127550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 112884e250ffa76dddc1bad84e04248a27f442c25986David Brownelldone: 112984e250ffa76dddc1bad84e04248a27f442c25986David Brownell if (ret < 0) { 113084e250ffa76dddc1bad84e04248a27f442c25986David Brownell if (sync) 113184e250ffa76dddc1bad84e04248a27f442c25986David Brownell iounmap(sync); 1132f405387435a85a440d1ce16f3ca36e042281643aSergei Shtylyov 1133b96d3b08365f5a9603f50f3aadca6012f7eaffa1Heikki Krogerus usb_put_transceiver(musb->xceiv); 113484e250ffa76dddc1bad84e04248a27f442c25986David Brownell usb_nop_xceiv_unregister(); 113584e250ffa76dddc1bad84e04248a27f442c25986David Brownell } 1136550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return ret; 1137550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 1138550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1139743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbistatic int tusb_musb_exit(struct musb *musb) 1140550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi{ 1141550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi del_timer_sync(&musb_idle_timer); 114284e250ffa76dddc1bad84e04248a27f442c25986David Brownell the_musb = NULL; 1143550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1144550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi if (musb->board_set_power) 1145550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi musb->board_set_power(0); 1146550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi 1147550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi iounmap(musb->sync_va); 1148f405387435a85a440d1ce16f3ca36e042281643aSergei Shtylyov 1149b96d3b08365f5a9603f50f3aadca6012f7eaffa1Heikki Krogerus usb_put_transceiver(musb->xceiv); 115084e250ffa76dddc1bad84e04248a27f442c25986David Brownell usb_nop_xceiv_unregister(); 1151550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi return 0; 1152550a7375fe720924241f0eb76e4a5c1a3eb8c32fFelipe Balbi} 1153743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi 1154f7ec94370f417fedad4db1054228ef958d48b926Felipe Balbistatic const struct musb_platform_ops tusb_ops = { 1155743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi .init = tusb_musb_init, 1156743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi .exit = tusb_musb_exit, 1157743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi 1158743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi .enable = tusb_musb_enable, 1159743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi .disable = tusb_musb_disable, 1160743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi 1161743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi .set_mode = tusb_musb_set_mode, 1162743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi .try_idle = tusb_musb_try_idle, 1163743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi 1164743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi .vbus_status = tusb_musb_vbus_status, 1165743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi .set_vbus = tusb_musb_set_vbus, 1166743411b3f3e96e8ac4cae73551a0a95392fed1eaFelipe Balbi}; 116718688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 116818688fbeb09665725c842291bbadd88295a359e1Felipe Balbistatic u64 tusb_dmamask = DMA_BIT_MASK(32); 116918688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 1170e9e8c85e69310141d78daaecd6a56138700ac317Felipe Balbistatic int __devinit tusb_probe(struct platform_device *pdev) 117118688fbeb09665725c842291bbadd88295a359e1Felipe Balbi{ 117218688fbeb09665725c842291bbadd88295a359e1Felipe Balbi struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; 117318688fbeb09665725c842291bbadd88295a359e1Felipe Balbi struct platform_device *musb; 11741add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi struct tusb6010_glue *glue; 117518688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 117618688fbeb09665725c842291bbadd88295a359e1Felipe Balbi int ret = -ENOMEM; 117718688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 11781add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi glue = kzalloc(sizeof(*glue), GFP_KERNEL); 11791add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi if (!glue) { 11801add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi dev_err(&pdev->dev, "failed to allocate glue context\n"); 11811add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi goto err0; 11821add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi } 11831add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi 118418688fbeb09665725c842291bbadd88295a359e1Felipe Balbi musb = platform_device_alloc("musb-hdrc", -1); 118518688fbeb09665725c842291bbadd88295a359e1Felipe Balbi if (!musb) { 118618688fbeb09665725c842291bbadd88295a359e1Felipe Balbi dev_err(&pdev->dev, "failed to allocate musb device\n"); 11871add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi goto err1; 118818688fbeb09665725c842291bbadd88295a359e1Felipe Balbi } 118918688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 119018688fbeb09665725c842291bbadd88295a359e1Felipe Balbi musb->dev.parent = &pdev->dev; 119118688fbeb09665725c842291bbadd88295a359e1Felipe Balbi musb->dev.dma_mask = &tusb_dmamask; 119218688fbeb09665725c842291bbadd88295a359e1Felipe Balbi musb->dev.coherent_dma_mask = tusb_dmamask; 119318688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 11941add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi glue->dev = &pdev->dev; 11951add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi glue->musb = musb; 11961add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi 1197f7ec94370f417fedad4db1054228ef958d48b926Felipe Balbi pdata->platform_ops = &tusb_ops; 1198f7ec94370f417fedad4db1054228ef958d48b926Felipe Balbi 11991add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi platform_set_drvdata(pdev, glue); 120018688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 120118688fbeb09665725c842291bbadd88295a359e1Felipe Balbi ret = platform_device_add_resources(musb, pdev->resource, 120218688fbeb09665725c842291bbadd88295a359e1Felipe Balbi pdev->num_resources); 120318688fbeb09665725c842291bbadd88295a359e1Felipe Balbi if (ret) { 120418688fbeb09665725c842291bbadd88295a359e1Felipe Balbi dev_err(&pdev->dev, "failed to add resources\n"); 12051add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi goto err2; 120618688fbeb09665725c842291bbadd88295a359e1Felipe Balbi } 120718688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 120818688fbeb09665725c842291bbadd88295a359e1Felipe Balbi ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); 120918688fbeb09665725c842291bbadd88295a359e1Felipe Balbi if (ret) { 121018688fbeb09665725c842291bbadd88295a359e1Felipe Balbi dev_err(&pdev->dev, "failed to add platform_data\n"); 12111add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi goto err2; 121218688fbeb09665725c842291bbadd88295a359e1Felipe Balbi } 121318688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 121418688fbeb09665725c842291bbadd88295a359e1Felipe Balbi ret = platform_device_add(musb); 121518688fbeb09665725c842291bbadd88295a359e1Felipe Balbi if (ret) { 121618688fbeb09665725c842291bbadd88295a359e1Felipe Balbi dev_err(&pdev->dev, "failed to register musb device\n"); 121718688fbeb09665725c842291bbadd88295a359e1Felipe Balbi goto err1; 121818688fbeb09665725c842291bbadd88295a359e1Felipe Balbi } 121918688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 122018688fbeb09665725c842291bbadd88295a359e1Felipe Balbi return 0; 122118688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 12221add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbierr2: 122318688fbeb09665725c842291bbadd88295a359e1Felipe Balbi platform_device_put(musb); 122418688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 12251add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbierr1: 12261add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi kfree(glue); 12271add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi 122818688fbeb09665725c842291bbadd88295a359e1Felipe Balbierr0: 122918688fbeb09665725c842291bbadd88295a359e1Felipe Balbi return ret; 123018688fbeb09665725c842291bbadd88295a359e1Felipe Balbi} 123118688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 1232e9e8c85e69310141d78daaecd6a56138700ac317Felipe Balbistatic int __devexit tusb_remove(struct platform_device *pdev) 123318688fbeb09665725c842291bbadd88295a359e1Felipe Balbi{ 12341add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi struct tusb6010_glue *glue = platform_get_drvdata(pdev); 123518688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 12361add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi platform_device_del(glue->musb); 12371add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi platform_device_put(glue->musb); 12381add75d2bd1a44553e2c40e30db5f90a500dc1abFelipe Balbi kfree(glue); 123918688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 124018688fbeb09665725c842291bbadd88295a359e1Felipe Balbi return 0; 124118688fbeb09665725c842291bbadd88295a359e1Felipe Balbi} 124218688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 124318688fbeb09665725c842291bbadd88295a359e1Felipe Balbistatic struct platform_driver tusb_driver = { 1244e9e8c85e69310141d78daaecd6a56138700ac317Felipe Balbi .probe = tusb_probe, 1245e9e8c85e69310141d78daaecd6a56138700ac317Felipe Balbi .remove = __devexit_p(tusb_remove), 124618688fbeb09665725c842291bbadd88295a359e1Felipe Balbi .driver = { 124718688fbeb09665725c842291bbadd88295a359e1Felipe Balbi .name = "musb-tusb", 124818688fbeb09665725c842291bbadd88295a359e1Felipe Balbi }, 124918688fbeb09665725c842291bbadd88295a359e1Felipe Balbi}; 125018688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 125118688fbeb09665725c842291bbadd88295a359e1Felipe BalbiMODULE_DESCRIPTION("TUSB6010 MUSB Glue Layer"); 125218688fbeb09665725c842291bbadd88295a359e1Felipe BalbiMODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 125318688fbeb09665725c842291bbadd88295a359e1Felipe BalbiMODULE_LICENSE("GPL v2"); 125418688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 125518688fbeb09665725c842291bbadd88295a359e1Felipe Balbistatic int __init tusb_init(void) 125618688fbeb09665725c842291bbadd88295a359e1Felipe Balbi{ 1257e9e8c85e69310141d78daaecd6a56138700ac317Felipe Balbi return platform_driver_register(&tusb_driver); 125818688fbeb09665725c842291bbadd88295a359e1Felipe Balbi} 1259e9e8c85e69310141d78daaecd6a56138700ac317Felipe Balbimodule_init(tusb_init); 126018688fbeb09665725c842291bbadd88295a359e1Felipe Balbi 126118688fbeb09665725c842291bbadd88295a359e1Felipe Balbistatic void __exit tusb_exit(void) 126218688fbeb09665725c842291bbadd88295a359e1Felipe Balbi{ 126318688fbeb09665725c842291bbadd88295a359e1Felipe Balbi platform_driver_unregister(&tusb_driver); 126418688fbeb09665725c842291bbadd88295a359e1Felipe Balbi} 126518688fbeb09665725c842291bbadd88295a359e1Felipe Balbimodule_exit(tusb_exit); 1266