usb: patches for v4.3 merge window

New support for Allwinne SoC on the MUSB driver has been added to the list of
 glue layers. MUSB also got support for building all DMA engines in one binary;
 this will be great for distros.
 
 DWC3 now has no trace of dev_dbg()/dev_vdbg() usage. We will rely solely on
 tracing to debug DWC3. There was also a fix for memory corruption with EP0 when
 maxpacket size transfers are > 512 bytes.
 
 Robert's EP capabilities flags is making EP selection a lot simpler. UDCs are
 now required to set these flags up when adding endpoints to the framework.
 
 Other than these, we have the usual set of miscelaneous cleanups and minor
 fixes.
 
 Signed-off-by: Felipe Balbi <balbi@ti.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJVzKiVAAoJEIaOsuA1yqRETzgP/3zwJOLKB1rA7FAXMSSps58G
 07hpKQumq4fd2JZzWulssIvLiShMKFHn/sqa4BJM2AAYpd/Ct3hCzI+WAseNTD7H
 mfkdezeEBSeZcG8BnMV08wUAf1MdUM4Xit60uVGSJi+dTT1Y8O/3QcTkXvnXwraN
 gH8/M/bO3YLu2uD627x3egLuYYfHn2waZnvpbxdLREirOW/OyYoNA9SUqh1VyNu7
 VIwKNF/l2RCKjI39FbUUjNMzZ468Cd53r1dLYeUMgwWMvziE4+iFum2qz/Gy5fBQ
 GxtHNVNcvovHc9NraAGMZx4oJeoAnlE2FJm4345i9E9YmYyEJfFyBU9HucmwLnU4
 R4wrz0IelCLDamdxzAjNYdD2JLLMGaFKMUxpfvn7KSYnHILedHgDe9xfYmfMQr+B
 oqPl1KptDgOeiea9bl2Vfdfm+TsroKXQF/YUBTEPy71vdQwSyK0W+YX6Ag2yBErC
 Fq3DcuFlSbDg7BAKXJV19FWNUt046k5pnf8s4W4fgmTZvHJeLTz8zpIYgOhXbzxc
 esR0igPZMuckeYDlTYKaFLJ/sqFX5eUpo38rO++wVIpxsEjmR9r1XZr6fkqT25hU
 mOS7S05xOCqAA66ErxrMk/bHznRMwB99f+BR1uOGDajqlgyg+wq6A5ftNbZrnGEw
 rv2rC0/Mo8rC136aV3UW
 =WuIB
 -----END PGP SIGNATURE-----

Merge tag 'usb-for-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next

Felipe writes:

usb: patches for v4.3 merge window

New support for Allwinne SoC on the MUSB driver has been added to the list of
glue layers. MUSB also got support for building all DMA engines in one binary;
this will be great for distros.

DWC3 now has no trace of dev_dbg()/dev_vdbg() usage. We will rely solely on
tracing to debug DWC3. There was also a fix for memory corruption with EP0 when
maxpacket size transfers are > 512 bytes.

Robert's EP capabilities flags is making EP selection a lot simpler. UDCs are
now required to set these flags up when adding endpoints to the framework.

Other than these, we have the usual set of miscelaneous cleanups and minor
fixes.

Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
Greg Kroah-Hartman 2015-08-14 16:41:11 -07:00
commit a3fbedf98f
113 changed files with 3440 additions and 1079 deletions

View file

@ -5,4 +5,4 @@ Description:
The attributes:
qlen - depth of loopback queue
bulk_buflen - buffer length
buflen - buffer length

View file

@ -9,4 +9,4 @@ Description:
isoc_maxpacket - 0 - 1023 (fs), 0 - 1024 (hs/ss)
isoc_mult - 0..2 (hs/ss only)
isoc_maxburst - 0..15 (ss only)
qlen - buffer length
buflen - buffer length

View file

@ -0,0 +1,29 @@
Allwinner sun4i A10 musb DRC/OTG controller
-------------------------------------------
Required properties:
- compatible : "allwinner,sun4i-a10-musb", "allwinner,sun6i-a31-musb"
or "allwinner,sun8i-a33-musb"
- reg : mmio address range of the musb controller
- clocks : clock specifier for the musb controller ahb gate clock
- reset : reset specifier for the ahb reset (A31 and newer only)
- interrupts : interrupt to which the musb controller is connected
- interrupt-names : must be "mc"
- phys : phy specifier for the otg phy
- phy-names : must be "usb"
- dr_mode : Dual-Role mode must be "host" or "otg"
- extcon : extcon specifier for the otg phy
Example:
usb_otg: usb@01c13000 {
compatible = "allwinner,sun4i-a10-musb";
reg = <0x01c13000 0x0400>;
clocks = <&ahb_gates 0>;
interrupts = <38>;
interrupt-names = "mc";
phys = <&usbphy 0>;
phy-names = "usb";
extcon = <&usbphy 0>;
status = "disabled";
};

View file

@ -11,6 +11,19 @@ Optional properties:
"peripheral" and "otg". In case this attribute isn't
passed via DT, USB DRD controllers should default to
OTG.
- otg-rev: tells usb driver the release number of the OTG and EH supplement
with which the device and its descriptors are compliant,
in binary-coded decimal (i.e. 2.0 is 0200H). This
property is used if any real OTG features(HNP/SRP/ADP)
is enabled, if ADP is required, otg-rev should be
0x0200 or above.
- hnp-disable: tells OTG controllers we want to disable OTG HNP, normally HNP
is the basic function of real OTG except you want it
to be a srp-capable only B device.
- srp-disable: tells OTG controllers we want to disable OTG SRP, SRP is
optional for OTG device.
- adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is
optional for OTG device.
This is an attribute to a USB controller such as:
@ -21,4 +34,6 @@ dwc3@4a030000 {
usb-phy = <&usb2_phy>, <&usb3,phy>;
maximum-speed = "super-speed";
dr_mode = "otg";
otg-rev = <0x0200>;
adp-disable;
};

View file

@ -52,6 +52,10 @@ Required properties:
Optional properties:
- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
- switch-gpio: A phandle + gpio-specifier pair. Some boards are using Dual
SPDT USB Switch, witch is cotrolled by GPIO to de/multiplex
D+/D- USB lines between connectors.
- qcom,phy-init-sequence: PHY configuration sequence values. This is related to Device
Mode Eye Diagram test. Start address at which these values will be
written is ULPI_EXT_VENDOR_SPECIFIC. Value of -1 is reserved as

View file

@ -0,0 +1,76 @@
Qualcomm's APQ8016/MSM8916 USB transceiver controller
- compatible:
Usage: required
Value type: <string>
Definition: Should contain "qcom,usb-8x16-phy".
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: USB PHY base address and length of the register map
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: See clock-bindings.txt section "consumers". List of
two clock specifiers for interface and core controller
clocks.
- clock-names:
Usage: required
Value type: <string>
Definition: Must contain "iface" and "core" strings.
- vddcx-supply:
Usage: required
Value type: <phandle>
Definition: phandle to the regulator VDCCX supply node.
- v1p8-supply:
Usage: required
Value type: <phandle>
Definition: phandle to the regulator 1.8V supply node.
- v3p3-supply:
Usage: required
Value type: <phandle>
Definition: phandle to the regulator 3.3V supply node.
- resets:
Usage: required
Value type: <prop-encoded-array>
Definition: See reset.txt section "consumers". PHY reset specifier.
- reset-names:
Usage: required
Value type: <string>
Definition: Must contain "phy" string.
- switch-gpio:
Usage: optional
Value type: <prop-encoded-array>
Definition: Some boards are using Dual SPDT USB Switch, witch is
controlled by GPIO to de/multiplex D+/D- USB lines
between connectors.
Example:
usb_phy: phy@78d9000 {
compatible = "qcom,usb-8x16-phy";
reg = <0x78d9000 0x400>;
vddcx-supply = <&pm8916_s1_corner>;
v1p8-supply = <&pm8916_l7>;
v3p3-supply = <&pm8916_l13>;
clocks = <&gcc GCC_USB_HS_AHB_CLK>,
<&gcc GCC_USB_HS_SYSTEM_CLK>;
clock-names = "iface", "core";
resets = <&gcc GCC_USB2A_PHY_BCR>;
reset-names = "phy";
// D+/D- lines: 1 - Routed to HUB, 0 - Device connector
switch-gpio = <&pm8916_gpios 4 GPIO_ACTIVE_HIGH>;
};

View file

@ -237,9 +237,7 @@ Testing the LOOPBACK function
-----------------------------
device: run the gadget
host: test-usb
http://www.linux-usb.org/usbtest/testusb.c
host: test-usb (tools/usb/testusb.c)
8. MASS STORAGE function
========================
@ -586,9 +584,8 @@ Testing the SOURCESINK function
-------------------------------
device: run the gadget
host: test-usb
host: test-usb (tools/usb/testusb.c)
http://www.linux-usb.org/usbtest/testusb.c
16. UAC1 function
=================

View file

@ -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 struct {
const char *name;
const struct usb_ep_caps caps;
} ep_info[NUM_ENDPOINTS] = {
#define EP_INFO(_name, _caps) \
{ \
.name = _name, \
.caps = _caps, \
}
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,
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);

View file

@ -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

View file

@ -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;

View file

@ -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"

View file

@ -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);

View file

@ -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");

View file

@ -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;
/*
* if we're using dma, we need to set the next-endpoint pointer
* to be something valid.

View file

@ -104,11 +104,4 @@ config USB_DWC3_QCOM
Recent Qualcomm SoCs ship with one DesignWare Core USB3 IP inside,
say 'Y' or 'M' if you have one such device.
comment "Debugging features"
config USB_DWC3_DEBUG
bool "Enable Debugging Messages"
help
Say Y here to enable debugging messages on DWC3 Driver.
endif

View file

@ -1,8 +1,6 @@
# define_trace.h needs to know how to find our header
CFLAGS_trace.o := -I$(src)
ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_DWC3) += dwc3.o
dwc3-y := core.o debug.o trace.o

View file

@ -455,8 +455,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
} else {
dev_warn(dwc->dev, "HSPHY Interface not defined\n");
/* Relying on default value. */
if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
break;

View file

@ -145,7 +145,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
if (IS_ERR(exynos->susp_clk)) {
dev_dbg(dev, "no suspend clk specified\n");
dev_info(dev, "no suspend clk specified\n");
exynos->susp_clk = NULL;
}
clk_prepare_enable(exynos->susp_clk);

View file

@ -115,7 +115,7 @@ static int kdwc3_probe(struct platform_device *pdev)
error = clk_prepare_enable(kdwc->clk);
if (error < 0) {
dev_dbg(kdwc->dev, "unable to enable usb clock, err %d\n",
dev_err(kdwc->dev, "unable to enable usb clock, error %d\n",
error);
return error;
}

View file

@ -128,8 +128,7 @@ struct dwc3_omap {
u32 dma_status:1;
struct extcon_specific_cable_nb extcon_vbus_dev;
struct extcon_specific_cable_nb extcon_id_dev;
struct extcon_dev *edev;
struct notifier_block vbus_nb;
struct notifier_block id_nb;
@ -225,12 +224,10 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
switch (status) {
case OMAP_DWC3_ID_GROUND:
dev_dbg(omap->dev, "ID GND\n");
if (omap->vbus_reg) {
ret = regulator_enable(omap->vbus_reg);
if (ret) {
dev_dbg(omap->dev, "regulator enable failed\n");
dev_err(omap->dev, "regulator enable failed\n");
return;
}
}
@ -245,8 +242,6 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
break;
case OMAP_DWC3_VBUS_VALID:
dev_dbg(omap->dev, "VBUS Connect\n");
val = dwc3_omap_read_utmi_ctrl(omap);
val &= ~USBOTGSS_UTMI_OTG_CTRL_SESSEND;
val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG
@ -261,8 +256,6 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
regulator_disable(omap->vbus_reg);
case OMAP_DWC3_VBUS_OFF:
dev_dbg(omap->dev, "VBUS Disconnect\n");
val = dwc3_omap_read_utmi_ctrl(omap);
val &= ~(USBOTGSS_UTMI_OTG_CTRL_SESSVALID
| USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
@ -273,7 +266,7 @@ static void dwc3_omap_set_mailbox(struct dwc3_omap *omap,
break;
default:
dev_dbg(omap->dev, "invalid state\n");
dev_WARN(omap->dev, "invalid state\n");
}
}
@ -284,37 +277,8 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
reg = dwc3_omap_read_irqmisc_status(omap);
if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) {
dev_dbg(omap->dev, "DMA Disable was Cleared\n");
if (reg & USBOTGSS_IRQMISC_DMADISABLECLR)
omap->dma_status = false;
}
if (reg & USBOTGSS_IRQMISC_OEVT)
dev_dbg(omap->dev, "OTG Event\n");
if (reg & USBOTGSS_IRQMISC_DRVVBUS_RISE)
dev_dbg(omap->dev, "DRVVBUS Rise\n");
if (reg & USBOTGSS_IRQMISC_CHRGVBUS_RISE)
dev_dbg(omap->dev, "CHRGVBUS Rise\n");
if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_RISE)
dev_dbg(omap->dev, "DISCHRGVBUS Rise\n");
if (reg & USBOTGSS_IRQMISC_IDPULLUP_RISE)
dev_dbg(omap->dev, "IDPULLUP Rise\n");
if (reg & USBOTGSS_IRQMISC_DRVVBUS_FALL)
dev_dbg(omap->dev, "DRVVBUS Fall\n");
if (reg & USBOTGSS_IRQMISC_CHRGVBUS_FALL)
dev_dbg(omap->dev, "CHRGVBUS Fall\n");
if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_FALL)
dev_dbg(omap->dev, "DISCHRGVBUS Fall\n");
if (reg & USBOTGSS_IRQMISC_IDPULLUP_FALL)
dev_dbg(omap->dev, "IDPULLUP Fall\n");
dwc3_omap_write_irqmisc_status(omap, reg);
@ -434,7 +398,7 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
reg &= ~USBOTGSS_UTMI_OTG_CTRL_SW_MODE;
break;
default:
dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
dev_WARN(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
}
dwc3_omap_write_utmi_ctrl(omap, reg);
@ -454,23 +418,23 @@ static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
}
omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
ret = extcon_register_interest(&omap->extcon_vbus_dev,
edev->name, "USB",
&omap->vbus_nb);
ret = extcon_register_notifier(edev, EXTCON_USB,
&omap->vbus_nb);
if (ret < 0)
dev_vdbg(omap->dev, "failed to register notifier for USB\n");
omap->id_nb.notifier_call = dwc3_omap_id_notifier;
ret = extcon_register_interest(&omap->extcon_id_dev,
edev->name, "USB-HOST",
&omap->id_nb);
ret = extcon_register_notifier(edev, EXTCON_USB_HOST,
&omap->id_nb);
if (ret < 0)
dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
if (extcon_get_cable_state(edev, "USB") == true)
if (extcon_get_cable_state_(edev, EXTCON_USB) == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
if (extcon_get_cable_state(edev, "USB-HOST") == true)
if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
omap->edev = edev;
}
return 0;
@ -565,11 +529,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
return 0;
err3:
if (omap->extcon_vbus_dev.edev)
extcon_unregister_interest(&omap->extcon_vbus_dev);
if (omap->extcon_id_dev.edev)
extcon_unregister_interest(&omap->extcon_id_dev);
extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
err2:
dwc3_omap_disable_irqs(omap);
@ -586,10 +547,8 @@ static int dwc3_omap_remove(struct platform_device *pdev)
{
struct dwc3_omap *omap = platform_get_drvdata(pdev);
if (omap->extcon_vbus_dev.edev)
extcon_unregister_interest(&omap->extcon_vbus_dev);
if (omap->extcon_id_dev.edev)
extcon_unregister_interest(&omap->extcon_id_dev);
extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
dwc3_omap_disable_irqs(omap);
of_platform_depopulate(omap->dev);
pm_runtime_put_sync(&pdev->dev);

View file

@ -83,17 +83,23 @@ static int dwc3_pci_quirks(struct pci_dev *pdev)
acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
acpi_dwc3_byt_gpios);
/* These GPIOs will turn on the USB2 PHY */
gpio = gpiod_get(&pdev->dev, "cs");
if (!IS_ERR(gpio)) {
gpiod_direction_output(gpio, 0);
gpiod_set_value_cansleep(gpio, 1);
gpiod_put(gpio);
}
/*
* These GPIOs will turn on the USB2 PHY. Note that we have to
* put the gpio descriptors again here because the phy driver
* might want to grab them, too.
*/
gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
gpio = gpiod_get(&pdev->dev, "reset");
if (!IS_ERR(gpio)) {
gpiod_direction_output(gpio, 0);
gpiod_set_value_cansleep(gpio, 1);
gpiod_put(gpio);
gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
if (gpio) {
gpiod_set_value_cansleep(gpio, 1);
gpiod_put(gpio);
usleep_range(10000, 11000);

View file

@ -48,13 +48,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
qdwc->iface_clk = devm_clk_get(qdwc->dev, "iface");
if (IS_ERR(qdwc->iface_clk)) {
dev_dbg(qdwc->dev, "failed to get optional iface clock\n");
dev_info(qdwc->dev, "failed to get optional iface clock\n");
qdwc->iface_clk = NULL;
}
qdwc->sleep_clk = devm_clk_get(qdwc->dev, "sleep");
if (IS_ERR(qdwc->sleep_clk)) {
dev_dbg(qdwc->dev, "failed to get optional sleep clock\n");
dev_info(qdwc->dev, "failed to get optional sleep clock\n");
qdwc->sleep_clk = NULL;
}

View file

@ -135,8 +135,6 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data)
| USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
val |= USB3_DEVICE_NOT_HOST;
dev_dbg(dwc3_data->dev, "Configuring as Device\n");
break;
case USB_DR_MODE_HOST:
@ -154,8 +152,6 @@ static int st_dwc3_drd_init(struct st_dwc3 *dwc3_data)
*/
val |= USB3_DELAY_VBUSVALID;
dev_dbg(dwc3_data->dev, "Configuring as Host\n");
break;
default:

View file

@ -56,7 +56,7 @@ static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
}
static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
u32 len, u32 type)
u32 len, u32 type, bool chain)
{
struct dwc3_gadget_ep_cmd_params params;
struct dwc3_trb *trb;
@ -70,7 +70,10 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
return 0;
}
trb = dwc->ep0_trb;
trb = &dwc->ep0_trb[dep->free_slot];
if (chain)
dep->free_slot++;
trb->bpl = lower_32_bits(buf_dma);
trb->bph = upper_32_bits(buf_dma);
@ -78,10 +81,17 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
trb->ctrl = type;
trb->ctrl |= (DWC3_TRB_CTRL_HWO
| DWC3_TRB_CTRL_LST
| DWC3_TRB_CTRL_IOC
| DWC3_TRB_CTRL_ISP_IMI);
if (chain)
trb->ctrl |= DWC3_TRB_CTRL_CHN;
else
trb->ctrl |= (DWC3_TRB_CTRL_IOC
| DWC3_TRB_CTRL_LST);
if (chain)
return 0;
memset(&params, 0, sizeof(params));
params.param0 = upper_32_bits(dwc->ep0_trb_addr);
params.param1 = lower_32_bits(dwc->ep0_trb_addr);
@ -302,7 +312,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
int ret;
ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
DWC3_TRBCTL_CONTROL_SETUP);
DWC3_TRBCTL_CONTROL_SETUP, false);
WARN_ON(ret < 0);
}
@ -783,7 +793,11 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
struct usb_request *ur;
struct dwc3_trb *trb;
struct dwc3_ep *ep0;
u32 transferred;
unsigned transfer_size = 0;
unsigned maxp;
unsigned remaining_ur_length;
void *buf;
u32 transferred = 0;
u32 status;
u32 length;
u8 epnum;
@ -812,17 +826,37 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
}
ur = &r->request;
buf = ur->buf;
remaining_ur_length = ur->length;
length = trb->size & DWC3_TRB_SIZE_MASK;
if (dwc->ep0_bounced) {
unsigned transfer_size = ur->length;
unsigned maxp = ep0->endpoint.maxpacket;
maxp = ep0->endpoint.maxpacket;
transfer_size += (maxp - (transfer_size % maxp));
transferred = min_t(u32, ur->length,
transfer_size - length);
memcpy(ur->buf, dwc->ep0_bounce, transferred);
if (dwc->ep0_bounced) {
/*
* Handle the first TRB before handling the bounce buffer if
* the request length is greater than the bounce buffer size
*/
if (ur->length > DWC3_EP0_BOUNCE_SIZE) {
transfer_size = ALIGN(ur->length - maxp, maxp);
transferred = transfer_size - length;
buf = (u8 *)buf + transferred;
ur->actual += transferred;
remaining_ur_length -= transferred;
trb++;
length = trb->size & DWC3_TRB_SIZE_MASK;
ep0->free_slot = 0;
}
transfer_size = roundup((ur->length - transfer_size),
maxp);
transferred = min_t(u32, remaining_ur_length,
transfer_size - length);
memcpy(buf, dwc->ep0_bounce, transferred);
} else {
transferred = ur->length - length;
}
@ -844,7 +878,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
ret = dwc3_ep0_start_trans(dwc, epnum,
dwc->ctrl_req_addr, 0,
DWC3_TRBCTL_CONTROL_DATA);
DWC3_TRBCTL_CONTROL_DATA, false);
WARN_ON(ret < 0);
}
}
@ -928,10 +962,10 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
if (req->request.length == 0) {
ret = dwc3_ep0_start_trans(dwc, dep->number,
dwc->ctrl_req_addr, 0,
DWC3_TRBCTL_CONTROL_DATA);
DWC3_TRBCTL_CONTROL_DATA, false);
} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
&& (dep->number == 0)) {
u32 transfer_size;
u32 transfer_size = 0;
u32 maxpacket;
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
@ -941,21 +975,26 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
return;
}
WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE);
maxpacket = dep->endpoint.maxpacket;
transfer_size = roundup(req->request.length, maxpacket);
if (req->request.length > DWC3_EP0_BOUNCE_SIZE) {
transfer_size = ALIGN(req->request.length - maxpacket,
maxpacket);
ret = dwc3_ep0_start_trans(dwc, dep->number,
req->request.dma,
transfer_size,
DWC3_TRBCTL_CONTROL_DATA,
true);
}
transfer_size = roundup((req->request.length - transfer_size),
maxpacket);
dwc->ep0_bounced = true;
/*
* REVISIT in case request length is bigger than
* DWC3_EP0_BOUNCE_SIZE we will need two chained
* TRBs to handle the transfer.
*/
ret = dwc3_ep0_start_trans(dwc, dep->number,
dwc->ep0_bounce_addr, transfer_size,
DWC3_TRBCTL_CONTROL_DATA);
DWC3_TRBCTL_CONTROL_DATA, false);
} else {
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
@ -965,7 +1004,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
}
ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
req->request.length, DWC3_TRBCTL_CONTROL_DATA);
req->request.length, DWC3_TRBCTL_CONTROL_DATA,
false);
}
WARN_ON(ret < 0);
@ -980,7 +1020,7 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
: DWC3_TRBCTL_CONTROL_STATUS2;
return dwc3_ep0_start_trans(dwc, dep->number,
dwc->ctrl_req_addr, 0, type);
dwc->ctrl_req_addr, 0, type, false);
}
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)

