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