diff options
Diffstat (limited to 'drivers')
99 files changed, 3076 insertions, 1064 deletions
diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index 4178d96f94cf..b6b76ff09657 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -3153,36 +3153,46 @@ static const struct usb_gadget_ops nbu2ss_gadget_ops = { .ioctl = nbu2ss_gad_ioctl, }; -static const char g_ep0_name[] = "ep0"; -static const char g_ep1_name[] = "ep1-bulk"; -static const char g_ep2_name[] = "ep2-bulk"; -static const char g_ep3_name[] = "ep3in-int"; -static const char g_ep4_name[] = "ep4-iso"; -static const char g_ep5_name[] = "ep5-iso"; -static const char g_ep6_name[] = "ep6-bulk"; -static const char g_ep7_name[] = "ep7-bulk"; -static const char g_ep8_name[] = "ep8in-int"; -static const char g_ep9_name[] = "ep9-iso"; -static const char g_epa_name[] = "epa-iso"; -static const char g_epb_name[] = "epb-bulk"; -static const char g_epc_name[] = "epc-nulk"; -static const char g_epd_name[] = "epdin-int"; - -static const char *gp_ep_name[NUM_ENDPOINTS] = { - g_ep0_name, - g_ep1_name, - g_ep2_name, - g_ep3_name, - g_ep4_name, - g_ep5_name, - g_ep6_name, - g_ep7_name, - g_ep8_name, - g_ep9_name, - g_epa_name, - g_epb_name, - g_epc_name, - g_epd_name, +static const struct { + const char *name; + const struct usb_ep_caps caps; +} ep_info[NUM_ENDPOINTS] = { +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + + EP_INFO("ep0", + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep1-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep2-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep3in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep4-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep5-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep6-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep7-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep8in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep9-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)), + EP_INFO("epa-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)), + EP_INFO("epb-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)), + EP_INFO("epc-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)), + EP_INFO("epdin-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), + +#undef EP_INFO }; /*-------------------------------------------------------------------------*/ @@ -3200,10 +3210,12 @@ static void __init nbu2ss_drv_ep_init(struct nbu2ss_udc *udc) ep->desc = NULL; ep->ep.driver_data = NULL; - ep->ep.name = gp_ep_name[i]; + ep->ep.name = ep_info[i].name; + ep->ep.caps = ep_info[i].caps; ep->ep.ops = &nbu2ss_ep_ops; - ep->ep.maxpacket = (i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE); + usb_ep_set_maxpacket_limit(&ep->ep, + i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE); list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); INIT_LIST_HEAD(&ep->queue); diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 6d6200e37b71..f243f0b431c3 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -406,8 +406,11 @@ static inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg, static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci) { #ifdef CONFIG_USB_OTG_FSM + struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps; + return ci->is_otg && ci->roles[CI_ROLE_HOST] && - ci->roles[CI_ROLE_GADGET]; + ci->roles[CI_ROLE_GADGET] && (otg_caps->srp_support || + otg_caps->hnp_support || otg_caps->adp_support); #else return false; #endif diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 3ad48e1c0c57..ab6212e888e1 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -560,6 +560,8 @@ static irqreturn_t ci_irq(int irq, void *data) static int ci_get_platdata(struct device *dev, struct ci_hdrc_platform_data *platdata) { + int ret; + if (!platdata->phy_mode) platdata->phy_mode = of_usb_get_phy_mode(dev->of_node); @@ -588,6 +590,19 @@ static int ci_get_platdata(struct device *dev, of_usb_host_tpl_support(dev->of_node); } + if (platdata->dr_mode == USB_DR_MODE_OTG) { + /* We can support HNP and SRP of OTG 2.0 */ + platdata->ci_otg_caps.otg_rev = 0x0200; + platdata->ci_otg_caps.hnp_support = true; + platdata->ci_otg_caps.srp_support = true; + + /* Update otg capabilities by DT properties */ + ret = of_usb_update_otg_caps(dev->of_node, + &platdata->ci_otg_caps); + if (ret) + return ret; + } + if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL) platdata->flags |= CI_HDRC_FORCE_FULLSPEED; diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 5b7061a33103..3869c6d75515 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -10,6 +10,7 @@ #include <linux/usb/phy.h> #include <linux/usb/otg.h> #include <linux/usb/otg-fsm.h> +#include <linux/usb/chipidea.h> #include "ci.h" #include "udc.h" diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 764f668d45a9..c592b6f0fe21 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1624,6 +1624,20 @@ static int init_eps(struct ci_hdrc *ci) hwep->ep.name = hwep->name; hwep->ep.ops = &usb_ep_ops; + + if (i == 0) { + hwep->ep.caps.type_control = true; + } else { + hwep->ep.caps.type_iso = true; + hwep->ep.caps.type_bulk = true; + hwep->ep.caps.type_int = true; + } + + if (j == TX) + hwep->ep.caps.dir_in = true; + else + hwep->ep.caps.dir_out = true; + /* * for ep0: maxP defined in desc, for other * eps, maxP is set by epautoconfig() called @@ -1827,6 +1841,7 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci) static int udc_start(struct ci_hdrc *ci) { struct device *dev = ci->dev; + struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps; int retval = 0; spin_lock_init(&ci->lock); @@ -1834,8 +1849,12 @@ static int udc_start(struct ci_hdrc *ci) ci->gadget.ops = &usb_gadget_ops; ci->gadget.speed = USB_SPEED_UNKNOWN; ci->gadget.max_speed = USB_SPEED_HIGH; - ci->gadget.is_otg = ci->is_otg ? 1 : 0; ci->gadget.name = ci->platdata->name; + ci->gadget.otg_caps = otg_caps; + + if (ci->is_otg && (otg_caps->hnp_support || otg_caps->srp_support || + otg_caps->adp_support)) + ci->gadget.is_otg = 1; INIT_LIST_HEAD(&ci->gadget.ep_list); diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index b530fd403ffb..9e39286a4e5a 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -154,6 +154,62 @@ bool of_usb_host_tpl_support(struct device_node *np) return false; } EXPORT_SYMBOL_GPL(of_usb_host_tpl_support); + +/** + * of_usb_update_otg_caps - to update usb otg capabilities according to + * the passed properties in DT. + * @np: Pointer to the given device_node + * @otg_caps: Pointer to the target usb_otg_caps to be set + * + * The function updates the otg capabilities + */ +int of_usb_update_otg_caps(struct device_node *np, + struct usb_otg_caps *otg_caps) +{ + u32 otg_rev; + + if (!otg_caps) + return -EINVAL; + + if (!of_property_read_u32(np, "otg-rev", &otg_rev)) { + switch (otg_rev) { + case 0x0100: + case 0x0120: + case 0x0130: + case 0x0200: + /* Choose the lesser one if it's already been set */ + if (otg_caps->otg_rev) + otg_caps->otg_rev = min_t(u16, otg_rev, + otg_caps->otg_rev); + else + otg_caps->otg_rev = otg_rev; + break; + default: + pr_err("%s: unsupported otg-rev: 0x%x\n", + np->full_name, otg_rev); + return -EINVAL; + } + } else { + /* + * otg-rev is mandatory for otg properties, if not passed + * we set it to be 0 and assume it's a legacy otg device. + * Non-dt platform can set it afterwards. + */ + otg_caps->otg_rev = 0; + } + + if (of_find_property(np, "hnp-disable", NULL)) + otg_caps->hnp_support = false; + if (of_find_property(np, "srp-disable", NULL)) + otg_caps->srp_support = false; + if (of_find_property(np, "adp-disable", NULL) || + (otg_caps->otg_rev < 0x0200)) + otg_caps->adp_support = false; + + return 0; +} +EXPORT_SYMBOL_GPL(of_usb_update_otg_caps); + #endif MODULE_LICENSE("GPL"); diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 4d47b7c09238..3ee5b4c77a1f 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -2880,7 +2880,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) epctl = readl(hs->regs + epreg); if (value) { - epctl |= DXEPCTL_STALL + DXEPCTL_SNAK; + epctl |= DXEPCTL_STALL | DXEPCTL_SNAK; if (epctl & DXEPCTL_EPENA) epctl |= DXEPCTL_EPDIS; } else { @@ -3289,6 +3289,19 @@ static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg, usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT); hs_ep->ep.ops = &s3c_hsotg_ep_ops; + if (epnum == 0) { + hs_ep->ep.caps.type_control = true; + } else { + hs_ep->ep.caps.type_iso = true; + hs_ep->ep.caps.type_bulk = true; + hs_ep->ep.caps.type_int = true; + } + + if (dir_in) + hs_ep->ep.caps.dir_in = true; + else + hs_ep->ep.caps.dir_out = true; |