View file

@ -547,6 +547,23 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
trb_link->ctrl |= DWC3_TRB_CTRL_HWO;
}
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
strlcat(dep->name, "-control", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_ISOC:
strlcat(dep->name, "-isoc", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_BULK:
strlcat(dep->name, "-bulk", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_INT:
strlcat(dep->name, "-int", sizeof(dep->name));
break;
default:
dev_err(dwc->dev, "invalid endpoint transfer type\n");
}
return 0;
}
@ -586,6 +603,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
struct dwc3 *dwc = dep->dwc;
u32 reg;
dwc3_trace(trace_dwc3_gadget, "Disabling %s", dep->name);
dwc3_remove_requests(dwc, dep);
/* make sure HW endpoint isn't stalled */
@ -602,6 +621,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->type = 0;
dep->flags = 0;
snprintf(dep->name, sizeof(dep->name), "ep%d%s",
dep->number >> 1,
(dep->number & 1) ? "in" : "out");
return 0;
}
@ -647,23 +670,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
return 0;
}
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
strlcat(dep->name, "-control", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_ISOC:
strlcat(dep->name, "-isoc", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_BULK:
strlcat(dep->name, "-bulk", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_INT:
strlcat(dep->name, "-int", sizeof(dep->name));
break;
default:
dev_err(dwc->dev, "invalid endpoint transfer type\n");
}
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false, false);
spin_unlock_irqrestore(&dwc->lock, flags);
@ -692,10 +698,6 @@ static int dwc3_gadget_ep_disable(struct usb_ep *ep)
return 0;
}
snprintf(dep->name, sizeof(dep->name), "ep%d%s",
dep->number >> 1,
(dep->number & 1) ? "in" : "out");
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_disable(dep);
spin_unlock_irqrestore(&dwc->lock, flags);
@ -1713,6 +1715,17 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
return ret;
}
if (epnum == 0 || epnum == 1) {
dep->endpoint.caps.type_control = true;
} else {
dep->endpoint.caps.type_iso = true;
dep->endpoint.caps.type_bulk = true;
dep->endpoint.caps.type_int = true;
}
dep->endpoint.caps.dir_in = !!direction;
dep->endpoint.caps.dir_out = !direction;
INIT_LIST_HEAD(&dep->request_list);
INIT_LIST_HEAD(&dep->req_queued);
}
@ -2685,7 +2698,7 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err0;
}
dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
&dwc->ep0_trb_addr, GFP_KERNEL);
if (!dwc->ep0_trb) {
dev_err(dwc->dev, "failed to allocate ep0 trb\n");

View file

@ -19,6 +19,7 @@
#include <linux/utsname.h>
#include <linux/usb/composite.h>
#include <linux/usb/otg.h>
#include <asm/unaligned.h>
#include "u_os_desc.h"
@ -209,6 +210,12 @@ int usb_add_function(struct usb_configuration *config,
function->config = config;
list_add_tail(&function->list, &config->functions);
if (function->bind_deactivated) {
value = usb_function_deactivate(function);
if (value)
goto done;
}
/* REVISIT *require* function->bind? */
if (function->bind) {
value = function->bind(config, function);
@ -279,7 +286,7 @@ int usb_function_deactivate(struct usb_function *function)
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->deactivations == 0)
status = usb_gadget_disconnect(cdev->gadget);
status = usb_gadget_deactivate(cdev->gadget);
if (status == 0)
cdev->deactivations++;
@ -311,7 +318,7 @@ int usb_function_activate(struct usb_function *function)
else {
cdev->deactivations--;
if (cdev->deactivations == 0)
status = usb_gadget_connect(cdev->gadget);
status = usb_gadget_activate(cdev->gadget);
}
spin_unlock_irqrestore(&cdev->lock, flags);
@ -896,7 +903,7 @@ void usb_remove_config(struct usb_composite_dev *cdev,
/* We support strings in multiple languages ... string descriptor zero
* says which languages are supported. The typical case will be that
* only one language (probably English) is used, with I18N handled on
* only one language (probably English) is used, with i18n handled on
* the host side.
*/
@ -949,7 +956,7 @@ static int get_string(struct usb_composite_dev *cdev,
struct usb_function *f;
int len;
/* Yes, not only is USB's I18N support probably more than most
/* Yes, not only is USB's i18n support probably more than most
* folk will ever care about ... also, it's all supported here.
* (Except for UTF8 support for Unicode's "Astral Planes".)
*/
@ -1534,6 +1541,32 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min(w_length, (u16) value);
}
break;
case USB_DT_OTG:
if (gadget_is_otg(gadget)) {
struct usb_configuration *config;
int otg_desc_len = 0;
if (cdev->config)
config = cdev->config;
else
config = list_first_entry(
&cdev->configs,
struct usb_configuration, list);
if (!config)
goto done;
if (gadget->otg_caps &&
(gadget->otg_caps->otg_rev >= 0x0200))
otg_desc_len += sizeof(
struct usb_otg20_descriptor);
else
otg_desc_len += sizeof(
struct usb_otg_descriptor);
value = min_t(int, w_length, otg_desc_len);
memcpy(req->buf, config->descriptors[0], value);
}
break;
}
break;

View file

@ -20,6 +20,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
#include <linux/usb/otg.h>
/**
* usb_descriptor_fillbuf - fill buffer with descriptors
@ -195,3 +196,58 @@ void usb_free_all_descriptors(struct usb_function *f)
usb_free_descriptors(f->ss_descriptors);
}
EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
struct usb_descriptor_header *usb_otg_descriptor_alloc(
struct usb_gadget *gadget)
{
struct usb_descriptor_header *otg_desc;
unsigned length = 0;
if (gadget->otg_caps && (gadget->otg_caps->otg_rev >= 0x0200))
length = sizeof(struct usb_otg20_descriptor);
else
length = sizeof(struct usb_otg_descriptor);
otg_desc = kzalloc(length, GFP_KERNEL);
return otg_desc;
}
EXPORT_SYMBOL_GPL(usb_otg_descriptor_alloc);
int usb_otg_descriptor_init(struct usb_gadget *gadget,
struct usb_descriptor_header *otg_desc)
{
struct usb_otg_descriptor *otg1x_desc;
struct usb_otg20_descriptor *otg20_desc;
struct usb_otg_caps *otg_caps = gadget->otg_caps;
u8 otg_attributes = 0;
if (!otg_desc)
return -EINVAL;
if (otg_caps && otg_caps->otg_rev) {
if (otg_caps->hnp_support)
otg_attributes |= USB_OTG_HNP;
if (otg_caps->srp_support)
otg_attributes |= USB_OTG_SRP;
if (otg_caps->adp_support && (otg_caps->otg_rev >= 0x0200))
otg_attributes |= USB_OTG_ADP;
} else {
otg_attributes = USB_OTG_SRP | USB_OTG_HNP;
}
if (otg_caps && (otg_caps->otg_rev >= 0x0200)) {
otg20_desc = (struct usb_otg20_descriptor *)otg_desc;
otg20_desc->bLength = sizeof(struct usb_otg20_descriptor);
otg20_desc->bDescriptorType = USB_DT_OTG;
otg20_desc->bmAttributes = otg_attributes;
otg20_desc->bcdOTG = cpu_to_le16(otg_caps->otg_rev);
} else {
otg1x_desc = (struct usb_otg_descriptor *)otg_desc;
otg1x_desc->bLength = sizeof(struct usb_otg_descriptor);
otg1x_desc->bDescriptorType = USB_DT_OTG;
otg1x_desc->bmAttributes = otg_attributes;
}
return 0;
}
EXPORT_SYMBOL_GPL(usb_otg_descriptor_init);

View file

@ -41,6 +41,8 @@ int check_user_usb_string(const char *name,
#define MAX_NAME_LEN 40
#define MAX_USB_STRING_LANGS 2
static const struct usb_descriptor_header *otg_desc[2];
struct gadget_info {
struct config_group group;
struct config_group functions_group;
@ -55,9 +57,6 @@ struct gadget_info {
struct list_head available_func;
const char *udc_name;
#ifdef CONFIG_USB_OTG
struct usb_otg_descriptor otg;
#endif
struct usb_composite_driver composite;
struct usb_composite_dev cdev;
bool use_os_desc;
@ -1376,6 +1375,19 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
}
if (gadget_is_otg(gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(gadget);
if (!usb_desc) {
ret = -ENOMEM;
goto err_comp_cleanup;
}
usb_otg_descriptor_init(gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
/* Go through all configs, attach all functions */
list_for_each_entry(c, &gi->cdev.configs, list) {
struct config_usb_cfg *cfg;
@ -1383,6 +1395,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
struct usb_function *tmp;
struct gadget_config_name *cn;
if (gadget_is_otg(gadget))
c->descriptors = otg_desc;
cfg = container_of(c, struct config_usb_cfg, c);
if (!list_empty(&cfg->string_list)) {
i = 0;
@ -1437,6 +1452,8 @@ static void configfs_composite_unbind(struct usb_gadget *gadget)
cdev = get_gadget_data(gadget);
gi = container_of(cdev, struct gadget_info, cdev);
kfree(otg_desc[0]);
otg_desc[0] = NULL;
purge_configs_funcs(gi);
composite_dev_cleanup(cdev);
usb_ep_autoconfig_reset(cdev->gadget);
@ -1510,12 +1527,6 @@ static struct config_group *gadgets_make(
if (!gi->composite.gadget_driver.function)
goto err;
#ifdef CONFIG_USB_OTG
gi->otg.bLength = sizeof(struct usb_otg_descriptor);
gi->otg.bDescriptorType = USB_DT_OTG;
gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP;
#endif
config_group_init_type_name(&gi->group, name,
&gadget_root_type);
return &gi->group;

View file

@ -20,186 +20,6 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include "gadget_chips.h"
/*
* This should work with endpoints from controller drivers sharing the
* same endpoint naming convention. By example:
*
* - ep1, ep2, ... address is fixed, not direction or type
* - ep1in, ep2out, ... address and direction are fixed, not type
* - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
* - ep1in-bulk, ep2out-iso, ... all three are fixed
* - ep-* ... no functionality restrictions
*
* Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
* Less common restrictions are implied by gadget_is_*().
*
* NOTE: each endpoint is unidirectional, as specified by its USB
* descriptor; and isn't specific to a configuration or altsetting.
*/
static int
ep_matches (
struct usb_gadget *gadget,
struct usb_ep *ep,
struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *ep_comp
)
{
u8 type;
const char *tmp;
u16 max;
int num_req_streams = 0;
/* endpoint already claimed? */
if (NULL != ep->driver_data)
return 0;
/* only support ep0 for portable CONTROL traffic */
type = usb_endpoint_type(desc);
if (USB_ENDPOINT_XFER_CONTROL == type)
return 0;
/* some other naming convention */
if ('e' != ep->name[0])
return 0;
/* type-restriction: "-iso", "-bulk", or "-int".
* direction-restriction: "in", "out".
*/
if ('-' != ep->name[2]) {
tmp = strrchr (ep->name, '-');
if (tmp) {
switch (type) {
case USB_ENDPOINT_XFER_INT:
/* bulk endpoints handle interrupt transfers,
* except the toggle-quirky iso-synch kind
*/
if ('s' == tmp[2]) // == "-iso"
return 0;
/* for now, avoid PXA "interrupt-in";
* it's documented as never using DATA1.
*/
if (gadget_is_pxa (gadget)
&& 'i' == tmp [1])
return 0;
break;
case USB_ENDPOINT_XFER_BULK:
if ('b' != tmp[1]) // != "-bulk"
return 0;
break;
case USB_ENDPOINT_XFER_ISOC:
if ('s' != tmp[2]) // != "-iso"
return 0;
}
} else {
tmp = ep->name + strlen (ep->name);
}
/* direction-restriction: "..in-..", "out-.." */
tmp--;
if (!isdigit (*tmp)) {
if (desc->bEndpointAddress & USB_DIR_IN) {
if ('n' != *tmp)
return 0;
} else {
if ('t' != *tmp)
return 0;
}
}
}
/*
* Get the number of required streams from the EP companion
* descriptor and see if the EP matches it
*/
if (usb_endpoint_xfer_bulk(desc)) {
if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
num_req_streams = ep_comp->bmAttributes & 0x1f;
if (num_req_streams > ep->max_streams)
return 0;
}
}
/*
* If the protocol driver hasn't yet decided on wMaxPacketSize
* and wants to know the maximum possible, provide the info.
*/
if (desc->wMaxPacketSize == 0)
desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
/* endpoint maxpacket size is an input parameter, except for bulk
* where it's an output parameter representing the full speed limit.
* the usb spec fixes high speed bulk maxpacket at 512 bytes.
*/
max = 0x7ff & usb_endpoint_maxp(desc);
switch (type) {
case USB_ENDPOINT_XFER_INT:
/* INT: limit 64 bytes full speed, 1024 high/super speed */
if (!gadget_is_dualspeed(gadget) && max > 64)
return 0;
/* FALLTHROUGH */
case USB_ENDPOINT_XFER_ISOC:
/* ISO: limit 1023 bytes full speed, 1024 high/super speed */
if (ep->maxpacket_limit < max)
return 0;
if (!gadget_is_dualspeed(gadget) && max > 1023)
return 0;
/* BOTH: "high bandwidth" works only at high speed */
if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
if (!gadget_is_dualspeed(gadget))
return 0;
/* configure your hardware with enough buffering!! */
}
break;
}
/* MATCH!! */
/* report address */
desc->bEndpointAddress &= USB_DIR_IN;
if (isdigit (ep->name [2])) {
u8 num = simple_strtoul (&ep->name [2], NULL, 10);
desc->bEndpointAddress |= num;
} else if (desc->bEndpointAddress & USB_DIR_IN) {
if (++gadget->in_epnum > 15)
return 0;
desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
} else {
if (++gadget->out_epnum > 15)
return 0;
desc->bEndpointAddress |= gadget->out_epnum;
}
/* report (variable) full speed bulk maxpacket */
if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
int size = ep->maxpacket_limit;
/* min() doesn't work on bitfields with gcc-3.5 */
if (size > 64)
size = 64;
desc->wMaxPacketSize = cpu_to_le16(size);
}
ep->address = desc->bEndpointAddress;
return 1;
}
static struct usb_ep *
find_ep (struct usb_gadget *gadget, const char *name)
{
struct usb_ep *ep;
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
if (0 == strcmp (ep->name, name))
return ep;
}
return NULL;
}
/**
* usb_ep_autoconfig_ss() - choose an endpoint matching the ep
* descriptor and ep companion descriptor
@ -240,7 +60,7 @@ find_ep (struct usb_gadget *gadget, const char *name)
* updated with the assigned number of streams if it is
* different from the original value. To prevent the endpoint
* from being returned by a later autoconfig call, claim it by
* assigning ep->driver_data to some non-null value.
* assigning ep->claimed to true.
*
* On failure, this returns a null endpoint descriptor.
*/
@ -255,74 +75,58 @@ struct usb_ep *usb_ep_autoconfig_ss(
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
/* First, apply chip-specific "best usage" knowledge.
* This might make a good usb_gadget_ops hook ...
*/
if (gadget_is_net2280(gadget)) {
char name[8];
if (type == USB_ENDPOINT_XFER_INT) {
/* ep-e, ep-f are PIO with only 64 byte fifos */
ep = find_ep(gadget, "ep-e");
if (ep && ep_matches(gadget, ep, desc, ep_comp))
goto found_ep;
ep = find_ep(gadget, "ep-f");
if (ep && ep_matches(gadget, ep, desc, ep_comp))
goto found_ep;
}
/* USB3380: use same address for usb and hardware endpoints */
snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
usb_endpoint_dir_in(desc) ? "in" : "out");
ep = find_ep(gadget, name);
if (ep && ep_matches(gadget, ep, desc, ep_comp))
if (gadget->ops->match_ep) {
ep = gadget->ops->match_ep(gadget, desc, ep_comp);
if (ep)
goto found_ep;
} else if (gadget_is_goku (gadget)) {
if (USB_ENDPOINT_XFER_INT == type) {
/* single buffering is enough */
ep = find_ep(gadget, "ep3-bulk");
if (ep && ep_matches(gadget, ep, desc, ep_comp))
goto found_ep;
} else if (USB_ENDPOINT_XFER_BULK == type
&& (USB_DIR_IN & desc->bEndpointAddress)) {
/* DMA may be available */
ep = find_ep(gadget, "ep2-bulk");
if (ep && ep_matches(gadget, ep, desc,
ep_comp))
goto found_ep;
}
#ifdef CONFIG_BLACKFIN
} else if (gadget_is_musbhdrc(gadget)) {
if ((USB_ENDPOINT_XFER_BULK == type) ||
(USB_ENDPOINT_XFER_ISOC == type)) {
if (USB_DIR_IN & desc->bEndpointAddress)
ep = find_ep (gadget, "ep5in");
else
ep = find_ep (gadget, "ep6out");
} else if (USB_ENDPOINT_XFER_INT == type) {
if (USB_DIR_IN & desc->bEndpointAddress)
ep = find_ep(gadget, "ep1in");
else
ep = find_ep(gadget, "ep2out");
} else
ep = NULL;
if (ep && ep_matches(gadget, ep, desc, ep_comp))
goto found_ep;
#endif
}
/* Second, look at endpoints until an unclaimed one looks usable */
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
if (ep_matches(gadget, ep, desc, ep_comp))
if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
goto found_ep;
}
/* Fail */
return NULL;
found_ep:
/*
* If the protocol driver hasn't yet decided on wMaxPacketSize
* and wants to know the maximum possible, provide the info.
*/
if (desc->wMaxPacketSize == 0)
desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
/* report address */
desc->bEndpointAddress &= USB_DIR_IN;
if (isdigit(ep->name[2])) {
u8 num = simple_strtoul(&ep->name[2], NULL, 10);
desc->bEndpointAddress |= num;
} else if (desc->bEndpointAddress & USB_DIR_IN) {
if (++gadget->in_epnum > 15)
return NULL;
desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
} else {
if (++gadget->out_epnum > 15)
return NULL;
desc->bEndpointAddress |= gadget->out_epnum;
}
/* report (variable) full speed bulk maxpacket */
if ((type == USB_ENDPOINT_XFER_BULK) && !ep_comp) {
int size = ep->maxpacket_limit;
/* min() doesn't work on bitfields with gcc-3.5 */
if (size > 64)
size = 64;
desc->wMaxPacketSize = cpu_to_le16(size);
}
ep->address = desc->bEndpointAddress;
ep->desc = NULL;
ep->comp_desc = NULL;
ep->claimed = true;
return ep;
}
EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
@ -354,7 +158,7 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
* is initialized as if the endpoint were used at full speed. To prevent
* the endpoint from being returned by a later autoconfig call, claim it
* by assigning ep->driver_data to some non-null value.
* by assigning ep->claimed to true.
*
* On failure, this returns a null endpoint descriptor.
*/
@ -373,7 +177,7 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
*
* Use this for devices where one configuration may need to assign
* endpoint resources very differently from the next one. It clears
* state such as ep->driver_data and the record of assigned endpoints
* state such as ep->claimed and the record of assigned endpoints
* used by usb_ep_autoconfig().
*/
void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
@ -381,7 +185,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
struct usb_ep *ep;
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
ep->driver_data = NULL;
ep->claimed = false;
}
gadget->in_epnum = 0;
gadget->out_epnum = 0;

