1.硬件原理图

看下面的原理图

VCC_OTG_EN 引脚,这个脚主要是用来控制给外部OTG设备提供电源控制的。如果设备作为DEVICE设备,这时候VBUS的电是由外部提供的,比如通过USB线和电脑连接,这个时候,VBUS的电压是由电脑提供的。

如果设备作为HOST设备,比如连接U盘,我们需要给U盘提供VBUS电压,就需要控制VCC_OTG_EN引脚给VBUS提供电压。

USB_OTG_ID 脚

这个脚用来判断有OTG设备插入

VBUS电压检测,这个电路看不懂有什么作用,硬件设计预期是希望如果有外部的USB设备给设备供电,就切换模式,但是实际上,不管设备作为HOST还是DEVICE,这个电压会一直存在。所以总觉得这个设计有点问题。

ID脚电压,没有插入OTG设备的时候,电压是1.79v,插入OTG设备的时候,电压是 0V。

2.软件控制

dts 部分

&usb0 {pinctrl-names = "iddig_irq_init", "drvvbus_init", "drvvbus_low", "drvvbus_high";pinctrl-0 = <&usb0_iddig>;pinctrl-1 = <&usb0_drvvbus>;pinctrl-2 = <&usb0_drvvbus_low>;pinctrl-3 = <&usb0_drvvbus_high>;usb-power-supply = <&mt6392_vusb_reg>;drvvbus_gpio = <&pio 0 2>;iddig_gpio = <&pio 41 2>;status = "okay";
};774 /* USB GPIO start */
775         usb0_drvvbus: drvvbus_init {
776                 pins_cmd_dat {
777                         pins = <MT8167_PIN_0_EINT0__FUNC_GPIO0>;
778                         output-low;
779                 };
780         };
781
782         usb0_drvvbus_high: drvvbus_high {
783                 pins_cmd_dat {
784                         pins = <MT8167_PIN_0_EINT0__FUNC_GPIO0>;
785                         slew-rate = <1>;
786                         output-high;
787                 };
788         };
789
790         usb0_drvvbus_low: drvvbus_low {
791                 pins_cmd_dat {
792                         pins = <MT8167_PIN_0_EINT0__FUNC_GPIO0>;
793                         slew-rate = <1>;
794                         output-low;
795                 };
796         };
797         usb0_iddig: iddig_irq_init {
798                 pins_cmd_dat {
799                         pins = <MT8167_PIN_41_KPROW1__FUNC_IDDIG>;
800                         slew-rate = <0>;
801                         bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
802                 };
803         };
804 /* USB GPIO end */

引脚初始化部分

void mt_usb_init_drvvbus(void)
{
#if (!(defined(SWITCH_CHARGER) || defined(FPGA_PLATFORM))) && !(defined(OTG_BOOST_BY_SWITCH_CHARGER))
#ifdef CONFIG_OF
#if defined(CONFIG_MTK_LEGACY)mt_set_gpio_mode(drvvbus_pin, drvvbus_pin_mode);/*should set GPIO2 as gpio mode.*/mt_set_gpio_dir(drvvbus_pin, GPIO_DIR_OUT);mt_get_gpio_pull_enable(drvvbus_pin);mt_set_gpio_pull_select(drvvbus_pin, GPIO_PULL_UP);
#elseint ret = 0;DBG(0, "****%s:%d Init Drive VBUS!!!!!\n", __func__, __LINE__);if (drvvbus_pin < 0)return;if (IS_ERR(pinctrl))return;pinctrl_drvvbus = pinctrl_lookup_state(pinctrl, "drvvbus_init");if (IS_ERR(pinctrl_drvvbus)) {ret = PTR_ERR(pinctrl_drvvbus);dev_err(mtk_musb->controller, "Cannot find usb pinctrl drvvbus\n");}pinctrl_drvvbus_low = pinctrl_lookup_state(pinctrl, "drvvbus_low");if (IS_ERR(pinctrl_drvvbus_low)) {ret = PTR_ERR(pinctrl_drvvbus_low);dev_err(mtk_musb->controller, "Cannot find usb pinctrl drvvbus_low\n");}pinctrl_drvvbus_high = pinctrl_lookup_state(pinctrl, "drvvbus_high");if (IS_ERR(pinctrl_drvvbus_high)) {ret = PTR_ERR(pinctrl_drvvbus_high);dev_err(mtk_musb->controller, "Cannot find usb pinctrl drvvbus_high\n");}if (!IS_ERR(pinctrl_drvvbus)) {pinctrl_select_state(pinctrl, pinctrl_drvvbus);DBG(0, "****%s:%d end Init Drive VBUS KS!!!!!\n", __func__, __LINE__);}
#endif
#elsemt_set_gpio_mode(GPIO_OTG_DRVVBUS_PIN, GPIO_OTG_DRVVBUS_PIN_M_GPIO);/*should set GPIO2 as gpio mode.*/mt_set_gpio_dir(GPIO_OTG_DRVVBUS_PIN, GPIO_DIR_OUT);mt_get_gpio_pull_enable(GPIO_OTG_DRVVBUS_PIN);mt_set_gpio_pull_select(GPIO_OTG_DRVVBUS_PIN, GPIO_PULL_UP);
#endif
#endif
}

