本文主要是介绍USB HOST和device切换原理--基于imx8qm,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
USB_HOST_GADGET_SWITCH
相关文件
kernel_imx\arch\arm64\boot\dts\freescale\fsl-imx8qm-mek-domu.dts
: 如果开机固定为host模式,只需修改dr_mode = “host”;如果需要OTG功能切换,底层是根据ID PIN引脚的高低电平进行判断(host device),软件上通过otgsc register判断。&usbotg1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_usbotg1>;srp-disable;hnp-disable;adp-disable;power-polarity-active-high;disable-over-current;dr_mode = "host";status = "okay"; };
kernel_imx/drivers/usb/common/common.c
-------------------------------------------------- platform_device->ci_get_platdata(dev, platdata);->usb_get_dr_mode(dev); --------------------------------------------------enum usb_dr_mode usb_get_dr_mode(struct device *dev) { const char *dr_mode;int err;err = device_property_read_string(dev, "dr_mode", &dr_mode);if (err < 0)return USB_DR_MODE_UNKNOWN;return usb_get_dr_mode_from_string(dr_mode); } EXPORT_SYMBOL_GPL(usb_get_dr_mode);
kernel_imx\drivers\usb\chipidea\core.c
: 由于我们ID脚悬空,则不适用OTG功能,在DTS中直接设置成host,则进入else判断分支。-------------------------------------------------- ci_hdrc_probe->-> ci->role = ci_get_role(ci); -------------------------------------------------- static enum ci_role ci_get_role(struct ci_hdrc *ci) {if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {if (ci->is_otg) {hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE);return ci_otg_role(ci);} else {/** If the controller is not OTG capable, but support* role switch, the defalt role is gadget, and the* user can switch it through debugfs.*/return CI_ROLE_GADGET;}} else {return ci->roles[CI_ROLE_HOST]? CI_ROLE_HOST: CI_ROLE_GADGET;} }
kernel_imx/drivers/usb/chipidea/otg.c
: 此为OTG功能时读取OTGSC寄存器进行判断。/** * ci_otg_role - pick role based on ID pin state* @ci: the controller */ enum ci_role ci_otg_role(struct ci_hdrc *ci) {enum ci_role role = hw_read_otgsc(ci, OTGSC_ID)? CI_ROLE_GADGET: CI_ROLE_HOST;return role; } /*** hw_read_otgsc returns otgsc register bits value.* @mask: bitfield mask*/ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask) {struct ci_hdrc_cable *cable;u32 val = hw_read(ci, OP_OTGSC, mask);/** If using extcon framework for VBUS and/or ID signal* detection overwrite OTGSC register value*/cable = &ci->platdata->vbus_extcon;if (!IS_ERR(cable->edev)) {if (cable->changed)val |= OTGSC_BSVIS;elseval &= ~OTGSC_BSVIS;if (cable->connected)val |= OTGSC_BSV;elseval &= ~OTGSC_BSV;if (cable->enabled)val |= OTGSC_BSVIE;elseval &= ~OTGSC_BSVIE;}cable = &ci->platdata->id_extcon;if (!IS_ERR(cable->edev)) {if (cable->changed)val |= OTGSC_IDIS;elseval &= ~OTGSC_IDIS;if (cable->connected)val &= ~OTGSC_ID; /* host */elseval |= OTGSC_ID; /* device */if (cable->enabled)val |= OTGSC_IDIE;elseval &= ~OTGSC_IDIE;}return val & mask; }
这篇关于USB HOST和device切换原理--基于imx8qm的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!