View file

@ -21,7 +21,6 @@
#include <linux/err.h>
#include "u_serial.h"
#include "gadget_chips.h"
/*

View file

@ -585,8 +585,8 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* Enable zlps by default for ECM conformance;
* override for musb_hdrc (avoids txdma ovhead).
*/
ecm->port.is_zlp_ok = !(gadget_is_musbhdrc(cdev->gadget)
);
ecm->port.is_zlp_ok =
gadget_is_zlp_supported(cdev->gadget);
ecm->port.cdc_filter = DEFAULT_FILTER;
DBG(cdev, "activate ecm\n");
net = gether_connect(&ecm->port);

View file

@ -2897,11 +2897,17 @@ static int ffs_func_bind(struct usb_configuration *c,
struct usb_function *f)
{
struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c);
struct ffs_function *func = ffs_func_from_usb(f);
int ret;
if (IS_ERR(ffs_opts))
return PTR_ERR(ffs_opts);
return _ffs_func_bind(c, f);
ret = _ffs_func_bind(c, f);
if (ret && !--ffs_opts->refcnt)
functionfs_unbind(func->ffs);
return ret;
}

View file

@ -28,11 +28,6 @@
* This takes messages of various sizes written OUT to a device, and loops
* them back so they can be read IN from it. It has been used by certain
* test applications. It supports limited testing of data queueing logic.
*
*
* This is currently packaged as a configuration driver, which can't be
* combined with other functions to make composite devices. However, it
* can be combined with other independent configurations.
*/
struct f_loopback {
struct usb_function function;

View file

@ -54,7 +54,7 @@
* following fields:
*
* nluns Number of LUNs function have (anywhere from 1
* to FSG_MAX_LUNS which is 8).
* to FSG_MAX_LUNS).
* luns An array of LUN configuration values. This
* should be filled for each LUN that
* function will include (ie. for "nluns"
@ -214,12 +214,12 @@
#include <linux/string.h>
#include <linux/freezer.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
#include "gadget_chips.h"
#include "configfs.h"
@ -279,9 +279,8 @@ struct fsg_common {
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
unsigned int nluns;
unsigned int lun;
struct fsg_lun **luns;
struct fsg_lun *luns[FSG_MAX_LUNS];
struct fsg_lun *curlun;
unsigned int bulk_out_maxpacket;
@ -490,6 +489,16 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req)
spin_unlock(&common->lock);
}
static int _fsg_common_get_max_lun(struct fsg_common *common)
{
int i = ARRAY_SIZE(common->luns) - 1;
while (i >= 0 && !common->luns[i])
--i;
return i;
}
static int fsg_setup(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
@ -533,7 +542,7 @@ static int fsg_setup(struct usb_function *f,
w_length != 1)
return -EDOM;
VDBG(fsg, "get max LUN\n");
*(u8 *)req->buf = fsg->common->nluns - 1;
*(u8 *)req->buf = _fsg_common_get_max_lun(fsg->common);
/* Respond with data/status */
req->length = min((u16)1, w_length);
@ -2131,8 +2140,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
}
/* Is the CBW meaningful? */
if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
if (cbw->Lun >= ARRAY_SIZE(common->luns) ||
cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 ||
cbw->Length > MAX_COMMAND_SIZE) {
DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
"cmdlen %u\n",
cbw->Lun, cbw->Flags, cbw->Length);
@ -2159,7 +2169,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh)
if (common->data_size == 0)
common->data_dir = DATA_DIR_NONE;
common->lun = cbw->Lun;
if (common->lun < common->nluns)
if (common->lun < ARRAY_SIZE(common->luns))
common->curlun = common->luns[common->lun];
else
common->curlun = NULL;
@ -2307,7 +2317,7 @@ reset:
}
common->running = 1;
for (i = 0; i < common->nluns; ++i)
for (i = 0; i < ARRAY_SIZE(common->luns); ++i)
if (common->luns[i])
common->luns[i]->unit_attention_data =
SS_RESET_OCCURRED;
@ -2409,7 +2419,7 @@ static void handle_exception(struct fsg_common *common)
if (old_state == FSG_STATE_ABORT_BULK_OUT)
common->state = FSG_STATE_STATUS_PHASE;
else {
for (i = 0; i < common->nluns; ++i) {
for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
curlun = common->luns[i];
if (!curlun)
continue;
@ -2453,7 +2463,7 @@ static void handle_exception(struct fsg_common *common)
* a waste of time. Ditto for the INTERFACE_CHANGE and
* CONFIG_CHANGE cases.
*/
/* for (i = 0; i < common->nluns; ++i) */
/* for (i = 0; i < common->ARRAY_SIZE(common->luns); ++i) */
/* if (common->luns[i]) */
/* common->luns[i]->unit_attention_data = */
/* SS_RESET_OCCURRED; */
@ -2552,12 +2562,11 @@ static int fsg_main_thread(void *common_)
if (!common->ops || !common->ops->thread_exits
|| common->ops->thread_exits(common) < 0) {
struct fsg_lun **curlun_it = common->luns;
unsigned i = common->nluns;
int i;
down_write(&common->filesem);
for (; i--; ++curlun_it) {
struct fsg_lun *curlun = *curlun_it;
for (i = 0; i < ARRAY_SIZE(common->luns); --i) {
struct fsg_lun *curlun = common->luns[i];
if (!curlun || !fsg_lun_is_open(curlun))
continue;
@ -2676,6 +2685,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common)
init_completion(&common->thread_notifier);
init_waitqueue_head(&common->fsg_wait);
common->state = FSG_STATE_TERMINATED;
memset(common->luns, 0, sizeof(common->luns));
return common;
}
@ -2742,9 +2752,9 @@ error_release:
}
EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers);
void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
void fsg_common_remove_lun(struct fsg_lun *lun)
{
if (sysfs)
if (device_is_registered(&lun->dev))
device_unregister(&lun->dev);
fsg_lun_close(lun);
kfree(lun);
@ -2757,48 +2767,16 @@ static void _fsg_common_remove_luns(struct fsg_common *common, int n)
for (i = 0; i < n; ++i)
if (common->luns[i]) {
fsg_common_remove_lun(common->luns[i], common->sysfs);
fsg_common_remove_lun(common->luns[i]);
common->luns[i] = NULL;
}
}
EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
void fsg_common_remove_luns(struct fsg_common *common)
{
_fsg_common_remove_luns(common, common->nluns);
_fsg_common_remove_luns(common, ARRAY_SIZE(common->luns));
}
void fsg_common_free_luns(struct fsg_common *common)
{
fsg_common_remove_luns(common);
kfree(common->luns);
common->luns = NULL;
}
EXPORT_SYMBOL_GPL(fsg_common_free_luns);
int fsg_common_set_nluns(struct fsg_common *common, int nluns)
{
struct fsg_lun **curlun;
/* Find out how many LUNs there should be */
if (nluns < 1 || nluns > FSG_MAX_LUNS) {
pr_err("invalid number of LUNs: %u\n", nluns);
return -EINVAL;
}
curlun = kcalloc(FSG_MAX_LUNS, sizeof(*curlun), GFP_KERNEL);
if (unlikely(!curlun))
return -ENOMEM;
if (common->luns)
fsg_common_free_luns(common);
common->luns = curlun;
common->nluns = nluns;
return 0;
}
EXPORT_SYMBOL_GPL(fsg_common_set_nluns);
EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops)
@ -2836,7 +2814,8 @@ int fsg_common_set_cdev(struct fsg_common *common,
* halt bulk endpoints correctly. If one of them is present,
* disable stalls.
*/
common->can_stall = can_stall && !(gadget_is_at91(common->gadget));
common->can_stall = can_stall &&
gadget_is_stall_supported(common->gadget);
return 0;
}
@ -2880,7 +2859,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
char *pathbuf, *p;
int rc = -ENOMEM;
if (!common->nluns || !common->luns)
if (id >= ARRAY_SIZE(common->luns))
return -ENODEV;
if (common->luns[id])
@ -2949,7 +2928,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
return 0;
error_lun:
if (common->sysfs)
if (device_is_registered(&lun->dev))
device_unregister(&lun->dev);
fsg_lun_close(lun);
common->luns[id] = NULL;
@ -2964,14 +2943,16 @@ int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
char buf[8]; /* enough for 100000000 different numbers, decimal */
int i, rc;
for (i = 0; i < common->nluns; ++i) {
fsg_common_remove_luns(common);
for (i = 0; i < cfg->nluns; ++i) {
snprintf(buf, sizeof(buf), "lun%d", i);
rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL);
if (rc)
goto fail;
}
pr_info("Number of LUNs=%d\n", common->nluns);
pr_info("Number of LUNs=%d\n", cfg->nluns);
return 0;
@ -3020,6 +3001,7 @@ EXPORT_SYMBOL_GPL(fsg_common_run_thread);
static void fsg_common_release(struct kref *ref)
{
struct fsg_common *common = container_of(ref, struct fsg_common, ref);
int i;
/* If the thread isn't already dead, tell it to exit now */
if (common->state != FSG_STATE_TERMINATED) {
@ -3027,22 +3009,14 @@ static void fsg_common_release(struct kref *ref)
wait_for_completion(&common->thread_notifier);
}
if (likely(common->luns)) {
struct fsg_lun **lun_it = common->luns;
unsigned i = common->nluns;
/* In error recovery common->nluns may be zero. */
for (; i; --i, ++lun_it) {
struct fsg_lun *lun = *lun_it;
if (!lun)
continue;
fsg_lun_close(lun);
if (common->sysfs)
device_unregister(&lun->dev);
kfree(lun);
}
kfree(common->luns);
for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
struct fsg_lun *lun = common->luns[i];
if (!lun)
continue;
fsg_lun_close(lun);
if (device_is_registered(&lun->dev))
device_unregister(&lun->dev);
kfree(lun);
}
_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
@ -3056,6 +3030,7 @@ static void fsg_common_release(struct kref *ref)
static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
struct fsg_common *common = fsg->common;
struct usb_gadget *gadget = c->cdev->gadget;
int i;
struct usb_ep *ep;
@ -3063,6 +3038,13 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
int ret;
struct fsg_opts *opts;
/* Don't allow to bind if we don't have at least one LUN */
ret = _fsg_common_get_max_lun(common);
if (ret < 0) {
pr_err("There should be at least one LUN.\n");
return -EINVAL;
}
opts = fsg_opts_from_func_inst(f->fi);
if (!opts->no_configfs) {
ret = fsg_common_set_cdev(fsg->common, c->cdev,
@ -3080,7 +3062,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
/* New interface */
i = usb_interface_id(c, f);
if (i < 0)
return i;
goto fail;
fsg_intf_desc.bInterfaceNumber = i;
fsg->interface_number = i;
@ -3123,7 +3105,14 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
autoconf_fail:
ERROR(fsg, "unable to autoconfigure all endpoints\n");
return -ENOTSUPP;
i = -ENOTSUPP;
fail:
/* terminate the thread */
if (fsg->common->state != FSG_STATE_TERMINATED) {
raise_exception(fsg->common, FSG_STATE_EXIT);
wait_for_completion(&fsg->common->thread_notifier);
}
return i;
}
/****************************** ALLOCATE FUNCTION *************************/
@ -3355,7 +3344,7 @@ static void fsg_lun_drop(struct config_group *group, struct config_item *item)
unregister_gadget_item(gadget);
}
fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs);
fsg_common_remove_lun(lun_opts->lun);
fsg_opts->common->luns[lun_opts->lun_id] = NULL;
lun_opts->lun_id = 0;
mutex_unlock(&fsg_opts->lock);
@ -3509,14 +3498,11 @@ static struct usb_function_instance *fsg_alloc_inst(void)
rc = PTR_ERR(opts->common);
goto release_opts;
}
rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS);
if (rc)
goto release_opts;
rc = fsg_common_set_num_buffers(opts->common,
CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS);
if (rc)
goto release_luns;
goto release_opts;
pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
@ -3524,6 +3510,9 @@ static struct usb_function_instance *fsg_alloc_inst(void)
config.removable = true;
rc = fsg_common_create_lun(opts->common, &config, 0, "lun.0",
(const char **)&opts->func_inst.group.cg_item.ci_name);
if (rc)
goto release_buffers;
opts->lun0.lun = opts->common->luns[0];
opts->lun0.lun_id = 0;
config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type);
@ -3534,8 +3523,8 @@ static struct usb_function_instance *fsg_alloc_inst(void)
return &opts->func_inst;
release_luns:
kfree(opts->common->luns);
release_buffers:
fsg_common_free_buffers(opts->common);
release_opts:
kfree(opts);
return ERR_PTR(rc);
@ -3561,23 +3550,12 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi)
struct fsg_opts *opts = fsg_opts_from_func_inst(fi);
struct fsg_common *common = opts->common;
struct fsg_dev *fsg;
unsigned nluns, i;
fsg = kzalloc(sizeof(*fsg), GFP_KERNEL);
if (unlikely(!fsg))
return ERR_PTR(-ENOMEM);
mutex_lock(&opts->lock);
if (!opts->refcnt) {
for (nluns = i = 0; i < FSG_MAX_LUNS; ++i)
if (common->luns[i])
nluns = i + 1;
if (!nluns)
pr_warn("No LUNS defined, continuing anyway\n");
else
common->nluns = nluns;
pr_info("Number of LUNs=%u\n", common->nluns);
}
opts->refcnt++;
mutex_unlock(&opts->lock);

View file

@ -137,14 +137,10 @@ void fsg_common_free_buffers(struct fsg_common *common);
int fsg_common_set_cdev(struct fsg_common *common,
struct usb_composite_dev *cdev, bool can_stall);
void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs);
void fsg_common_remove_lun(struct fsg_lun *lun);
void fsg_common_remove_luns(struct fsg_common *common);
void fsg_common_free_luns(struct fsg_common *common);
int fsg_common_set_nluns(struct fsg_common *common, int nluns);
void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops);

View file

@ -329,6 +329,10 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
unsigned i;
int err;
/* For Control Device interface we do nothing */
if (intf == 0)
return 0;
err = f_midi_start_ep(midi, f, midi->in_ep);
if (err)
return err;

View file

@ -853,9 +853,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* Enable zlps by default for NCM conformance;
* override for musb_hdrc (avoids txdma ovhead)
*/
ncm->port.is_zlp_ok = !(
gadget_is_musbhdrc(cdev->gadget)
);
ncm->port.is_zlp_ok =
gadget_is_zlp_supported(cdev->gadget);
ncm->port.cdc_filter = DEFAULT_FILTER;
DBG(cdev, "activate ncm\n");
net = gether_connect(&ncm->port);

View file