ID 引脚初始化部分

static void otg_int_init(void)
{
#if CONFIG_OF
#if defined(CONFIG_MTK_LEGACY)mt_set_gpio_mode(iddig_pin, GPIO_MODE_00);mt_set_gpio_dir(iddig_pin, GPIO_DIR_IN);mt_set_gpio_pull_enable(iddig_pin, GPIO_PULL_ENABLE);mt_set_gpio_pull_select(iddig_pin, GPIO_PULL_UP);mt_eint_set_sens(IDDIG_EINT_PIN, MT_LEVEL_SENSITIVE);mt_eint_set_hw_debounce(IDDIG_EINT_PIN, 64);mt_eint_registration(IDDIG_EINT_PIN, EINTF_TRIGGER_LOW, mt_usb_ext_iddig_int, FALSE);
#elseint ret = 0;DBG(0, "****%s:%d before Init IDDIG KS!!!!!\n", __func__, __LINE__);if (iddig_pin < 0) {DBG(0, "iddig_pin is invalid:%d\n", iddig_pin);return;}pinctrl_iddig = pinctrl_lookup_state(pinctrl, "iddig_irq_init");if (IS_ERR(pinctrl_iddig)) {ret = PTR_ERR(pinctrl_iddig);DBG(0, "Cannot find usb pinctrl iddig_irq_init\n");}if (IS_ERR(pinctrl) || IS_ERR(pinctrl_iddig)) {DBG(0, "pinctrl or pinctrl_iddig error\n");return;}pinctrl_select_state(pinctrl, pinctrl_iddig);DBG(0, "usb iddig_pin %d\n", iddig_pin);#if 0gpio_set_debounce(iddig_pin, 64000);DBG(0, "will call __gpio_to_irq\n");
#endifusb_iddig_number = __gpio_to_irq(iddig_pin);DBG(0, "usb usb_iddig_number %d\n", usb_iddig_number);ret = request_irq(usb_iddig_number, mt_usb_ext_iddig_int, IRQF_TRIGGER_LOW, "USB_IDDIG", NULL);if (ret > 0)DBG(0, "USB IDDIG IRQ LINE not available!!\n");elseDBG(0, "USB IDDIG IRQ LINE available!!\n");irq_set_irq_wake(usb_iddig_number, 1);
#endif
#elseu32 phy_id_pull = 0;phy_id_pull = __raw_readl(U2PHYDTM1);phy_id_pull |= ID_PULL_UP;__raw_writel(phy_id_pull, U2PHYDTM1);musb_writel(mtk_musb->mregs, USB_L1INTM, IDDIG_INT_STATUS | musb_readl(mtk_musb->mregs, USB_L1INTM));
#endif
}

