1 /* 2 * MUSB OTG driver virtual root hub support 3 * 4 * Copyright 2005 Mentor Graphics Corporation 5 * Copyright (C) 2005-2006 by Texas Instruments 6 * Copyright (C) 2006-2007 Nokia Corporation 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 * 22 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 25 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35 #include <linux/module.h> 36 #include <linux/kernel.h> 37 #include <linux/sched.h> 38 #include <linux/errno.h> 39 #include <linux/init.h> 40 #include <linux/time.h> 41 #include <linux/timer.h> 42 43 #include <asm/unaligned.h> 44 45 #include "musb_core.h" 46 47 48 static void musb_port_suspend(struct musb *musb, bool do_suspend) 49 { 50 struct usb_otg *otg = musb->xceiv->otg; 51 u8 power; 52 void __iomem *mbase = musb->mregs; 53 54 if (!is_host_active(musb)) 55 return; 56 57 /* NOTE: this doesn't necessarily put PHY into low power mode, 58 * turning off its clock; that's a function of PHY integration and 59 * MUSB_POWER_ENSUSPEND. PHY may need a clock (sigh) to detect 60 * SE0 changing to connect (J) or wakeup (K) states. 61 */ 62 power = musb_readb(mbase, MUSB_POWER); 63 if (do_suspend) { 64 int retries = 10000; 65 66 power &= ~MUSB_POWER_RESUME; 67 power |= MUSB_POWER_SUSPENDM; 68 musb_writeb(mbase, MUSB_POWER, power); 69 70 /* Needed for OPT A tests */ 71 power = musb_readb(mbase, MUSB_POWER); 72 while (power & MUSB_POWER_SUSPENDM) { 73 power = musb_readb(mbase, MUSB_POWER); 74 if (retries-- < 1) 75 break; 76 } 77 78 dev_dbg(musb->controller, "Root port suspended, power %02x\n", power); 79 80 musb->port1_status |= USB_PORT_STAT_SUSPEND; 81 switch (musb->xceiv->state) { 82 case OTG_STATE_A_HOST: 83 musb->xceiv->state = OTG_STATE_A_SUSPEND; 84 musb->is_active = is_otg_enabled(musb) 85 && otg->host->b_hnp_enable; 86 if (musb->is_active) 87 mod_timer(&musb->otg_timer, jiffies 88 + msecs_to_jiffies( 89 OTG_TIME_A_AIDL_BDIS)); 90 musb_platform_try_idle(musb, 0); 91 break; 92 case OTG_STATE_B_HOST: 93 musb->xceiv->state = OTG_STATE_B_WAIT_ACON; 94 musb->is_active = is_otg_enabled(musb) 95 && otg->host->b_hnp_enable; 96 musb_platform_try_idle(musb, 0); 97 break; 98 default: 99 dev_dbg(musb->controller, "bogus rh suspend? %s\n", 100 otg_state_string(musb->xceiv->state)); 101 } 102 } else if (power & MUSB_POWER_SUSPENDM) { 103 power &= ~MUSB_POWER_SUSPENDM; 104 power |= MUSB_POWER_RESUME; 105 musb_writeb(mbase, MUSB_POWER, power); 106 107 dev_dbg(musb->controller, "Root port resuming, power %02x\n", power); 108 109 /* later, GetPortStatus will stop RESUME signaling */ 110 musb->port1_status |= MUSB_PORT_STAT_RESUME; 111 musb->rh_timer = jiffies + msecs_to_jiffies(20); 112 } 113 } 114 115 static void musb_port_reset(struct musb *musb, bool do_reset) 116 { 117 u8 power; 118 void __iomem *mbase = musb->mregs; 119 120 if (musb->xceiv->state == OTG_STATE_B_IDLE) { 121 dev_dbg(musb->controller, "HNP: Returning from HNP; no hub reset from b_idle\n"); 122 musb->port1_status &= ~USB_PORT_STAT_RESET; 123 return; 124 } 125 126 if (!is_host_active(musb)) 127 return; 128 129 /* NOTE: caller guarantees it will turn off the reset when 130 * the appropriate amount of time has passed 131 */ 132 power = musb_readb(mbase, MUSB_POWER); 133 if (do_reset) { 134 135 /* 136 * If RESUME is set, we must make sure it stays minimum 20 ms. 137 * Then we must clear RESUME and wait a bit to let musb start 138 * generating SOFs. If we don't do this, OPT HS A 6.8 tests 139 * fail with "Error! Did not receive an SOF before suspend 140 * detected". 141 */ 142 if (power & MUSB_POWER_RESUME) { 143 while (time_before(jiffies, musb->rh_timer)) 144 msleep(1); 145 musb_writeb(mbase, MUSB_POWER, 146 power & ~MUSB_POWER_RESUME); 147 msleep(1); 148 } 149 150 musb->ignore_disconnect = true; 151 power &= 0xf0; 152 musb_writeb(mbase, MUSB_POWER, 153 power | MUSB_POWER_RESET); 154 155 musb->port1_status |= USB_PORT_STAT_RESET; 156 musb->port1_status &= ~USB_PORT_STAT_ENABLE; 157 musb->rh_timer = jiffies + msecs_to_jiffies(50); 158 } else { 159 dev_dbg(musb->controller, "root port reset stopped\n"); 160 musb_writeb(mbase, MUSB_POWER, 161 power & ~MUSB_POWER_RESET); 162 163 musb->ignore_disconnect = false; 164 165 power = musb_readb(mbase, MUSB_POWER); 166 if (power & MUSB_POWER_HSMODE) { 167 dev_dbg(musb->controller, "high-speed device connected\n"); 168 musb->port1_status |= USB_PORT_STAT_HIGH_SPEED; 169 } 170 171 musb->port1_status &= ~USB_PORT_STAT_RESET; 172 musb->port1_status |= USB_PORT_STAT_ENABLE 173 | (USB_PORT_STAT_C_RESET << 16) 174 | (USB_PORT_STAT_C_ENABLE << 16); 175 usb_hcd_poll_rh_status(musb_to_hcd(musb)); 176 177 musb->vbuserr_retry = VBUSERR_RETRY_COUNT; 178 } 179 } 180 181 void musb_root_disconnect(struct musb *musb) 182 { 183 struct usb_otg *otg = musb->xceiv->otg; 184 185 musb->port1_status = USB_PORT_STAT_POWER 186 | (USB_PORT_STAT_C_CONNECTION << 16); 187 188 usb_hcd_poll_rh_status(musb_to_hcd(musb)); 189 musb->is_active = 0; 190 191 switch (musb->xceiv->state) { 192 case OTG_STATE_A_SUSPEND: 193 if (is_otg_enabled(musb) 194 && otg->host->b_hnp_enable) { 195 musb->xceiv->state = OTG_STATE_A_PERIPHERAL; 196 musb->g.is_a_peripheral = 1; 197 break; 198 } 199 /* FALLTHROUGH */ 200 case OTG_STATE_A_HOST: 201 musb->xceiv->state = OTG_STATE_A_WAIT_BCON; 202 musb->is_active = 0; 203 break; 204 case OTG_STATE_A_WAIT_VFALL: 205 musb->xceiv->state = OTG_STATE_B_IDLE; 206 break; 207 default: 208 dev_dbg(musb->controller, "host disconnect (%s)\n", 209 otg_state_string(musb->xceiv->state)); 210 } 211 } 212 213 214 /*---------------------------------------------------------------------*/ 215 216 /* Caller may or may not hold musb->lock */ 217 int musb_hub_status_data(struct usb_hcd *hcd, char *buf) 218 { 219 struct musb *musb = hcd_to_musb(hcd); 220 int retval = 0; 221 222 /* called in_irq() via usb_hcd_poll_rh_status() */ 223 if (musb->port1_status & 0xffff0000) { 224 *buf = 0x02; 225 retval = 1; 226 } 227 return retval; 228 } 229 230 int musb_hub_control( 231 struct usb_hcd *hcd, 232 u16 typeReq, 233 u16 wValue, 234 u16 wIndex, 235 char *buf, 236 u16 wLength) 237 { 238 struct musb *musb = hcd_to_musb(hcd); 239 u32 temp; 240 int retval = 0; 241 unsigned long flags; 242 243 spin_lock_irqsave(&musb->lock, flags); 244 245 if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) { 246 spin_unlock_irqrestore(&musb->lock, flags); 247 return -ESHUTDOWN; 248 } 249 250 /* hub features: always zero, setting is a NOP 251 * port features: reported, sometimes updated when host is active 252 * no indicators 253 */ 254 switch (typeReq) { 255 case ClearHubFeature: 256 case SetHubFeature: 257 switch (wValue) { 258 case C_HUB_OVER_CURRENT: 259 case C_HUB_LOCAL_POWER: 260 break; 261 default: 262 goto error; 263 } 264 break; 265 case ClearPortFeature: 266 if ((wIndex & 0xff) != 1) 267 goto error; 268 269 switch (wValue) { 270 case USB_PORT_FEAT_ENABLE: 271 break; 272 case USB_PORT_FEAT_SUSPEND: 273 musb_port_suspend(musb, false); 274 break; 275 case USB_PORT_FEAT_POWER: 276 if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) 277 musb_platform_set_vbus(musb, 0); 278 break; 279 case USB_PORT_FEAT_C_CONNECTION: 280 case USB_PORT_FEAT_C_ENABLE: 281 case USB_PORT_FEAT_C_OVER_CURRENT: 282 case USB_PORT_FEAT_C_RESET: 283 case USB_PORT_FEAT_C_SUSPEND: 284 break; 285 default: 286 goto error; 287 } 288 dev_dbg(musb->controller, "clear feature %d\n", wValue); 289 musb->port1_status &= ~(1 << wValue); 290 break; 291 case GetHubDescriptor: 292 { 293 struct usb_hub_descriptor *desc = (void *)buf; 294 295 desc->bDescLength = 9; 296 desc->bDescriptorType = 0x29; 297 desc->bNbrPorts = 1; 298 desc->wHubCharacteristics = cpu_to_le16( 299 0x0001 /* per-port power switching */ 300 | 0x0010 /* no overcurrent reporting */ 301 ); 302 desc->bPwrOn2PwrGood = 5; /* msec/2 */ 303 desc->bHubContrCurrent = 0; 304 305 /* workaround bogus struct definition */ 306 desc->u.hs.DeviceRemovable[0] = 0x02; /* port 1 */ 307 desc->u.hs.DeviceRemovable[1] = 0xff; 308 } 309 break; 310 case GetHubStatus: 311 temp = 0; 312 *(__le32 *) buf = cpu_to_le32(temp); 313 break; 314 case GetPortStatus: 315 if (wIndex != 1) 316 goto error; 317 318 /* finish RESET signaling? */ 319 if ((musb->port1_status & USB_PORT_STAT_RESET) 320 && time_after_eq(jiffies, musb->rh_timer)) 321 musb_port_reset(musb, false); 322 323 /* finish RESUME signaling? */ 324 if ((musb->port1_status & MUSB_PORT_STAT_RESUME) 325 && time_after_eq(jiffies, musb->rh_timer)) { 326 u8 power; 327 328 power = musb_readb(musb->mregs, MUSB_POWER); 329 power &= ~MUSB_POWER_RESUME; 330 dev_dbg(musb->controller, "root port resume stopped, power %02x\n", 331 power); 332 musb_writeb(musb->mregs, MUSB_POWER, power); 333 334 /* ISSUE: DaVinci (RTL 1.300) disconnects after 335 * resume of high speed peripherals (but not full 336 * speed ones). 337 */ 338 339 musb->is_active = 1; 340 musb->port1_status &= ~(USB_PORT_STAT_SUSPEND 341 | MUSB_PORT_STAT_RESUME); 342 musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; 343 usb_hcd_poll_rh_status(musb_to_hcd(musb)); 344 /* NOTE: it might really be A_WAIT_BCON ... */ 345 musb->xceiv->state = OTG_STATE_A_HOST; 346 } 347 348 put_unaligned(cpu_to_le32(musb->port1_status 349 & ~MUSB_PORT_STAT_RESUME), 350 (__le32 *) buf); 351 352 /* port change status is more interesting */ 353 dev_dbg(musb->controller, "port status %08x\n", 354 musb->port1_status); 355 break; 356 case SetPortFeature: 357 if ((wIndex & 0xff) != 1) 358 goto error; 359 360 switch (wValue) { 361 case USB_PORT_FEAT_POWER: 362 /* NOTE: this controller has a strange state machine 363 * that involves "requesting sessions" according to 364 * magic side effects from incompletely-described 365 * rules about startup... 366 * 367 * This call is what really starts the host mode; be 368 * very careful about side effects if you reorder any 369 * initialization logic, e.g. for OTG, or change any 370 * logic relating to VBUS power-up. 371 */ 372 if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) 373 musb_start(musb); 374 break; 375 case USB_PORT_FEAT_RESET: 376 musb_port_reset(musb, true); 377 break; 378 case USB_PORT_FEAT_SUSPEND: 379 musb_port_suspend(musb, true); 380 break; 381 case USB_PORT_FEAT_TEST: 382 if (unlikely(is_host_active(musb))) 383 goto error; 384 385 wIndex >>= 8; 386 switch (wIndex) { 387 case 1: 388 pr_debug("TEST_J\n"); 389 temp = MUSB_TEST_J; 390 break; 391 case 2: 392 pr_debug("TEST_K\n"); 393 temp = MUSB_TEST_K; 394 break; 395 case 3: 396 pr_debug("TEST_SE0_NAK\n"); 397 temp = MUSB_TEST_SE0_NAK; 398 break; 399 case 4: 400 pr_debug("TEST_PACKET\n"); 401 temp = MUSB_TEST_PACKET; 402 musb_load_testpacket(musb); 403 break; 404 case 5: 405 pr_debug("TEST_FORCE_ENABLE\n"); 406 temp = MUSB_TEST_FORCE_HOST 407 | MUSB_TEST_FORCE_HS; 408 409 musb_writeb(musb->mregs, MUSB_DEVCTL, 410 MUSB_DEVCTL_SESSION); 411 break; 412 case 6: 413 pr_debug("TEST_FIFO_ACCESS\n"); 414 temp = MUSB_TEST_FIFO_ACCESS; 415 break; 416 default: 417 goto error; 418 } 419 musb_writeb(musb->mregs, MUSB_TESTMODE, temp); 420 break; 421 default: 422 goto error; 423 } 424 dev_dbg(musb->controller, "set feature %d\n", wValue); 425 musb->port1_status |= 1 << wValue; 426 break; 427 428 default: 429 error: 430 /* "protocol stall" on error */ 431 retval = -EPIPE; 432 } 433 spin_unlock_irqrestore(&musb->lock, flags); 434 return retval; 435 } 436