@ -20,7 +20,6 @@
#include <linux/module.h>
#include "u_serial.h"
#include "gadget_chips.h"
/*
@ -37,7 +36,6 @@ struct f_obex {
u8 data_id;
u8 cur_alt;
u8 port_num;
u8 can_activate;
};
static inline struct f_obex *func_to_obex(struct usb_function *f)
@ -268,9 +266,6 @@ static void obex_connect(struct gserial *g)
struct usb_composite_dev *cdev = g->func.config->cdev;
int status;
if (!obex->can_activate)
return;
status = usb_function_activate(&g->func);
if (status)
dev_dbg(&cdev->gadget->dev,
@ -284,9 +279,6 @@ static void obex_disconnect(struct gserial *g)
struct usb_composite_dev *cdev = g->func.config->cdev;
int status;
if (!obex->can_activate)
return;
status = usb_function_deactivate(&g->func);
if (status)
dev_dbg(&cdev->gadget->dev,
@ -304,7 +296,7 @@ static inline bool can_support_obex(struct usb_configuration *c)
*
* Altsettings are mandatory, however...
*/
if (!gadget_supports_altsettings(c->cdev->gadget))
if (!gadget_is_altset_supported(c->cdev->gadget))
return false;
/* everything else is *probably* fine ... */
@ -378,17 +370,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
if (status)
goto fail;
/* Avoid letting this gadget enumerate until the userspace
* OBEX server is active.
*/
status = usb_function_deactivate(f);
if (status < 0)
WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n",
obex->port_num, status);
else
obex->can_activate = true;
dev_dbg(&cdev->gadget->dev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
obex->port_num,
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@ -529,6 +510,7 @@ static struct usb_function *obex_alloc(struct usb_function_instance *fi)
obex->port.func.get_alt = obex_get_alt;
obex->port.func.disable = obex_disable;
obex->port.func.free_func = obex_free;
obex->port.func.bind_deactivated = true;
return &obex->port.func;
}

View file

@ -804,6 +804,8 @@ done:
static void printer_reset_interface(struct printer_dev *dev)
{
unsigned long flags;
if (dev->interface < 0)
return;
@ -815,9 +817,11 @@ static void printer_reset_interface(struct printer_dev *dev)
if (dev->out_ep->desc)
usb_ep_disable(dev->out_ep);
spin_lock_irqsave(&dev->lock, flags);
dev->in_ep->desc = NULL;
dev->out_ep->desc = NULL;
dev->interface = -1;
spin_unlock_irqrestore(&dev->lock, flags);
}
/* Change our operational Interface. */
@ -1131,13 +1135,10 @@ static int printer_func_set_alt(struct usb_function *f,
static void printer_func_disable(struct usb_function *f)
{
struct printer_dev *dev = func_to_printer(f);
unsigned long flags;
DBG(dev, "%s\n", __func__);
spin_lock_irqsave(&dev->lock, flags);
printer_reset_interface(dev);
spin_unlock_irqrestore(&dev->lock, flags);
}
static inline struct f_printer_opts

View file

@ -16,7 +16,6 @@
#include <linux/device.h>
#include "u_serial.h"
#include "gadget_chips.h"
/*

View file

@ -20,7 +20,6 @@
#include <linux/err.h>
#include "g_zero.h"
#include "gadget_chips.h"
#include "u_f.h"
/*
@ -42,11 +41,6 @@
* queues are relatively independent, will receive a range of packet sizes,
* and can often be made to run out completely. Those issues are important
* when stress testing peripheral controller drivers.
*
*
* This is currently packaged as a configuration driver, which can't be
* combined with other functions to make composite devices. However, it
* can be combined with other independent configurations.
*/
struct f_sourcesink {
struct usb_function function;

View file

@ -975,6 +975,29 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
"%s:%d Error!\n", __func__, __LINE__);
}
static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
struct usb_endpoint_descriptor *ep_desc,
unsigned int factor, bool is_playback)
{
int chmask, srate, ssize;
u16 max_packet_size;
if (is_playback) {
chmask = uac2_opts->p_chmask;
srate = uac2_opts->p_srate;
ssize = uac2_opts->p_ssize;
} else {
chmask = uac2_opts->c_chmask;
srate = uac2_opts->c_srate;
ssize = uac2_opts->c_ssize;
}
max_packet_size = num_channels(chmask) * ssize *
DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_packet_size,
le16_to_cpu(ep_desc->wMaxPacketSize)));
}
static int
afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
{
@ -1070,10 +1093,14 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
uac2->p_prm.uac2 = uac2;
uac2->c_prm.uac2 = uac2;
/* Calculate wMaxPacketSize according to audio bandwidth */
set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true);
set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false);
set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true);
set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false);
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize;
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
if (ret)

View file

@ -733,12 +733,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc->control_req->complete = uvc_function_ep0_complete;
uvc->control_req->context = uvc;
/* Avoid letting this gadget enumerate until the userspace server is
* active.
*/
if ((ret = usb_function_deactivate(f)) < 0)
goto error;
if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) {
printk(KERN_INFO "v4l2_device_register failed\n");
goto error;
@ -949,6 +943,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
uvc->func.disable = uvc_function_disable;
uvc->func.setup = uvc_function_setup;
uvc->func.free_func = uvc_free;
uvc->func.bind_deactivated = true;
return &uvc->func;
}

View file