USB 触发中断代码

/** handle all the irqs defined by the HDRC core. for now we expect:  other* irq sources (phy, dma, etc) will be handled first, musb->int_* values* will be assigned, and the irq will already have been acked.** called in irq context with spinlock held, irqs blocked*/
irqreturn_t musb_interrupt(struct musb *musb)
{irqreturn_t retval = IRQ_NONE;u8 devctl, power = 0;
#ifndef USE_SSUSB_QMUu32 reg = 0, ep_num = 0;
#endif#ifdef POWER_SAVING_MODEif (!(os_readl(U3D_SSUSB_U2_CTRL_0P) & SSUSB_U2_PORT_PDN)) {devctl = (u8) os_readl(U3D_DEVICE_CONTROL);power = (u8) os_readl(U3D_POWER_MANAGEMENT);} else {devctl = 0;power = 0;musb->int_usb = 0;}
#elsedevctl = (u8) os_readl(U3D_DEVICE_CONTROL);power = (u8) os_readl(U3D_POWER_MANAGEMENT);
#endif/* dev_dbg(musb->controller, "** IRQ %s usb%04x tx%04x rx%04x\n", */os_printk(K_DEBUG, "IRQ %s usb%04x tx%04x rx%04x\n",(devctl & USB_DEVCTL_HOSTMODE) ? "host" : "peripheral",musb->int_usb, musb->int_tx, musb->int_rx);if (unlikely(!musb->softconnect)) {os_printk(K_WARNIN, "!softconnect, IRQ %s usb%04x tx%04x rx%04x\n",(devctl & USB_DEVCTL_HOSTMODE) ? "host" : "peripheral",musb->int_usb, musb->int_tx, musb->int_rx);return IRQ_HANDLED;}/* the core can interrupt us for multiple reasons; docs have* a generic interrupt flowchart to follow*/if (musb->int_usb)retval |= musb_stage0_irq(musb, musb->int_usb, devctl, power);/* "stage 1" is handling endpoint irqs *//* handle endpoint 0 first */if (musb->int_tx & 1)retval |= musb_g_ep0_irq(musb);#ifndef USE_SSUSB_QMU/* RX on endpoints 1-15 */reg = musb->int_rx >> 1;ep_num = 1;while (reg) {if (reg & 1) {/* musb_ep_select(musb->mregs, ep_num); *//* REVISIT just retval = ep->rx_irq(...) */retval = IRQ_HANDLED;musb_g_rx(musb, ep_num);}reg >>= 1;ep_num++;}/* TX on endpoints 1-15 */reg = musb->int_tx >> 1;ep_num = 1;while (reg) {if (reg & 1) {/* musb_ep_select(musb->mregs, ep_num); *//* REVISIT just retval |= ep->tx_irq(...) */retval = IRQ_HANDLED;musb_g_tx(musb, ep_num);}reg >>= 1;ep_num++;}
#endifreturn retval;
}
EXPORT_SYMBOL_GPL(musb_interrupt);

中断函数注册,主要是在插入把拔出usb的时候产生中断

 /* attach to the IRQ */if (request_irq(musb->nIrq, musb->isr, IRQF_TRIGGER_LOW, dev_name(dev), musb)) {DBG(0, "request_irq %d failed!\n", musb->nIrq);status = -ENODEV;goto fail3;}

3.问题以及分析

我们项目遇到一个问题

插入OTG设备后,再拔掉,仍是OTG模式,没检测到OTG设备拔出

插入OTG设备和拔开OTG设备的软件日志