@ -123,7 +123,7 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun)
#define FSG_BUFLEN ((u32)16384)
/* Maximal number of LUNs supported in mass storage function */
#define FSG_MAX_LUNS 8
#define FSG_MAX_LUNS 16
enum fsg_buffer_state {
BUF_STATE_EMPTY = 0,

View file

@ -20,8 +20,6 @@
#include <linux/usb/cdc.h>
#include <linux/netdevice.h>
#include "gadget_chips.h"
#define QMULT_DEFAULT 5
/*
@ -259,7 +257,7 @@ void gether_disconnect(struct gether *);
/* Some controllers can't support CDC Ethernet (ECM) ... */
static inline bool can_support_ecm(struct usb_gadget *gadget)
{
if (!gadget_supports_altsettings(gadget))
if (!gadget_is_altset_supported(gadget))
return false;
/* Everything else is *presumably* fine ... but this is a bit

View file

@ -21,8 +21,6 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "gadget_chips.h"
#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p"
#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c"
#define FILE_CONTROL "/dev/snd/controlC0"

View file

@ -339,6 +339,7 @@ config USB_CDC_COMPOSITE
config USB_G_NOKIA
tristate "Nokia composite gadget"
depends on PHONET
depends on BLOCK
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_U_ETHER
@ -346,6 +347,7 @@ config USB_G_NOKIA
select USB_F_OBEX
select USB_F_PHONET
select USB_F_ECM
select USB_F_MASS_STORAGE
help
The Nokia composite gadget provides support for acm, obex
and phonet in only one composite gadget driver.

View file

@ -58,21 +58,7 @@ static struct usb_device_descriptor device_desc = {
/*.bNumConfigurations = DYNAMIC*/
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/*
* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@ -200,10 +186,6 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
if (status)
goto fail;
status = fsg_common_set_nluns(opts->common, config.nluns);
if (status)
goto fail_set_nluns;
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
@ -225,10 +207,21 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
if (gadget_is_otg(gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(gadget);
if (!usb_desc)
goto fail_string_ids;
usb_otg_descriptor_init(gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
/* register our configuration */
status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config);
if (status < 0)
goto fail_string_ids;
goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@ -236,11 +229,12 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
return 0;
/* error recovery */
fail_otg_desc:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
fsg_common_free_luns(opts->common);
fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
@ -255,6 +249,9 @@ static int acm_ms_unbind(struct usb_composite_dev *cdev)
usb_put_function_instance(fi_msg);
usb_put_function(f_acm);
usb_put_function_instance(f_acm_inst);
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/usb/composite.h>
#include "gadget_chips.h"
#define DRIVER_DESC "Linux USB Audio Gadget"
#define DRIVER_VERSION "Feb 2, 2012"
@ -124,7 +123,7 @@ static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x200),
.bcdUSB = cpu_to_le16(0x200),
#ifdef CONFIG_GADGET_UAC1
.bDeviceClass = USB_CLASS_PER_INTERFACE,
@ -141,8 +140,8 @@ static struct usb_device_descriptor device_desc = {
* we support. (As does bNumConfigurations.) These values can
* also be overridden by module parameters.
*/
.idVendor = __constant_cpu_to_le16(AUDIO_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16(AUDIO_PRODUCT_NUM),
.idVendor = cpu_to_le16(AUDIO_VENDOR_NUM),
.idProduct = cpu_to_le16(AUDIO_PRODUCT_NUM),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@ -150,20 +149,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@ -259,14 +245,28 @@ static int audio_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
if (!usb_desc)
goto fail;
usb_otg_descriptor_init(cdev->gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
status = usb_add_config(cdev, &audio_config_driver, audio_do_config);
if (status < 0)
goto fail;
goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION);
return 0;
fail_otg_desc:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail:
#ifndef CONFIG_GADGET_UAC1
usb_put_function_instance(fi_uac2);
@ -289,6 +289,9 @@ static int audio_unbind(struct usb_composite_dev *cdev)
if (!IS_ERR_OR_NULL(fi_uac2))
usb_put_function_instance(fi_uac2);
#endif
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -60,21 +60,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@ -193,10 +179,21 @@ static int cdc_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
if (gadget_is_otg(gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(gadget);
if (!usb_desc)
goto fail1;
usb_otg_descriptor_init(gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
/* register our configuration */
status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
if (status < 0)
goto fail1;
goto fail2;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@ -204,6 +201,9 @@ static int cdc_bind(struct usb_composite_dev *cdev)
return 0;
fail2:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail1:
usb_put_function_instance(fi_serial);
fail:
@ -219,6 +219,9 @@ static int cdc_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_ecm);
if (!IS_ERR_OR_NULL(fi_ecm))
usb_put_function_instance(fi_ecm);
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -35,10 +35,10 @@ static struct dbgp {
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_VENDOR_SPEC,
.idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
.idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
.idVendor = cpu_to_le16(DRIVER_VENDOR_ID),
.idProduct = cpu_to_le16(DRIVER_PRODUCT_ID),
.bNumConfigurations = 1,
};
@ -251,7 +251,7 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
dbgp.i_ep->driver_data = gadget;
i_desc.wMaxPacketSize =
__constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
if (!dbgp.o_ep) {
@ -262,7 +262,7 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
dbgp.o_ep->driver_data = gadget;
o_desc.wMaxPacketSize =
__constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress;
dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress;

View file

@ -171,20 +171,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
@ -416,17 +403,28 @@ static int eth_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
if (gadget_is_otg(gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(gadget);
if (!usb_desc)
goto fail1;
usb_otg_descriptor_init(gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
/* register our configuration(s); RNDIS first, if it's used */
if (has_rndis()) {
status = usb_add_config(cdev, &rndis_config_driver,
rndis_do_config);
if (status < 0)
goto fail1;
goto fail2;
}
status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
if (status < 0)
goto fail1;
goto fail2;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@ -434,6 +432,9 @@ static int eth_bind(struct usb_composite_dev *cdev)
return 0;
fail2:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail1:
if (has_rndis())
usb_put_function_instance(fi_rndis);
@ -463,6 +464,9 @@ static int eth_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_geth);
usb_put_function_instance(fi_geth);
}
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -88,21 +88,7 @@ MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
module_param_array_named(functions, func_names, charp, &func_num, 0);
MODULE_PARM_DESC(functions, "USB Functions list");
static const struct usb_descriptor_header *gfs_otg_desc[] = {
(const struct usb_descriptor_header *)
&(const struct usb_otg_descriptor) {
.bLength = sizeof(struct usb_otg_descriptor),
.bDescriptorType = USB_DT_OTG,
/*
* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
},
NULL
};
static const struct usb_descriptor_header *gfs_otg_desc[2];
/* String IDs are assigned dynamically */
static struct usb_string gfs_strings[] = {
@ -412,6 +398,17 @@ static int gfs_bind(struct usb_composite_dev *cdev)
goto error_rndis;
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
if (gadget_is_otg(cdev->gadget) && !gfs_otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
if (!usb_desc)
goto error_rndis;
usb_otg_descriptor_init(cdev->gadget, usb_desc);
gfs_otg_desc[0] = usb_desc;
gfs_otg_desc[1] = NULL;
}
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
struct gfs_configuration *c = gfs_configurations + i;
int sid = USB_GADGET_FIRST_AVAIL_IDX + i;
@ -432,6 +429,8 @@ static int gfs_bind(struct usb_composite_dev *cdev)
/* TODO */
error_unbind:
kfree(gfs_otg_desc[0]);
gfs_otg_desc[0] = NULL;
error_rndis:
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
usb_put_function_instance(fi_rndis);
@ -473,6 +472,9 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
for (i = 0; i < N_CONF * func_num; ++i)
usb_put_function(*(f_ffs[0] + i));
kfree(gfs_otg_desc[0]);
gfs_otg_desc[0] = NULL;
return 0;
}

View file

@ -35,8 +35,6 @@
#include <linux/usb/audio.h>
#include <linux/usb/midi.h>
#include "gadget_chips.h"
#include "u_midi.h"
/*-------------------------------------------------------------------------*/
@ -88,10 +86,10 @@ MODULE_PARM_DESC(out_ports, "Number of MIDI output ports");
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
.idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
.idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
.idVendor = cpu_to_le16(DRIVER_VENDOR_NUM),
.idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
.bNumConfigurations = 1,

View file

@ -19,7 +19,6 @@
#include <linux/usb/composite.h>
#include <linux/usb/g_hid.h>
#include "gadget_chips.h"
#define DRIVER_DESC "HID Gadget"
#define DRIVER_VERSION "2010/03/16"
@ -68,21 +67,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@ -186,16 +171,30 @@ static int hid_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
if (gadget_is_otg(gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(gadget);
if (!usb_desc)
goto put;
usb_otg_descriptor_init(gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
/* register our configuration */
status = usb_add_config(cdev, &config_driver, do_config);
if (status < 0)
goto put;
goto free_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
return 0;
free_otg_desc:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
put:
list_for_each_entry(m, &hidg_func_list, node) {
if (m == n)
@ -213,6 +212,10 @@ static int hid_unbind(struct usb_composite_dev *cdev)
usb_put_function(n->f);
usb_put_function_instance(n->fi);
}
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -64,21 +64,7 @@ static struct usb_device_descriptor msg_device_desc = {
.bNumConfigurations = 1,
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/*
* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
@ -191,10 +177,6 @@ static int msg_bind(struct usb_composite_dev *cdev)
if (status)
goto fail;
status = fsg_common_set_nluns(opts->common, config.nluns);
if (status)
goto fail_set_nluns;
fsg_common_set_ops(opts->common, &ops);
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
@ -214,9 +196,20 @@ static int msg_bind(struct usb_composite_dev *cdev)
goto fail_string_ids;
msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
if (!usb_desc)
goto fail_string_ids;
usb_otg_descriptor_init(cdev->gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
if (status < 0)
goto fail_string_ids;
goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&cdev->gadget->dev,
@ -224,11 +217,12 @@ static int msg_bind(struct usb_composite_dev *cdev)
set_bit(0, &msg_registered);
return 0;
fail_otg_desc:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
fsg_common_free_luns(opts->common);
fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
@ -243,6 +237,9 @@ static int msg_unbind(struct usb_composite_dev *cdev)
if (!IS_ERR(fi_msg))
usb_put_function_instance(fi_msg);
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -78,21 +78,7 @@ static struct usb_device_descriptor device_desc = {
.idProduct = cpu_to_le16(MULTI_PRODUCT_NUM),
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &(struct usb_otg_descriptor){
.bLength = sizeof(struct usb_otg_descriptor),
.bDescriptorType = USB_DT_OTG,
/*
* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
},
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
enum {
MULTI_STRING_RNDIS_CONFIG_IDX = USB_GADGET_FIRST_AVAIL_IDX,
@ -407,10 +393,6 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
if (status)
goto fail2;
status = fsg_common_set_nluns(fsg_opts->common, config.nluns);
if (status)
goto fail_set_nluns;
status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
@ -429,14 +411,25 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
goto fail_string_ids;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
if (gadget_is_otg(gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(gadget);
if (!usb_desc)
goto fail_string_ids;
usb_otg_descriptor_init(gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
/* register configurations */
status = rndis_config_register(cdev);
if (unlikely(status < 0))
goto fail_string_ids;
goto fail_otg_desc;
status = cdc_config_register(cdev);
if (unlikely(status < 0))
goto fail_string_ids;
goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
/* we're done */
@ -445,11 +438,12 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
/* error recovery */
fail_otg_desc:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(fsg_opts->common);
fail_set_cdev:
fsg_common_free_luns(fsg_opts->common);
fail_set_nluns:
fsg_common_free_buffers(fsg_opts->common);
fail2:
usb_put_function_instance(fi_msg);
@ -490,6 +484,9 @@ static int multi_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_ecm);
usb_put_function_instance(fi_ecm);
#endif
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -69,20 +69,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@ -171,16 +158,30 @@ static int gncm_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
if (gadget_is_otg(gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(gadget);
if (!usb_desc)
goto fail;
usb_otg_descriptor_init(gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
status = usb_add_config(cdev, &ncm_config_driver,
ncm_do_config);
if (status < 0)
goto fail;
goto fail1;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s\n", DRIVER_DESC);
return 0;
fail1:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail:
usb_put_function_instance(f_ncm_inst);
return status;
@ -192,6 +193,9 @@ static int gncm_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_ncm);
if (!IS_ERR_OR_NULL(f_ncm_inst))
usb_put_function_instance(f_ncm_inst);
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -23,7 +23,7 @@
#include "u_ether.h"
#include "u_phonet.h"
#include "u_ecm.h"
#include "gadget_chips.h"
#include "f_mass_storage.h"
/* Defines */
@ -34,6 +34,29 @@ USB_GADGET_COMPOSITE_OPTIONS();
USB_ETHERNET_MODULE_PARAMETERS();
static struct fsg_module_parameters fsg_mod_data = {
.stall = 0,
.luns = 2,
.removable_count = 2,
.removable = { 1, 1, },
};
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
#else
/*
* Number of buffers we will use.
* 2 is usually enough for good buffering pipeline
*/
#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
#endif /* CONFIG_USB_DEBUG */
FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
#define NOKIA_VENDOR_ID 0x0421 /* Nokia */
#define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */
@ -66,10 +89,10 @@ static struct usb_gadget_strings *dev_strings[] = {
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = __constant_cpu_to_le16(0x0200),
.bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_COMM,
.idVendor = __constant_cpu_to_le16(NOKIA_VENDOR_ID),
.idProduct = __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
.idVendor = cpu_to_le16(NOKIA_VENDOR_ID),
.idProduct = cpu_to_le16(NOKIA_PRODUCT_ID),
.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM),
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@ -94,6 +117,8 @@ static struct usb_function *f_obex1_cfg2;
static struct usb_function *f_obex2_cfg2;
static struct usb_function *f_phonet_cfg1;
static struct usb_function *f_phonet_cfg2;
static struct usb_function *f_msg_cfg1;
static struct usb_function *f_msg_cfg2;
static struct usb_configuration nokia_config_500ma_driver = {
@ -117,6 +142,7 @@ static struct usb_function_instance *fi_ecm;
static struct usb_function_instance *fi_obex1;
static struct usb_function_instance *fi_obex2;
static struct usb_function_instance *fi_phonet;
static struct usb_function_instance *fi_msg;
static int nokia_bind_config(struct usb_configuration *c)
{
@ -125,6 +151,8 @@ static int nokia_bind_config(struct usb_configuration *c)
struct usb_function *f_obex1 = NULL;
struct usb_function *f_ecm;
struct usb_function *f_obex2 = NULL;
struct usb_function *f_msg;
struct fsg_opts *fsg_opts;
int status = 0;
int obex1_stat = -1;
int obex2_stat = -1;
@ -160,6 +188,12 @@ static int nokia_bind_config(struct usb_configuration *c)
goto err_get_ecm;
}
f_msg = usb_get_function(fi_msg);
if (IS_ERR(f_msg)) {
status = PTR_ERR(f_msg);
goto err_get_msg;
}
if (!IS_ERR_OR_NULL(f_phonet)) {
phonet_stat = usb_add_function(c, f_phonet);
if (phonet_stat)
@ -187,21 +221,36 @@ static int nokia_bind_config(struct usb_configuration *c)
pr_debug("could not bind ecm config %d\n", status);
goto err_ecm;
}
fsg_opts = fsg_opts_from_func_inst(fi_msg);
status = fsg_common_run_thread(fsg_opts->common);
if (status)
goto err_msg;
status = usb_add_function(c, f_msg);
if (status)
goto err_msg;
if (c == &nokia_config_500ma_driver) {
f_acm_cfg1 = f_acm;
f_ecm_cfg1 = f_ecm;
f_phonet_cfg1 = f_phonet;
f_obex1_cfg1 = f_obex1;
f_obex2_cfg1 = f_obex2;
f_msg_cfg1 = f_msg;
} else {
f_acm_cfg2 = f_acm;
f_ecm_cfg2 = f_ecm;
f_phonet_cfg2 = f_phonet;
f_obex1_cfg2 = f_obex1;
f_obex2_cfg2 = f_obex2;
f_msg_cfg2 = f_msg;
}
return status;
err_msg:
usb_remove_function(c, f_ecm);
err_ecm:
usb_remove_function(c, f_acm);
err_conf:
@ -211,6 +260,8 @@ err_conf:
usb_remove_function(c, f_obex1);
if (!phonet_stat)
usb_remove_function(c, f_phonet);
usb_put_function(f_msg);
err_get_msg:
usb_put_function(f_ecm);
err_get_ecm:
usb_put_function(f_acm);
@ -227,6 +278,8 @@ err_get_acm:
static int nokia_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct fsg_opts *fsg_opts;
struct fsg_config fsg_config;
int status;
status = usb_string_ids_tab(cdev, strings_dev);
@ -238,7 +291,7 @@ static int nokia_bind(struct usb_composite_dev *cdev)
nokia_config_500ma_driver.iConfiguration = status;
nokia_config_100ma_driver.iConfiguration = status;
if (!gadget_supports_altsettings(gadget)) {
if (!gadget_is_altset_supported(gadget)) {
status = -ENODEV;
goto err_usb;
}
@ -267,11 +320,42 @@ static int nokia_bind(struct usb_composite_dev *cdev)
goto err_acm_inst;
}
fi_msg = usb_get_function_instance("mass_storage");
if (IS_ERR(fi_msg)) {
status = PTR_ERR(fi_msg);
goto err_ecm_inst;
}
/* set up mass storage function */
fsg_config_from_params(&fsg_config, &fsg_mod_data, fsg_num_buffers);
fsg_config.vendor_name = "Nokia";
fsg_config.product_name = "N900";
fsg_opts = fsg_opts_from_func_inst(fi_msg);
fsg_opts->no_configfs = true;
status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers);
if (status)
goto err_msg_inst;
status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall);
if (status)
goto err_msg_buf;
fsg_common_set_sysfs(fsg_opts->common, true);
status = fsg_common_create_luns(fsg_opts->common, &fsg_config);
if (status)
goto err_msg_buf;
fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name,
fsg_config.product_name);
/* finally register the configuration */
status = usb_add_config(cdev, &nokia_config_500ma_driver,
nokia_bind_config);
if (status < 0)
goto err_ecm_inst;
goto err_msg_luns;
status = usb_add_config(cdev, &nokia_config_100ma_driver,
nokia_bind_config);
@ -292,6 +376,12 @@ err_put_cfg1:
if (!IS_ERR_OR_NULL(f_phonet_cfg1))
usb_put_function(f_phonet_cfg1);
usb_put_function(f_ecm_cfg1);
err_msg_luns:
fsg_common_remove_luns(fsg_opts->common);
err_msg_buf:
fsg_common_free_buffers(fsg_opts->common);
err_msg_inst:
usb_put_function_instance(fi_msg);
err_ecm_inst:
usb_put_function_instance(fi_ecm);
err_acm_inst:
@ -325,7 +415,10 @@ static int nokia_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_acm_cfg2);
usb_put_function(f_ecm_cfg1);
usb_put_function(f_ecm_cfg2);
usb_put_function(f_msg_cfg1);
usb_put_function(f_msg_cfg2);
usb_put_function_instance(fi_msg);
usb_put_function_instance(fi_ecm);
if (!IS_ERR(fi_obex2))
usb_put_function_instance(fi_obex2);

View file

@ -19,8 +19,6 @@
#include <linux/usb/gadget.h>
#include <linux/usb/g_printer.h>
#include "gadget_chips.h"
USB_GADGET_COMPOSITE_OPTIONS();
#define DRIVER_DESC "Printer Gadget"
@ -82,16 +80,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
.bmAttributes = USB_OTG_SRP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@ -136,7 +125,6 @@ static int printer_do_config(struct usb_configuration *c)
usb_gadget_set_selfpowered(gadget);
if (gadget_is_otg(gadget)) {
otg_descriptor.bmAttributes |= USB_OTG_HNP;
printer_cfg_driver.descriptors = otg_desc;
printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
@ -174,21 +162,39 @@ static int printer_bind(struct usb_composite_dev *cdev)
opts->q_len = QLEN;
ret = usb_string_ids_tab(cdev, strings);
if (ret < 0) {
usb_put_function_instance(fi_printer);
return ret;
}
if (ret < 0)
goto fail_put_func_inst;
device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id;
device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id;
ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
if (ret) {
usb_put_function_instance(fi_printer);
return ret;
if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
if (!usb_desc) {
ret = -ENOMEM;
goto fail_put_func_inst;
}
usb_otg_descriptor_init(cdev->gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
if (ret)
goto fail_free_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
return ret;
fail_free_otg_desc:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail_put_func_inst:
usb_put_function_instance(fi_printer);
return ret;
}
static int printer_unbind(struct usb_composite_dev *cdev)
@ -196,6 +202,9 @@ static int printer_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_printer);
usb_put_function_instance(fi_printer);
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -17,7 +17,6 @@
#include <linux/tty_flip.h>
#include "u_serial.h"
#include "gadget_chips.h"
/* Defines */
@ -79,20 +78,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@ -191,6 +177,18 @@ static int gs_bind(struct usb_composite_dev *cdev)
serial_config_driver.iConfiguration = status;
if (gadget_is_otg(cdev->gadget)) {
if (!otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
if (!usb_desc) {
status = -ENOMEM;
goto fail;
}
usb_otg_descriptor_init(cdev->gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
serial_config_driver.descriptors = otg_desc;
serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
@ -208,13 +206,15 @@ static int gs_bind(struct usb_composite_dev *cdev)
"gser");
}
if (status < 0)
goto fail;
goto fail1;
usb_composite_overwrite_options(cdev, &coverwrite);
INFO(cdev, "%s\n", GS_VERSION_NAME);
return 0;
fail1:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail:
return status;
}
@ -227,6 +227,10 @@ static int gs_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_serial[i]);
usb_put_function_instance(fi_serial[i]);
}
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -121,24 +121,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 2,
};
#ifdef CONFIG_USB_OTG
static struct usb_otg_descriptor otg_descriptor = {
.bLength = sizeof otg_descriptor,
.bDescriptorType = USB_DT_OTG,
/* REVISIT SRP-only hardware is possible, although
* it would not be called "OTG" ...
*/
.bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
};
static const struct usb_descriptor_header *otg_desc[] = {
(struct usb_descriptor_header *) &otg_descriptor,
NULL,
};
#else
#define otg_desc NULL
#endif
static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
/* default serial number takes at least two packets */
@ -341,6 +324,18 @@ static int zero_bind(struct usb_composite_dev *cdev)
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
if (!otg_desc[0]) {
struct usb_descriptor_header *usb_desc;
usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
if (!usb_desc) {
status = -ENOMEM;
goto err_conf_flb;
}
usb_otg_descriptor_init(cdev->gadget, usb_desc);
otg_desc[0] = usb_desc;
otg_desc[1] = NULL;
}
sourcesink_driver.descriptors = otg_desc;
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
loopback_driver.descriptors = otg_desc;
@ -359,12 +354,12 @@ static int zero_bind(struct usb_composite_dev *cdev)
}
status = usb_add_function(&sourcesink_driver, func_ss);
if (status)
goto err_conf_flb;
goto err_free_otg_desc;
usb_ep_autoconfig_reset(cdev->gadget);
status = usb_add_function(&loopback_driver, func_lb);
if (status)
goto err_conf_flb;
goto err_free_otg_desc;
usb_ep_autoconfig_reset(cdev->gadget);
usb_composite_overwrite_options(cdev, &coverwrite);
@ -373,6 +368,9 @@ static int zero_bind(struct usb_composite_dev *cdev)
return 0;
err_free_otg_desc:
kfree(otg_desc[0]);
otg_desc[0] = NULL;
err_conf_flb:
usb_put_function(func_lb);
func_lb = NULL;
@ -397,6 +395,9 @@ static int zero_unbind(struct usb_composite_dev *cdev)
if (!IS_ERR_OR_NULL(func_lb))
usb_put_function(func_lb);
usb_put_function_instance(func_inst_lb);
kfree(otg_desc[0]);
otg_desc[0] = NULL;
return 0;
}

View file

@ -138,15 +138,82 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect,
/* endpoint names used for print */
static const char ep0_string[] = "ep0in";
static const char *const ep_string[] = {
ep0_string,
"ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
"ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
"ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk",
"ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk",
"ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk",
"ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk",
"ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
static const struct {
const char *name;
const struct usb_ep_caps caps;
} ep_info[] = {
#define EP_INFO(_name, _caps) \
{ \
.name = _name, \
.caps = _caps, \
}
EP_INFO(ep0_string,
USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep1in-int",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep2in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep3in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep4in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep5in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep6in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep7in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep8in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep9in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep10in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep11in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep12in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep13in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep14in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep15in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep0out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep1out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep2out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep3out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep4out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep5out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep6out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep7out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep8out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep9out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep10out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep11out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep12out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep13out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep14out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep15out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
#undef EP_INFO
};
/* DMA usage flag */
@ -1517,7 +1584,8 @@ static void udc_setup_endpoints(struct udc *dev)
for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
ep = &dev->ep[tmp];
ep->dev = dev;
ep->ep.name = ep_string[tmp];
ep->ep.name = ep_info[tmp].name;
ep->ep.caps = ep_info[tmp].caps;
ep->num = tmp;
/* txfifo size is calculated at enable time */
ep->txfifo = dev->txfifo;

View file

@ -59,15 +59,34 @@
#define DRIVER_VERSION "3 May 2006"
static const char driver_name [] = "at91_udc";
static const char * const ep_names[] = {
"ep0",
"ep1",
"ep2",
"ep3-int",
"ep4",
"ep5",
static const struct {
const char *name;
const struct usb_ep_caps caps;
} ep_info[] = {
#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",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep2",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep3-int",
USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep4",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep5",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
#undef EP_INFO
};
#define ep0name ep_names[0]
#define ep0name ep_info[0].name
#define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000)
@ -825,6 +844,7 @@ static void udc_reinit(struct at91_udc *udc)
INIT_LIST_HEAD(&udc->gadget.ep_list);
INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
udc->gadget.quirk_stall_not_supp = 1;
for (i = 0; i < NUM_ENDPOINTS; i++) {
struct at91_ep *ep = &udc->ep[i];
@ -1830,7 +1850,8 @@ static int at91udc_probe(struct platform_device *pdev)
for (i = 0; i < NUM_ENDPOINTS; i++) {
ep = &udc->ep[i];
ep->ep.name = ep_names[i];
ep->ep.name = ep_info[i].name;
ep->ep.caps = ep_info[i].caps;
ep->ep.ops = &at91_ep_ops;
ep->udc = udc;
ep->int_mask = BIT(i);

View file

@ -1989,6 +1989,10 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc");
ret = of_property_read_string(pp, "name", &name);
if (ret) {
dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret);
goto err;
}
ep->ep.name = name;
ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
@ -2063,6 +2067,17 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev,
ep->can_dma = pdata->ep[i].can_dma;
ep->can_isoc = pdata->ep[i].can_isoc;
if (i == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = ep->can_isoc;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
if (i)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
}

View file

@ -44,9 +44,29 @@
#define DRV_MODULE_NAME "bcm63xx_udc"
static const char bcm63xx_ep0name[] = "ep0";
static const char *const bcm63xx_ep_name[] = {
bcm63xx_ep0name,
"ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int",
static const struct {
const char *name;
const struct usb_ep_caps caps;
} bcm63xx_ep_info[] = {
#define EP_INFO(_name, _caps) \
{ \
.name = _name, \
.caps = _caps, \
}
EP_INFO(bcm63xx_ep0name,
USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep1in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep2out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep3in-int",
USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep4out-int",
USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_OUT)),
#undef EP_INFO
};
static bool use_fullspeed;
@ -943,7 +963,8 @@ static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc)
for (i = 0; i < BCM63XX_NUM_EP; i++) {
struct bcm63xx_ep *bep = &udc->bep[i];
bep->ep.name = bcm63xx_ep_name[i];
bep->ep.name = bcm63xx_ep_info[i].name;
bep->ep.caps = bcm63xx_ep_info[i].caps;
bep->ep_num = i;
bep->ep.ops = &bcm63xx_udc_ep_ops;
list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);

View file

@ -1952,12 +1952,18 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir)
ep->bdc = bdc;
ep->dir = dir;
if (dir)
ep->usb_ep.caps.dir_in = true;
else
ep->usb_ep.caps.dir_out = true;
/* ep->ep_num is the index inside bdc_ep */
if (epnum == 1) {
ep->ep_num = 1;
bdc->bdc_ep_array[ep->ep_num] = ep;
snprintf(ep->name, sizeof(ep->name), "ep%d", epnum - 1);
usb_ep_set_maxpacket_limit(&ep->usb_ep, EP0_MAX_PKT_SIZE);
ep->usb_ep.caps.type_control = true;
ep->comp_desc = NULL;
bdc->gadget.ep0 = &ep->usb_ep;
} else {
@ -1971,6 +1977,9 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir)
dir & 1 ? "in" : "out");
usb_ep_set_maxpacket_limit(&ep->usb_ep, 1024);
ep->usb_ep.caps.type_iso = true;
ep->usb_ep.caps.type_bulk = true;
ep->usb_ep.caps.type_int = true;
ep->usb_ep.max_streams = 0;
list_add_tail(&ep->usb_ep.ep_list, &bdc->gadget.ep_list);
}

View file

@ -127,23 +127,87 @@ static inline struct dummy_request *usb_request_to_dummy_request
static const char ep0name[] = "ep0";
static const char *const ep_name[] = {
ep0name, /* everyone has ep0 */
static const struct {
const char *name;
const struct usb_ep_caps caps;
} ep_info[] = {
#define EP_INFO(_name, _caps) \
{ \
.name = _name, \
.caps = _caps, \
}
/* everyone has ep0 */
EP_INFO(ep0name,
USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
/* act like a pxa250: fifteen fixed function endpoints */
"ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int",
"ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int",
"ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",
"ep15in-int",
EP_INFO("ep1in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep2out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep3in-iso",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep4out-iso",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep5in-int",
USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep6in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep7out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep8in-iso",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep9out-iso",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep10in-int",
USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep11in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep12out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep13in-iso",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep14out-iso",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep15in-int",
USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
/* or like sa1100: two fixed function endpoints */
"ep1out-bulk", "ep2in-bulk",
EP_INFO("ep1out-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep2in-bulk",
USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
/* and now some generic EPs so we have enough in multi config */
"ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in",
"ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out",
EP_INFO("ep3out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep4in",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep5out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep6out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep7in",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep8out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep9in",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep10out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep11out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep12in",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep13out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep14in",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep15out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
#undef EP_INFO
};
#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name)
#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_info)
/*-------------------------------------------------------------------------*/
@ -938,9 +1002,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
for (i = 0; i < DUMMY_ENDPOINTS; i++) {
struct dummy_ep *ep = &dum->ep[i];
if (!ep_name[i])
if (!ep_info[i].name)
break;
ep->ep.name = ep_name[i];
ep->ep.name = ep_info[i].name;
ep->ep.caps = ep_info[i].caps;
ep->ep.ops = &dummy_ep_ops;
list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
ep->halted = ep->wedged = ep->already_seen =
@ -1684,7 +1749,7 @@ static void dummy_timer(unsigned long _dum_hcd)
}
for (i = 0; i < DUMMY_ENDPOINTS; i++) {
if (!ep_name[i])
if (!ep_info[i].name)
break;
dum->ep[i].already_seen = 0;
}

View file

@ -384,25 +384,15 @@ static void fotg210_ep0_queue(struct fotg210_ep *ep,
return;
}
if (ep->dir_in) { /* if IN */
if (req->req.length) {
fotg210_start_dma(ep, req);
} else {
pr_err("%s : req->req.length = 0x%x\n",
__func__, req->req.length);
}
fotg210_start_dma(ep, req);
if ((req->req.length == req->req.actual) ||
(req->req.actual < ep->ep.maxpacket))
fotg210_done(ep, req, 0);
} else { /* OUT */
if (!req->req.length) {
fotg210_done(ep, req, 0);
} else {
u32 value = ioread32(ep->fotg210->reg +
FOTG210_DMISGR0);
u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR0);
value &= ~DMISGR0_MCX_OUT_INT;
iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
}
value &= ~DMISGR0_MCX_OUT_INT;
iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
}
}
@ -1153,6 +1143,17 @@ static int fotg210_udc_probe(struct platform_device *pdev)
ep->ep.name = fotg210_ep_name[i];
ep->ep.ops = &fotg210_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
if (i == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
fotg210->gadget.ep0 = &fotg210->ep[0]->ep;

View file

@ -2417,6 +2417,17 @@ static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num)
strcpy(ep->name, ep_name[pipe_num]);
ep->ep.name = ep_name[pipe_num];
if (pipe_num == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
ep->ep.ops = &qe_ep_ops;
ep->stopped = 1;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);

View file

@ -2313,6 +2313,19 @@ static int struct_ep_setup(struct fsl_udc *udc, unsigned char index,
ep->ep.ops = &fsl_ep_ops;
ep->stopped = 0;
if (index == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
if (index & 1)
ep->ep.caps.dir_in = true;
else
ep->ep.caps.dir_out = true;
/* for ep0: maxP defined in desc
* for other eps, maxP is set by epautoconfig() called by gadget layer
*/

View file

@ -1450,6 +1450,17 @@ static int fusb300_probe(struct platform_device *pdev)
ep->ep.name = fusb300_ep_name[i];
ep->ep.ops = &fusb300_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
if (i == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
fusb300->ep[0]->epnum = 0;

View file

@ -1,55 +0,0 @@
/*
* USB device controllers have lots of quirks. Use these macros in
* gadget drivers or other code that needs to deal with them, and which
* autoconfigures instead of using early binding to the hardware.
*
* This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
* some config file that gets updated as new hardware is supported.
* (And avoiding all runtime comparisons in typical one-choice configs!)
*
* NOTE: some of these controller drivers may not be available yet.
* Some are available on 2.4 kernels; several are available, but not
* yet pushed in the 2.6 mainline tree.
*/
#ifndef __GADGET_CHIPS_H
#define __GADGET_CHIPS_H
#include <linux/usb/gadget.h>
/*
* NOTICE: the entries below are alphabetical and should be kept
* that way.
*
* Always be sure to add new entries to the correct position or
* accept the bashing later.
*
* If you have forgotten the alphabetical order let VIM/EMACS
* do that for you.
*/
#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name))
#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name))
#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name))
#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name))
#define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name))
#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name))
/**
* gadget_supports_altsettings - return true if altsettings work
* @gadget: the gadget in question
*/
static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
{
/* PXA 21x/25x/26x has no altsettings at all */
if (gadget_is_pxa(gadget))
return false;
/* PXA 27x and 3xx have *broken* altsetting support */
if (gadget_is_pxa27x(gadget))
return false;
/* Everything else is *presumably* fine ... */
return true;
}
#endif /* __GADGET_CHIPS_H */

View file

@ -990,6 +990,35 @@ static int goku_get_frame(struct usb_gadget *_gadget)
return -EOPNOTSUPP;
}
static struct usb_ep *goku_match_ep(struct usb_gadget *g,
struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *ep_comp)
{
struct goku_udc *dev = to_goku_udc(g);
struct usb_ep *ep;
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_INT:
/* single buffering is enough */
ep = &dev->ep[3].ep;
if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
return ep;
break;
case USB_ENDPOINT_XFER_BULK:
if (usb_endpoint_dir_in(desc)) {
/* DMA may be available */
ep = &dev->ep[2].ep;
if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
return ep;
}
break;
default:
/* nothing */ ;
}
return NULL;
}
static int goku_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int goku_udc_stop(struct usb_gadget *g);
@ -998,6 +1027,7 @@ static const struct usb_gadget_ops goku_ops = {
.get_frame = goku_get_frame,
.udc_start = goku_udc_start,
.udc_stop = goku_udc_stop,
.match_ep = goku_match_ep,
// no remote wakeup
// not selfpowered
};
@ -1257,6 +1287,14 @@ static void udc_reinit (struct goku_udc *dev)
INIT_LIST_HEAD (&ep->queue);
ep_reset(NULL, ep);
if (i == 0)
ep->ep.caps.type_control = true;
else
ep->ep.caps.type_bulk = true;
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
}
dev->ep[0].reg_mode = NULL;

View file

@ -2018,12 +2018,23 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE);
ep->bytes_per_buffer = MAX_CTRL_PL_SIZE;
ep->ep.caps.type_control = true;
} else {
usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
list_add_tail(&ep->ep_list, &dev->ep_list);
if (is_in)
ep->ep.caps.dir_in = true;
else
ep->ep.caps.dir_out = true;
ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit,
&ep->tailbuf_paddr, GFP_ATOMIC);
if (!ep->tailbuf)

View file

@ -2575,6 +2575,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep0",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 0,
@ -2586,6 +2588,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep1-int",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 2,
@ -2597,6 +2601,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep2-bulk",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 4,
@ -2608,6 +2614,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep3-iso",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 6,
@ -2619,6 +2627,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep4-int",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 8,
@ -2630,6 +2640,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep5-bulk",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 10,
@ -2641,6 +2653,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep6-iso",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 12,
@ -2652,6 +2666,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep7-int",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 14,
@ -2663,6 +2679,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep8-bulk",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 16,
@ -2674,6 +2692,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep9-iso",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 18,
@ -2685,6 +2705,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep10-int",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 20,
@ -2696,6 +2718,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep11-bulk",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 22,
@ -2707,6 +2731,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep12-iso",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 24,
@ -2718,6 +2744,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep13-int",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 26,
@ -2729,6 +2757,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep14-bulk",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 28,
@ -2740,6 +2770,8 @@ static const struct lpc32xx_udc controller_template = {
.ep = {
.name = "ep15-bulk",
.ops = &lpc32xx_ep_ops,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 30,

View file

@ -1052,7 +1052,7 @@ static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl)
tmp = m66592_read(m66592, M66592_INTSTS0) &
M66592_CTSQ;
udelay(1);
} while (tmp != M66592_CS_IDST || timeout-- > 0);
} while (tmp != M66592_CS_IDST && timeout-- > 0);
if (tmp == M66592_CS_IDST)
m66592_bset(m66592,
@ -1644,6 +1644,17 @@ static int m66592_probe(struct platform_device *pdev)
ep->ep.name = m66592_ep_name[i];
ep->ep.ops = &m66592_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
if (i == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
m66592->ep[0].pipenum = 0;

View file

@ -1324,6 +1324,9 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
ep->ep.ops = &mv_u3d_ep_ops;
ep->wedge = 0;
usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
ep->ep.caps.type_control = true;
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
ep->ep_num = 0;
ep->ep.desc = &mv_u3d_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@ -1339,14 +1342,20 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d)
if (i & 1) {
snprintf(name, sizeof(name), "ep%din", i >> 1);
ep->direction = MV_U3D_EP_DIR_IN;
ep->ep.caps.dir_in = true;
} else {
snprintf(name, sizeof(name), "ep%dout", i >> 1);
ep->direction = MV_U3D_EP_DIR_OUT;
ep->ep.caps.dir_out = true;
}
ep->u3d = u3d;
strncpy(ep->name, name, sizeof(ep->name));
ep->ep.name = ep->name;
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
ep->ep.ops = &mv_u3d_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
ep->ep_num = i / 2;

View file

@ -1257,6 +1257,9 @@ static int eps_init(struct mv_udc *udc)
ep->wedge = 0;
ep->stopped = 0;
usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
ep->ep.caps.type_control = true;
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
ep->ep_num = 0;
ep->ep.desc = &mv_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@ -1269,14 +1272,20 @@ static int eps_init(struct mv_udc *udc)
if (i % 2) {
snprintf(name, sizeof(name), "ep%din", i / 2);
ep->direction = EP_DIR_IN;
ep->ep.caps.dir_in = true;
} else {
snprintf(name, sizeof(name), "ep%dout", i / 2);
ep->direction = EP_DIR_OUT;
ep->ep.caps.dir_out = true;
}
ep->udc = udc;
strncpy(ep->name, name, sizeof(ep->name));
ep->ep.name = ep->name;
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
ep->ep.ops = &mv_ep_ops;
ep->stopped = 0;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);

View file

@ -1404,6 +1404,17 @@ net2272_usb_reinit(struct net2272 *dev)
else
ep->fifo_size = 64;
net2272_ep_reset(ep);
if (i == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
@ -1826,9 +1837,9 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat)
if (!e || u.r.wLength > 2)
goto do_stall;
if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT))
status = __constant_cpu_to_le16(1);
status = cpu_to_le16(1);
else
status = __constant_cpu_to_le16(0);
status = cpu_to_le16(0);
/* don't bother with a request object! */
net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);

View file

@ -74,18 +74,57 @@ static const char driver_desc[] = DRIVER_DESC;
static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 };
static const char ep0name[] = "ep0";
static const char *const ep_name[] = {
ep0name,
"ep-a", "ep-b", "ep-c", "ep-d",
"ep-e", "ep-f", "ep-g", "ep-h",
#define EP_INFO(_name, _caps) \
{ \
.name = _name, \
.caps = _caps, \
}
static const struct {
const char *name;
const struct usb_ep_caps caps;
} ep_info_dft[] = { /* Default endpoint configuration */
EP_INFO(ep0name,
USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep-a",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep-b",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep-c",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep-d",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep-e",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep-f",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep-g",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep-h",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
}, ep_info_adv[] = { /* Endpoints for usb3380 advance mode */
EP_INFO(ep0name,
USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
EP_INFO("ep1in",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep2out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep3in",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep4out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep1out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep2in",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
EP_INFO("ep3out",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
EP_INFO("ep4in",
USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
};
/* Endpoint names for usb3380 advance mode */
static const char *const ep_name_adv[] = {
ep0name,
"ep1in", "ep2out", "ep3in", "ep4out",
"ep1out", "ep2in", "ep3out", "ep4in",
};
#undef EP_INFO
/* mode 0 == ep-{a,b,c,d} 1K fifo each
* mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
@ -1511,6 +1550,33 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
return 0;
}
static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget,
struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *ep_comp)
{
char name[8];
struct usb_ep *ep;
if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT) {
/* ep-e, ep-f are PIO with only 64 byte fifos */
ep = gadget_find_ep_by_name(_gadget, "ep-e");
if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
return ep;
ep = gadget_find_ep_by_name(_gadget, "ep-f");
if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
return ep;
}
/* USB3380: use same address for usb and hardware endpoints */
snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
usb_endpoint_dir_in(desc) ? "in" : "out");
ep = gadget_find_ep_by_name(_gadget, name);
if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
return ep;
return NULL;
}
static int net2280_start(struct usb_gadget *_gadget,
struct usb_gadget_driver *driver);
static int net2280_stop(struct usb_gadget *_gadget);
@ -1522,6 +1588,7 @@ static const struct usb_gadget_ops net2280_ops = {
.pullup = net2280_pullup,
.udc_start = net2280_start,
.udc_stop = net2280_stop,
.match_ep = net2280_match_ep,
};
/*-------------------------------------------------------------------------*/
@ -2055,7 +2122,8 @@ static void usb_reinit_228x(struct net2280 *dev)
for (tmp = 0; tmp < 7; tmp++) {
struct net2280_ep *ep = &dev->ep[tmp];
ep->ep.name = ep_name[tmp];
ep->ep.name = ep_info_dft[tmp].name;
ep->ep.caps = ep_info_dft[tmp].caps;
ep->dev = dev;
ep->num = tmp;
@ -2095,7 +2163,10 @@ static void usb_reinit_338x(struct net2280 *dev)
for (i = 0; i < dev->n_ep; i++) {
struct net2280_ep *ep = &dev->ep[i];
ep->ep.name = dev->enhanced_mode ? ep_name_adv[i] : ep_name[i];
ep->ep.name = dev->enhanced_mode ? ep_info_adv[i].name :
ep_info_dft[i].name;
ep->ep.caps = dev->enhanced_mode ? ep_info_adv[i].caps :
ep_info_dft[i].caps;
ep->dev = dev;
ep->num = i;

View file

@ -2579,6 +2579,28 @@ omap_ep_setup(char *name, u8 addr, u8 type,
ep->double_buf = dbuf;
ep->udc = udc;
switch (type) {
case USB_ENDPOINT_XFER_CONTROL:
ep->ep.caps.type_control = true;
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
break;
case USB_ENDPOINT_XFER_ISOC:
ep->ep.caps.type_iso = true;
break;
case USB_ENDPOINT_XFER_BULK:
ep->ep.caps.type_bulk = true;
break;
case USB_ENDPOINT_XFER_INT:
ep->ep.caps.type_int = true;
break;
};
if (addr & USB_DIR_IN)
ep->ep.caps.dir_in = true;
else
ep->ep.caps.dir_out = true;
ep->ep.name = ep->name;
ep->ep.ops = &omap_ep_ops;
ep->maxpacket = maxp;

View file

@ -620,9 +620,9 @@ static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
dev->vbus_session = 1;
} else {
if (dev->driver && dev->driver->disconnect) {
spin_unlock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_unlock(&dev->lock);
}
pch_udc_set_disconnect(dev);
dev->vbus_session = 0;
@ -1191,9 +1191,9 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
pch_udc_reconnect(dev);
} else {
if (dev->driver && dev->driver->disconnect) {
spin_unlock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_unlock(&dev->lock);
}
pch_udc_set_disconnect(dev);
}
@ -1488,11 +1488,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
req->dma_mapped = 0;
}
ep->halted = 1;
spin_unlock(&dev->lock);
spin_lock(&dev->lock);
if (!ep->in)
pch_udc_ep_clear_rrdy(ep);
usb_gadget_giveback_request(&ep->ep, &req->req);
spin_lock(&dev->lock);
spin_unlock(&dev->lock);
ep->halted = halted;
}
@ -1793,7 +1793,7 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep,
}
/* prevent from using desc. - set HOST BUSY */
dma_desc->status |= PCH_UDC_BS_HST_BSY;
dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID);
dma_desc->dataptr = cpu_to_le32(DMA_ADDR_INVALID);
req->td_data = dma_desc;
req->td_data_last = dma_desc;
req->chain_len = 1;
@ -2414,7 +2414,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
else /* OUT */
dev->gadget.ep0 = &ep->ep;
spin_unlock(&dev->lock);
spin_lock(&dev->lock);
/* If Mass storage Reset */
if ((dev->setup_data.bRequestType == 0x21) &&
(dev->setup_data.bRequest == 0xFF))
@ -2422,7 +2422,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
/* call gadget with setup data received */
setup_supported = dev->driver->setup(&dev->gadget,
&dev->setup_data);
spin_lock(&dev->lock);
spin_unlock(&dev->lock);
if (dev->setup_data.bRequestType & USB_DIR_IN) {
ep->td_data->status = (ep->td_data->status &
@ -2594,9 +2594,9 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
empty_req_queue(ep);
}
if (dev->driver) {
spin_unlock(&dev->lock);
usb_gadget_udc_reset(&dev->gadget, dev->driver);
spin_lock(&dev->lock);
usb_gadget_udc_reset(&dev->gadget, dev->driver);
spin_unlock(&dev->lock);
}
}
@ -2675,9 +2675,9 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev)
dev->ep[i].halted = 0;
}
dev->stall = 0;
spin_unlock(&dev->lock);
ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_lock(&dev->lock);
ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_unlock(&dev->lock);
}
/**
@ -2712,9 +2712,9 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev)
dev->stall = 0;
/* call gadget zero with setup data received */
spin_unlock(&dev->lock);
ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_lock(&dev->lock);
ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_unlock(&dev->lock);
}
/**
@ -2747,18 +2747,18 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
if (dev_intr & UDC_DEVINT_US) {
if (dev->driver
&& dev->driver->suspend) {
spin_unlock(&dev->lock);
dev->driver->suspend(&dev->gadget);
spin_lock(&dev->lock);
dev->driver->suspend(&dev->gadget);
spin_unlock(&dev->lock);
}
vbus = pch_vbus_gpio_get_value(dev);
if ((dev->vbus_session == 0)
&& (vbus != 1)) {
if (dev->driver && dev->driver->disconnect) {
spin_unlock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
spin_unlock(&dev->lock);
}
pch_udc_reconnect(dev);
} else if ((dev->vbus_session == 0)
@ -2895,11 +2895,21 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev)
ep->in = ~i & 1;
ep->ep.name = ep_string[i];
ep->ep.ops = &pch_udc_ep_ops;
if (ep->in)
if (ep->in) {
ep->offset_addr = ep->num * UDC_EP_REG_SHIFT;
else
ep->ep.caps.dir_in = true;
} else {
ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
UDC_EP_REG_SHIFT;
ep->ep.caps.dir_out = true;
}
if (i == UDC_EP0IN_IDX || i == UDC_EP0OUT_IDX) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
/* need to set ep->ep.maxpacket and set Default Configuration?*/
usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);