====插入OTG====
[1623:kworker/0:2][MUSB]musb_id_pin_work 376: work start, is_host=0
[1623:kworker/0:2][MUSB]musb_is_host 231: will mask PMIC charger detection
[1623:kworker/0:2][MUSB]musb_is_host 254: iddig_state = 0
[1623:kworker/0:2][MUSB]musb_is_host 283: usb_is_host = 1
[1623:kworker/0:2][MUSB]musb_id_pin_work 384: musb is as host, already lock
[1623:kworker/0:2][MUSB]musb_id_pin_work 424: force PHY to host mode, 0x6d=3e, 0x6c=2c
[1623:kworker/0:2][MUSB]musb_start 1290: start, is_host=1 is_active=0
[1623:kworker/0:2][MUSB]musb_id_pin_work 464: work end, is_host=1
[1623:kworker/0:2]musb-hdrc musb-hdrc: prop=1, power=1, is_host=1
[1623:kworker/0:2]musb-hdrc musb-hdrc: prop=2, power=1, is_host=1
[1623:kworker/0:2]musb-hdrc musb-hdrc: prop=3, power=1, is_host=1
[646:usb@1.1-service]musb-hdrc musb-hdrc: prop=2, power=1, is_host=1
[646:usb@1.1-service]musb-hdrc musb-hdrc: prop=3, power=1, is_host=1
[646:usb@1.1-service]musb-hdrc musb-hdrc: prop=1, power=1, is_host=1
[0:swapper/0][MUSB]musb_stage0_irq 1102: CONNECT (a_host) devctl 5d
[1623:kworker/0:2]scsi host1: usb-storage 1-1:1.0
[1829:cat][MUSB]musb_host_rx 2048: RX end 5 STALL
[2423:usb-storage][MUSB]musb_host_rx 2048: RX end 5 STALL
[0:swapper/0][MUSB]musb_host_rx 2048: RX end 5 STALL
[0:swapper/0][MUSB]musb_host_rx 2048: RX end 5 STALL
[0:swapper/0][MUSB]musb_host_rx 2048: RX end 5 STALL
[0:swapper/0][MUSB]musb_host_rx 2048: RX end 5 STALL
[658:Binder:536_5][MUSB]musb_host_rx 2048: RX end 5 STALL
[0:swapper/0][MUSB]musb_host_rx 2048: RX end 5 STALL====拔下OTG====[0:swapper/0][MUSB]musb_stage0_irq 1107: DISCONNECT (a_host) as Host, devctl 19
[0:swapper/0][MUSB]musb_root_disconnect 197: host disconnect (a_host)
[1623:kworker/0:2][MUSB]musb_id_pin_work 376: work start, is_host=1
[1623:kworker/0:2][MUSB]musb_is_host 231: will mask PMIC charger detection
[1623:kworker/0:2][MUSB]musb_is_host 254: iddig_state = 1
[1623:kworker/0:2][MUSB]musb_is_host 274: will unmask PMIC charger detection
[1623:kworker/0:2][MUSB]musb_is_host 283: usb_is_host = 0
[1623:kworker/0:2][MUSB]switch_int_to_host 334: enable iddig irq LOW @lin 334
[1623:kworker/0:2][MUSB]switch_int_to_host 340: switch_int_to_host is done
[1623:kworker/0:2][MUSB]musb_id_pin_work 464: work end, is_host=0
[1623:kworker/0:2]musb-hdrc musb-hdrc: prop=1, power=0, is_host=0
[1623:kworker/0:2]musb-hdrc musb-hdrc: prop=2, power=0, is_host=0
[1623:kworker/0:2]musb-hdrc musb-hdrc: prop=3, power=0, is_host=0
[646:usb@1.1-service]musb-hdrc musb-hdrc: prop=2, power=0, is_host=0
[646:usb@1.1-service]musb-hdrc musb-hdrc: prop=3, power=0, is_host=0
[646:usb@1.1-service]musb-hdrc musb-hdrc: prop=1, power=0, is_host=0

获取otg状态的函数

static bool musb_is_host(void)
{u8 devctl = 0;int iddig_state = 1;bool usb_is_host = 0;DBG(0, "will mask PMIC charger detection\n");
#ifndef FPGA_PLATFORM
#ifdef CONFIG_MTK_DUAL_INPUT_CHARGER_SUPPORT
#ifdef CONFIG_MTK_LOAD_SWITCH_FPF3040pmic_chrdet_int_en(0);
#endif
#endif
#endifmusb_platform_enable(mtk_musb);if (iddig_pin < 0) {DBG(0, "iddig_pin is invalid:%d, return non-host!\n", iddig_pin);usb_is_host = 0;return usb_is_host;}#ifdef ID_PIN_USE_EX_EINT
#if defined(CONFIG_MTK_LEGACY)iddig_state = mt_get_gpio_in(iddig_pin);
#elseiddig_state = __gpio_get_value(iddig_pin);
#endifDBG(0, "iddig_state = %d\n", iddig_state);
#elseiddig_state = 0;devctl = musb_readb(mtk_musb->mregs, MUSB_DEVCTL);DBG(0, "devctl = %x before end session\n", devctl);devctl &= ~MUSB_DEVCTL_SESSION; /* this will cause A-device change back to B-device after A-cable plug out*/musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, devctl);msleep(delay_time);devctl = musb_readb(mtk_musb->mregs, MUSB_DEVCTL);DBG(0, "devctl = %x before set session\n", devctl);devctl |= MUSB_DEVCTL_SESSION;musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, devctl);msleep(delay_time1);devctl = musb_readb(mtk_musb->mregs, MUSB_DEVCTL);DBG(0, "devclt = %x\n", devctl);
#endifif (devctl & MUSB_DEVCTL_BDEVICE || iddig_state) {DBG(0, "will unmask PMIC charger detection\n");
#ifndef FPGA_PLATFORMpmic_chrdet_int_en(1);
#endifusb_is_host = false;} else {usb_is_host = true;}DBG(0, "usb_is_host = %d\n", usb_is_host);return usb_is_host;
}

插拔otg 的时候,会进入这个函数里面进行判断

从日志和下面的代码可以得出一个结论,我们在插入OTG和拔下OTG的时候,软件已经正常运行了,但是拔出后,可能因为某个原因,USB处在一个错误的状态,这个状态导致再插入正常的USB就没有反应了。