View file

@ -1176,6 +1176,7 @@ static void udc_reinit(struct pxa25x_udc *dev)
INIT_LIST_HEAD (&dev->gadget.ep_list);
INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
dev->ep0state = EP0_IDLE;
dev->gadget.quirk_altset_not_supp = 1;
/* basic endpoint records init */
for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
@ -1821,6 +1822,8 @@ static struct pxa25x_udc memory = {
.name = ep0name,
.ops = &pxa25x_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.reg_udccs = &UDCCS0,
@ -1833,6 +1836,8 @@ static struct pxa25x_udc memory = {
.name = "ep1in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@ -1846,6 +1851,8 @@ static struct pxa25x_udc memory = {
.name = "ep2out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@ -1861,6 +1868,8 @@ static struct pxa25x_udc memory = {
.name = "ep3in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@ -1874,6 +1883,8 @@ static struct pxa25x_udc memory = {
.name = "ep4out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@ -1888,6 +1899,7 @@ static struct pxa25x_udc memory = {
.name = "ep5in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
.caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
@ -1903,6 +1915,8 @@ static struct pxa25x_udc memory = {
.name = "ep6in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@ -1916,6 +1930,8 @@ static struct pxa25x_udc memory = {
.name = "ep7out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@ -1930,6 +1946,8 @@ static struct pxa25x_udc memory = {
.name = "ep8in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@ -1943,6 +1961,8 @@ static struct pxa25x_udc memory = {
.name = "ep9out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@ -1957,6 +1977,7 @@ static struct pxa25x_udc memory = {
.name = "ep10in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
.caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
@ -1972,6 +1993,8 @@ static struct pxa25x_udc memory = {
.name = "ep11in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@ -1985,6 +2008,8 @@ static struct pxa25x_udc memory = {
.name = "ep12out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@ -1999,6 +2024,8 @@ static struct pxa25x_udc memory = {
.name = "ep13in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@ -2012,6 +2039,8 @@ static struct pxa25x_udc memory = {
.name = "ep14out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@ -2026,6 +2055,7 @@ static struct pxa25x_udc memory = {
.name = "ep15in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
.caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,

View file

@ -1710,6 +1710,7 @@ static void udc_init_data(struct pxa_udc *dev)
INIT_LIST_HEAD(&dev->gadget.ep_list);
INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
dev->gadget.quirk_altset_not_supp = 1;
ep0_idle(dev);
/* PXA endpoints init */
@ -2422,7 +2423,7 @@ static int pxa_udc_probe(struct platform_device *pdev)
}
udc->udc_command = mach->udc_command;
} else {
udc->gpiod = devm_gpiod_get(&pdev->dev, NULL);
udc->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_ASIS);
}
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);

View file

@ -234,25 +234,35 @@
/*
* Endpoint definition helpers
*/
#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
#define USB_EP_DEF(addr, bname, dir, type, maxpkt, ctype, cdir) \
{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, \
.caps = USB_EP_CAPS(ctype, cdir), }, \
.desc = { .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
.bmAttributes = type, \
.bmAttributes = USB_ENDPOINT_XFER_ ## type, \
.wMaxPacketSize = maxpkt, }, \
.dev = &memory \
}
#define USB_EP_BULK(addr, bname, dir) \
USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
#define USB_EP_ISO(addr, bname, dir) \
USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
#define USB_EP_INT(addr, bname, dir) \
USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1)
#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0)
#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1)
#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0)
#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1)
#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, 0, EP0_FIFO_SIZE)
#define USB_EP_BULK(addr, bname, dir, cdir) \
USB_EP_DEF(addr, bname, dir, BULK, BULK_FIFO_SIZE, \
USB_EP_CAPS_TYPE_BULK, cdir)
#define USB_EP_ISO(addr, bname, dir, cdir) \
USB_EP_DEF(addr, bname, dir, ISOC, ISO_FIFO_SIZE, \
USB_EP_CAPS_TYPE_ISO, cdir)
#define USB_EP_INT(addr, bname, dir, cdir) \
USB_EP_DEF(addr, bname, dir, INT, INT_FIFO_SIZE, \
USB_EP_CAPS_TYPE_INT, cdir)
#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1, \
USB_EP_CAPS_DIR_IN)
#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0, \
USB_EP_CAPS_DIR_OUT)
#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1, \
USB_EP_CAPS_DIR_IN)
#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0, \
USB_EP_CAPS_DIR_OUT)
#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1, \
USB_EP_CAPS_DIR_IN)
#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, CONTROL, EP0_FIFO_SIZE, \
USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)
#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
{ \

View file

@ -1935,6 +1935,16 @@ static int r8a66597_probe(struct platform_device *pdev)
ep->ep.name = r8a66597_ep_name[i];
ep->ep.ops = &r8a66597_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
if (i == 0) {
ep->ep.caps.type_control = true;
} else {
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
}
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64);
r8a66597->ep[0].pipenum = 0;