static void musb_id_pin_work(struct work_struct *data)
{u8 devctl = 0;unsigned long flags;/* need prepare clock because  musb_generic_disable may call prepare clock in atomic context */mt_usb_clock_prepare(mtk_musb);spin_lock_irqsave(&mtk_musb->lock, flags);musb_generic_disable(mtk_musb);spin_unlock_irqrestore(&mtk_musb->lock, flags);down(&mtk_musb->musb_lock);DBG(0, "work start, is_host=%d\n", mtk_musb->is_host);if (mtk_musb->in_ipo_off) {DBG(0, "do nothing due to in_ipo_off\n");goto out;}wake_lock(&mtk_musb->usb_lock);mtk_musb->is_host = musb_is_host();DBG(0, "musb is as %s, already lock\n", mtk_musb->is_host?"host":"device");switch_set_state((struct switch_dev *)&otg_state, mtk_musb->is_host);if (mtk_musb->is_host) {/*setup fifo for host mode*/ep_config_from_table_for_host(mtk_musb);/* wake_lock(&mtk_musb->usb_lock); */musb_platform_set_vbus(mtk_musb, 1);/* for no VBUS sensing IP*/
#if 1/* wait VBUS ready */msleep(100);/* clear session*/devctl = musb_readb(mtk_musb->mregs, MUSB_DEVCTL);musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, (devctl&(~MUSB_DEVCTL_SESSION)));/* USB MAC OFF*//* VBUSVALID=0, AVALID=0, BVALID=0, SESSEND=1, IDDIG=X */USBPHY_SET8(0x6c, 0x10);USBPHY_CLR8(0x6c, 0x2e);USBPHY_SET8(0x6d, 0x3e);DBG(0, "force PHY to idle, 0x6d=%x, 0x6c=%x\n", USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));/* wait */mdelay(5);/* remove babble: NOISE_STILL_SOF:1, BABBLE_CLR_EN:0 */devctl = musb_readb(mtk_musb->mregs, MUSB_ULPI_REG_DATA);devctl = devctl | 0x80;devctl = devctl & 0xbf;musb_writeb(mtk_musb->mregs, MUSB_ULPI_REG_DATA, devctl);mdelay(5);/* restart session */devctl = musb_readb(mtk_musb->mregs, MUSB_DEVCTL);musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, (devctl | MUSB_DEVCTL_SESSION));/* USB MAC ONand Host Mode*//* VBUSVALID=1, AVALID=1, BVALID=1, SESSEND=0, IDDIG=0 */USBPHY_CLR8(0x6c, 0x10);USBPHY_SET8(0x6c, 0x2c);USBPHY_SET8(0x6d, 0x3e);DBG(0, "force PHY to host mode, 0x6d=%x, 0x6c=%x\n", USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));
#endifmusb_start(mtk_musb);MUSB_HST_MODE(mtk_musb);switch_int_to_device(mtk_musb);#ifdef CONFIG_PMmtk_musb->is_active = 0;DBG(0, "set active to 0 in Pm runtime issue\n");
#endif} else {DBG(0, "devctl is %x\n", musb_readb(mtk_musb->mregs, MUSB_DEVCTL));musb_writeb(mtk_musb->mregs, MUSB_DEVCTL, 0);musb_platform_set_vbus(mtk_musb, 0);/* for no VBUS sensing IP */
#if 1/* USB MAC OFF*//* VBUSVALID=0, AVALID=0, BVALID=0, SESSEND=1, IDDIG=X */USBPHY_SET8(0x6c, 0x10);USBPHY_CLR8(0x6c, 0x2e);USBPHY_SET8(0x6d, 0x3e);DBG(0, "force PHY to idle, 0x6d=%x, 0x6c=%x\n", USBPHY_READ8(0x6d), USBPHY_READ8(0x6c));
#endif#if !defined(MTK_HDMI_SUPPORT)musb_stop(mtk_musb);
#elsemt_usb_check_reconnect();/*ALPS01688604, IDDIG noise caused by MHL init*/
#endifif (wake_lock_active(&mtk_musb->usb_lock))wake_unlock(&mtk_musb->usb_lock);mtk_musb->xceiv->otg->state = OTG_STATE_B_IDLE;MUSB_DEV_MODE(mtk_musb);switch_int_to_host(mtk_musb);}
out:DBG(0, "work end, is_host=%d\n", mtk_musb->is_host);up(&mtk_musb->musb_lock);mt_usb_clock_unprepare(mtk_musb);
}

里面有一个switch_int_to_host 把设备切换成host模式,从上面的日志上看,这个函数已经执行了,但是设备没有成功切换成host模式。

所以让设备恢复正常应该不是这个函数。

void switch_int_to_host(struct musb *musb)
{
#ifdef ID_PIN_USE_EX_EINT
#if defined(CONFIG_MTK_LEGACY)mt_eint_set_polarity(IDDIG_EINT_PIN, MT_EINT_POL_NEG);mt_eint_unmask(IDDIG_EINT_PIN);
#elseirq_set_irq_type(usb_iddig_number, IRQF_TRIGGER_LOW);enable_irq(usb_iddig_number);irq_set_irq_wake(usb_iddig_number, 1);DBG(0, "enable iddig irq LOW @lin %d\n", __LINE__);
#endif
#elsemusb_writel(musb->mregs, USB_L1INTP, IDDIG_INT_STATUS);musb_writel(musb->mregs, USB_L1INTM, IDDIG_INT_STATUS|musb_readl(musb->mregs, USB_L1INTM));
#endifDBG(0, "switch_int_to_host is done\n");
}

最后我解决的方法也很简单,就是在otg拔出的时候,再connect一下usb就好了。

这个connectusb应该不是简单的connect,是让usb进入device的状态。

index b260550fb7..ba66a7444c
--- a/kernel-4.4/drivers/misc/mediatek/usb20/mt8167/usb20_host.c
+++ b/kernel-4.4/drivers/misc/mediatek/usb20/mt8167/usb20_host.c
@@ -459,6 +459,9 @@ static void musb_id_pin_work(struct work_struct *data)mtk_musb->xceiv->otg->state = OTG_STATE_B_IDLE;MUSB_DEV_MODE(mtk_musb);switch_int_to_host(mtk_musb);
+               mt_usb_connect();
+               /*weiqifa modify*/
+               printk("===weiqifa=== mt_usb_connect() \n");}out:DBG(0, "work end, is_host=%d\n", mtk_musb->is_host);

这个修改是参考了MTK的补丁,他们的做法是用一个新的GPIO口用来检测USB状态.

就是上图的那个引脚,但是可惜的是,我们引脚上接的这个脚不是GPIO功能脚,所以MTK的补丁用不上,他们的补丁也就是检测是否有USB插入,并通过OTGID脚状态,然后再适配usb的状态。

用两个GPIO一起适配的原因是为了适应系统的低功耗机制,也就是说,USB的状态只有在插入usb的时候才会设置成connect状态,如果拔出,就不是connect状态,这样可以降低功耗。刚好,我们是DC供电,不是电池供电,这个可以忽略。

关于usb状态的轮询,可以看这个函数

如果进入OTG模式后,USB会一直处在DISCONNECT状态中。

#define USB_STATE_MONITOR_DELAY 5000
static struct delayed_work usb_state_monitor_dw;
static void do_usb_state_monitor_work(struct work_struct *work)
{struct gadget_info *gi = dev_get_drvdata(android_device);struct usb_composite_dev *cdev = &gi->cdev;char *usb_state = "NO-DEV";unsigned long flags;spin_lock_irqsave(&cdev->lock, flags);if (cdev->config)usb_state = "CONFIGURED";else if (gi->connected)usb_state = "CONNECTED";elseusb_state = "DISCONNECTED";spin_unlock_irqrestore(&cdev->lock, flags);pr_info("usb_state<%s>\n", usb_state);schedule_delayed_work(&usb_state_monitor_dw, msecs_to_jiffies(USB_STATE_MONITOR_DELAY));
}

4.总结

在接手这个问题之前,我是没有搞过usb相关的,当然了,我看过很多文章和书籍,之前在rockchip平台上,我也有接触过usb相关的知识,解决实际问题还是第一次,看MTK代码的时候,大部分都是通过函数名字和变量定义猜测意图,加上硬件的一些验证。

比如

下面这个引脚的功能,参考设计和我们的设计不同,我们通过验证发现,只有这个引脚有电压,PMU就会工作走开机流程。

type-c 和传统的USB是不同的,传统的USB线为了实现OTG功能会增加一个OTG引脚,但是TPYEC上是没有这个OTG线的,看下TPYEC的引脚图。


上面有CC1、CC2引脚,是用这个来实现OTG功能的。

但是我们引脚设计上,就不会这样搞了,我们是TYPEC接口,但是实现OTG功能还是用的原来的方式,我们没有使用CC1、CC2、这几个引脚。

如下图,是使用TYPEC实现OTG的硬件原理图

普通的TYPE C充电线CC管脚通过56K电阻上拉到VBUS,而OTG线一般这是通过5.1K欧下拉接地。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