View file

@ -1005,6 +1005,21 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc,
hsep->stopped = 0;
hsep->wedge = 0;
if (epnum == 0) {
hsep->ep.caps.type_control = true;
hsep->ep.caps.dir_in = true;
hsep->ep.caps.dir_out = true;
} else {
hsep->ep.caps.type_iso = true;
hsep->ep.caps.type_bulk = true;
hsep->ep.caps.type_int = true;
}
if (epnum & 1)
hsep->ep.caps.dir_in = true;
else
hsep->ep.caps.dir_out = true;
set_index(hsudc, epnum);
writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR);
}

View file

@ -1691,6 +1691,8 @@ static struct s3c2410_udc memory = {
.name = ep0name,
.ops = &s3c2410_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
},
@ -1702,6 +1704,8 @@ static struct s3c2410_udc memory = {
.name = "ep1-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@ -1714,6 +1718,8 @@ static struct s3c2410_udc memory = {
.name = "ep2-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@ -1726,6 +1732,8 @@ static struct s3c2410_udc memory = {
.name = "ep3-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@ -1738,6 +1746,8 @@ static struct s3c2410_udc memory = {
.name = "ep4-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
.caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,

View file

@ -131,6 +131,96 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
/* ------------------------------------------------------------------------- */
/**
* gadget_find_ep_by_name - returns ep whose name is the same as sting passed
* in second parameter or NULL if searched endpoint not found
* @g: controller to check for quirk
* @name: name of searched endpoint
*/
struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, const char *name)
{
struct usb_ep *ep;
gadget_for_each_ep(ep, g) {
if (!strcmp(ep->name, name))
return ep;
}
return NULL;
}
EXPORT_SYMBOL_GPL(gadget_find_ep_by_name);
/* ------------------------------------------------------------------------- */
int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *ep_comp)
{
u8 type;
u16 max;
int num_req_streams = 0;
/* endpoint already claimed? */
if (ep->claimed)
return 0;
type = usb_endpoint_type(desc);
max = 0x7ff & usb_endpoint_maxp(desc);
if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
return 0;
if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
return 0;
if (max > ep->maxpacket_limit)
return 0;
/* "high bandwidth" works only at high speed */
if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11))
return 0;
switch (type) {
case USB_ENDPOINT_XFER_CONTROL:
/* only support ep0 for portable CONTROL traffic */
return 0;
case USB_ENDPOINT_XFER_ISOC:
if (!ep->caps.type_iso)
return 0;
/* ISO: limit 1023 bytes full speed, 1024 high/super speed */
if (!gadget_is_dualspeed(gadget) && max > 1023)
return 0;
break;
case USB_ENDPOINT_XFER_BULK:
if (!ep->caps.type_bulk)
return 0;
if (ep_comp && gadget_is_superspeed(gadget)) {
/* Get the number of required streams from the
* EP companion descriptor and see if the EP
* matches it
*/
num_req_streams = ep_comp->bmAttributes & 0x1f;
if (num_req_streams > ep->max_streams)
return 0;
}
break;
case USB_ENDPOINT_XFER_INT:
/* Bulk endpoints handle interrupt transfers,
* except the toggle-quirky iso-synch kind
*/
if (!ep->caps.type_int && !ep->caps.type_bulk)
return 0;
/* INT: limit 64 bytes full speed, 1024 high/super speed */
if (!gadget_is_dualspeed(gadget) && max > 64)
return 0;
break;
}
return 1;
}
EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
/* ------------------------------------------------------------------------- */
static void usb_gadget_state_work(struct work_struct *work)
{
struct usb_gadget *gadget = work_to_gadget(work);

View file

@ -1317,12 +1317,21 @@ static void xudc_eps_init(struct xusb_udc *udc)
snprintf(ep->name, EPNAME_SIZE, "ep%d", ep_number);
ep->ep_usb.name = ep->name;
ep->ep_usb.ops = &xusb_ep_ops;
ep->ep_usb.caps.type_iso = true;
ep->ep_usb.caps.type_bulk = true;
ep->ep_usb.caps.type_int = true;
} else {
ep->ep_usb.name = ep0name;
usb_ep_set_maxpacket_limit(&ep->ep_usb, EP0_MAX_PACKET);
ep->ep_usb.ops = &xusb_ep0_ops;
ep->ep_usb.caps.type_control = true;
}
ep->ep_usb.caps.dir_in = true;
ep->ep_usb.caps.dir_out = true;
ep->udc = udc;
ep->epnumber = ep_number;
ep->desc = NULL;

View file

@ -1382,14 +1382,25 @@ static void isp1760_udc_init_eps(struct isp1760_udc *udc)
* This fits in the 8kB FIFO without double-buffering.
*/
if (ep_num == 0) {
ep->ep.maxpacket = 64;
usb_ep_set_maxpacket_limit(&ep->ep, 64);
ep->ep.caps.type_control = true;
ep->ep.caps.dir_in = true;
ep->ep.caps.dir_out = true;
ep->maxpacket = 64;
udc->gadget.ep0 = &ep->ep;
} else {
ep->ep.maxpacket = 512;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
ep->ep.caps.type_iso = true;
ep->ep.caps.type_bulk = true;
ep->ep.caps.type_int = true;
ep->maxpacket = 0;
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
}
if (is_in)
ep->ep.caps.dir_in = true;
else
ep->ep.caps.dir_out = true;
}
}

View file

@ -5,7 +5,7 @@
# (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
config USB_MUSB_HDRC
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, AW, ...)'
depends on (USB || USB_GADGET)
help
Say Y here if your system has a dual role high speed USB
@ -20,6 +20,8 @@ config USB_MUSB_HDRC
Analog Devices parts using this IP include Blackfin BF54x,
BF525 and BF527.
Allwinner SoCs using this IP include A10, A13, A20, ...
If you do not know what this is, please say N.
To compile this driver as a module, choose M here; the
@ -60,6 +62,15 @@ endchoice
comment "Platform Glue Layer"
config USB_MUSB_SUNXI
tristate "Allwinner (sunxi)"
depends on ARCH_SUNXI
depends on NOP_USB_XCEIV
depends on PHY_SUN4I_USB
depends on EXTCON
depends on GENERIC_PHY
select SUNXI_SRAM
config USB_MUSB_DAVINCI
tristate "DaVinci"
depends on ARCH_DAVINCI_DMx
@ -113,19 +124,20 @@ config USB_MUSB_JZ4740
config USB_MUSB_AM335X_CHILD
tristate
choice
prompt 'MUSB DMA mode'
default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM || USB_MUSB_JZ4740
default USB_UX500_DMA if USB_MUSB_UX500
default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
default USB_TUSB_OMAP_DMA if USB_MUSB_TUSB6010
default MUSB_PIO_ONLY if USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X \
|| USB_MUSB_DSPS
comment "MUSB DMA mode"
config MUSB_PIO_ONLY
bool 'Disable DMA (always use PIO)'
help
Unfortunately, only one option can be enabled here. Ideally one
should be able to build all these drivers into one kernel to
allow using DMA on multiplatform kernels.
All data is copied between memory and FIFO by the CPU.
DMA controllers are ignored.
Do not choose this unless DMA support for your SOC or board
is unavailable (or unstable). When DMA is enabled at compile time,
you can still disable it at run time using the "use_dma=n" module
parameter.
if !MUSB_PIO_ONLY
config USB_UX500_DMA
bool 'ST Ericsson Ux500'
@ -157,17 +169,6 @@ config USB_TUSB_OMAP_DMA
help
Enable DMA transfers on TUSB 6010 when OMAP DMA is available.
config MUSB_PIO_ONLY
bool 'Disable DMA (always use PIO)'
help
All data is copied between memory and FIFO by the CPU.
DMA controllers are ignored.
Do not choose this unless DMA support for your SOC or board
is unavailable (or unstable). When DMA is enabled at compile time,
you can still disable it at run time using the "use_dma=n" module
parameter.
endchoice
endif # !MUSB_PIO_ONLY
endif # USB_MUSB_HDRC

View file

@ -20,6 +20,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o
obj-$(CONFIG_USB_MUSB_BLACKFIN) += blackfin.o
obj-$(CONFIG_USB_MUSB_UX500) += ux500.o
obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o
obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o
obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o

View file

@ -614,7 +614,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
{
struct musb *musb = controller->musb;
struct device *dev = musb->controller;
struct device_node *np = dev->of_node;
struct device_node *np = dev->parent->of_node;
struct cppi41_dma_channel *cppi41_channel;
int count;
int i;
@ -664,7 +664,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
musb_dma->status = MUSB_DMA_STATUS_FREE;
musb_dma->max_len = SZ_4M;
dc = dma_request_slave_channel(dev, str);
dc = dma_request_slave_channel(dev->parent, str);
if (!dc) {
dev_err(dev, "Failed to request %s.\n", str);
ret = -EPROBE_DEFER;
@ -695,7 +695,7 @@ cppi41_dma_controller_create(struct musb *musb, void __iomem *base)
struct cppi41_dma_controller *controller;
int ret = 0;
if (!musb->controller->of_node) {
if (!musb->controller->parent->of_node) {
dev_err(musb->controller, "Need DT for the DMA engine.\n");
return NULL;
}

View file

@ -313,8 +313,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
/* MUSB_TXCSR_P_ISO is still set correctly */
#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA)
{
if (musb_dma_inventra(musb) || musb_dma_ux500(musb)) {
if (request_size < musb_ep->packet_sz)
musb_ep->dma->desired_mode = 0;
else
@ -365,7 +364,6 @@ static void txstate(struct musb *musb, struct musb_request *req)
}
}
#endif
if (is_cppi_enabled(musb)) {
/* program endpoint CSR first, then setup DMA */
csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
@ -641,8 +639,10 @@ static void rxstate(struct musb *musb, struct musb_request *req)
use_mode_1 = 0;
if (request->actual < request->length) {
#ifdef CONFIG_USB_INVENTRA_DMA
if (is_buffer_mapped(req)) {
if (!is_buffer_mapped(req))
goto buffer_aint_mapped;
if (musb_dma_inventra(musb)) {
struct dma_controller *c;
struct dma_channel *channel;
int use_dma = 0;
@ -716,8 +716,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
if (use_dma)
return;
}
#elif defined(CONFIG_USB_UX500_DMA)
if ((is_buffer_mapped(req)) &&
if ((musb_dma_ux500(musb)) &&
(request->actual < request->length)) {
struct dma_controller *c;
@ -765,7 +765,6 @@ static void rxstate(struct musb *musb, struct musb_request *req)
return;
}
#endif /* Mentor's DMA */
len = request->length - request->actual;
dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
@ -775,8 +774,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
fifo_count = min_t(unsigned, len, fifo_count);
#ifdef CONFIG_USB_TUSB_OMAP_DMA
if (tusb_dma_omap(musb) && is_buffer_mapped(req)) {
if (tusb_dma_omap(musb)) {
struct dma_controller *c = musb->dma_controller;
struct dma_channel *channel = musb_ep->dma;
u32 dma_addr = request->dma + request->actual;
@ -790,23 +788,22 @@ static void rxstate(struct musb *musb, struct musb_request *req)
if (ret)
return;
}
#endif
/*
* Unmap the dma buffer back to cpu if dma channel
* programming fails. This buffer is mapped if the
* channel allocation is successful
*/
if (is_buffer_mapped(req)) {
unmap_dma_buffer(req, musb);
unmap_dma_buffer(req, musb);
/*
* Clear DMAENAB and AUTOCLEAR for the
* PIO mode transfer
*/
csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR);
musb_writew(epio, MUSB_RXCSR, csr);
}
/*
* Clear DMAENAB and AUTOCLEAR for the
* PIO mode transfer
*/
csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR);
musb_writew(epio, MUSB_RXCSR, csr);
buffer_aint_mapped:
musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
(request->buf + request->actual));
request->actual += fifo_count;
@ -1684,6 +1681,40 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
#ifdef CONFIG_BLACKFIN
static struct usb_ep *musb_match_ep(struct usb_gadget *g,
struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *ep_comp)
{
struct usb_ep *ep = NULL;
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_ISOC:
case USB_ENDPOINT_XFER_BULK:
if (usb_endpoint_dir_in(desc))
ep = gadget_find_ep_by_name(g, "ep5in");
else
ep = gadget_find_ep_by_name(g, "ep6out");
break;
case USB_ENDPOINT_XFER_INT:
if (usb_endpoint_dir_in(desc))
ep = gadget_find_ep_by_name(g, "ep1in");
else
ep = gadget_find_ep_by_name(g, "ep2out");
break;
default:
break;
}
if (ep && usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
return ep;
return NULL;
}
#else
#define musb_match_ep NULL
#endif
static int musb_gadget_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int musb_gadget_stop(struct usb_gadget *g);
@ -1697,6 +1728,7 @@ static const struct usb_gadget_ops musb_gadget_operations = {
.pullup = musb_gadget_pullup,
.udc_start = musb_gadget_start,
.udc_stop = musb_gadget_stop,
.match_ep = musb_match_ep,
};
/* ----------------------------------------------------------------------- */
@ -1729,6 +1761,7 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
INIT_LIST_HEAD(&ep->end_point.ep_list);
if (!epnum) {
usb_ep_set_maxpacket_limit(&ep->end_point, 64);
ep->end_point.caps.type_control = true;
ep->end_point.ops = &musb_g_ep0_ops;
musb->g.ep0 = &ep->end_point;
} else {
@ -1736,9 +1769,20 @@ init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_tx);
else
usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_rx);
ep->end_point.caps.type_iso = true;
ep->end_point.caps.type_bulk = true;
ep->end_point.caps.type_int = true;
ep->end_point.ops = &musb_ep_ops;
list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list);
}
if (!epnum || hw_ep->is_shared_fifo) {
ep->end_point.caps.dir_in = true;
ep->end_point.caps.dir_out = true;
} else if (is_in)
ep->end_point.caps.dir_in = true;
else
ep->end_point.caps.dir_out = true;
}
/*
@ -2075,6 +2119,7 @@ __acquires(musb->lock)
musb->g.b_hnp_enable = 0;
musb->g.a_alt_hnp_support = 0;
musb->g.a_hnp_support = 0;
musb->g.quirk_zlp_not_supp = 1;
/* Normal reset, as B-Device;
* or else after HNP, as A-Device

756
drivers/usb/musb/sunxi.c Normal file
View file

@ -0,0 +1,756 @@
/*
* Allwinner sun4i MUSB Glue Layer
*
* Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
*
* Based on code from
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/extcon.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy/phy-sun4i-usb.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/soc/sunxi/sunxi_sram.h>
#include <linux/usb/musb.h>
#include <linux/usb/of.h>
#include <linux/usb/usb_phy_generic.h>
#include <linux/workqueue.h>
#include "musb_core.h"
/*
* Register offsets, note sunxi musb has a different layout then most
* musb implementations, we translate the layout in musb_readb & friends.
*/
#define SUNXI_MUSB_POWER 0x0040
#define SUNXI_MUSB_DEVCTL 0x0041
#define SUNXI_MUSB_INDEX 0x0042
#define SUNXI_MUSB_VEND0 0x0043
#define SUNXI_MUSB_INTRTX 0x0044
#define SUNXI_MUSB_INTRRX 0x0046
#define SUNXI_MUSB_INTRTXE 0x0048
#define SUNXI_MUSB_INTRRXE 0x004a
#define SUNXI_MUSB_INTRUSB 0x004c
#define SUNXI_MUSB_INTRUSBE 0x0050
#define SUNXI_MUSB_FRAME 0x0054
#define SUNXI_MUSB_TXFIFOSZ 0x0090
#define SUNXI_MUSB_TXFIFOADD 0x0092
#define SUNXI_MUSB_RXFIFOSZ 0x0094
#define SUNXI_MUSB_RXFIFOADD 0x0096
#define SUNXI_MUSB_FADDR 0x0098
#define SUNXI_MUSB_TXFUNCADDR 0x0098
#define SUNXI_MUSB_TXHUBADDR 0x009a
#define SUNXI_MUSB_TXHUBPORT 0x009b
#define SUNXI_MUSB_RXFUNCADDR 0x009c
#define SUNXI_MUSB_RXHUBADDR 0x009e
#define SUNXI_MUSB_RXHUBPORT 0x009f
#define SUNXI_MUSB_CONFIGDATA 0x00c0
/* VEND0 bits */
#define SUNXI_MUSB_VEND0_PIO_MODE 0
/* flags */
#define SUNXI_MUSB_FL_ENABLED 0
#define SUNXI_MUSB_FL_HOSTMODE 1
#define SUNXI_MUSB_FL_HOSTMODE_PEND 2
#define SUNXI_MUSB_FL_VBUS_ON 3
#define SUNXI_MUSB_FL_PHY_ON 4
#define SUNXI_MUSB_FL_HAS_SRAM 5
#define SUNXI_MUSB_FL_HAS_RESET 6
#define SUNXI_MUSB_FL_NO_CONFIGDATA 7
/* Our read/write methods need access and do not get passed in a musb ref :| */
static struct musb *sunxi_musb;
struct sunxi_glue {
struct device *dev;
struct platform_device *musb;
struct clk *clk;
struct reset_control *rst;
struct phy *phy;
struct platform_device *usb_phy;
struct usb_phy *xceiv;
unsigned long flags;
struct work_struct work;
struct extcon_dev *extcon;
struct notifier_block host_nb;
};
/* phy_power_on / off may sleep, so we use a workqueue */
static void sunxi_musb_work(struct work_struct *work)
{
struct sunxi_glue *glue = container_of(work, struct sunxi_glue, work);
bool vbus_on, phy_on;
if (!test_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
return;
if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) {
struct musb *musb = platform_get_drvdata(glue->musb);
unsigned long flags;
u8 devctl;
spin_lock_irqsave(&musb->lock, flags);
devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL);
if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
musb->xceiv->otg->default_a = 1;
musb->xceiv->otg->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
devctl |= MUSB_DEVCTL_SESSION;
} else {
clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
musb->xceiv->otg->default_a = 0;
musb->xceiv->otg->state = OTG_STATE_B_IDLE;
MUSB_DEV_MODE(musb);
devctl &= ~MUSB_DEVCTL_SESSION;
}
writeb(devctl, musb->mregs + SUNXI_MUSB_DEVCTL);
spin_unlock_irqrestore(&musb->lock, flags);
}
vbus_on = test_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
phy_on = test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
if (phy_on != vbus_on) {
if (vbus_on) {
phy_power_on(glue->phy);
set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
} else {
phy_power_off(glue->phy);
clear_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
}
}
}
static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
{
struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
if (is_on)
set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
else
clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
schedule_work(&glue->work);
}
static void sunxi_musb_pre_root_reset_end(struct musb *musb)
{
struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
sun4i_usb_phy_set_squelch_detect(glue->phy, false);
}
static void sunxi_musb_post_root_reset_end(struct musb *musb)
{
struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
sun4i_usb_phy_set_squelch_detect(glue->phy, true);
}
static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
{
struct musb *musb = __hci;
unsigned long flags;
spin_lock_irqsave(&musb->lock, flags);
musb->int_usb = readb(musb->mregs + SUNXI_MUSB_INTRUSB);
if (musb->int_usb)
writeb(musb->int_usb, musb->mregs + SUNXI_MUSB_INTRUSB);
/*
* sunxi musb often signals babble on low / full speed device
* disconnect, without ever raising MUSB_INTR_DISCONNECT, since
* normally babble never happens treat it as disconnect.
*/
if ((musb->int_usb & MUSB_INTR_BABBLE) && is_host_active(musb)) {
musb->int_usb &= ~MUSB_INTR_BABBLE;
musb->int_usb |= MUSB_INTR_DISCONNECT;
}
if ((musb->int_usb & MUSB_INTR_RESET) && !is_host_active(musb)) {
/* ep0 FADDR must be 0 when (re)entering peripheral mode */
musb_ep_select(musb->mregs, 0);
musb_writeb(musb->mregs, MUSB_FADDR, 0);
}
musb->int_tx = readw(musb->mregs + SUNXI_MUSB_INTRTX);
if (musb->int_tx)
writew(musb->int_tx, musb->mregs + SUNXI_MUSB_INTRTX);
musb->int_rx = readw(musb->mregs + SUNXI_MUSB_INTRRX);
if (musb->int_rx)
writew(musb->int_rx, musb->mregs + SUNXI_MUSB_INTRRX);
musb_interrupt(musb);
spin_unlock_irqrestore(&musb->lock, flags);
return IRQ_HANDLED;
}
static int sunxi_musb_host_notifier(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct sunxi_glue *glue = container_of(nb, struct sunxi_glue, host_nb);
if (event)
set_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
else
clear_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
set_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags);
schedule_work(&glue->work);
return NOTIFY_DONE;
}
static int sunxi_musb_init(struct musb *musb)
{
struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
int ret;
sunxi_musb = musb;
musb->phy = glue->phy;
musb->xceiv = glue->xceiv;
if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
ret = sunxi_sram_claim(musb->controller->parent);
if (ret)
return ret;
}
ret = clk_prepare_enable(glue->clk);
if (ret)
goto error_sram_release;
if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
ret = reset_control_deassert(glue->rst);
if (ret)
goto error_clk_disable;
}
writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
/* Register notifier before calling phy_init() */
if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) {
ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
&glue->host_nb);
if (ret)
goto error_reset_assert;
}
ret = phy_init(glue->phy);
if (ret)
goto error_unregister_notifier;
if (musb->port_mode == MUSB_PORT_MODE_HOST) {
ret = phy_power_on(glue->phy);
if (ret)
goto error_phy_exit;
set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
/* Stop musb work from turning vbus off again */
set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
}
musb->isr = sunxi_musb_interrupt;
/* Stop the musb-core from doing runtime pm (not supported on sunxi) */
pm_runtime_get(musb->controller);
return 0;
error_phy_exit:
phy_exit(glue->phy);
error_unregister_notifier:
if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
&glue->host_nb);
error_reset_assert:
if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
reset_control_assert(glue->rst);
error_clk_disable:
clk_disable_unprepare(glue->clk);
error_sram_release:
if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
sunxi_sram_release(musb->controller->parent);
return ret;
}
static int sunxi_musb_exit(struct musb *musb)
{
struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
pm_runtime_put(musb->controller);
cancel_work_sync(&glue->work);
if (test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags))
phy_power_off(glue->phy);
phy_exit(glue->phy);
if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
&glue->host_nb);
if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
reset_control_assert(glue->rst);
clk_disable_unprepare(glue->clk);
if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
sunxi_sram_release(musb->controller->parent);
return 0;
}
static void sunxi_musb_enable(struct musb *musb)
{
struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
/* musb_core does not call us in a balanced manner */
if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
return;
schedule_work(&glue->work);
}
static void sunxi_musb_disable(struct musb *musb)
{
struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags);
}
/*
* sunxi musb register layout
* 0x00 - 0x17 fifo regs, 1 long per fifo
* 0x40 - 0x57 generic control regs (power - frame)
* 0x80 - 0x8f ep control regs (addressed through hw_ep->regs, indexed)
* 0x90 - 0x97 fifo control regs (indexed)
* 0x98 - 0x9f multipoint / busctl regs (indexed)
* 0xc0 configdata reg
*/
static u32 sunxi_musb_fifo_offset(u8 epnum)
{
return (epnum * 4);
}
static u32 sunxi_musb_ep_offset(u8 epnum, u16 offset)
{
WARN_ONCE(offset != 0,
"sunxi_musb_ep_offset called with non 0 offset\n");
return 0x80; /* indexed, so ignore epnum */
}
static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset)
{
return SUNXI_MUSB_TXFUNCADDR + offset;
}
static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset)
{
struct sunxi_glue *glue;
if (addr == sunxi_musb->mregs) {
/* generic control or fifo control reg access */
switch (offset) {
case MUSB_FADDR:
return readb(addr + SUNXI_MUSB_FADDR);
case MUSB_POWER:
return readb(addr + SUNXI_MUSB_POWER);
case MUSB_INTRUSB:
return readb(addr + SUNXI_MUSB_INTRUSB);
case MUSB_INTRUSBE:
return readb(addr + SUNXI_MUSB_INTRUSBE);
case MUSB_INDEX:
return readb(addr + SUNXI_MUSB_INDEX);
case MUSB_TESTMODE:
return 0; /* No testmode on sunxi */
case MUSB_DEVCTL:
return readb(addr + SUNXI_MUSB_DEVCTL);
case MUSB_TXFIFOSZ:
return readb(addr + SUNXI_MUSB_TXFIFOSZ);
case MUSB_RXFIFOSZ:
return readb(addr + SUNXI_MUSB_RXFIFOSZ);
case MUSB_CONFIGDATA + 0x10: /* See musb_read_configdata() */
glue = dev_get_drvdata(sunxi_musb->controller->parent);
/* A33 saves a reg, and we get to hardcode this */
if (test_bit(SUNXI_MUSB_FL_NO_CONFIGDATA,
&glue->flags))
return 0xde;
return readb(addr + SUNXI_MUSB_CONFIGDATA);
/* Offset for these is fixed by sunxi_musb_busctl_offset() */
case SUNXI_MUSB_TXFUNCADDR:
case SUNXI_MUSB_TXHUBADDR:
case SUNXI_MUSB_TXHUBPORT:
case SUNXI_MUSB_RXFUNCADDR:
case SUNXI_MUSB_RXHUBADDR:
case SUNXI_MUSB_RXHUBPORT:
/* multipoint / busctl reg access */
return readb(addr + offset);
default:
dev_err(sunxi_musb->controller->parent,
"Error unknown readb offset %u\n", offset);
return 0;
}
} else if (addr == (sunxi_musb->mregs + 0x80)) {
/* ep control reg access */
/* sunxi has a 2 byte hole before the txtype register */
if (offset >= MUSB_TXTYPE)
offset += 2;
return readb(addr + offset);
}
dev_err(sunxi_musb->controller->parent,
"Error unknown readb at 0x%x bytes offset\n",
(int)(addr - sunxi_musb->mregs));
return 0;
}
static void sunxi_musb_writeb(void __iomem *addr, unsigned offset, u8 data)
{
if (addr == sunxi_musb->mregs) {
/* generic control or fifo control reg access */
switch (offset) {
case MUSB_FADDR:
return writeb(data, addr + SUNXI_MUSB_FADDR);
case MUSB_POWER:
return writeb(data, addr + SUNXI_MUSB_POWER);
case MUSB_INTRUSB:
return writeb(data, addr + SUNXI_MUSB_INTRUSB);
case MUSB_INTRUSBE:
return writeb(data, addr + SUNXI_MUSB_INTRUSBE);
case MUSB_INDEX:
return writeb(data, addr + SUNXI_MUSB_INDEX);
case MUSB_TESTMODE:
if (data)
dev_warn(sunxi_musb->controller->parent,
"sunxi-musb does not have testmode\n");
return;
case MUSB_DEVCTL:
return writeb(data, addr + SUNXI_MUSB_DEVCTL);
case MUSB_TXFIFOSZ:
return writeb(data, addr + SUNXI_MUSB_TXFIFOSZ);
case MUSB_RXFIFOSZ:
return writeb(data, addr + SUNXI_MUSB_RXFIFOSZ);
/* Offset for these is fixed by sunxi_musb_busctl_offset() */
case SUNXI_MUSB_TXFUNCADDR:
case SUNXI_MUSB_TXHUBADDR:
case SUNXI_MUSB_TXHUBPORT:
case SUNXI_MUSB_RXFUNCADDR:
case SUNXI_MUSB_RXHUBADDR:
case SUNXI_MUSB_RXHUBPORT:
/* multipoint / busctl reg access */
return writeb(data, addr + offset);
default:
dev_err(sunxi_musb->controller->parent,
"Error unknown writeb offset %u\n", offset);
return;
}
} else if (addr == (sunxi_musb->mregs + 0x80)) {
/* ep control reg access */
if (offset >= MUSB_TXTYPE)
offset += 2;
return writeb(data, addr + offset);
}
dev_err(sunxi_musb->controller->parent,
"Error unknown writeb at 0x%x bytes offset\n",
(int)(addr - sunxi_musb->mregs));
}
static u16 sunxi_musb_readw(const void __iomem *addr, unsigned offset)
{
if (addr == sunxi_musb->mregs) {
/* generic control or fifo control reg access */
switch (offset) {
case MUSB_INTRTX:
return readw(addr + SUNXI_MUSB_INTRTX);
case MUSB_INTRRX:
return readw(addr + SUNXI_MUSB_INTRRX);
case MUSB_INTRTXE:
return readw(addr + SUNXI_MUSB_INTRTXE);
case MUSB_INTRRXE:
return readw(addr + SUNXI_MUSB_INTRRXE);
case MUSB_FRAME:
return readw(addr + SUNXI_MUSB_FRAME);
case MUSB_TXFIFOADD:
return readw(addr + SUNXI_MUSB_TXFIFOADD);
case MUSB_RXFIFOADD:
return readw(addr + SUNXI_MUSB_RXFIFOADD);
case MUSB_HWVERS:
return 0; /* sunxi musb version is not known */
default:
dev_err(sunxi_musb->controller->parent,
"Error unknown readw offset %u\n", offset);
return 0;
}
} else if (addr == (sunxi_musb->mregs + 0x80)) {
/* ep control reg access */
return readw(addr + offset);
}
dev_err(sunxi_musb->controller->parent,
"Error unknown readw at 0x%x bytes offset\n",
(int)(addr - sunxi_musb->mregs));
return 0;
}
static void sunxi_musb_writew(void __iomem *addr, unsigned offset, u16 data)
{
if (addr == sunxi_musb->mregs) {
/* generic control or fifo control reg access */
switch (offset) {
case MUSB_INTRTX:
return writew(data, addr + SUNXI_MUSB_INTRTX);
case MUSB_INTRRX:
return writew(data, addr + SUNXI_MUSB_INTRRX);
case MUSB_INTRTXE:
return writew(data, addr + SUNXI_MUSB_INTRTXE);
case MUSB_INTRRXE:
return writew(data, addr + SUNXI_MUSB_INTRRXE);
case MUSB_FRAME:
return writew(data, addr + SUNXI_MUSB_FRAME);
case MUSB_TXFIFOADD:
return writew(data, addr + SUNXI_MUSB_TXFIFOADD);
case MUSB_RXFIFOADD:
return writew(data, addr + SUNXI_MUSB_RXFIFOADD);
default:
dev_err(sunxi_musb->controller->parent,
"Error unknown writew offset %u\n", offset);
return;
}
} else if (addr == (sunxi_musb->mregs + 0x80)) {
/* ep control reg access */
return writew(data, addr + offset);
}
dev_err(sunxi_musb->controller->parent,
"Error unknown writew at 0x%x bytes offset\n",
(int)(addr - sunxi_musb->mregs));
}
static const struct musb_platform_ops sunxi_musb_ops = {
.quirks = MUSB_INDEXED_EP,
.init = sunxi_musb_init,
.exit = sunxi_musb_exit,
.enable = sunxi_musb_enable,
.disable = sunxi_musb_disable,
.fifo_offset = sunxi_musb_fifo_offset,
.ep_offset = sunxi_musb_ep_offset,
.busctl_offset = sunxi_musb_busctl_offset,
.readb = sunxi_musb_readb,
.writeb = sunxi_musb_writeb,
.readw = sunxi_musb_readw,
.writew = sunxi_musb_writew,
.set_vbus = sunxi_musb_set_vbus,
.pre_root_reset_end = sunxi_musb_pre_root_reset_end,
.post_root_reset_end = sunxi_musb_post_root_reset_end,
};
/* Allwinner OTG supports up to 5 endpoints */
#define SUNXI_MUSB_MAX_EP_NUM 6
#define SUNXI_MUSB_RAM_BITS 11
static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = {
MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512),
MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512),
};
static struct musb_hdrc_config sunxi_musb_hdrc_config = {
.fifo_cfg = sunxi_musb_mode_cfg,
.fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg),
.multipoint = true,
.dyn_fifo = true,
.soft_con = true,
.num_eps = SUNXI_MUSB_MAX_EP_NUM,
.ram_bits = SUNXI_MUSB_RAM_BITS,
.dma = 0,
};
static int sunxi_musb_probe(struct platform_device *pdev)
{
struct musb_hdrc_platform_data pdata;
struct platform_device_info pinfo;
struct sunxi_glue *glue;
struct device_node *np = pdev->dev.of_node;
int ret;
if (!np) {
dev_err(&pdev->dev, "Error no device tree node found\n");
return -EINVAL;
}
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue)
return -ENOMEM;
memset(&pdata, 0, sizeof(pdata));
switch (of_usb_get_dr_mode(np)) {
#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
case USB_DR_MODE_HOST:
pdata.mode = MUSB_PORT_MODE_HOST;
break;
#endif
#ifdef CONFIG_USB_MUSB_DUAL_ROLE
case USB_DR_MODE_OTG:
glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
if (IS_ERR(glue->extcon)) {
if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_err(&pdev->dev, "Invalid or missing extcon\n");
return PTR_ERR(glue->extcon);
}
pdata.mode = MUSB_PORT_MODE_DUAL_ROLE;
break;
#endif
default:
dev_err(&pdev->dev, "Invalid or missing 'dr_mode' property\n");
return -EINVAL;
}
pdata.platform_ops = &sunxi_musb_ops;
pdata.config = &sunxi_musb_hdrc_config;
glue->dev = &pdev->dev;
INIT_WORK(&glue->work, sunxi_musb_work);
glue->host_nb.notifier_call = sunxi_musb_host_notifier;
if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb")) {
set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags);
}
glue->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(glue->clk)) {
dev_err(&pdev->dev, "Error getting clock: %ld\n",
PTR_ERR(glue->clk));
return PTR_ERR(glue->clk);
}
if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
glue->rst = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(glue->rst)) {
if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_err(&pdev->dev, "Error getting reset %ld\n",
PTR_ERR(glue->rst));
return PTR_ERR(glue->rst);
}
}
glue->phy = devm_phy_get(&pdev->dev, "usb");
if (IS_ERR(glue->phy)) {
if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_err(&pdev->dev, "Error getting phy %ld\n",
PTR_ERR(glue->phy));
return PTR_ERR(glue->phy);
}
glue->usb_phy = usb_phy_generic_register();
if (IS_ERR(glue->usb_phy)) {
dev_err(&pdev->dev, "Error registering usb-phy %ld\n",
PTR_ERR(glue->usb_phy));
return PTR_ERR(glue->usb_phy);
}
glue->xceiv = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (IS_ERR(glue->xceiv)) {
ret = PTR_ERR(glue->xceiv);
dev_err(&pdev->dev, "Error getting usb-phy %d\n", ret);
goto err_unregister_usb_phy;
}
platform_set_drvdata(pdev, glue);
memset(&pinfo, 0, sizeof(pinfo));
pinfo.name = "musb-hdrc";
pinfo.id = PLATFORM_DEVID_AUTO;
pinfo.parent = &pdev->dev;
pinfo.res = pdev->resource;
pinfo.num_res = pdev->num_resources;
pinfo.data = &pdata;
pinfo.size_data = sizeof(pdata);
glue->musb = platform_device_register_full(&pinfo);
if (IS_ERR(glue->musb)) {
ret = PTR_ERR(glue->musb);
dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret);
goto err_unregister_usb_phy;
}
return 0;
err_unregister_usb_phy:
usb_phy_generic_unregister(glue->usb_phy);
return ret;
}
static int sunxi_musb_remove(struct platform_device *pdev)
{
struct sunxi_glue *glue = platform_get_drvdata(pdev);
struct platform_device *usb_phy = glue->usb_phy;
platform_device_unregister(glue->musb); /* Frees glue ! */
usb_phy_generic_unregister(usb_phy);
return 0;
}
static const struct of_device_id sunxi_musb_match[] = {
{ .compatible = "allwinner,sun4i-a10-musb", },
{ .compatible = "allwinner,sun6i-a31-musb", },
{ .compatible = "allwinner,sun8i-a33-musb", },
{}
};
static struct platform_driver sunxi_musb_driver = {
.probe = sunxi_musb_probe,
.remove = sunxi_musb_remove,
.driver = {
.name = "musb-sunxi",
.of_match_table = sunxi_musb_match,
},
};
module_platform_driver(sunxi_musb_driver);
MODULE_DESCRIPTION("Allwinner sunxi MUSB Glue Layer");
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_LICENSE("GPL v2");

View file

@ -152,6 +152,20 @@ config USB_MSM_OTG
This driver is not supported on boards like trout which
has an external PHY.
config USB_QCOM_8X16_PHY
tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support"
depends on ARCH_QCOM || COMPILE_TEST
depends on RESET_CONTROLLER
select USB_PHY
select USB_ULPI_VIEWPORT
help
Enable this to support the USB transceiver on Qualcomm 8x16 chipsets.
It handles PHY initialization, clock management, power management,
and workarounds required after resetting the hardware.
To compile this driver as a module, choose M here: the
module will be called phy-qcom-8x16-usb.
config USB_MV_OTG
tristate "Marvell USB OTG support"
depends on USB_EHCI_MV && USB_MV_UDC && PM

View file

@ -20,6 +20,7 @@ obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o
obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o
obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o
obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o
obj-$(CONFIG_USB_QCOM_8X16_PHY) += phy-qcom-8x16-usb.o
obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o
obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o
obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o

View file

@ -218,11 +218,13 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
clk_rate = 0;
needs_vcc = of_property_read_bool(node, "vcc-supply");
nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset");
nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
GPIOD_ASIS);
err = PTR_ERR_OR_ZERO(nop->gpiod_reset);
if (!err) {
nop->gpiod_vbus = devm_gpiod_get_optional(dev,
"vbus-detect");
"vbus-detect",
GPIOD_ASIS);
err = PTR_ERR_OR_ZERO(nop->gpiod_vbus);
}
} else if (pdata) {

Some files were not shown because too many files have changed in this diff Show more