看我解决Linux下的OTG切换问题相关推荐

  1. 解决Linux下MySQL启动错误Starting MySQL.Manager of pid-file quit without updating file.[FAILED]...

    刚装完MySQL,启动时报如下错误: Starting MySQL.Manager of pid-file quit without updating file.[FAILED] 解决Linux下My ...

  2. 解决linux下/etc/rc.local开机器不执行的原因

    解决linux下/etc/rc.local开机器不执行的原因. 今天一用户报数据库又连接不上了,一检查发现机器重启了,手工启动即可,但想到每次都这样,于是做了一个自动启动脚本 /home/oracle ...

  3. linux arp防火墙关闭,解决linux下arp攻击的方法

    一般Windows用户可以使用antiArp防火墙,但是有些计算专业的朋友们由于工作或其他原因使用的是linux系统,那么linux下arp攻击怎么办呢?下面就是一位高手解决linux下arp攻击的方 ...

  4. linux sudo 命令无法使用,Linux运维知识之解决Linux下无法使用sudo命令问题

    本文主要向大家介绍了Linux运维知识之解决Linux下无法使用sudo命令问题,通过具体的内容向大家展现,希望对大家学习Linux运维知识有所帮助. 问题描述 使用普通用户登录后在终端中执行sudo ...

  5. linux apr防火墙,教你一招:解决linux下arp攻击的方法

    一般Windows用户可以使用antiArp防火墙,但是有些计算专业的朋友们由于工作或其他原因使用的是linux系统,那么linux下arp攻击怎么办呢?下面就是一位高手解决linux下arp攻击的方 ...

  6. linux防火墙arp攻击,解决linux下arp攻击的方法

    一般Windows用户可以使用antiArp防火墙,但是有些计算专业的朋友们由于工作或其他原因使用的是linux系统,那么linux下arp攻击怎么办呢?下面就是一位高手解决linux下arp攻击的方 ...

  7. 解决Linux下inode使用率100%的问题

    解决Linux下inode使用率100%的问题 参考文章: (1)解决Linux下inode使用率100%的问题 (2)https://www.cnblogs.com/pltier/p/1048388 ...

  8. linux mysql插入中文乱码_解决Linux下Tomcat向MySQL插入数据中文乱码问题

    一.问题 在windows上面使用eclipse开发的项目在windows上面运行一切正常,部署到腾讯云时出现向MySQL数据库中插入数据是中文乱码 二.解决办法 1.尝试一 直接在linux上面使用 ...

  9. centos挂载u盘只读_完美解决linux下U盘文件只读的问题

    1. 在终端运行如下命令 tail -f /var/log/syslog 2. 插入有只读文件系统故障的U盘 3. 观察命令行输出 输出局部如下: Jul  8 16:44:50 cslouis-pc ...

最新文章

  1. linux can t open sh,Linux python3 - Can't open lib 'SQL Server'
  2. 一个http-request的源码及改进
  3. Java黑皮书课后题第8章:**8.12(金融应用:计算税款)使用数组重写程序清单3-5,每个纳税人身份都有6种税率。每种税率都应用在某个特定范围内的可征税收入
  4. 由归并算法引申出来的其他问题
  5. mysql 触发器 运算符_mysql三元运算,上下连表,视图,触发器,存储过程,事务等不常用方法...
  6. android svg指纹录取动画_你知道几种前端动画的实现方式?
  7. Protobuf的优点
  8. 百万年薪挖了个P7程序员,难道是“水货”?
  9. 力扣-剑指Offer-57 和为s的连续正数序列
  10. 选课系统服务器,选课系统概要设计
  11. 山大软件项目管理复习整理
  12. 偷用计算机作文,【实用】《偷着》作文500字4篇
  13. python读取日志匹配日志信息(二)
  14. 跟小博老师一起学JSP ——通信作用域
  15. 中央企业数字化转型案例架构
  16. 华为鸿蒙基金,基金筛选:华为鸿蒙新版即将揭开面纱
  17. 2019美国大学计算机专业硕士申请条件,104@2019美国大学计算机(CS)硕士申请难度大比拼(二)...
  18. dlg和app的区别
  19. IB中文课程介绍:语文的另一种可能
  20. 币圈名词解释之对冲搬砖

热门文章

  1. MySQL查看连接数和进程信息
  2. Gitlab的branch与Tag的使用
  3. JavaWeb----Ajax技术
  4. 数据库多表联查的方式
  5. c#通用后台管理系统
  6. jquery $.each(data, function (index, value) {
  7. 【83】secureCRT 7.0登录Ubuntu 20.04提示key exchange failed
  8. Redis之多实例的操作
  9. 代谢组学资讯,全球爆火的ChatGPT,是如何看待三阴性乳腺癌的?
  10. 学一点SQL注入基础