提交 f8712528 编写于 作者: G Greg Kroah-Hartman

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

Felipe writes:

usb: patches for v3.16 merge window

Not a lot here during this merge window. Mostly we just have
the usual miscellaneous patches (removal of unnecessary prints,
proper dependencies being added to Kconfig, build warning fixes,
new device ID, etc.

Other than those, the only important new features are the
new support for OS Strings which should help Linux Gadget
Drivers behave better under MS Windows. Also Babble Recovery
implementation for MUSB on AM335x. Lastly, we also have
ARCH_QCOM PHY support though phy-msm.
Signed-of-by: NFelipe Balbi <balbi@ti.com>

Conflicts:
	drivers/usb/phy/phy-mv-u3d-usb.c
...@@ -62,6 +62,40 @@ KernelVersion: 3.11 ...@@ -62,6 +62,40 @@ KernelVersion: 3.11
Description: Description:
This group contains functions available to this USB gadget. This group contains functions available to this USB gadget.
What: /config/usb-gadget/gadget/functions/<func>.<inst>/interface.<n>
Date: May 2014
KernelVersion: 3.16
Description:
This group contains "Feature Descriptors" specific for one
gadget's USB interface or one interface group described
by an IAD.
The attributes:
compatible_id - 8-byte string for "Compatible ID"
sub_compatible_id - 8-byte string for "Sub Compatible ID"
What: /config/usb-gadget/gadget/functions/<func>.<inst>/interface.<n>/<property>
Date: May 2014
KernelVersion: 3.16
Description:
This group contains "Extended Property Descriptors" specific for one
gadget's USB interface or one interface group described
by an IAD.
The attributes:
type - value 1..7 for interpreting the data
1: unicode string
2: unicode string with environment variable
3: binary
4: little-endian 32-bit
5: big-endian 32-bit
6: unicode string with a symbolic link
7: multiple unicode strings
data - blob of data to be interpreted depending on
type
What: /config/usb-gadget/gadget/strings What: /config/usb-gadget/gadget/strings
Date: Jun 2013 Date: Jun 2013
KernelVersion: 3.11 KernelVersion: 3.11
...@@ -79,3 +113,14 @@ Description: ...@@ -79,3 +113,14 @@ Description:
product - gadget's product description product - gadget's product description
manufacturer - gadget's manufacturer description manufacturer - gadget's manufacturer description
What: /config/usb-gadget/gadget/os_desc
Date: May 2014
KernelVersion: 3.16
Description:
This group contains "OS String" extension handling attributes.
use - flag turning "OS Desctiptors" support on/off
b_vendor_code - one-byte value used for custom per-device and
per-interface requests
qw_sign - an identifier to be reported as "OS String"
proper
...@@ -14,7 +14,8 @@ DOCBOOKS := z8530book.xml device-drivers.xml \ ...@@ -14,7 +14,8 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
80211.xml debugobjects.xml sh.xml regulator.xml \ 80211.xml debugobjects.xml sh.xml regulator.xml \
alsa-driver-api.xml writing-an-alsa-driver.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \
tracepoint.xml drm.xml media_api.xml w1.xml tracepoint.xml drm.xml media_api.xml w1.xml \
writing_musb_glue_layer.xml
include Documentation/DocBook/media/Makefile include Documentation/DocBook/media/Makefile
......
此差异已折叠。
...@@ -12,17 +12,23 @@ Required properties: ...@@ -12,17 +12,23 @@ Required properties:
- reg : Address and length of the register set for the device - reg : Address and length of the register set for the device
- interrupts : Interrupt numbers for this device - interrupts : Interrupt numbers for this device. Either one interrupt number
for all interrupts, or one for status related interrupts, one for IN
endpoint related interrupts and one for OUT endpoint related interrupts.
Optional properties: Optional properties:
- epobufsizes : An array of buffer sizes for OUT endpoints. If the property is - epobufsizes : Array of buffer sizes for OUT endpoints when they differ
not present, or for endpoints outside of the array, 1024 is assumed by from the default size of 1024. The array is indexed by the OUT endpoint
the driver. number. If the property is present it typically contains one entry for
each OUT endpoint of the core. Fewer entries overrides the default sizes
- epibufsizes : An array of buffer sizes for IN endpoints. If the property is only for as many endpoints as the array contains.
not present, or for endpoints outside of the array, 1024 is assumed by
the driver. - epibufsizes : Array of buffer sizes for IN endpoints when they differ
from the default size of 1024. The array is indexed by the IN endpoint
number. If the property is present it typically contains one entry for
each IN endpoint of the core. Fewer entries overrides the default sizes
only for as many endpoints as the array contains.
For further information look in the documentation for the GLIB IP core library: For further information look in the documentation for the GLIB IP core library:
http://www.gaisler.com/products/grlib/grip.pdf http://www.gaisler.com/products/grlib/grip.pdf
...@@ -15,3 +15,81 @@ Example EHCI controller device node: ...@@ -15,3 +15,81 @@ Example EHCI controller device node:
usb-phy = <&usb_otg>; usb-phy = <&usb_otg>;
}; };
USB PHY with optional OTG:
Required properties:
- compatible: Should contain:
"qcom,usb-otg-ci" for chipsets with ChipIdea 45nm PHY
"qcom,usb-otg-snps" for chipsets with Synopsys 28nm PHY
- regs: Offset and length of the register set in the memory map
- interrupts: interrupt-specifier for the OTG interrupt.
- clocks: A list of phandle + clock-specifier pairs for the
clocks listed in clock-names
- clock-names: Should contain the following:
"phy" USB PHY reference clock
"core" Protocol engine clock
"iface" Interface bus clock
"alt_core" Protocol engine clock for targets with asynchronous
reset methodology. (optional)
- vdccx-supply: phandle to the regulator for the vdd supply for
digital circuit operation.
- v1p8-supply: phandle to the regulator for the 1.8V supply
- v3p3-supply: phandle to the regulator for the 3.3V supply
- resets: A list of phandle + reset-specifier pairs for the
resets listed in reset-names
- reset-names: Should contain the following:
"phy" USB PHY controller reset
"link" USB LINK controller reset
- qcom,otg-control: OTG control (VBUS and ID notifications) can be one of
1 - PHY control
2 - PMIC control
Optional properties:
- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
- 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
"do not overwrite default value at this address".
For example: qcom,phy-init-sequence = < -1 0x63 >;
Will update only value at address ULPI_EXT_VENDOR_SPECIFIC + 1.
- qcom,phy-num: Select number of pyco-phy to use, can be one of
0 - PHY one, default
1 - Second PHY
Some platforms may have configuration to allow USB
controller work with any of the two HSPHYs present.
- qcom,vdd-levels: This property must be a list of three integer values
(no, min, max) where each value represents either a voltage
in microvolts or a value corresponding to voltage corner.
Example HSUSB OTG controller device node:
usb@f9a55000 {
compatible = "qcom,usb-otg-snps";
reg = <0xf9a55000 0x400>;
interrupts = <0 134 0>;
dr_mode = "peripheral";
clocks = <&gcc GCC_XO_CLK>, <&gcc GCC_USB_HS_SYSTEM_CLK>,
<&gcc GCC_USB_HS_AHB_CLK>;
clock-names = "phy", "core", "iface";
vddcx-supply = <&pm8841_s2_corner>;
v1p8-supply = <&pm8941_l6>;
v3p3-supply = <&pm8941_l24>;
resets = <&gcc GCC_USB2A_PHY_BCR>, <&gcc GCC_USB_HS_BCR>;
reset-names = "phy", "link";
qcom,otg-control = <1>;
qcom,phy-init-sequence = < -1 0x63 >;
qcom,vdd-levels = <1 5 7>;
};
...@@ -95,7 +95,7 @@ static int hsusb_phy_clk_reset(struct clk *phy_clk) ...@@ -95,7 +95,7 @@ static int hsusb_phy_clk_reset(struct clk *phy_clk)
static struct msm_otg_platform_data msm_otg_pdata = { static struct msm_otg_platform_data msm_otg_pdata = {
.phy_init_seq = hsusb_phy_init_seq, .phy_init_seq = hsusb_phy_init_seq,
.mode = USB_PERIPHERAL, .mode = USB_DR_MODE_PERIPHERAL,
.otg_control = OTG_PHY_CONTROL, .otg_control = OTG_PHY_CONTROL,
.link_clk_reset = hsusb_link_clk_reset, .link_clk_reset = hsusb_link_clk_reset,
.phy_clk_reset = hsusb_phy_clk_reset, .phy_clk_reset = hsusb_phy_clk_reset,
......
...@@ -116,7 +116,7 @@ static int hsusb_phy_clk_reset(struct clk *phy_clk) ...@@ -116,7 +116,7 @@ static int hsusb_phy_clk_reset(struct clk *phy_clk)
static struct msm_otg_platform_data msm_otg_pdata = { static struct msm_otg_platform_data msm_otg_pdata = {
.phy_init_seq = hsusb_phy_init_seq, .phy_init_seq = hsusb_phy_init_seq,
.mode = USB_PERIPHERAL, .mode = USB_DR_MODE_PERIPHERAL,
.otg_control = OTG_PHY_CONTROL, .otg_control = OTG_PHY_CONTROL,
.link_clk_reset = hsusb_link_clk_reset, .link_clk_reset = hsusb_link_clk_reset,
.phy_clk_reset = hsusb_phy_clk_reset, .phy_clk_reset = hsusb_phy_clk_reset,
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/usb/phy.h> #include <linux/usb/phy.h>
#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/i2c/twl.h> #include <linux/i2c/twl.h>
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/usb/phy.h> #include <linux/usb/phy.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include "soc.h" #include "soc.h"
#include "omap_device.h" #include "omap_device.h"
...@@ -349,7 +349,7 @@ static struct fixed_voltage_config hsusb_reg_config = { ...@@ -349,7 +349,7 @@ static struct fixed_voltage_config hsusb_reg_config = {
/* .init_data filled later */ /* .init_data filled later */
}; };
static const char *nop_name = "usb_phy_gen_xceiv"; /* NOP PHY driver */ static const char *nop_name = "usb_phy_generic"; /* NOP PHY driver */
static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */ static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */
/** /**
...@@ -435,7 +435,7 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) ...@@ -435,7 +435,7 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys)
struct platform_device *pdev; struct platform_device *pdev;
char *phy_id; char *phy_id;
struct platform_device_info pdevinfo; struct platform_device_info pdevinfo;
struct usb_phy_gen_xceiv_platform_data nop_pdata; struct usb_phy_generic_platform_data nop_pdata;
for (i = 0; i < num_phys; i++) { for (i = 0; i < num_phys; i++) {
...@@ -469,8 +469,8 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) ...@@ -469,8 +469,8 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys)
pdevinfo.id = phy->port; pdevinfo.id = phy->port;
pdevinfo.data = &nop_pdata; pdevinfo.data = &nop_pdata;
pdevinfo.size_data = pdevinfo.size_data =
sizeof(struct usb_phy_gen_xceiv_platform_data); sizeof(struct usb_phy_generic_platform_data);
scnprintf(phy_id, MAX_STR, "usb_phy_gen_xceiv.%d", scnprintf(phy_id, MAX_STR, "usb_phy_generic.%d",
phy->port); phy->port);
pdev = platform_device_register_full(&pdevinfo); pdev = platform_device_register_full(&pdevinfo);
if (IS_ERR(pdev)) { if (IS_ERR(pdev)) {
......
...@@ -44,7 +44,7 @@ comment "Platform Glue Driver Support" ...@@ -44,7 +44,7 @@ comment "Platform Glue Driver Support"
config USB_DWC3_OMAP config USB_DWC3_OMAP
tristate "Texas Instruments OMAP5 and similar Platforms" tristate "Texas Instruments OMAP5 and similar Platforms"
depends on EXTCON depends on EXTCON && (ARCH_OMAP2PLUS || COMPILE_TEST)
default USB_DWC3 default USB_DWC3
help help
Some platforms from Texas Instruments like OMAP5, DRA7xxx and Some platforms from Texas Instruments like OMAP5, DRA7xxx and
...@@ -54,6 +54,7 @@ config USB_DWC3_OMAP ...@@ -54,6 +54,7 @@ config USB_DWC3_OMAP
config USB_DWC3_EXYNOS config USB_DWC3_EXYNOS
tristate "Samsung Exynos Platform" tristate "Samsung Exynos Platform"
depends on ARCH_EXYNOS || COMPILE_TEST
default USB_DWC3 default USB_DWC3
help help
Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside, Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside,
...@@ -72,6 +73,7 @@ config USB_DWC3_PCI ...@@ -72,6 +73,7 @@ config USB_DWC3_PCI
config USB_DWC3_KEYSTONE config USB_DWC3_KEYSTONE
tristate "Texas Instruments Keystone2 Platforms" tristate "Texas Instruments Keystone2 Platforms"
depends on ARCH_KEYSTONE || COMPILE_TEST
default USB_DWC3 default USB_DWC3
help help
Support of USB2/3 functionality in TI Keystone2 platforms. Support of USB2/3 functionality in TI Keystone2 platforms.
......
...@@ -486,70 +486,20 @@ static void dwc3_core_exit(struct dwc3 *dwc) ...@@ -486,70 +486,20 @@ static void dwc3_core_exit(struct dwc3 *dwc)
phy_exit(dwc->usb3_generic_phy); phy_exit(dwc->usb3_generic_phy);
} }
#define DWC3_ALIGN_MASK (16 - 1) static int dwc3_core_get_phy(struct dwc3 *dwc)
static int dwc3_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = dwc->dev;
struct dwc3_platform_data *pdata = dev_get_platdata(dev);
struct device_node *node = dev->of_node; struct device_node *node = dev->of_node;
struct resource *res; int ret;
struct dwc3 *dwc;
int ret = -ENOMEM;
void __iomem *regs;
void *mem;
mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
if (!mem) {
dev_err(dev, "not enough memory\n");
return -ENOMEM;
}
dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
dwc->mem = mem;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(dev, "missing IRQ\n");
return -ENODEV;
}
dwc->xhci_resources[1].start = res->start;
dwc->xhci_resources[1].end = res->end;
dwc->xhci_resources[1].flags = res->flags;
dwc->xhci_resources[1].name = res->name;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "missing memory resource\n");
return -ENODEV;
}
if (node) { if (node) {
dwc->maximum_speed = of_usb_get_maximum_speed(node);
dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
dwc->dr_mode = of_usb_get_dr_mode(node);
} else if (pdata) {
dwc->maximum_speed = pdata->maximum_speed;
dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
dwc->needs_fifo_resize = pdata->tx_fifo_resize;
dwc->dr_mode = pdata->dr_mode;
} else { } else {
dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
} }
/* default to superspeed if no maximum_speed passed */
if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
dwc->maximum_speed = USB_SPEED_SUPER;
if (IS_ERR(dwc->usb2_phy)) { if (IS_ERR(dwc->usb2_phy)) {
ret = PTR_ERR(dwc->usb2_phy); ret = PTR_ERR(dwc->usb2_phy);
if (ret == -ENXIO || ret == -ENODEV) { if (ret == -ENXIO || ret == -ENODEV) {
...@@ -600,6 +550,132 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -600,6 +550,132 @@ static int dwc3_probe(struct platform_device *pdev)
} }
} }
return 0;
}
static int dwc3_core_init_mode(struct dwc3 *dwc)
{
struct device *dev = dwc->dev;
int ret;
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
ret = dwc3_gadget_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize gadget\n");
return ret;
}
break;
case USB_DR_MODE_HOST:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
ret = dwc3_host_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize host\n");
return ret;
}
break;
case USB_DR_MODE_OTG:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
ret = dwc3_host_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize host\n");
return ret;
}
ret = dwc3_gadget_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize gadget\n");
return ret;
}
break;
default:
dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
return -EINVAL;
}
return 0;
}
static void dwc3_core_exit_mode(struct dwc3 *dwc)
{
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc3_gadget_exit(dwc);
break;
case USB_DR_MODE_HOST:
dwc3_host_exit(dwc);
break;
case USB_DR_MODE_OTG:
dwc3_host_exit(dwc);
dwc3_gadget_exit(dwc);
break;
default:
/* do nothing */
break;
}
}
#define DWC3_ALIGN_MASK (16 - 1)
static int dwc3_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dwc3_platform_data *pdata = dev_get_platdata(dev);
struct device_node *node = dev->of_node;
struct resource *res;
struct dwc3 *dwc;
int ret;
void __iomem *regs;
void *mem;
mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
if (!mem) {
dev_err(dev, "not enough memory\n");
return -ENOMEM;
}
dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
dwc->mem = mem;
dwc->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(dev, "missing IRQ\n");
return -ENODEV;
}
dwc->xhci_resources[1].start = res->start;
dwc->xhci_resources[1].end = res->end;
dwc->xhci_resources[1].flags = res->flags;
dwc->xhci_resources[1].name = res->name;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "missing memory resource\n");
return -ENODEV;
}
if (node) {
dwc->maximum_speed = of_usb_get_maximum_speed(node);
dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
dwc->dr_mode = of_usb_get_dr_mode(node);
} else if (pdata) {
dwc->maximum_speed = pdata->maximum_speed;
dwc->needs_fifo_resize = pdata->tx_fifo_resize;
dwc->dr_mode = pdata->dr_mode;
}
/* default to superspeed if no maximum_speed passed */
if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
dwc->maximum_speed = USB_SPEED_SUPER;
ret = dwc3_core_get_phy(dwc);
if (ret)
return ret;
dwc->xhci_resources[0].start = res->start; dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END; DWC3_XHCI_REGS_END;
...@@ -621,7 +697,6 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -621,7 +697,6 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->regs = regs; dwc->regs = regs;
dwc->regs_size = resource_size(res); dwc->regs_size = resource_size(res);
dwc->dev = dev;
dev->dma_mask = dev->parent->dma_mask; dev->dma_mask = dev->parent->dma_mask;
dev->dma_parms = dev->parent->dma_parms; dev->dma_parms = dev->parent->dma_parms;
...@@ -670,41 +745,9 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -670,41 +745,9 @@ static int dwc3_probe(struct platform_device *pdev)
goto err_usb3phy_power; goto err_usb3phy_power;
} }
switch (dwc->dr_mode) { ret = dwc3_core_init_mode(dwc);
case USB_DR_MODE_PERIPHERAL: if (ret)
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
ret = dwc3_gadget_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize gadget\n");
goto err2;
}
break;
case USB_DR_MODE_HOST:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
ret = dwc3_host_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize host\n");
goto err2;
}
break;
case USB_DR_MODE_OTG:
dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
ret = dwc3_host_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize host\n");
goto err2;
}
ret = dwc3_gadget_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize gadget\n");
goto err2;
}
break;
default:
dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
goto err2; goto err2;
}
ret = dwc3_debugfs_init(dwc); ret = dwc3_debugfs_init(dwc);
if (ret) { if (ret) {
...@@ -717,21 +760,7 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -717,21 +760,7 @@ static int dwc3_probe(struct platform_device *pdev)
return 0; return 0;
err3: err3:
switch (dwc->dr_mode) { dwc3_core_exit_mode(dwc);
case USB_DR_MODE_PERIPHERAL:
dwc3_gadget_exit(dwc);
break;
case USB_DR_MODE_HOST:
dwc3_host_exit(dwc);
break;
case USB_DR_MODE_OTG:
dwc3_host_exit(dwc);
dwc3_gadget_exit(dwc);
break;
default:
/* do nothing */
break;
}
err2: err2:
dwc3_event_buffers_cleanup(dwc); dwc3_event_buffers_cleanup(dwc);
...@@ -766,23 +795,7 @@ static int dwc3_remove(struct platform_device *pdev) ...@@ -766,23 +795,7 @@ static int dwc3_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
dwc3_debugfs_exit(dwc); dwc3_debugfs_exit(dwc);
dwc3_core_exit_mode(dwc);
switch (dwc->dr_mode) {
case USB_DR_MODE_PERIPHERAL:
dwc3_gadget_exit(dwc);
break;
case USB_DR_MODE_HOST:
dwc3_host_exit(dwc);
break;
case USB_DR_MODE_OTG:
dwc3_host_exit(dwc);
dwc3_gadget_exit(dwc);
break;
default:
/* do nothing */
break;
}
dwc3_event_buffers_cleanup(dwc); dwc3_event_buffers_cleanup(dwc);
dwc3_free_event_buffers(dwc); dwc3_free_event_buffers(dwc);
dwc3_core_exit(dwc); dwc3_core_exit(dwc);
......
...@@ -24,9 +24,10 @@ ...@@ -24,9 +24,10 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/regulator/consumer.h>
struct dwc3_exynos { struct dwc3_exynos {
struct platform_device *usb2_phy; struct platform_device *usb2_phy;
...@@ -34,17 +35,19 @@ struct dwc3_exynos { ...@@ -34,17 +35,19 @@ struct dwc3_exynos {
struct device *dev; struct device *dev;
struct clk *clk; struct clk *clk;
struct regulator *vdd33;
struct regulator *vdd10;
}; };
static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos) static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
{ {
struct usb_phy_gen_xceiv_platform_data pdata; struct usb_phy_generic_platform_data pdata;
struct platform_device *pdev; struct platform_device *pdev;
int ret; int ret;
memset(&pdata, 0x00, sizeof(pdata)); memset(&pdata, 0x00, sizeof(pdata));
pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO); pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO);
if (!pdev) if (!pdev)
return -ENOMEM; return -ENOMEM;
...@@ -56,7 +59,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos) ...@@ -56,7 +59,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
if (ret) if (ret)
goto err1; goto err1;
pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO); pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO);
if (!pdev) { if (!pdev) {
ret = -ENOMEM; ret = -ENOMEM;
goto err1; goto err1;
...@@ -107,12 +110,12 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -107,12 +110,12 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node; struct device_node *node = dev->of_node;
int ret = -ENOMEM; int ret;
exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL); exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
if (!exynos) { if (!exynos) {
dev_err(dev, "not enough memory\n"); dev_err(dev, "not enough memory\n");
goto err1; return -ENOMEM;
} }
/* /*
...@@ -122,21 +125,20 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -122,21 +125,20 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
*/ */
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret) if (ret)
goto err1; return ret;
platform_set_drvdata(pdev, exynos); platform_set_drvdata(pdev, exynos);
ret = dwc3_exynos_register_phys(exynos); ret = dwc3_exynos_register_phys(exynos);
if (ret) { if (ret) {
dev_err(dev, "couldn't register PHYs\n"); dev_err(dev, "couldn't register PHYs\n");
goto err1; return ret;
} }
clk = devm_clk_get(dev, "usbdrd30"); clk = devm_clk_get(dev, "usbdrd30");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(dev, "couldn't get clock\n"); dev_err(dev, "couldn't get clock\n");
ret = -EINVAL; return -EINVAL;
goto err1;
} }
exynos->dev = dev; exynos->dev = dev;
...@@ -144,23 +146,48 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -144,23 +146,48 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
clk_prepare_enable(exynos->clk); clk_prepare_enable(exynos->clk);
exynos->vdd33 = devm_regulator_get(dev, "vdd33");
if (IS_ERR(exynos->vdd33)) {
ret = PTR_ERR(exynos->vdd33);
goto err2;
}
ret = regulator_enable(exynos->vdd33);
if (ret) {
dev_err(dev, "Failed to enable VDD33 supply\n");
goto err2;
}
exynos->vdd10 = devm_regulator_get(dev, "vdd10");
if (IS_ERR(exynos->vdd10)) {
ret = PTR_ERR(exynos->vdd10);
goto err3;
}
ret = regulator_enable(exynos->vdd10);
if (ret) {
dev_err(dev, "Failed to enable VDD10 supply\n");
goto err3;
}
if (node) { if (node) {
ret = of_platform_populate(node, NULL, NULL, dev); ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) { if (ret) {
dev_err(dev, "failed to add dwc3 core\n"); dev_err(dev, "failed to add dwc3 core\n");
goto err2; goto err4;
} }
} else { } else {
dev_err(dev, "no device node, failed to add dwc3 core\n"); dev_err(dev, "no device node, failed to add dwc3 core\n");
ret = -ENODEV; ret = -ENODEV;
goto err2; goto err4;
} }
return 0; return 0;
err4:
regulator_disable(exynos->vdd10);
err3:
regulator_disable(exynos->vdd33);
err2: err2:
clk_disable_unprepare(clk); clk_disable_unprepare(clk);
err1:
return ret; return ret;
} }
...@@ -174,6 +201,9 @@ static int dwc3_exynos_remove(struct platform_device *pdev) ...@@ -174,6 +201,9 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
clk_disable_unprepare(exynos->clk); clk_disable_unprepare(exynos->clk);
regulator_disable(exynos->vdd33);
regulator_disable(exynos->vdd10);
return 0; return 0;
} }
...@@ -192,12 +222,27 @@ static int dwc3_exynos_suspend(struct device *dev) ...@@ -192,12 +222,27 @@ static int dwc3_exynos_suspend(struct device *dev)
clk_disable(exynos->clk); clk_disable(exynos->clk);
regulator_disable(exynos->vdd33);
regulator_disable(exynos->vdd10);
return 0; return 0;
} }
static int dwc3_exynos_resume(struct device *dev) static int dwc3_exynos_resume(struct device *dev)
{ {
struct dwc3_exynos *exynos = dev_get_drvdata(dev); struct dwc3_exynos *exynos = dev_get_drvdata(dev);
int ret;
ret = regulator_enable(exynos->vdd33);
if (ret) {
dev_err(dev, "Failed to enable VDD33 supply\n");
return ret;
}
ret = regulator_enable(exynos->vdd10);
if (ret) {
dev_err(dev, "Failed to enable VDD10 supply\n");
return ret;
}
clk_enable(exynos->clk); clk_enable(exynos->clk);
......
...@@ -393,7 +393,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -393,7 +393,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
struct extcon_dev *edev; struct extcon_dev *edev;
struct regulator *vbus_reg = NULL; struct regulator *vbus_reg = NULL;
int ret = -ENOMEM; int ret;
int irq; int irq;
int utmi_mode = 0; int utmi_mode = 0;
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
/* FIXME define these in <linux/pci_ids.h> */ /* FIXME define these in <linux/pci_ids.h> */
#define PCI_VENDOR_ID_SYNOPSYS 0x16c3 #define PCI_VENDOR_ID_SYNOPSYS 0x16c3
...@@ -40,13 +40,13 @@ struct dwc3_pci { ...@@ -40,13 +40,13 @@ struct dwc3_pci {
static int dwc3_pci_register_phys(struct dwc3_pci *glue) static int dwc3_pci_register_phys(struct dwc3_pci *glue)
{ {
struct usb_phy_gen_xceiv_platform_data pdata; struct usb_phy_generic_platform_data pdata;
struct platform_device *pdev; struct platform_device *pdev;
int ret; int ret;
memset(&pdata, 0x00, sizeof(pdata)); memset(&pdata, 0x00, sizeof(pdata));
pdev = platform_device_alloc("usb_phy_gen_xceiv", 0); pdev = platform_device_alloc("usb_phy_generic", 0);
if (!pdev) if (!pdev)
return -ENOMEM; return -ENOMEM;
...@@ -58,7 +58,7 @@ static int dwc3_pci_register_phys(struct dwc3_pci *glue) ...@@ -58,7 +58,7 @@ static int dwc3_pci_register_phys(struct dwc3_pci *glue)
if (ret) if (ret)
goto err1; goto err1;
pdev = platform_device_alloc("usb_phy_gen_xceiv", 1); pdev = platform_device_alloc("usb_phy_generic", 1);
if (!pdev) { if (!pdev) {
ret = -ENOMEM; ret = -ENOMEM;
goto err1; goto err1;
...@@ -99,7 +99,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, ...@@ -99,7 +99,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
struct resource res[2]; struct resource res[2];
struct platform_device *dwc3; struct platform_device *dwc3;
struct dwc3_pci *glue; struct dwc3_pci *glue;
int ret = -ENOMEM; int ret;
struct device *dev = &pci->dev; struct device *dev = &pci->dev;
glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL); glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
...@@ -110,7 +110,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, ...@@ -110,7 +110,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
glue->dev = dev; glue->dev = dev;
ret = pci_enable_device(pci); ret = pcim_enable_device(pci);
if (ret) { if (ret) {
dev_err(dev, "failed to enable pci device\n"); dev_err(dev, "failed to enable pci device\n");
return -ENODEV; return -ENODEV;
...@@ -127,8 +127,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, ...@@ -127,8 +127,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc3) { if (!dwc3) {
dev_err(dev, "couldn't allocate dwc3 device\n"); dev_err(dev, "couldn't allocate dwc3 device\n");
ret = -ENOMEM; return -ENOMEM;
goto err1;
} }
memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
...@@ -145,7 +144,7 @@ static int dwc3_pci_probe(struct pci_dev *pci, ...@@ -145,7 +144,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));
if (ret) { if (ret) {
dev_err(dev, "couldn't add resources to dwc3 device\n"); dev_err(dev, "couldn't add resources to dwc3 device\n");
goto err1; return ret;
} }
pci_set_drvdata(pci, glue); pci_set_drvdata(pci, glue);
...@@ -167,9 +166,6 @@ static int dwc3_pci_probe(struct pci_dev *pci, ...@@ -167,9 +166,6 @@ static int dwc3_pci_probe(struct pci_dev *pci,
err3: err3:
platform_device_put(dwc3); platform_device_put(dwc3);
err1:
pci_disable_device(pci);
return ret; return ret;
} }
...@@ -180,7 +176,6 @@ static void dwc3_pci_remove(struct pci_dev *pci) ...@@ -180,7 +176,6 @@ static void dwc3_pci_remove(struct pci_dev *pci)
platform_device_unregister(glue->dwc3); platform_device_unregister(glue->dwc3);
platform_device_unregister(glue->usb2_phy); platform_device_unregister(glue->usb2_phy);
platform_device_unregister(glue->usb3_phy); platform_device_unregister(glue->usb3_phy);
pci_disable_device(pci);
} }
static const struct pci_device_id dwc3_pci_id_table[] = { static const struct pci_device_id dwc3_pci_id_table[] = {
......
...@@ -298,11 +298,76 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd) ...@@ -298,11 +298,76 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd)
} }
} }
static const char *dwc3_gadget_generic_cmd_string(u8 cmd)
{
switch (cmd) {
case DWC3_DGCMD_SET_LMP:
return "Set LMP";
case DWC3_DGCMD_SET_PERIODIC_PAR:
return "Set Periodic Parameters";
case DWC3_DGCMD_XMIT_FUNCTION:
return "Transmit Function Wake Device Notification";
case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO:
return "Set Scratchpad Buffer Array Address Lo";
case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI:
return "Set Scratchpad Buffer Array Address Hi";
case DWC3_DGCMD_SELECTED_FIFO_FLUSH:
return "Selected FIFO Flush";
case DWC3_DGCMD_ALL_FIFO_FLUSH:
return "All FIFO Flush";
case DWC3_DGCMD_SET_ENDPOINT_NRDY:
return "Set Endpoint NRDY";
case DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK:
return "Run SoC Bus Loopback Test";
default:
return "UNKNOWN";
}
}
static const char *dwc3_gadget_link_string(enum dwc3_link_state link_state)
{
switch (link_state) {
case DWC3_LINK_STATE_U0:
return "U0";
case DWC3_LINK_STATE_U1:
return "U1";
case DWC3_LINK_STATE_U2:
return "U2";
case DWC3_LINK_STATE_U3:
return "U3";
case DWC3_LINK_STATE_SS_DIS:
return "SS.Disabled";
case DWC3_LINK_STATE_RX_DET:
return "RX.Detect";
case DWC3_LINK_STATE_SS_INACT:
return "SS.Inactive";
case DWC3_LINK_STATE_POLL:
return "Polling";
case DWC3_LINK_STATE_RECOV:
return "Recovery";
case DWC3_LINK_STATE_HRESET:
return "Hot Reset";
case DWC3_LINK_STATE_CMPLY:
return "Compliance";
case DWC3_LINK_STATE_LPBK:
return "Loopback";
case DWC3_LINK_STATE_RESET:
return "Reset";
case DWC3_LINK_STATE_RESUME:
return "Resume";
default:
return "UNKNOWN link state\n";
}
}
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param) int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param)
{ {
u32 timeout = 500; u32 timeout = 500;
u32 reg; u32 reg;
dev_vdbg(dwc->dev, "generic cmd '%s' [%d] param %08x\n",
dwc3_gadget_generic_cmd_string(cmd), cmd, param);
dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param); dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param);
dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT); dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
...@@ -332,9 +397,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, ...@@ -332,9 +397,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
u32 timeout = 500; u32 timeout = 500;
u32 reg; u32 reg;
dev_vdbg(dwc->dev, "%s: cmd '%s' params %08x %08x %08x\n", dev_vdbg(dwc->dev, "%s: cmd '%s' [%d] params %08x %08x %08x\n",
dep->name, dep->name,
dwc3_gadget_ep_cmd_string(cmd), params->param0, dwc3_gadget_ep_cmd_string(cmd), cmd, params->param0,
params->param1, params->param2); params->param1, params->param2);
dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0); dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0);
...@@ -515,7 +580,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, ...@@ -515,7 +580,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
{ {
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
u32 reg; u32 reg;
int ret = -ENOMEM; int ret;
dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
...@@ -604,6 +669,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) ...@@ -604,6 +669,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dwc3_remove_requests(dwc, dep); dwc3_remove_requests(dwc, dep);
/* make sure HW endpoint isn't stalled */
if (dep->flags & DWC3_EP_STALL)
__dwc3_gadget_ep_set_halt(dep, 0);
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg &= ~DWC3_DALEPENA_EP(dep->number); reg &= ~DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
...@@ -2441,8 +2510,6 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, ...@@ -2441,8 +2510,6 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
} }
} }
dwc->link_state = next;
switch (next) { switch (next) {
case DWC3_LINK_STATE_U1: case DWC3_LINK_STATE_U1:
if (dwc->speed == USB_SPEED_SUPER) if (dwc->speed == USB_SPEED_SUPER)
...@@ -2460,7 +2527,11 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, ...@@ -2460,7 +2527,11 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
break; break;
} }
dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state); dev_vdbg(dwc->dev, "link change: %s [%d] -> %s [%d]\n",
dwc3_gadget_link_string(dwc->link_state),
dwc->link_state, dwc3_gadget_link_string(next), next);
dwc->link_state = next;
} }
static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc, static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc,
......
...@@ -1686,7 +1686,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) ...@@ -1686,7 +1686,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
reset_all_endpoints(udc); reset_all_endpoints(udc);
if (udc->gadget.speed != USB_SPEED_UNKNOWN if (udc->gadget.speed != USB_SPEED_UNKNOWN
&& udc->driver->disconnect) { && udc->driver && udc->driver->disconnect) {
udc->gadget.speed = USB_SPEED_UNKNOWN; udc->gadget.speed = USB_SPEED_UNKNOWN;
spin_unlock(&udc->lock); spin_unlock(&udc->lock);
udc->driver->disconnect(&udc->gadget); udc->driver->disconnect(&udc->gadget);
......
...@@ -21,6 +21,24 @@ ...@@ -21,6 +21,24 @@
#include <linux/usb/composite.h> #include <linux/usb/composite.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "u_os_desc.h"
/**
* struct usb_os_string - represents OS String to be reported by a gadget
* @bLength: total length of the entire descritor, always 0x12
* @bDescriptorType: USB_DT_STRING
* @qwSignature: the OS String proper
* @bMS_VendorCode: code used by the host for subsequent requests
* @bPad: not used, must be zero
*/
struct usb_os_string {
__u8 bLength;
__u8 bDescriptorType;
__u8 qwSignature[OS_STRING_QW_SIGN_LEN];
__u8 bMS_VendorCode;
__u8 bPad;
} __packed;
/* /*
* The code in this file is utility code, used to build a gadget driver * The code in this file is utility code, used to build a gadget driver
* from one or more "function" drivers, one or more "configuration" * from one or more "function" drivers, one or more "configuration"
...@@ -422,6 +440,7 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) ...@@ -422,6 +440,7 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
{ {
struct usb_gadget *gadget = cdev->gadget; struct usb_gadget *gadget = cdev->gadget;
struct usb_configuration *c; struct usb_configuration *c;
struct list_head *pos;
u8 type = w_value >> 8; u8 type = w_value >> 8;
enum usb_device_speed speed = USB_SPEED_UNKNOWN; enum usb_device_speed speed = USB_SPEED_UNKNOWN;
...@@ -440,7 +459,20 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) ...@@ -440,7 +459,20 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
/* This is a lookup by config *INDEX* */ /* This is a lookup by config *INDEX* */
w_value &= 0xff; w_value &= 0xff;
list_for_each_entry(c, &cdev->configs, list) {
pos = &cdev->configs;
c = cdev->os_desc_config;
if (c)
goto check_config;
while ((pos = pos->next) != &cdev->configs) {
c = list_entry(pos, typeof(*c), list);
/* skip OS Descriptors config which is handled separately */
if (c == cdev->os_desc_config)
continue;
check_config:
/* ignore configs that won't work at this speed */ /* ignore configs that won't work at this speed */
switch (speed) { switch (speed) {
case USB_SPEED_SUPER: case USB_SPEED_SUPER:
...@@ -634,6 +666,7 @@ static int set_config(struct usb_composite_dev *cdev, ...@@ -634,6 +666,7 @@ static int set_config(struct usb_composite_dev *cdev,
if (!c) if (!c)
goto done; goto done;
usb_gadget_set_state(gadget, USB_STATE_CONFIGURED);
cdev->config = c; cdev->config = c;
/* Initialize all interfaces by setting them to altsetting zero. */ /* Initialize all interfaces by setting them to altsetting zero. */
...@@ -960,6 +993,19 @@ static int get_string(struct usb_composite_dev *cdev, ...@@ -960,6 +993,19 @@ static int get_string(struct usb_composite_dev *cdev,
return s->bLength; return s->bLength;
} }
if (cdev->use_os_string && language == 0 && id == OS_STRING_IDX) {
struct usb_os_string *b = buf;
b->bLength = sizeof(*b);
b->bDescriptorType = USB_DT_STRING;
compiletime_assert(
sizeof(b->qwSignature) == sizeof(cdev->qw_sign),
"qwSignature size must be equal to qw_sign");
memcpy(&b->qwSignature, cdev->qw_sign, sizeof(b->qwSignature));
b->bMS_VendorCode = cdev->b_vendor_code;
b->bPad = 0;
return sizeof(*b);
}
list_for_each_entry(uc, &cdev->gstrings, list) { list_for_each_entry(uc, &cdev->gstrings, list) {
struct usb_gadget_strings **sp; struct usb_gadget_strings **sp;
...@@ -1206,6 +1252,158 @@ static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -1206,6 +1252,158 @@ static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
req->status, req->actual, req->length); req->status, req->actual, req->length);
} }
static int count_ext_compat(struct usb_configuration *c)
{
int i, res;
res = 0;
for (i = 0; i < c->next_interface_id; ++i) {
struct usb_function *f;
int j;
f = c->interface[i];
for (j = 0; j < f->os_desc_n; ++j) {
struct usb_os_desc *d;
if (i != f->os_desc_table[j].if_id)
continue;
d = f->os_desc_table[j].os_desc;
if (d && d->ext_compat_id)
++res;
}
}
BUG_ON(res > 255);
return res;
}
static void fill_ext_compat(struct usb_configuration *c, u8 *buf)
{
int i, count;
count = 16;
for (i = 0; i < c->next_interface_id; ++i) {
struct usb_function *f;
int j;
f = c->interface[i];
for (j = 0; j < f->os_desc_n; ++j) {
struct usb_os_desc *d;
if (i != f->os_desc_table[j].if_id)
continue;
d = f->os_desc_table[j].os_desc;
if (d && d->ext_compat_id) {
*buf++ = i;
*buf++ = 0x01;
memcpy(buf, d->ext_compat_id, 16);
buf += 22;
} else {
++buf;
*buf = 0x01;
buf += 23;
}
count += 24;
if (count >= 4096)
return;
}
}
}
static int count_ext_prop(struct usb_configuration *c, int interface)
{
struct usb_function *f;
int j, res;
res = 0;
f = c->interface[interface];
for (j = 0; j < f->os_desc_n; ++j) {
struct usb_os_desc *d;
if (interface != f->os_desc_table[j].if_id)
continue;
d = f->os_desc_table[j].os_desc;
if (d && d->ext_compat_id)
return d->ext_prop_count;
}
return res;
}
static int len_ext_prop(struct usb_configuration *c, int interface)
{
struct usb_function *f;
struct usb_os_desc *d;
int j, res;
res = 10; /* header length */
f = c->interface[interface];
for (j = 0; j < f->os_desc_n; ++j) {
if (interface != f->os_desc_table[j].if_id)
continue;
d = f->os_desc_table[j].os_desc;
if (d)
return min(res + d->ext_prop_len, 4096);
}
return res;
}
static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
{
struct usb_function *f;
struct usb_os_desc *d;
struct usb_os_desc_ext_prop *ext_prop;
int j, count, n, ret;
u8 *start = buf;
f = c->interface[interface];
for (j = 0; j < f->os_desc_n; ++j) {
if (interface != f->os_desc_table[j].if_id)
continue;
d = f->os_desc_table[j].os_desc;
if (d)
list_for_each_entry(ext_prop, &d->ext_prop, entry) {
/* 4kB minus header length */
n = buf - start;
if (n >= 4086)
return 0;
count = ext_prop->data_len +
ext_prop->name_len + 14;
if (count > 4086 - n)
return -EINVAL;
usb_ext_prop_put_size(buf, count);
usb_ext_prop_put_type(buf, ext_prop->type);
ret = usb_ext_prop_put_name(buf, ext_prop->name,
ext_prop->name_len);
if (ret < 0)
return ret;
switch (ext_prop->type) {
case USB_EXT_PROP_UNICODE:
case USB_EXT_PROP_UNICODE_ENV:
case USB_EXT_PROP_UNICODE_LINK:
usb_ext_prop_put_unicode(buf, ret,
ext_prop->data,
ext_prop->data_len);
break;
case USB_EXT_PROP_BINARY:
usb_ext_prop_put_binary(buf, ret,
ext_prop->data,
ext_prop->data_len);
break;
case USB_EXT_PROP_LE32:
/* not implemented */
case USB_EXT_PROP_BE32:
/* not implemented */
default:
return -EINVAL;
}
buf += count;
}
}
return 0;
}
/* /*
* The setup() callback implements all the ep0 functionality that's * The setup() callback implements all the ep0 functionality that's
* not handled lower down, in hardware or the hardware driver(like * not handled lower down, in hardware or the hardware driver(like
...@@ -1415,6 +1613,91 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1415,6 +1613,91 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
break; break;
default: default:
unknown: unknown:
/*
* OS descriptors handling
*/
if (cdev->use_os_string && cdev->os_desc_config &&
(ctrl->bRequest & USB_TYPE_VENDOR) &&
ctrl->bRequest == cdev->b_vendor_code) {
struct usb_request *req;
struct usb_configuration *os_desc_cfg;
u8 *buf;
int interface;
int count = 0;
req = cdev->os_desc_req;
req->complete = composite_setup_complete;
buf = req->buf;
os_desc_cfg = cdev->os_desc_config;
memset(buf, 0, w_length);
buf[5] = 0x01;
switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
if (w_index != 0x4 || (w_value >> 8))
break;
buf[6] = w_index;
if (w_length == 0x10) {
/* Number of ext compat interfaces */
count = count_ext_compat(os_desc_cfg);
buf[8] = count;
count *= 24; /* 24 B/ext compat desc */
count += 16; /* header */
put_unaligned_le32(count, buf);
value = w_length;
} else {
/* "extended compatibility ID"s */
count = count_ext_compat(os_desc_cfg);
buf[8] = count;
count *= 24; /* 24 B/ext compat desc */
count += 16; /* header */
put_unaligned_le32(count, buf);
buf += 16;
fill_ext_compat(os_desc_cfg, buf);
value = w_length;
}
break;
case USB_RECIP_INTERFACE:
if (w_index != 0x5 || (w_value >> 8))
break;
interface = w_value & 0xFF;
buf[6] = w_index;
if (w_length == 0x0A) {
count = count_ext_prop(os_desc_cfg,
interface);
put_unaligned_le16(count, buf + 8);
count = len_ext_prop(os_desc_cfg,
interface);
put_unaligned_le32(count, buf);
value = w_length;
} else {
count = count_ext_prop(os_desc_cfg,
interface);
put_unaligned_le16(count, buf + 8);
count = len_ext_prop(os_desc_cfg,
interface);
put_unaligned_le32(count, buf);
buf += 10;
value = fill_ext_prop(os_desc_cfg,
interface, buf);
if (value < 0)
return value;
value = w_length;
}
break;
}
req->length = value;
req->zero = value < w_length;
value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
DBG(cdev, "ep_queue --> %d\n", value);
req->status = 0;
composite_setup_complete(gadget->ep0, req);
}
return value;
}
VDBG(cdev, VDBG(cdev,
"non-core control req%02x.%02x v%04x i%04x l%d\n", "non-core control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest, ctrl->bRequestType, ctrl->bRequest,
...@@ -1638,6 +1921,29 @@ int composite_dev_prepare(struct usb_composite_driver *composite, ...@@ -1638,6 +1921,29 @@ int composite_dev_prepare(struct usb_composite_driver *composite,
return ret; return ret;
} }
int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
struct usb_ep *ep0)
{
int ret = 0;
cdev->os_desc_req = usb_ep_alloc_request(ep0, GFP_KERNEL);
if (!cdev->os_desc_req) {
ret = PTR_ERR(cdev->os_desc_req);
goto end;
}
/* OS feature descriptor length <= 4kB */
cdev->os_desc_req->buf = kmalloc(4096, GFP_KERNEL);
if (!cdev->os_desc_req->buf) {
ret = PTR_ERR(cdev->os_desc_req->buf);
kfree(cdev->os_desc_req);
goto end;
}
cdev->os_desc_req->complete = composite_setup_complete;
end:
return ret;
}
void composite_dev_cleanup(struct usb_composite_dev *cdev) void composite_dev_cleanup(struct usb_composite_dev *cdev)
{ {
struct usb_gadget_string_container *uc, *tmp; struct usb_gadget_string_container *uc, *tmp;
...@@ -1646,6 +1952,10 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev) ...@@ -1646,6 +1952,10 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
list_del(&uc->list); list_del(&uc->list);
kfree(uc); kfree(uc);
} }
if (cdev->os_desc_req) {
kfree(cdev->os_desc_req->buf);
usb_ep_free_request(cdev->gadget->ep0, cdev->os_desc_req);
}
if (cdev->req) { if (cdev->req) {
kfree(cdev->req->buf); kfree(cdev->req->buf);
usb_ep_free_request(cdev->gadget->ep0, cdev->req); usb_ep_free_request(cdev->gadget->ep0, cdev->req);
...@@ -1683,6 +1993,12 @@ static int composite_bind(struct usb_gadget *gadget, ...@@ -1683,6 +1993,12 @@ static int composite_bind(struct usb_gadget *gadget,
if (status < 0) if (status < 0)
goto fail; goto fail;
if (cdev->use_os_string) {
status = composite_os_desc_req_prepare(cdev, gadget->ep0);
if (status)
goto fail;
}
update_unchanged_dev_desc(&cdev->desc, composite->dev); update_unchanged_dev_desc(&cdev->desc, composite->dev);
/* has userspace failed to provide a serial number? */ /* has userspace failed to provide a serial number? */
......
...@@ -2,9 +2,12 @@ ...@@ -2,9 +2,12 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/nls.h>
#include <linux/usb/composite.h> #include <linux/usb/composite.h>
#include <linux/usb/gadget_configfs.h> #include <linux/usb/gadget_configfs.h>
#include "configfs.h" #include "configfs.h"
#include "u_f.h"
#include "u_os_desc.h"
int check_user_usb_string(const char *name, int check_user_usb_string(const char *name,
struct usb_gadget_strings *stringtab_dev) struct usb_gadget_strings *stringtab_dev)
...@@ -43,7 +46,8 @@ struct gadget_info { ...@@ -43,7 +46,8 @@ struct gadget_info {
struct config_group functions_group; struct config_group functions_group;
struct config_group configs_group; struct config_group configs_group;
struct config_group strings_group; struct config_group strings_group;
struct config_group *default_groups[4]; struct config_group os_desc_group;
struct config_group *default_groups[5];
struct mutex lock; struct mutex lock;
struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
...@@ -56,6 +60,9 @@ struct gadget_info { ...@@ -56,6 +60,9 @@ struct gadget_info {
#endif #endif
struct usb_composite_driver composite; struct usb_composite_driver composite;
struct usb_composite_dev cdev; struct usb_composite_dev cdev;
bool use_os_desc;
char b_vendor_code;
char qw_sign[OS_STRING_QW_SIGN_LEN];
}; };
struct config_usb_cfg { struct config_usb_cfg {
...@@ -79,6 +86,10 @@ struct gadget_strings { ...@@ -79,6 +86,10 @@ struct gadget_strings {
struct list_head list; struct list_head list;
}; };
struct os_desc {
struct config_group group;
};
struct gadget_config_name { struct gadget_config_name {
struct usb_gadget_strings stringtab_dev; struct usb_gadget_strings stringtab_dev;
struct usb_string strings; struct usb_string strings;
...@@ -736,6 +747,525 @@ static void gadget_strings_attr_release(struct config_item *item) ...@@ -736,6 +747,525 @@ static void gadget_strings_attr_release(struct config_item *item)
USB_CONFIG_STRING_RW_OPS(gadget_strings); USB_CONFIG_STRING_RW_OPS(gadget_strings);
USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info); USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info);
static inline struct os_desc *to_os_desc(struct config_item *item)
{
return container_of(to_config_group(item), struct os_desc, group);
}
CONFIGFS_ATTR_STRUCT(os_desc);
CONFIGFS_ATTR_OPS(os_desc);
static ssize_t os_desc_use_show(struct os_desc *os_desc, char *page)
{
struct gadget_info *gi;
gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
return sprintf(page, "%d", gi->use_os_desc);
}
static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
size_t len)
{
struct gadget_info *gi;
int ret;
bool use;
gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
mutex_lock(&gi->lock);
ret = strtobool(page, &use);
if (!ret) {
gi->use_os_desc = use;
ret = len;
}
mutex_unlock(&gi->lock);
return ret;
}
static struct os_desc_attribute os_desc_use =
__CONFIGFS_ATTR(use, S_IRUGO | S_IWUSR,
os_desc_use_show,
os_desc_use_store);
static ssize_t os_desc_b_vendor_code_show(struct os_desc *os_desc, char *page)
{
struct gadget_info *gi;
gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
return sprintf(page, "%d", gi->b_vendor_code);
}
static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
const char *page, size_t len)
{
struct gadget_info *gi;
int ret;
u8 b_vendor_code;
gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
mutex_lock(&gi->lock);
ret = kstrtou8(page, 0, &b_vendor_code);
if (!ret) {
gi->b_vendor_code = b_vendor_code;
ret = len;
}
mutex_unlock(&gi->lock);
return ret;
}
static struct os_desc_attribute os_desc_b_vendor_code =
__CONFIGFS_ATTR(b_vendor_code, S_IRUGO | S_IWUSR,
os_desc_b_vendor_code_show,
os_desc_b_vendor_code_store);
static ssize_t os_desc_qw_sign_show(struct os_desc *os_desc, char *page)
{
struct gadget_info *gi;
gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
memcpy(page, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
return OS_STRING_QW_SIGN_LEN;
}
static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
size_t len)
{
struct gadget_info *gi;
int res, l;
gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1);
if (page[l - 1] == '\n')
--l;
mutex_lock(&gi->lock);
res = utf8s_to_utf16s(page, l,
UTF16_LITTLE_ENDIAN, (wchar_t *) gi->qw_sign,
OS_STRING_QW_SIGN_LEN);
if (res > 0)
res = len;
mutex_unlock(&gi->lock);
return res;
}
static struct os_desc_attribute os_desc_qw_sign =
__CONFIGFS_ATTR(qw_sign, S_IRUGO | S_IWUSR,
os_desc_qw_sign_show,
os_desc_qw_sign_store);
static struct configfs_attribute *os_desc_attrs[] = {
&os_desc_use.attr,
&os_desc_b_vendor_code.attr,
&os_desc_qw_sign.attr,
NULL,
};
static void os_desc_attr_release(struct config_item *item)
{
struct os_desc *os_desc = to_os_desc(item);
kfree(os_desc);
}
static int os_desc_link(struct config_item *os_desc_ci,
struct config_item *usb_cfg_ci)
{
struct gadget_info *gi = container_of(to_config_group(os_desc_ci),
struct gadget_info, os_desc_group);
struct usb_composite_dev *cdev = &gi->cdev;
struct config_usb_cfg *c_target =
container_of(to_config_group(usb_cfg_ci),
struct config_usb_cfg, group);
struct usb_configuration *c;
int ret;
mutex_lock(&gi->lock);
list_for_each_entry(c, &cdev->configs, list) {
if (c == &c_target->c)
break;
}
if (c != &c_target->c) {
ret = -EINVAL;
goto out;
}
if (cdev->os_desc_config) {
ret = -EBUSY;
goto out;
}
cdev->os_desc_config = &c_target->c;
ret = 0;
out:
mutex_unlock(&gi->lock);
return ret;
}
static int os_desc_unlink(struct config_item *os_desc_ci,
struct config_item *usb_cfg_ci)
{
struct gadget_info *gi = container_of(to_config_group(os_desc_ci),
struct gadget_info, os_desc_group);
struct usb_composite_dev *cdev = &gi->cdev;
mutex_lock(&gi->lock);
if (gi->udc_name)
unregister_gadget(gi);
cdev->os_desc_config = NULL;
WARN_ON(gi->udc_name);
mutex_unlock(&gi->lock);
return 0;
}
static struct configfs_item_operations os_desc_ops = {
.release = os_desc_attr_release,
.show_attribute = os_desc_attr_show,
.store_attribute = os_desc_attr_store,
.allow_link = os_desc_link,
.drop_link = os_desc_unlink,
};
static struct config_item_type os_desc_type = {
.ct_item_ops = &os_desc_ops,
.ct_attrs = os_desc_attrs,
.ct_owner = THIS_MODULE,
};
CONFIGFS_ATTR_STRUCT(usb_os_desc);
CONFIGFS_ATTR_OPS(usb_os_desc);
static inline struct usb_os_desc_ext_prop
*to_usb_os_desc_ext_prop(struct config_item *item)
{
return container_of(item, struct usb_os_desc_ext_prop, item);
}
CONFIGFS_ATTR_STRUCT(usb_os_desc_ext_prop);
CONFIGFS_ATTR_OPS(usb_os_desc_ext_prop);
static ssize_t ext_prop_type_show(struct usb_os_desc_ext_prop *ext_prop,
char *page)
{
return sprintf(page, "%d", ext_prop->type);
}
static ssize_t ext_prop_type_store(struct usb_os_desc_ext_prop *ext_prop,
const char *page, size_t len)
{
struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
u8 type;
int ret;
if (desc->opts_mutex)
mutex_lock(desc->opts_mutex);
ret = kstrtou8(page, 0, &type);
if (ret)
goto end;
if (type < USB_EXT_PROP_UNICODE || type > USB_EXT_PROP_UNICODE_MULTI) {
ret = -EINVAL;
goto end;
}
if ((ext_prop->type == USB_EXT_PROP_BINARY ||
ext_prop->type == USB_EXT_PROP_LE32 ||
ext_prop->type == USB_EXT_PROP_BE32) &&
(type == USB_EXT_PROP_UNICODE ||
type == USB_EXT_PROP_UNICODE_ENV ||
type == USB_EXT_PROP_UNICODE_LINK))
ext_prop->data_len <<= 1;
else if ((ext_prop->type == USB_EXT_PROP_UNICODE ||
ext_prop->type == USB_EXT_PROP_UNICODE_ENV ||
ext_prop->type == USB_EXT_PROP_UNICODE_LINK) &&
(type == USB_EXT_PROP_BINARY ||
type == USB_EXT_PROP_LE32 ||
type == USB_EXT_PROP_BE32))
ext_prop->data_len >>= 1;
ext_prop->type = type;
ret = len;
end:
if (desc->opts_mutex)
mutex_unlock(desc->opts_mutex);
return ret;
}
static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
char *page)
{
int len = ext_prop->data_len;
if (ext_prop->type == USB_EXT_PROP_UNICODE ||
ext_prop->type == USB_EXT_PROP_UNICODE_ENV ||
ext_prop->type == USB_EXT_PROP_UNICODE_LINK)
len >>= 1;
memcpy(page, ext_prop->data, len);
return len;
}
static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
const char *page, size_t len)
{
struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
char *new_data;
size_t ret_len = len;
if (page[len - 1] == '\n' || page[len - 1] == '\0')
--len;
new_data = kzalloc(len, GFP_KERNEL);
if (!new_data)
return -ENOMEM;
memcpy(new_data, page, len);
if (desc->opts_mutex)
mutex_lock(desc->opts_mutex);
kfree(ext_prop->data);
ext_prop->data = new_data;
desc->ext_prop_len -= ext_prop->data_len;
ext_prop->data_len = len;
desc->ext_prop_len += ext_prop->data_len;
if (ext_prop->type == USB_EXT_PROP_UNICODE ||
ext_prop->type == USB_EXT_PROP_UNICODE_ENV ||
ext_prop->type == USB_EXT_PROP_UNICODE_LINK) {
desc->ext_prop_len -= ext_prop->data_len;
ext_prop->data_len <<= 1;
ext_prop->data_len += 2;
desc->ext_prop_len += ext_prop->data_len;
}
if (desc->opts_mutex)
mutex_unlock(desc->opts_mutex);
return ret_len;
}
static struct usb_os_desc_ext_prop_attribute ext_prop_type =
__CONFIGFS_ATTR(type, S_IRUGO | S_IWUSR,
ext_prop_type_show, ext_prop_type_store);
static struct usb_os_desc_ext_prop_attribute ext_prop_data =
__CONFIGFS_ATTR(data, S_IRUGO | S_IWUSR,
ext_prop_data_show, ext_prop_data_store);
static struct configfs_attribute *ext_prop_attrs[] = {
&ext_prop_type.attr,
&ext_prop_data.attr,
NULL,
};
static void usb_os_desc_ext_prop_release(struct config_item *item)
{
struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
kfree(ext_prop); /* frees a whole chunk */
}
static struct configfs_item_operations ext_prop_ops = {
.release = usb_os_desc_ext_prop_release,
.show_attribute = usb_os_desc_ext_prop_attr_show,
.store_attribute = usb_os_desc_ext_prop_attr_store,
};
static struct config_item *ext_prop_make(
struct config_group *group,
const char *name)
{
struct usb_os_desc_ext_prop *ext_prop;
struct config_item_type *ext_prop_type;
struct usb_os_desc *desc;
char *vlabuf;
vla_group(data_chunk);
vla_item(data_chunk, struct usb_os_desc_ext_prop, ext_prop, 1);
vla_item(data_chunk, struct config_item_type, ext_prop_type, 1);
vlabuf = kzalloc(vla_group_size(data_chunk), GFP_KERNEL);
if (!vlabuf)
return ERR_PTR(-ENOMEM);
ext_prop = vla_ptr(vlabuf, data_chunk, ext_prop);
ext_prop_type = vla_ptr(vlabuf, data_chunk, ext_prop_type);
desc = container_of(group, struct usb_os_desc, group);
ext_prop_type->ct_item_ops = &ext_prop_ops;
ext_prop_type->ct_attrs = ext_prop_attrs;
ext_prop_type->ct_owner = desc->owner;
config_item_init_type_name(&ext_prop->item, name, ext_prop_type);
ext_prop->name = kstrdup(name, GFP_KERNEL);
if (!ext_prop->name) {
kfree(vlabuf);
return ERR_PTR(-ENOMEM);
}
desc->ext_prop_len += 14;
ext_prop->name_len = 2 * strlen(ext_prop->name) + 2;
if (desc->opts_mutex)
mutex_lock(desc->opts_mutex);
desc->ext_prop_len += ext_prop->name_len;
list_add_tail(&ext_prop->entry, &desc->ext_prop);
++desc->ext_prop_count;
if (desc->opts_mutex)
mutex_unlock(desc->opts_mutex);
return &ext_prop->item;
}
static void ext_prop_drop(struct config_group *group, struct config_item *item)
{
struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
struct usb_os_desc *desc = to_usb_os_desc(&group->cg_item);
if (desc->opts_mutex)
mutex_lock(desc->opts_mutex);
list_del(&ext_prop->entry);
--desc->ext_prop_count;
kfree(ext_prop->name);
desc->ext_prop_len -= (ext_prop->name_len + ext_prop->data_len + 14);
if (desc->opts_mutex)
mutex_unlock(desc->opts_mutex);
config_item_put(item);
}
static struct configfs_group_operations interf_grp_ops = {
.make_item = &ext_prop_make,
.drop_item = &ext_prop_drop,
};
static struct configfs_item_operations interf_item_ops = {
.show_attribute = usb_os_desc_attr_show,
.store_attribute = usb_os_desc_attr_store,
};
static ssize_t rndis_grp_compatible_id_show(struct usb_os_desc *desc,
char *page)
{
memcpy(page, desc->ext_compat_id, 8);
return 8;
}
static ssize_t rndis_grp_compatible_id_store(struct usb_os_desc *desc,
const char *page, size_t len)
{
int l;
l = min_t(int, 8, len);
if (page[l - 1] == '\n')
--l;
if (desc->opts_mutex)
mutex_lock(desc->opts_mutex);
memcpy(desc->ext_compat_id, page, l);
desc->ext_compat_id[l] = '\0';
if (desc->opts_mutex)
mutex_unlock(desc->opts_mutex);
return len;
}
static struct usb_os_desc_attribute rndis_grp_attr_compatible_id =
__CONFIGFS_ATTR(compatible_id, S_IRUGO | S_IWUSR,
rndis_grp_compatible_id_show,
rndis_grp_compatible_id_store);
static ssize_t rndis_grp_sub_compatible_id_show(struct usb_os_desc *desc,
char *page)
{
memcpy(page, desc->ext_compat_id + 8, 8);
return 8;
}
static ssize_t rndis_grp_sub_compatible_id_store(struct usb_os_desc *desc,
const char *page, size_t len)
{
int l;
l = min_t(int, 8, len);
if (page[l - 1] == '\n')
--l;
if (desc->opts_mutex)
mutex_lock(desc->opts_mutex);
memcpy(desc->ext_compat_id + 8, page, l);
desc->ext_compat_id[l + 8] = '\0';
if (desc->opts_mutex)
mutex_unlock(desc->opts_mutex);
return len;
}
static struct usb_os_desc_attribute rndis_grp_attr_sub_compatible_id =
__CONFIGFS_ATTR(sub_compatible_id, S_IRUGO | S_IWUSR,
rndis_grp_sub_compatible_id_show,
rndis_grp_sub_compatible_id_store);
static struct configfs_attribute *interf_grp_attrs[] = {
&rndis_grp_attr_compatible_id.attr,
&rndis_grp_attr_sub_compatible_id.attr,
NULL
};
int usb_os_desc_prepare_interf_dir(struct config_group *parent,
int n_interf,
struct usb_os_desc **desc,
struct module *owner)
{
struct config_group **f_default_groups, *os_desc_group,
**interface_groups;
struct config_item_type *os_desc_type, *interface_type;
vla_group(data_chunk);
vla_item(data_chunk, struct config_group *, f_default_groups, 2);
vla_item(data_chunk, struct config_group, os_desc_group, 1);
vla_item(data_chunk, struct config_group *, interface_groups,
n_interf + 1);
vla_item(data_chunk, struct config_item_type, os_desc_type, 1);
vla_item(data_chunk, struct config_item_type, interface_type, 1);
char *vlabuf = kzalloc(vla_group_size(data_chunk), GFP_KERNEL);
if (!vlabuf)
return -ENOMEM;
f_default_groups = vla_ptr(vlabuf, data_chunk, f_default_groups);
os_desc_group = vla_ptr(vlabuf, data_chunk, os_desc_group);
os_desc_type = vla_ptr(vlabuf, data_chunk, os_desc_type);
interface_groups = vla_ptr(vlabuf, data_chunk, interface_groups);
interface_type = vla_ptr(vlabuf, data_chunk, interface_type);
parent->default_groups = f_default_groups;
os_desc_type->ct_owner = owner;
config_group_init_type_name(os_desc_group, "os_desc", os_desc_type);
f_default_groups[0] = os_desc_group;
os_desc_group->default_groups = interface_groups;
interface_type->ct_item_ops = &interf_item_ops;
interface_type->ct_group_ops = &interf_grp_ops;
interface_type->ct_attrs = interf_grp_attrs;
interface_type->ct_owner = owner;
while (n_interf--) {
struct usb_os_desc *d;
d = desc[n_interf];
d->owner = owner;
config_group_init_type_name(&d->group, "", interface_type);
config_item_set_name(&d->group.cg_item, "interface.%d",
n_interf);
interface_groups[n_interf] = &d->group;
}
return 0;
}
EXPORT_SYMBOL(usb_os_desc_prepare_interf_dir);
static int configfs_do_nothing(struct usb_composite_dev *cdev) static int configfs_do_nothing(struct usb_composite_dev *cdev)
{ {
WARN_ON(1); WARN_ON(1);
...@@ -745,6 +1275,9 @@ static int configfs_do_nothing(struct usb_composite_dev *cdev) ...@@ -745,6 +1275,9 @@ static int configfs_do_nothing(struct usb_composite_dev *cdev)
int composite_dev_prepare(struct usb_composite_driver *composite, int composite_dev_prepare(struct usb_composite_driver *composite,
struct usb_composite_dev *dev); struct usb_composite_dev *dev);
int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
struct usb_ep *ep0);
static void purge_configs_funcs(struct gadget_info *gi) static void purge_configs_funcs(struct gadget_info *gi)
{ {
struct usb_configuration *c; struct usb_configuration *c;
...@@ -793,7 +1326,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget, ...@@ -793,7 +1326,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
ret = -EINVAL; ret = -EINVAL;
if (list_empty(&gi->cdev.configs)) { if (list_empty(&gi->cdev.configs)) {
pr_err("Need atleast one configuration in %s.\n", pr_err("Need at least one configuration in %s.\n",
gi->composite.name); gi->composite.name);
goto err_comp_cleanup; goto err_comp_cleanup;
} }
...@@ -804,7 +1337,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget, ...@@ -804,7 +1337,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
cfg = container_of(c, struct config_usb_cfg, c); cfg = container_of(c, struct config_usb_cfg, c);
if (list_empty(&cfg->func_list)) { if (list_empty(&cfg->func_list)) {
pr_err("Config %s/%d of %s needs atleast one function.\n", pr_err("Config %s/%d of %s needs at least one function.\n",
c->label, c->bConfigurationValue, c->label, c->bConfigurationValue,
gi->composite.name); gi->composite.name);
goto err_comp_cleanup; goto err_comp_cleanup;
...@@ -839,6 +1372,12 @@ static int configfs_composite_bind(struct usb_gadget *gadget, ...@@ -839,6 +1372,12 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id; gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id;
} }
if (gi->use_os_desc) {
cdev->use_os_string = true;
cdev->b_vendor_code = gi->b_vendor_code;
memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
}
/* Go through all configs, attach all functions */ /* Go through all configs, attach all functions */
list_for_each_entry(c, &gi->cdev.configs, list) { list_for_each_entry(c, &gi->cdev.configs, list) {
struct config_usb_cfg *cfg; struct config_usb_cfg *cfg;
...@@ -874,6 +1413,12 @@ static int configfs_composite_bind(struct usb_gadget *gadget, ...@@ -874,6 +1413,12 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
} }
usb_ep_autoconfig_reset(cdev->gadget); usb_ep_autoconfig_reset(cdev->gadget);
} }
if (cdev->use_os_string) {
ret = composite_os_desc_req_prepare(cdev, gadget->ep0);
if (ret)
goto err_purge_funcs;
}
usb_ep_autoconfig_reset(cdev->gadget); usb_ep_autoconfig_reset(cdev->gadget);
return 0; return 0;
...@@ -929,6 +1474,7 @@ static struct config_group *gadgets_make( ...@@ -929,6 +1474,7 @@ static struct config_group *gadgets_make(
gi->group.default_groups[0] = &gi->functions_group; gi->group.default_groups[0] = &gi->functions_group;
gi->group.default_groups[1] = &gi->configs_group; gi->group.default_groups[1] = &gi->configs_group;
gi->group.default_groups[2] = &gi->strings_group; gi->group.default_groups[2] = &gi->strings_group;
gi->group.default_groups[3] = &gi->os_desc_group;
config_group_init_type_name(&gi->functions_group, "functions", config_group_init_type_name(&gi->functions_group, "functions",
&functions_type); &functions_type);
...@@ -936,6 +1482,8 @@ static struct config_group *gadgets_make( ...@@ -936,6 +1482,8 @@ static struct config_group *gadgets_make(
&config_desc_type); &config_desc_type);
config_group_init_type_name(&gi->strings_group, "strings", config_group_init_type_name(&gi->strings_group, "strings",
&gadget_strings_strings_type); &gadget_strings_strings_type);
config_group_init_type_name(&gi->os_desc_group, "os_desc",
&os_desc_type);
gi->composite.bind = configfs_do_nothing; gi->composite.bind = configfs_do_nothing;
gi->composite.unbind = configfs_do_nothing; gi->composite.unbind = configfs_do_nothing;
...@@ -1005,7 +1553,7 @@ void unregister_gadget_item(struct config_item *item) ...@@ -1005,7 +1553,7 @@ void unregister_gadget_item(struct config_item *item)
unregister_gadget(gi); unregister_gadget(gi);
} }
EXPORT_SYMBOL(unregister_gadget_item); EXPORT_SYMBOL_GPL(unregister_gadget_item);
static int __init gadget_cfs_init(void) static int __init gadget_cfs_init(void)
{ {
......
#ifndef USB__GADGET__CONFIGFS__H #ifndef USB__GADGET__CONFIGFS__H
#define USB__GADGET__CONFIGFS__H #define USB__GADGET__CONFIGFS__H
#include <linux/configfs.h>
void unregister_gadget_item(struct config_item *item); void unregister_gadget_item(struct config_item *item);
int usb_os_desc_prepare_interf_dir(struct config_group *parent,
int n_interf,
struct usb_os_desc **desc,
struct module *owner);
static inline struct usb_os_desc *to_usb_os_desc(struct config_item *item)
{
return container_of(to_config_group(item), struct usb_os_desc, group);
}
#endif /* USB__GADGET__CONFIGFS__H */ #endif /* USB__GADGET__CONFIGFS__H */
...@@ -33,36 +33,11 @@ ...@@ -33,36 +33,11 @@
#include <linux/poll.h> #include <linux/poll.h>
#include "u_fs.h" #include "u_fs.h"
#include "u_f.h"
#include "configfs.h" #include "configfs.h"
#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ #define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */
/* Variable Length Array Macros **********************************************/
#define vla_group(groupname) size_t groupname##__next = 0
#define vla_group_size(groupname) groupname##__next
#define vla_item(groupname, type, name, n) \
size_t groupname##_##name##__offset = ({ \
size_t align_mask = __alignof__(type) - 1; \
size_t offset = (groupname##__next + align_mask) & ~align_mask;\
size_t size = (n) * sizeof(type); \
groupname##__next = offset + size; \
offset; \
})
#define vla_item_with_sz(groupname, type, name, n) \
size_t groupname##_##name##__sz = (n) * sizeof(type); \
size_t groupname##_##name##__offset = ({ \
size_t align_mask = __alignof__(type) - 1; \
size_t offset = (groupname##__next + align_mask) & ~align_mask;\
size_t size = groupname##_##name##__sz; \
groupname##__next = offset + size; \
offset; \
})
#define vla_ptr(ptr, groupname, name) \
((void *) ((char *)ptr + groupname##_##name##__offset))
/* Reference counter handling */ /* Reference counter handling */
static void ffs_data_get(struct ffs_data *ffs); static void ffs_data_get(struct ffs_data *ffs);
static void ffs_data_put(struct ffs_data *ffs); static void ffs_data_put(struct ffs_data *ffs);
...@@ -190,7 +165,7 @@ ffs_sb_create_file(struct super_block *sb, const char *name, void *data, ...@@ -190,7 +165,7 @@ ffs_sb_create_file(struct super_block *sb, const char *name, void *data,
/* Devices management *******************************************************/ /* Devices management *******************************************************/
DEFINE_MUTEX(ffs_lock); DEFINE_MUTEX(ffs_lock);
EXPORT_SYMBOL(ffs_lock); EXPORT_SYMBOL_GPL(ffs_lock);
static struct ffs_dev *_ffs_find_dev(const char *name); static struct ffs_dev *_ffs_find_dev(const char *name);
static struct ffs_dev *_ffs_alloc_dev(void); static struct ffs_dev *_ffs_alloc_dev(void);
...@@ -2883,7 +2858,7 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name) ...@@ -2883,7 +2858,7 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name)
return ret; return ret;
} }
EXPORT_SYMBOL(ffs_name_dev); EXPORT_SYMBOL_GPL(ffs_name_dev);
int ffs_single_dev(struct ffs_dev *dev) int ffs_single_dev(struct ffs_dev *dev)
{ {
...@@ -2900,7 +2875,7 @@ int ffs_single_dev(struct ffs_dev *dev) ...@@ -2900,7 +2875,7 @@ int ffs_single_dev(struct ffs_dev *dev)
ffs_dev_unlock(); ffs_dev_unlock();
return ret; return ret;
} }
EXPORT_SYMBOL(ffs_single_dev); EXPORT_SYMBOL_GPL(ffs_single_dev);
/* /*
* ffs_lock must be taken by the caller of this function * ffs_lock must be taken by the caller of this function
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "u_ether_configfs.h" #include "u_ether_configfs.h"
#include "u_rndis.h" #include "u_rndis.h"
#include "rndis.h" #include "rndis.h"
#include "configfs.h"
/* /*
* This function is an RNDIS Ethernet port -- a Microsoft protocol that's * This function is an RNDIS Ethernet port -- a Microsoft protocol that's
...@@ -682,6 +683,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -682,6 +683,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst); rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst);
if (cdev->use_os_string) {
f->os_desc_table = kzalloc(sizeof(*f->os_desc_table),
GFP_KERNEL);
if (!f->os_desc_table)
return PTR_ERR(f->os_desc_table);
f->os_desc_n = 1;
f->os_desc_table[0].os_desc = &rndis_opts->rndis_os_desc;
}
/* /*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind() * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry, * configurations are bound in sequence with list_for_each_entry,
...@@ -693,14 +703,16 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -693,14 +703,16 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
gether_set_gadget(rndis_opts->net, cdev->gadget); gether_set_gadget(rndis_opts->net, cdev->gadget);
status = gether_register_netdev(rndis_opts->net); status = gether_register_netdev(rndis_opts->net);
if (status) if (status)
return status; goto fail;
rndis_opts->bound = true; rndis_opts->bound = true;
} }
us = usb_gstrings_attach(cdev, rndis_strings, us = usb_gstrings_attach(cdev, rndis_strings,
ARRAY_SIZE(rndis_string_defs)); ARRAY_SIZE(rndis_string_defs));
if (IS_ERR(us)) if (IS_ERR(us)) {
return PTR_ERR(us); status = PTR_ERR(us);
goto fail;
}
rndis_control_intf.iInterface = us[0].id; rndis_control_intf.iInterface = us[0].id;
rndis_data_intf.iInterface = us[1].id; rndis_data_intf.iInterface = us[1].id;
rndis_iad_descriptor.iFunction = us[2].id; rndis_iad_descriptor.iFunction = us[2].id;
...@@ -802,6 +814,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -802,6 +814,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
kfree(f->os_desc_table);
f->os_desc_n = 0;
usb_free_all_descriptors(f); usb_free_all_descriptors(f);
if (rndis->notify_req) { if (rndis->notify_req) {
...@@ -834,7 +848,7 @@ void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net) ...@@ -834,7 +848,7 @@ void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)
opts->borrowed_net = opts->bound = true; opts->borrowed_net = opts->bound = true;
opts->net = net; opts->net = net;
} }
EXPORT_SYMBOL(rndis_borrow_net); EXPORT_SYMBOL_GPL(rndis_borrow_net);
static inline struct f_rndis_opts *to_f_rndis_opts(struct config_item *item) static inline struct f_rndis_opts *to_f_rndis_opts(struct config_item *item)
{ {
...@@ -882,16 +896,21 @@ static void rndis_free_inst(struct usb_function_instance *f) ...@@ -882,16 +896,21 @@ static void rndis_free_inst(struct usb_function_instance *f)
else else
free_netdev(opts->net); free_netdev(opts->net);
} }
kfree(opts->rndis_os_desc.group.default_groups); /* single VLA chunk */
kfree(opts); kfree(opts);
} }
static struct usb_function_instance *rndis_alloc_inst(void) static struct usb_function_instance *rndis_alloc_inst(void)
{ {
struct f_rndis_opts *opts; struct f_rndis_opts *opts;
struct usb_os_desc *descs[1];
opts = kzalloc(sizeof(*opts), GFP_KERNEL); opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts) if (!opts)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
opts->rndis_os_desc.ext_compat_id = opts->rndis_ext_compat_id;
mutex_init(&opts->lock); mutex_init(&opts->lock);
opts->func_inst.free_func_inst = rndis_free_inst; opts->func_inst.free_func_inst = rndis_free_inst;
opts->net = gether_setup_default(); opts->net = gether_setup_default();
...@@ -900,7 +919,11 @@ static struct usb_function_instance *rndis_alloc_inst(void) ...@@ -900,7 +919,11 @@ static struct usb_function_instance *rndis_alloc_inst(void)
kfree(opts); kfree(opts);
return ERR_CAST(net); return ERR_CAST(net);
} }
INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop);
descs[0] = &opts->rndis_os_desc;
usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
THIS_MODULE);
config_group_init_type_name(&opts->func_inst.group, "", config_group_init_type_name(&opts->func_inst.group, "",
&rndis_func_type); &rndis_func_type);
...@@ -925,6 +948,8 @@ static void rndis_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -925,6 +948,8 @@ static void rndis_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
struct f_rndis *rndis = func_to_rndis(f); struct f_rndis *rndis = func_to_rndis(f);
kfree(f->os_desc_table);
f->os_desc_n = 0;
usb_free_all_descriptors(f); usb_free_all_descriptors(f);
kfree(rndis->notify_req->buf); kfree(rndis->notify_req->buf);
......
...@@ -276,7 +276,7 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt) ...@@ -276,7 +276,7 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
} }
net = gether_connect(&geth->port); net = gether_connect(&geth->port);
return PTR_RET(net); return PTR_ERR_OR_ZERO(net);
} }
static void geth_disable(struct usb_function *f) static void geth_disable(struct usb_function *f)
......
...@@ -196,7 +196,7 @@ agdev_iso_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -196,7 +196,7 @@ agdev_iso_complete(struct usb_ep *ep, struct usb_request *req)
struct snd_uac2_chip *uac2 = prm->uac2; struct snd_uac2_chip *uac2 = prm->uac2;
/* i/f shutting down */ /* i/f shutting down */
if (!prm->ep_enabled) if (!prm->ep_enabled || req->status == -ESHUTDOWN)
return; return;
/* /*
...@@ -974,8 +974,6 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) ...@@ -974,8 +974,6 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
if (!prm->rbuf) { if (!prm->rbuf) {
prm->max_psize = 0; prm->max_psize = 0;
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
goto err; goto err;
} }
...@@ -984,8 +982,6 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) ...@@ -984,8 +982,6 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
if (!prm->rbuf) { if (!prm->rbuf) {
prm->max_psize = 0; prm->max_psize = 0;
dev_err(&uac2->pdev.dev,
"%s:%d Error!\n", __func__, __LINE__);
goto err; goto err;
} }
...@@ -1298,10 +1294,8 @@ static int audio_bind_config(struct usb_configuration *cfg) ...@@ -1298,10 +1294,8 @@ static int audio_bind_config(struct usb_configuration *cfg)
int res; int res;
agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL); agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL);
if (agdev_g == NULL) { if (agdev_g == NULL)
printk(KERN_ERR "Unable to allocate audio gadget\n");
return -ENOMEM; return -ENOMEM;
}
res = usb_string_ids_tab(cfg->cdev, strings_fn); res = usb_string_ids_tab(cfg->cdev, strings_fn);
if (res) if (res)
......
...@@ -1112,17 +1112,13 @@ static int fotg210_udc_probe(struct platform_device *pdev) ...@@ -1112,17 +1112,13 @@ static int fotg210_udc_probe(struct platform_device *pdev)
/* initialize udc */ /* initialize udc */
fotg210 = kzalloc(sizeof(struct fotg210_udc), GFP_KERNEL); fotg210 = kzalloc(sizeof(struct fotg210_udc), GFP_KERNEL);
if (fotg210 == NULL) { if (fotg210 == NULL)
pr_err("kzalloc error\n");
goto err_alloc; goto err_alloc;
}
for (i = 0; i < FOTG210_MAX_NUM_EP; i++) { for (i = 0; i < FOTG210_MAX_NUM_EP; i++) {
_ep[i] = kzalloc(sizeof(struct fotg210_ep), GFP_KERNEL); _ep[i] = kzalloc(sizeof(struct fotg210_ep), GFP_KERNEL);
if (_ep[i] == NULL) { if (_ep[i] == NULL)
pr_err("_ep kzalloc error\n");
goto err_alloc; goto err_alloc;
}
fotg210->ep[i] = _ep[i]; fotg210->ep[i] = _ep[i];
} }
......
...@@ -2256,10 +2256,8 @@ static int __init struct_udc_setup(struct fsl_udc *udc, ...@@ -2256,10 +2256,8 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
udc->phy_mode = pdata->phy_mode; udc->phy_mode = pdata->phy_mode;
udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL); udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
if (!udc->eps) { if (!udc->eps)
ERR("malloc fsl_ep failed\n");
return -1; return -1;
}
/* initialized QHs, take care of alignment */ /* initialized QHs, take care of alignment */
size = udc->max_ep * sizeof(struct ep_queue_head); size = udc->max_ep * sizeof(struct ep_queue_head);
...@@ -2342,10 +2340,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev) ...@@ -2342,10 +2340,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
u32 dccparams; u32 dccparams;
udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
if (udc_controller == NULL) { if (udc_controller == NULL)
ERR("malloc udc failed\n");
return -ENOMEM; return -ENOMEM;
}
pdata = dev_get_platdata(&pdev->dev); pdata = dev_get_platdata(&pdev->dev);
udc_controller->pdata = pdata; udc_controller->pdata = pdata;
......
...@@ -1400,17 +1400,13 @@ static int __init fusb300_probe(struct platform_device *pdev) ...@@ -1400,17 +1400,13 @@ static int __init fusb300_probe(struct platform_device *pdev)
/* initialize udc */ /* initialize udc */
fusb300 = kzalloc(sizeof(struct fusb300), GFP_KERNEL); fusb300 = kzalloc(sizeof(struct fusb300), GFP_KERNEL);
if (fusb300 == NULL) { if (fusb300 == NULL)
pr_err("kzalloc error\n");
goto clean_up; goto clean_up;
}
for (i = 0; i < FUSB300_MAX_NUM_EP; i++) { for (i = 0; i < FUSB300_MAX_NUM_EP; i++) {
_ep[i] = kzalloc(sizeof(struct fusb300_ep), GFP_KERNEL); _ep[i] = kzalloc(sizeof(struct fusb300_ep), GFP_KERNEL);
if (_ep[i] == NULL) { if (_ep[i] == NULL)
pr_err("_ep kzalloc error\n");
goto clean_up; goto clean_up;
}
fusb300->ep[i] = _ep[i]; fusb300->ep[i] = _ep[i];
} }
......
...@@ -143,6 +143,7 @@ static void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep) ...@@ -143,6 +143,7 @@ static void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep)
seq_printf(seq, " wedged = %d\n", ep->wedged); seq_printf(seq, " wedged = %d\n", ep->wedged);
seq_printf(seq, " callback = %d\n", ep->callback); seq_printf(seq, " callback = %d\n", ep->callback);
seq_printf(seq, " maxpacket = %d\n", ep->ep.maxpacket); seq_printf(seq, " maxpacket = %d\n", ep->ep.maxpacket);
seq_printf(seq, " maxpacket_limit = %d\n", ep->ep.maxpacket_limit);
seq_printf(seq, " bytes_per_buffer = %d\n", ep->bytes_per_buffer); seq_printf(seq, " bytes_per_buffer = %d\n", ep->bytes_per_buffer);
if (mode == 1 || mode == 3) if (mode == 1 || mode == 3)
seq_printf(seq, " nt = %d\n", seq_printf(seq, " nt = %d\n",
...@@ -1541,6 +1542,10 @@ static int gr_ep_enable(struct usb_ep *_ep, ...@@ -1541,6 +1542,10 @@ static int gr_ep_enable(struct usb_ep *_ep,
} else if (max == 0) { } else if (max == 0) {
dev_err(dev->dev, "Max payload cannot be set to 0\n"); dev_err(dev->dev, "Max payload cannot be set to 0\n");
return -EINVAL; return -EINVAL;
} else if (max > ep->ep.maxpacket_limit) {
dev_err(dev->dev, "Requested max payload %d > limit %d\n",
max, ep->ep.maxpacket_limit);
return -EINVAL;
} }
spin_lock(&ep->dev->lock); spin_lock(&ep->dev->lock);
...@@ -1679,7 +1684,7 @@ static int gr_queue_ext(struct usb_ep *_ep, struct usb_request *_req, ...@@ -1679,7 +1684,7 @@ static int gr_queue_ext(struct usb_ep *_ep, struct usb_request *_req,
if (ep->is_in) if (ep->is_in)
gr_dbgprint_request("EXTERN", ep, req); gr_dbgprint_request("EXTERN", ep, req);
ret = gr_queue(ep, req, gfp_flags); ret = gr_queue(ep, req, GFP_ATOMIC);
spin_unlock(&ep->dev->lock); spin_unlock(&ep->dev->lock);
...@@ -1985,8 +1990,8 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit) ...@@ -1985,8 +1990,8 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
INIT_LIST_HEAD(&ep->queue); INIT_LIST_HEAD(&ep->queue);
if (num == 0) { if (num == 0) {
_req = gr_alloc_request(&ep->ep, GFP_KERNEL); _req = gr_alloc_request(&ep->ep, GFP_ATOMIC);
buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_KERNEL); buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC);
if (!_req || !buf) { if (!_req || !buf) {
/* possible _req freed by gr_probe via gr_remove */ /* possible _req freed by gr_probe via gr_remove */
return -ENOMEM; return -ENOMEM;
...@@ -2020,9 +2025,7 @@ static int gr_udc_init(struct gr_udc *dev) ...@@ -2020,9 +2025,7 @@ static int gr_udc_init(struct gr_udc *dev)
u32 dmactrl_val; u32 dmactrl_val;
int i; int i;
int ret = 0; int ret = 0;
u32 *bufsizes;
u32 bufsize; u32 bufsize;
int len;
gr_set_address(dev, 0); gr_set_address(dev, 0);
...@@ -2033,19 +2036,17 @@ static int gr_udc_init(struct gr_udc *dev) ...@@ -2033,19 +2036,17 @@ static int gr_udc_init(struct gr_udc *dev)
INIT_LIST_HEAD(&dev->ep_list); INIT_LIST_HEAD(&dev->ep_list);
gr_set_ep0state(dev, GR_EP0_DISCONNECT); gr_set_ep0state(dev, GR_EP0_DISCONNECT);
bufsizes = (u32 *)of_get_property(np, "epobufsizes", &len);
len /= sizeof(u32);
for (i = 0; i < dev->nepo; i++) { for (i = 0; i < dev->nepo; i++) {
bufsize = (bufsizes && i < len) ? bufsizes[i] : 1024; if (of_property_read_u32_index(np, "epobufsizes", i, &bufsize))
bufsize = 1024;
ret = gr_ep_init(dev, i, 0, bufsize); ret = gr_ep_init(dev, i, 0, bufsize);
if (ret) if (ret)
return ret; return ret;
} }
bufsizes = (u32 *)of_get_property(np, "epibufsizes", &len);
len /= sizeof(u32);
for (i = 0; i < dev->nepi; i++) { for (i = 0; i < dev->nepi; i++) {
bufsize = (bufsizes && i < len) ? bufsizes[i] : 1024; if (of_property_read_u32_index(np, "epibufsizes", i, &bufsize))
bufsize = 1024;
ret = gr_ep_init(dev, i, 1, bufsize); ret = gr_ep_init(dev, i, 1, bufsize);
if (ret) if (ret)
return ret; return ret;
...@@ -2065,9 +2066,9 @@ static int gr_udc_init(struct gr_udc *dev) ...@@ -2065,9 +2066,9 @@ static int gr_udc_init(struct gr_udc *dev)
return 0; return 0;
} }
static int gr_remove(struct platform_device *ofdev) static int gr_remove(struct platform_device *pdev)
{ {
struct gr_udc *dev = dev_get_drvdata(&ofdev->dev); struct gr_udc *dev = platform_get_drvdata(pdev);
if (dev->added) if (dev->added)
usb_del_gadget_udc(&dev->gadget); /* Shuts everything down */ usb_del_gadget_udc(&dev->gadget); /* Shuts everything down */
...@@ -2077,7 +2078,7 @@ static int gr_remove(struct platform_device *ofdev) ...@@ -2077,7 +2078,7 @@ static int gr_remove(struct platform_device *ofdev)
gr_dfs_delete(dev); gr_dfs_delete(dev);
if (dev->desc_pool) if (dev->desc_pool)
dma_pool_destroy(dev->desc_pool); dma_pool_destroy(dev->desc_pool);
dev_set_drvdata(&ofdev->dev, NULL); platform_set_drvdata(pdev, NULL);
gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req); gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req); gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req);
...@@ -2090,7 +2091,7 @@ static int gr_request_irq(struct gr_udc *dev, int irq) ...@@ -2090,7 +2091,7 @@ static int gr_request_irq(struct gr_udc *dev, int irq)
IRQF_SHARED, driver_name, dev); IRQF_SHARED, driver_name, dev);
} }
static int gr_probe(struct platform_device *ofdev) static int gr_probe(struct platform_device *pdev)
{ {
struct gr_udc *dev; struct gr_udc *dev;
struct resource *res; struct resource *res;
...@@ -2098,30 +2099,32 @@ static int gr_probe(struct platform_device *ofdev) ...@@ -2098,30 +2099,32 @@ static int gr_probe(struct platform_device *ofdev)
int retval; int retval;
u32 status; u32 status;
dev = devm_kzalloc(&ofdev->dev, sizeof(*dev), GFP_KERNEL); dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev) if (!dev)
return -ENOMEM; return -ENOMEM;
dev->dev = &ofdev->dev; dev->dev = &pdev->dev;
res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev->dev, res); regs = devm_ioremap_resource(dev->dev, res);
if (IS_ERR(regs)) if (IS_ERR(regs))
return PTR_ERR(regs); return PTR_ERR(regs);
dev->irq = irq_of_parse_and_map(dev->dev->of_node, 0); dev->irq = platform_get_irq(pdev, 0);
if (!dev->irq) { if (dev->irq <= 0) {
dev_err(dev->dev, "No irq found\n"); dev_err(dev->dev, "No irq found\n");
return -ENODEV; return -ENODEV;
} }
/* Some core configurations has separate irqs for IN and OUT events */ /* Some core configurations has separate irqs for IN and OUT events */
dev->irqi = irq_of_parse_and_map(dev->dev->of_node, 1); dev->irqi = platform_get_irq(pdev, 1);
if (dev->irqi) { if (dev->irqi > 0) {
dev->irqo = irq_of_parse_and_map(dev->dev->of_node, 2); dev->irqo = platform_get_irq(pdev, 2);
if (!dev->irqo) { if (dev->irqo <= 0) {
dev_err(dev->dev, "Found irqi but not irqo\n"); dev_err(dev->dev, "Found irqi but not irqo\n");
return -ENODEV; return -ENODEV;
} }
} else {
dev->irqi = 0;
} }
dev->gadget.name = driver_name; dev->gadget.name = driver_name;
...@@ -2132,7 +2135,7 @@ static int gr_probe(struct platform_device *ofdev) ...@@ -2132,7 +2135,7 @@ static int gr_probe(struct platform_device *ofdev)
spin_lock_init(&dev->lock); spin_lock_init(&dev->lock);
dev->regs = regs; dev->regs = regs;
dev_set_drvdata(&ofdev->dev, dev); platform_set_drvdata(pdev, dev);
/* Determine number of endpoints and data interface mode */ /* Determine number of endpoints and data interface mode */
status = gr_read32(&dev->regs->status); status = gr_read32(&dev->regs->status);
...@@ -2204,7 +2207,7 @@ static int gr_probe(struct platform_device *ofdev) ...@@ -2204,7 +2207,7 @@ static int gr_probe(struct platform_device *ofdev)
spin_unlock(&dev->lock); spin_unlock(&dev->lock);
if (retval) if (retval)
gr_remove(ofdev); gr_remove(pdev);
return retval; return retval;
} }
......
...@@ -1494,6 +1494,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1494,6 +1494,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
*/ */
if (value == 0) { if (value == 0) {
INFO (dev, "configuration #%d\n", dev->current_config); INFO (dev, "configuration #%d\n", dev->current_config);
usb_gadget_set_state(gadget, USB_STATE_CONFIGURED);
if (dev->usermode_setup) { if (dev->usermode_setup) {
dev->setup_can_stall = 0; dev->setup_can_stall = 0;
goto delegate; goto delegate;
......
...@@ -1594,7 +1594,6 @@ static int __init m66592_probe(struct platform_device *pdev) ...@@ -1594,7 +1594,6 @@ static int __init m66592_probe(struct platform_device *pdev)
m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL); m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
if (m66592 == NULL) { if (m66592 == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
pr_err("kzalloc error\n");
goto clean_up; goto clean_up;
} }
......
...@@ -297,10 +297,8 @@ static struct mv_u3d_trb *mv_u3d_build_trb_one(struct mv_u3d_req *req, ...@@ -297,10 +297,8 @@ static struct mv_u3d_trb *mv_u3d_build_trb_one(struct mv_u3d_req *req,
u3d = req->ep->u3d; u3d = req->ep->u3d;
trb = kzalloc(sizeof(*trb), GFP_ATOMIC); trb = kzalloc(sizeof(*trb), GFP_ATOMIC);
if (!trb) { if (!trb)
dev_err(u3d->dev, "%s, trb alloc fail\n", __func__);
return NULL; return NULL;
}
/* /*
* Be careful that no _GFP_HIGHMEM is set, * Be careful that no _GFP_HIGHMEM is set,
...@@ -446,17 +444,12 @@ static int mv_u3d_req_to_trb(struct mv_u3d_req *req) ...@@ -446,17 +444,12 @@ static int mv_u3d_req_to_trb(struct mv_u3d_req *req)
trb_num++; trb_num++;
trb = kcalloc(trb_num, sizeof(*trb), GFP_ATOMIC); trb = kcalloc(trb_num, sizeof(*trb), GFP_ATOMIC);
if (!trb) { if (!trb)
dev_err(u3d->dev,
"%s, trb alloc fail\n", __func__);
return -ENOMEM; return -ENOMEM;
}
trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC); trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC);
if (!trb_hw) { if (!trb_hw) {
kfree(trb); kfree(trb);
dev_err(u3d->dev,
"%s, trb_hw alloc fail\n", __func__);
return -ENOMEM; return -ENOMEM;
} }
...@@ -1811,7 +1804,6 @@ static int mv_u3d_probe(struct platform_device *dev) ...@@ -1811,7 +1804,6 @@ static int mv_u3d_probe(struct platform_device *dev)
u3d = kzalloc(sizeof(*u3d), GFP_KERNEL); u3d = kzalloc(sizeof(*u3d), GFP_KERNEL);
if (!u3d) { if (!u3d) {
dev_err(&dev->dev, "failed to allocate memory for u3d\n");
retval = -ENOMEM; retval = -ENOMEM;
goto err_alloc_private; goto err_alloc_private;
} }
...@@ -1905,7 +1897,6 @@ static int mv_u3d_probe(struct platform_device *dev) ...@@ -1905,7 +1897,6 @@ static int mv_u3d_probe(struct platform_device *dev)
size = u3d->max_eps * sizeof(struct mv_u3d_ep) * 2; size = u3d->max_eps * sizeof(struct mv_u3d_ep) * 2;
u3d->eps = kzalloc(size, GFP_KERNEL); u3d->eps = kzalloc(size, GFP_KERNEL);
if (!u3d->eps) { if (!u3d->eps) {
dev_err(&dev->dev, "allocate ep memory failed\n");
retval = -ENOMEM; retval = -ENOMEM;
goto err_alloc_eps; goto err_alloc_eps;
} }
...@@ -1913,7 +1904,6 @@ static int mv_u3d_probe(struct platform_device *dev) ...@@ -1913,7 +1904,6 @@ static int mv_u3d_probe(struct platform_device *dev)
/* initialize ep0 status request structure */ /* initialize ep0 status request structure */
u3d->status_req = kzalloc(sizeof(struct mv_u3d_req) + 8, GFP_KERNEL); u3d->status_req = kzalloc(sizeof(struct mv_u3d_req) + 8, GFP_KERNEL);
if (!u3d->status_req) { if (!u3d->status_req) {
dev_err(&dev->dev, "allocate status_req memory failed\n");
retval = -ENOMEM; retval = -ENOMEM;
goto err_alloc_status_req; goto err_alloc_status_req;
} }
......
...@@ -1972,7 +1972,9 @@ static int net2280_stop(struct usb_gadget *_gadget, ...@@ -1972,7 +1972,9 @@ static int net2280_stop(struct usb_gadget *_gadget,
device_remove_file (&dev->pdev->dev, &dev_attr_function); device_remove_file (&dev->pdev->dev, &dev_attr_function);
device_remove_file (&dev->pdev->dev, &dev_attr_queues); device_remove_file (&dev->pdev->dev, &dev_attr_queues);
DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name); DEBUG(dev, "unregistered driver '%s'\n",
driver ? driver->driver.name : "");
return 0; return 0;
} }
......
...@@ -1904,7 +1904,6 @@ static int __init r8a66597_probe(struct platform_device *pdev) ...@@ -1904,7 +1904,6 @@ static int __init r8a66597_probe(struct platform_device *pdev)
r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL); r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL);
if (r8a66597 == NULL) { if (r8a66597 == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
dev_err(&pdev->dev, "kzalloc error\n");
goto clean_up; goto clean_up;
} }
......
...@@ -761,7 +761,7 @@ int rndis_signal_connect(int configNr) ...@@ -761,7 +761,7 @@ int rndis_signal_connect(int configNr)
return rndis_indicate_status_msg(configNr, return rndis_indicate_status_msg(configNr,
RNDIS_STATUS_MEDIA_CONNECT); RNDIS_STATUS_MEDIA_CONNECT);
} }
EXPORT_SYMBOL(rndis_signal_connect); EXPORT_SYMBOL_GPL(rndis_signal_connect);
int rndis_signal_disconnect(int configNr) int rndis_signal_disconnect(int configNr)
{ {
...@@ -770,7 +770,7 @@ int rndis_signal_disconnect(int configNr) ...@@ -770,7 +770,7 @@ int rndis_signal_disconnect(int configNr)
return rndis_indicate_status_msg(configNr, return rndis_indicate_status_msg(configNr,
RNDIS_STATUS_MEDIA_DISCONNECT); RNDIS_STATUS_MEDIA_DISCONNECT);
} }
EXPORT_SYMBOL(rndis_signal_disconnect); EXPORT_SYMBOL_GPL(rndis_signal_disconnect);
void rndis_uninit(int configNr) void rndis_uninit(int configNr)
{ {
...@@ -785,13 +785,13 @@ void rndis_uninit(int configNr) ...@@ -785,13 +785,13 @@ void rndis_uninit(int configNr)
while ((buf = rndis_get_next_response(configNr, &length))) while ((buf = rndis_get_next_response(configNr, &length)))
rndis_free_response(configNr, buf); rndis_free_response(configNr, buf);
} }
EXPORT_SYMBOL(rndis_uninit); EXPORT_SYMBOL_GPL(rndis_uninit);
void rndis_set_host_mac(int configNr, const u8 *addr) void rndis_set_host_mac(int configNr, const u8 *addr)
{ {
rndis_per_dev_params[configNr].host_mac = addr; rndis_per_dev_params[configNr].host_mac = addr;
} }
EXPORT_SYMBOL(rndis_set_host_mac); EXPORT_SYMBOL_GPL(rndis_set_host_mac);
/* /*
* Message Parser * Message Parser
...@@ -874,7 +874,7 @@ int rndis_msg_parser(u8 configNr, u8 *buf) ...@@ -874,7 +874,7 @@ int rndis_msg_parser(u8 configNr, u8 *buf)
return -ENOTSUPP; return -ENOTSUPP;
} }
EXPORT_SYMBOL(rndis_msg_parser); EXPORT_SYMBOL_GPL(rndis_msg_parser);
int rndis_register(void (*resp_avail)(void *v), void *v) int rndis_register(void (*resp_avail)(void *v), void *v)
{ {
...@@ -896,7 +896,7 @@ int rndis_register(void (*resp_avail)(void *v), void *v) ...@@ -896,7 +896,7 @@ int rndis_register(void (*resp_avail)(void *v), void *v)
return -ENODEV; return -ENODEV;
} }
EXPORT_SYMBOL(rndis_register); EXPORT_SYMBOL_GPL(rndis_register);
void rndis_deregister(int configNr) void rndis_deregister(int configNr)
{ {
...@@ -905,7 +905,7 @@ void rndis_deregister(int configNr) ...@@ -905,7 +905,7 @@ void rndis_deregister(int configNr)
if (configNr >= RNDIS_MAX_CONFIGS) return; if (configNr >= RNDIS_MAX_CONFIGS) return;
rndis_per_dev_params[configNr].used = 0; rndis_per_dev_params[configNr].used = 0;
} }
EXPORT_SYMBOL(rndis_deregister); EXPORT_SYMBOL_GPL(rndis_deregister);
int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
{ {
...@@ -919,7 +919,7 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) ...@@ -919,7 +919,7 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
return 0; return 0;
} }
EXPORT_SYMBOL(rndis_set_param_dev); EXPORT_SYMBOL_GPL(rndis_set_param_dev);
int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr) int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
{ {
...@@ -932,7 +932,7 @@ int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr) ...@@ -932,7 +932,7 @@ int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
return 0; return 0;
} }
EXPORT_SYMBOL(rndis_set_param_vendor); EXPORT_SYMBOL_GPL(rndis_set_param_vendor);
int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
{ {
...@@ -944,7 +944,7 @@ int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) ...@@ -944,7 +944,7 @@ int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
return 0; return 0;
} }
EXPORT_SYMBOL(rndis_set_param_medium); EXPORT_SYMBOL_GPL(rndis_set_param_medium);
void rndis_add_hdr(struct sk_buff *skb) void rndis_add_hdr(struct sk_buff *skb)
{ {
...@@ -959,7 +959,7 @@ void rndis_add_hdr(struct sk_buff *skb) ...@@ -959,7 +959,7 @@ void rndis_add_hdr(struct sk_buff *skb)
header->DataOffset = cpu_to_le32(36); header->DataOffset = cpu_to_le32(36);
header->DataLength = cpu_to_le32(skb->len - sizeof(*header)); header->DataLength = cpu_to_le32(skb->len - sizeof(*header));
} }
EXPORT_SYMBOL(rndis_add_hdr); EXPORT_SYMBOL_GPL(rndis_add_hdr);
void rndis_free_response(int configNr, u8 *buf) void rndis_free_response(int configNr, u8 *buf)
{ {
...@@ -976,7 +976,7 @@ void rndis_free_response(int configNr, u8 *buf) ...@@ -976,7 +976,7 @@ void rndis_free_response(int configNr, u8 *buf)
} }
} }
} }
EXPORT_SYMBOL(rndis_free_response); EXPORT_SYMBOL_GPL(rndis_free_response);
u8 *rndis_get_next_response(int configNr, u32 *length) u8 *rndis_get_next_response(int configNr, u32 *length)
{ {
...@@ -998,7 +998,7 @@ u8 *rndis_get_next_response(int configNr, u32 *length) ...@@ -998,7 +998,7 @@ u8 *rndis_get_next_response(int configNr, u32 *length)
return NULL; return NULL;
} }
EXPORT_SYMBOL(rndis_get_next_response); EXPORT_SYMBOL_GPL(rndis_get_next_response);
static rndis_resp_t *rndis_add_response(int configNr, u32 length) static rndis_resp_t *rndis_add_response(int configNr, u32 length)
{ {
...@@ -1042,7 +1042,7 @@ int rndis_rm_hdr(struct gether *port, ...@@ -1042,7 +1042,7 @@ int rndis_rm_hdr(struct gether *port,
skb_queue_tail(list, skb); skb_queue_tail(list, skb);
return 0; return 0;
} }
EXPORT_SYMBOL(rndis_rm_hdr); EXPORT_SYMBOL_GPL(rndis_rm_hdr);
#ifdef CONFIG_USB_GADGET_DEBUG_FILES #ifdef CONFIG_USB_GADGET_DEBUG_FILES
......
...@@ -117,7 +117,8 @@ static int dprintk(int level, const char *fmt, ...) ...@@ -117,7 +117,8 @@ static int dprintk(int level, const char *fmt, ...)
sizeof(printk_buf)-len, fmt, args); sizeof(printk_buf)-len, fmt, args);
va_end(args); va_end(args);
return pr_debug("%s", printk_buf); pr_debug("%s", printk_buf);
return len;
} }
#else #else
static int dprintk(int level, const char *fmt, ...) static int dprintk(int level, const char *fmt, ...)
......
...@@ -43,7 +43,7 @@ struct usb_interface_descriptor fsg_intf_desc = { ...@@ -43,7 +43,7 @@ struct usb_interface_descriptor fsg_intf_desc = {
.bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */
.iInterface = FSG_STRING_INTERFACE, .iInterface = FSG_STRING_INTERFACE,
}; };
EXPORT_SYMBOL(fsg_intf_desc); EXPORT_SYMBOL_GPL(fsg_intf_desc);
/* /*
* Three full-speed endpoint descriptors: bulk-in, bulk-out, and * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
...@@ -58,7 +58,7 @@ struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = { ...@@ -58,7 +58,7 @@ struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
/* wMaxPacketSize set by autoconfiguration */ /* wMaxPacketSize set by autoconfiguration */
}; };
EXPORT_SYMBOL(fsg_fs_bulk_in_desc); EXPORT_SYMBOL_GPL(fsg_fs_bulk_in_desc);
struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = { struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
...@@ -68,7 +68,7 @@ struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = { ...@@ -68,7 +68,7 @@ struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
/* wMaxPacketSize set by autoconfiguration */ /* wMaxPacketSize set by autoconfiguration */
}; };
EXPORT_SYMBOL(fsg_fs_bulk_out_desc); EXPORT_SYMBOL_GPL(fsg_fs_bulk_out_desc);
struct usb_descriptor_header *fsg_fs_function[] = { struct usb_descriptor_header *fsg_fs_function[] = {
(struct usb_descriptor_header *) &fsg_intf_desc, (struct usb_descriptor_header *) &fsg_intf_desc,
...@@ -76,7 +76,7 @@ struct usb_descriptor_header *fsg_fs_function[] = { ...@@ -76,7 +76,7 @@ struct usb_descriptor_header *fsg_fs_function[] = {
(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
NULL, NULL,
}; };
EXPORT_SYMBOL(fsg_fs_function); EXPORT_SYMBOL_GPL(fsg_fs_function);
/* /*
...@@ -95,7 +95,7 @@ struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = { ...@@ -95,7 +95,7 @@ struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512), .wMaxPacketSize = cpu_to_le16(512),
}; };
EXPORT_SYMBOL(fsg_hs_bulk_in_desc); EXPORT_SYMBOL_GPL(fsg_hs_bulk_in_desc);
struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = { struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
...@@ -106,7 +106,7 @@ struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = { ...@@ -106,7 +106,7 @@ struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = {
.wMaxPacketSize = cpu_to_le16(512), .wMaxPacketSize = cpu_to_le16(512),
.bInterval = 1, /* NAK every 1 uframe */ .bInterval = 1, /* NAK every 1 uframe */
}; };
EXPORT_SYMBOL(fsg_hs_bulk_out_desc); EXPORT_SYMBOL_GPL(fsg_hs_bulk_out_desc);
struct usb_descriptor_header *fsg_hs_function[] = { struct usb_descriptor_header *fsg_hs_function[] = {
...@@ -115,7 +115,7 @@ struct usb_descriptor_header *fsg_hs_function[] = { ...@@ -115,7 +115,7 @@ struct usb_descriptor_header *fsg_hs_function[] = {
(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
NULL, NULL,
}; };
EXPORT_SYMBOL(fsg_hs_function); EXPORT_SYMBOL_GPL(fsg_hs_function);
struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = { struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
...@@ -125,7 +125,7 @@ struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = { ...@@ -125,7 +125,7 @@ struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024), .wMaxPacketSize = cpu_to_le16(1024),
}; };
EXPORT_SYMBOL(fsg_ss_bulk_in_desc); EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_desc);
struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
.bLength = sizeof(fsg_ss_bulk_in_comp_desc), .bLength = sizeof(fsg_ss_bulk_in_comp_desc),
...@@ -133,7 +133,7 @@ struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { ...@@ -133,7 +133,7 @@ struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
/*.bMaxBurst = DYNAMIC, */ /*.bMaxBurst = DYNAMIC, */
}; };
EXPORT_SYMBOL(fsg_ss_bulk_in_comp_desc); EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_comp_desc);
struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = { struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
...@@ -143,7 +143,7 @@ struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = { ...@@ -143,7 +143,7 @@ struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024), .wMaxPacketSize = cpu_to_le16(1024),
}; };
EXPORT_SYMBOL(fsg_ss_bulk_out_desc); EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_desc);
struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
.bLength = sizeof(fsg_ss_bulk_in_comp_desc), .bLength = sizeof(fsg_ss_bulk_in_comp_desc),
...@@ -151,7 +151,7 @@ struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { ...@@ -151,7 +151,7 @@ struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
/*.bMaxBurst = DYNAMIC, */ /*.bMaxBurst = DYNAMIC, */
}; };
EXPORT_SYMBOL(fsg_ss_bulk_out_comp_desc); EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_comp_desc);
struct usb_descriptor_header *fsg_ss_function[] = { struct usb_descriptor_header *fsg_ss_function[] = {
(struct usb_descriptor_header *) &fsg_intf_desc, (struct usb_descriptor_header *) &fsg_intf_desc,
...@@ -161,7 +161,7 @@ struct usb_descriptor_header *fsg_ss_function[] = { ...@@ -161,7 +161,7 @@ struct usb_descriptor_header *fsg_ss_function[] = {
(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
NULL, NULL,
}; };
EXPORT_SYMBOL(fsg_ss_function); EXPORT_SYMBOL_GPL(fsg_ss_function);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -179,7 +179,7 @@ void fsg_lun_close(struct fsg_lun *curlun) ...@@ -179,7 +179,7 @@ void fsg_lun_close(struct fsg_lun *curlun)
curlun->filp = NULL; curlun->filp = NULL;
} }
} }
EXPORT_SYMBOL(fsg_lun_close); EXPORT_SYMBOL_GPL(fsg_lun_close);
int fsg_lun_open(struct fsg_lun *curlun, const char *filename) int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
{ {
...@@ -278,7 +278,7 @@ int fsg_lun_open(struct fsg_lun *curlun, const char *filename) ...@@ -278,7 +278,7 @@ int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
fput(filp); fput(filp);
return rc; return rc;
} }
EXPORT_SYMBOL(fsg_lun_open); EXPORT_SYMBOL_GPL(fsg_lun_open);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -295,7 +295,7 @@ int fsg_lun_fsync_sub(struct fsg_lun *curlun) ...@@ -295,7 +295,7 @@ int fsg_lun_fsync_sub(struct fsg_lun *curlun)
return 0; return 0;
return vfs_fsync(filp, 1); return vfs_fsync(filp, 1);
} }
EXPORT_SYMBOL(fsg_lun_fsync_sub); EXPORT_SYMBOL_GPL(fsg_lun_fsync_sub);
void store_cdrom_address(u8 *dest, int msf, u32 addr) void store_cdrom_address(u8 *dest, int msf, u32 addr)
{ {
...@@ -314,7 +314,7 @@ void store_cdrom_address(u8 *dest, int msf, u32 addr) ...@@ -314,7 +314,7 @@ void store_cdrom_address(u8 *dest, int msf, u32 addr)
put_unaligned_be32(addr, dest); put_unaligned_be32(addr, dest);
} }
} }
EXPORT_SYMBOL(store_cdrom_address); EXPORT_SYMBOL_GPL(store_cdrom_address);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -325,13 +325,13 @@ ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf) ...@@ -325,13 +325,13 @@ ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf)
? curlun->ro ? curlun->ro
: curlun->initially_ro); : curlun->initially_ro);
} }
EXPORT_SYMBOL(fsg_show_ro); EXPORT_SYMBOL_GPL(fsg_show_ro);
ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf) ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf)
{ {
return sprintf(buf, "%u\n", curlun->nofua); return sprintf(buf, "%u\n", curlun->nofua);
} }
EXPORT_SYMBOL(fsg_show_nofua); EXPORT_SYMBOL_GPL(fsg_show_nofua);
ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
char *buf) char *buf)
...@@ -357,19 +357,19 @@ ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ...@@ -357,19 +357,19 @@ ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
up_read(filesem); up_read(filesem);
return rc; return rc;
} }
EXPORT_SYMBOL(fsg_show_file); EXPORT_SYMBOL_GPL(fsg_show_file);
ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf) ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf)
{ {
return sprintf(buf, "%u\n", curlun->cdrom); return sprintf(buf, "%u\n", curlun->cdrom);
} }
EXPORT_SYMBOL(fsg_show_cdrom); EXPORT_SYMBOL_GPL(fsg_show_cdrom);
ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf) ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf)
{ {
return sprintf(buf, "%u\n", curlun->removable); return sprintf(buf, "%u\n", curlun->removable);
} }
EXPORT_SYMBOL(fsg_show_removable); EXPORT_SYMBOL_GPL(fsg_show_removable);
/* /*
* The caller must hold fsg->filesem for reading when calling this function. * The caller must hold fsg->filesem for reading when calling this function.
...@@ -410,7 +410,7 @@ ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, ...@@ -410,7 +410,7 @@ ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem,
return rc; return rc;
} }
EXPORT_SYMBOL(fsg_store_ro); EXPORT_SYMBOL_GPL(fsg_store_ro);
ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count) ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count)
{ {
...@@ -429,7 +429,7 @@ ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count) ...@@ -429,7 +429,7 @@ ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count)
return count; return count;
} }
EXPORT_SYMBOL(fsg_store_nofua); EXPORT_SYMBOL_GPL(fsg_store_nofua);
ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -460,7 +460,7 @@ ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, ...@@ -460,7 +460,7 @@ ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
up_write(filesem); up_write(filesem);
return (rc < 0 ? rc : count); return (rc < 0 ? rc : count);
} }
EXPORT_SYMBOL(fsg_store_file); EXPORT_SYMBOL_GPL(fsg_store_file);
ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem, ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -483,7 +483,7 @@ ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem, ...@@ -483,7 +483,7 @@ ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
return ret; return ret;
} }
EXPORT_SYMBOL(fsg_store_cdrom); EXPORT_SYMBOL_GPL(fsg_store_cdrom);
ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf, ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
size_t count) size_t count)
...@@ -499,6 +499,6 @@ ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf, ...@@ -499,6 +499,6 @@ ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
return count; return count;
} }
EXPORT_SYMBOL(fsg_store_removable); EXPORT_SYMBOL_GPL(fsg_store_removable);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -1383,10 +1383,8 @@ static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg) ...@@ -1383,10 +1383,8 @@ static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
struct usbg_nacl *nacl; struct usbg_nacl *nacl;
nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL); nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
if (!nacl) { if (!nacl)
printk(KERN_ERR "Unable to allocate struct usbg_nacl\n");
return NULL; return NULL;
}
return &nacl->se_node_acl; return &nacl->se_node_acl;
} }
...@@ -1561,10 +1559,8 @@ static struct se_portal_group *usbg_make_tpg( ...@@ -1561,10 +1559,8 @@ static struct se_portal_group *usbg_make_tpg(
} }
tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL); tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL);
if (!tpg) { if (!tpg)
printk(KERN_ERR "Unable to allocate struct usbg_tpg");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
mutex_init(&tpg->tpg_mutex); mutex_init(&tpg->tpg_mutex);
atomic_set(&tpg->tpg_port_count, 0); atomic_set(&tpg->tpg_port_count, 0);
tpg->workqueue = alloc_workqueue("tcm_usb_gadget", 0, 1); tpg->workqueue = alloc_workqueue("tcm_usb_gadget", 0, 1);
...@@ -1613,10 +1609,8 @@ static struct se_wwn *usbg_make_tport( ...@@ -1613,10 +1609,8 @@ static struct se_wwn *usbg_make_tport(
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
tport = kzalloc(sizeof(struct usbg_tport), GFP_KERNEL); tport = kzalloc(sizeof(struct usbg_tport), GFP_KERNEL);
if (!(tport)) { if (!(tport))
printk(KERN_ERR "Unable to allocate struct usbg_tport");
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
tport->tport_wwpn = wwpn; tport->tport_wwpn = wwpn;
snprintf(tport->tport_name, sizeof(tport->tport_name), "%s", wnn_name); snprintf(tport->tport_name, sizeof(tport->tport_name), "%s", wnn_name);
return &tport->tport_wwn; return &tport->tport_wwn;
...@@ -1727,10 +1721,8 @@ static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name) ...@@ -1727,10 +1721,8 @@ static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
ret = -ENOMEM; ret = -ENOMEM;
tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL); tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL);
if (!tv_nexus) { if (!tv_nexus)
pr_err("Unable to allocate struct tcm_vhost_nexus\n");
goto err_unlock; goto err_unlock;
}
tv_nexus->tvn_se_sess = transport_init_session(TARGET_PROT_NORMAL); tv_nexus->tvn_se_sess = transport_init_session(TARGET_PROT_NORMAL);
if (IS_ERR(tv_nexus->tvn_se_sess)) if (IS_ERR(tv_nexus->tvn_se_sess))
goto err_free; goto err_free;
......
...@@ -818,7 +818,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, ...@@ -818,7 +818,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
return dev; return dev;
} }
EXPORT_SYMBOL(gether_setup_name); EXPORT_SYMBOL_GPL(gether_setup_name);
struct net_device *gether_setup_name_default(const char *netname) struct net_device *gether_setup_name_default(const char *netname)
{ {
...@@ -855,7 +855,7 @@ struct net_device *gether_setup_name_default(const char *netname) ...@@ -855,7 +855,7 @@ struct net_device *gether_setup_name_default(const char *netname)
return net; return net;
} }
EXPORT_SYMBOL(gether_setup_name_default); EXPORT_SYMBOL_GPL(gether_setup_name_default);
int gether_register_netdev(struct net_device *net) int gether_register_netdev(struct net_device *net)
{ {
...@@ -893,7 +893,7 @@ int gether_register_netdev(struct net_device *net) ...@@ -893,7 +893,7 @@ int gether_register_netdev(struct net_device *net)
return status; return status;
} }
EXPORT_SYMBOL(gether_register_netdev); EXPORT_SYMBOL_GPL(gether_register_netdev);
void gether_set_gadget(struct net_device *net, struct usb_gadget *g) void gether_set_gadget(struct net_device *net, struct usb_gadget *g)
{ {
...@@ -903,7 +903,7 @@ void gether_set_gadget(struct net_device *net, struct usb_gadget *g) ...@@ -903,7 +903,7 @@ void gether_set_gadget(struct net_device *net, struct usb_gadget *g)
dev->gadget = g; dev->gadget = g;
SET_NETDEV_DEV(net, &g->dev); SET_NETDEV_DEV(net, &g->dev);
} }
EXPORT_SYMBOL(gether_set_gadget); EXPORT_SYMBOL_GPL(gether_set_gadget);
int gether_set_dev_addr(struct net_device *net, const char *dev_addr) int gether_set_dev_addr(struct net_device *net, const char *dev_addr)
{ {
...@@ -916,7 +916,7 @@ int gether_set_dev_addr(struct net_device *net, const char *dev_addr) ...@@ -916,7 +916,7 @@ int gether_set_dev_addr(struct net_device *net, const char *dev_addr)
memcpy(dev->dev_mac, new_addr, ETH_ALEN); memcpy(dev->dev_mac, new_addr, ETH_ALEN);
return 0; return 0;
} }
EXPORT_SYMBOL(gether_set_dev_addr); EXPORT_SYMBOL_GPL(gether_set_dev_addr);
int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len) int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len)
{ {
...@@ -925,7 +925,7 @@ int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len) ...@@ -925,7 +925,7 @@ int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len)
dev = netdev_priv(net); dev = netdev_priv(net);
return get_ether_addr_str(dev->dev_mac, dev_addr, len); return get_ether_addr_str(dev->dev_mac, dev_addr, len);
} }
EXPORT_SYMBOL(gether_get_dev_addr); EXPORT_SYMBOL_GPL(gether_get_dev_addr);
int gether_set_host_addr(struct net_device *net, const char *host_addr) int gether_set_host_addr(struct net_device *net, const char *host_addr)
{ {
...@@ -938,7 +938,7 @@ int gether_set_host_addr(struct net_device *net, const char *host_addr) ...@@ -938,7 +938,7 @@ int gether_set_host_addr(struct net_device *net, const char *host_addr)
memcpy(dev->host_mac, new_addr, ETH_ALEN); memcpy(dev->host_mac, new_addr, ETH_ALEN);
return 0; return 0;
} }
EXPORT_SYMBOL(gether_set_host_addr); EXPORT_SYMBOL_GPL(gether_set_host_addr);
int gether_get_host_addr(struct net_device *net, char *host_addr, int len) int gether_get_host_addr(struct net_device *net, char *host_addr, int len)
{ {
...@@ -947,7 +947,7 @@ int gether_get_host_addr(struct net_device *net, char *host_addr, int len) ...@@ -947,7 +947,7 @@ int gether_get_host_addr(struct net_device *net, char *host_addr, int len)
dev = netdev_priv(net); dev = netdev_priv(net);
return get_ether_addr_str(dev->host_mac, host_addr, len); return get_ether_addr_str(dev->host_mac, host_addr, len);
} }
EXPORT_SYMBOL(gether_get_host_addr); EXPORT_SYMBOL_GPL(gether_get_host_addr);
int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len) int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len)
{ {
...@@ -961,7 +961,7 @@ int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len) ...@@ -961,7 +961,7 @@ int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len)
return strlen(host_addr); return strlen(host_addr);
} }
EXPORT_SYMBOL(gether_get_host_addr_cdc); EXPORT_SYMBOL_GPL(gether_get_host_addr_cdc);
void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN]) void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN])
{ {
...@@ -970,7 +970,7 @@ void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN]) ...@@ -970,7 +970,7 @@ void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN])
dev = netdev_priv(net); dev = netdev_priv(net);
memcpy(host_mac, dev->host_mac, ETH_ALEN); memcpy(host_mac, dev->host_mac, ETH_ALEN);
} }
EXPORT_SYMBOL(gether_get_host_addr_u8); EXPORT_SYMBOL_GPL(gether_get_host_addr_u8);
void gether_set_qmult(struct net_device *net, unsigned qmult) void gether_set_qmult(struct net_device *net, unsigned qmult)
{ {
...@@ -979,7 +979,7 @@ void gether_set_qmult(struct net_device *net, unsigned qmult) ...@@ -979,7 +979,7 @@ void gether_set_qmult(struct net_device *net, unsigned qmult)
dev = netdev_priv(net); dev = netdev_priv(net);
dev->qmult = qmult; dev->qmult = qmult;
} }
EXPORT_SYMBOL(gether_set_qmult); EXPORT_SYMBOL_GPL(gether_set_qmult);
unsigned gether_get_qmult(struct net_device *net) unsigned gether_get_qmult(struct net_device *net)
{ {
...@@ -988,7 +988,7 @@ unsigned gether_get_qmult(struct net_device *net) ...@@ -988,7 +988,7 @@ unsigned gether_get_qmult(struct net_device *net)
dev = netdev_priv(net); dev = netdev_priv(net);
return dev->qmult; return dev->qmult;
} }
EXPORT_SYMBOL(gether_get_qmult); EXPORT_SYMBOL_GPL(gether_get_qmult);
int gether_get_ifname(struct net_device *net, char *name, int len) int gether_get_ifname(struct net_device *net, char *name, int len)
{ {
...@@ -997,7 +997,7 @@ int gether_get_ifname(struct net_device *net, char *name, int len) ...@@ -997,7 +997,7 @@ int gether_get_ifname(struct net_device *net, char *name, int len)
rtnl_unlock(); rtnl_unlock();
return strlen(name); return strlen(name);
} }
EXPORT_SYMBOL(gether_get_ifname); EXPORT_SYMBOL_GPL(gether_get_ifname);
/** /**
* gether_cleanup - remove Ethernet-over-USB device * gether_cleanup - remove Ethernet-over-USB device
...@@ -1014,7 +1014,7 @@ void gether_cleanup(struct eth_dev *dev) ...@@ -1014,7 +1014,7 @@ void gether_cleanup(struct eth_dev *dev)
flush_work(&dev->work); flush_work(&dev->work);
free_netdev(dev->net); free_netdev(dev->net);
} }
EXPORT_SYMBOL(gether_cleanup); EXPORT_SYMBOL_GPL(gether_cleanup);
/** /**
* gether_connect - notify network layer that USB link is active * gether_connect - notify network layer that USB link is active
...@@ -1095,7 +1095,7 @@ struct net_device *gether_connect(struct gether *link) ...@@ -1095,7 +1095,7 @@ struct net_device *gether_connect(struct gether *link)
return ERR_PTR(result); return ERR_PTR(result);
return dev->net; return dev->net;
} }
EXPORT_SYMBOL(gether_connect); EXPORT_SYMBOL_GPL(gether_connect);
/** /**
* gether_disconnect - notify network layer that USB link is inactive * gether_disconnect - notify network layer that USB link is inactive
...@@ -1166,7 +1166,7 @@ void gether_disconnect(struct gether *link) ...@@ -1166,7 +1166,7 @@ void gether_disconnect(struct gether *link)
dev->port_usb = NULL; dev->port_usb = NULL;
spin_unlock(&dev->lock); spin_unlock(&dev->lock);
} }
EXPORT_SYMBOL(gether_disconnect); EXPORT_SYMBOL_GPL(gether_disconnect);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell"); MODULE_AUTHOR("David Brownell");
...@@ -29,4 +29,4 @@ struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len) ...@@ -29,4 +29,4 @@ struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len)
} }
return req; return req;
} }
EXPORT_SYMBOL(alloc_ep_req); EXPORT_SYMBOL_GPL(alloc_ep_req);
...@@ -16,6 +16,32 @@ ...@@ -16,6 +16,32 @@
#ifndef __U_F_H__ #ifndef __U_F_H__
#define __U_F_H__ #define __U_F_H__
/* Variable Length Array Macros **********************************************/
#define vla_group(groupname) size_t groupname##__next = 0
#define vla_group_size(groupname) groupname##__next
#define vla_item(groupname, type, name, n) \
size_t groupname##_##name##__offset = ({ \
size_t align_mask = __alignof__(type) - 1; \
size_t offset = (groupname##__next + align_mask) & ~align_mask;\
size_t size = (n) * sizeof(type); \
groupname##__next = offset + size; \
offset; \
})
#define vla_item_with_sz(groupname, type, name, n) \
size_t groupname##_##name##__sz = (n) * sizeof(type); \
size_t groupname##_##name##__offset = ({ \
size_t align_mask = __alignof__(type) - 1; \
size_t offset = (groupname##__next + align_mask) & ~align_mask;\
size_t size = groupname##_##name##__sz; \
groupname##__next = offset + size; \
offset; \
})
#define vla_ptr(ptr, groupname, name) \
((void *) ((char *)ptr + groupname##_##name##__offset))
struct usb_ep; struct usb_ep;
struct usb_request; struct usb_request;
......
/*
* u_os_desc.h
*
* Utility definitions for "OS Descriptors" support
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __U_OS_DESC_H__
#define __U_OS_DESC_H__
#include <asm/unaligned.h>
#include <linux/nls.h>
#define USB_EXT_PROP_DW_SIZE 0
#define USB_EXT_PROP_DW_PROPERTY_DATA_TYPE 4
#define USB_EXT_PROP_W_PROPERTY_NAME_LENGTH 8
#define USB_EXT_PROP_B_PROPERTY_NAME 10
#define USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH 10
#define USB_EXT_PROP_B_PROPERTY_DATA 14
#define USB_EXT_PROP_RESERVED 0
#define USB_EXT_PROP_UNICODE 1
#define USB_EXT_PROP_UNICODE_ENV 2
#define USB_EXT_PROP_BINARY 3
#define USB_EXT_PROP_LE32 4
#define USB_EXT_PROP_BE32 5
#define USB_EXT_PROP_UNICODE_LINK 6
#define USB_EXT_PROP_UNICODE_MULTI 7
static inline void usb_ext_prop_put_size(u8 *buf, int dw_size)
{
put_unaligned_le32(dw_size, &buf[USB_EXT_PROP_DW_SIZE]);
}
static inline void usb_ext_prop_put_type(u8 *buf, int type)
{
put_unaligned_le32(type, &buf[USB_EXT_PROP_DW_PROPERTY_DATA_TYPE]);
}
static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
{
int result;
put_unaligned_le16(pnl, &buf[USB_EXT_PROP_W_PROPERTY_NAME_LENGTH]);
result = utf8s_to_utf16s(name, strlen(name), UTF16_LITTLE_ENDIAN,
(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_NAME], pnl - 2);
if (result < 0)
return result;
put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl]);
return pnl;
}
static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data,
int data_len)
{
put_unaligned_le32(data_len,
&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
memcpy(&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl], data, data_len);
}
static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
int data_len)
{
int result;
put_unaligned_le32(data_len,
&buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN,
(wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl],
data_len - 2);
if (result < 0)
return result;
put_unaligned_le16(0,
&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len]);
return data_len;
}
#endif /* __U_OS_DESC_H__ */
...@@ -26,6 +26,9 @@ struct f_rndis_opts { ...@@ -26,6 +26,9 @@ struct f_rndis_opts {
bool bound; bool bound;
bool borrowed_net; bool borrowed_net;
struct usb_os_desc rndis_os_desc;
char rndis_ext_compat_id[16];
/* /*
* Read/write access to configfs attributes is handled by configfs. * Read/write access to configfs attributes is handled by configfs.
* *
......
...@@ -428,6 +428,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ...@@ -428,6 +428,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
list_for_each_entry(udc, &udc_list, list) list_for_each_entry(udc, &udc_list, list)
if (udc->driver == driver) { if (udc->driver == driver) {
usb_gadget_remove_driver(udc); usb_gadget_remove_driver(udc);
usb_gadget_set_state(udc->gadget,
USB_STATE_NOTATTACHED);
ret = 0; ret = 0;
break; break;
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <media/v4l2-common.h>
#include <media/videobuf2-vmalloc.h> #include <media/videobuf2-vmalloc.h>
#include "uvc.h" #include "uvc.h"
...@@ -136,6 +137,8 @@ static int uvc_queue_init(struct uvc_video_queue *queue, ...@@ -136,6 +137,8 @@ static int uvc_queue_init(struct uvc_video_queue *queue,
queue->queue.buf_struct_size = sizeof(struct uvc_buffer); queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
queue->queue.ops = &uvc_queue_qops; queue->queue.ops = &uvc_queue_qops;
queue->queue.mem_ops = &vb2_vmalloc_memops; queue->queue.mem_ops = &vb2_vmalloc_memops;
queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
| V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
ret = vb2_queue_init(&queue->queue); ret = vb2_queue_init(&queue->queue);
if (ret) if (ret)
return ret; return ret;
...@@ -379,14 +382,9 @@ static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, ...@@ -379,14 +382,9 @@ static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
else else
nextbuf = NULL; nextbuf = NULL;
/* buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
* FIXME: with videobuf2, the sequence number or timestamp fields
* are valid only for video capture devices and the UVC gadget usually
* is a video output device. Keeping these until the specs are clear on
* this aspect.
*/
buf->buf.v4l2_buf.sequence = queue->sequence++; buf->buf.v4l2_buf.sequence = queue->sequence++;
do_gettimeofday(&buf->buf.v4l2_buf.timestamp); v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp);
vb2_set_plane_payload(&buf->buf, 0, buf->bytesused); vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE); vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
......
...@@ -170,7 +170,6 @@ config USB_EHCI_MSM ...@@ -170,7 +170,6 @@ config USB_EHCI_MSM
tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller" tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller"
depends on ARCH_MSM depends on ARCH_MSM
select USB_EHCI_ROOT_HUB_TT select USB_EHCI_ROOT_HUB_TT
select USB_MSM_OTG
---help--- ---help---
Enables support for the USB Host controller present on the Enables support for the USB Host controller present on the
Qualcomm chipsets. Root Hub has inbuilt TT. Qualcomm chipsets. Root Hub has inbuilt TT.
......
...@@ -76,7 +76,7 @@ config USB_MUSB_TUSB6010 ...@@ -76,7 +76,7 @@ config USB_MUSB_TUSB6010
config USB_MUSB_OMAP2PLUS config USB_MUSB_OMAP2PLUS
tristate "OMAP2430 and onwards" tristate "OMAP2430 and onwards"
depends on ARCH_OMAP2PLUS depends on ARCH_OMAP2PLUS && USB
select GENERIC_PHY select GENERIC_PHY
config USB_MUSB_AM35X config USB_MUSB_AM35X
...@@ -141,10 +141,11 @@ config USB_TI_CPPI_DMA ...@@ -141,10 +141,11 @@ config USB_TI_CPPI_DMA
config USB_TI_CPPI41_DMA config USB_TI_CPPI41_DMA
bool 'TI CPPI 4.1 (AM335x)' bool 'TI CPPI 4.1 (AM335x)'
depends on ARCH_OMAP depends on ARCH_OMAP
select TI_CPPI41
config USB_TUSB_OMAP_DMA config USB_TUSB_OMAP_DMA
bool 'TUSB 6010' bool 'TUSB 6010'
depends on USB_MUSB_TUSB6010 depends on USB_MUSB_TUSB6010 = USB_MUSB_HDRC # both built-in or both modules
depends on ARCH_OMAP depends on ARCH_OMAP
help help
Enable DMA transfers on TUSB 6010 when OMAP DMA is available. Enable DMA transfers on TUSB 6010 when OMAP DMA is available.
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include <linux/platform_data/usb-omap.h> #include <linux/platform_data/usb-omap.h>
#include "musb_core.h" #include "musb_core.h"
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
struct am35x_glue { struct am35x_glue {
struct device *dev; struct device *dev;
struct platform_device *musb; struct platform_device *musb;
struct platform_device *phy;
struct clk *phy_clk; struct clk *phy_clk;
struct clk *clk; struct clk *clk;
}; };
...@@ -360,7 +361,6 @@ static int am35x_musb_init(struct musb *musb) ...@@ -360,7 +361,6 @@ static int am35x_musb_init(struct musb *musb)
if (!rev) if (!rev)
return -ENODEV; return -ENODEV;
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv)) if (IS_ERR_OR_NULL(musb->xceiv))
return -EPROBE_DEFER; return -EPROBE_DEFER;
...@@ -402,7 +402,6 @@ static int am35x_musb_exit(struct musb *musb) ...@@ -402,7 +402,6 @@ static int am35x_musb_exit(struct musb *musb)
data->set_phy_power(0); data->set_phy_power(0);
usb_put_phy(musb->xceiv); usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0; return 0;
} }
...@@ -505,6 +504,9 @@ static int am35x_probe(struct platform_device *pdev) ...@@ -505,6 +504,9 @@ static int am35x_probe(struct platform_device *pdev)
pdata->platform_ops = &am35x_ops; pdata->platform_ops = &am35x_ops;
glue->phy = usb_phy_generic_register();
if (IS_ERR(glue->phy))
goto err7;
platform_set_drvdata(pdev, glue); platform_set_drvdata(pdev, glue);
pinfo = am35x_dev_info; pinfo = am35x_dev_info;
...@@ -518,11 +520,14 @@ static int am35x_probe(struct platform_device *pdev) ...@@ -518,11 +520,14 @@ static int am35x_probe(struct platform_device *pdev)
if (IS_ERR(musb)) { if (IS_ERR(musb)) {
ret = PTR_ERR(musb); ret = PTR_ERR(musb);
dev_err(&pdev->dev, "failed to register musb device: %d\n", ret); dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
goto err7; goto err8;
} }
return 0; return 0;
err8:
usb_phy_generic_unregister(glue->phy);
err7: err7:
clk_disable(clk); clk_disable(clk);
...@@ -547,6 +552,7 @@ static int am35x_remove(struct platform_device *pdev) ...@@ -547,6 +552,7 @@ static int am35x_remove(struct platform_device *pdev)
struct am35x_glue *glue = platform_get_drvdata(pdev); struct am35x_glue *glue = platform_get_drvdata(pdev);
platform_device_unregister(glue->musb); platform_device_unregister(glue->musb);
usb_phy_generic_unregister(glue->phy);
clk_disable(glue->clk); clk_disable(glue->clk);
clk_disable(glue->phy_clk); clk_disable(glue->phy_clk);
clk_put(glue->clk); clk_put(glue->clk);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/prefetch.h> #include <linux/prefetch.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
struct bfin_glue { struct bfin_glue {
struct device *dev; struct device *dev;
struct platform_device *musb; struct platform_device *musb;
struct platform_device *phy;
}; };
#define glue_to_musb(g) platform_get_drvdata(g->musb) #define glue_to_musb(g) platform_get_drvdata(g->musb)
...@@ -401,7 +402,6 @@ static int bfin_musb_init(struct musb *musb) ...@@ -401,7 +402,6 @@ static int bfin_musb_init(struct musb *musb)
} }
gpio_direction_output(musb->config->gpio_vrsel, 0); gpio_direction_output(musb->config->gpio_vrsel, 0);
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv)) { if (IS_ERR_OR_NULL(musb->xceiv)) {
gpio_free(musb->config->gpio_vrsel); gpio_free(musb->config->gpio_vrsel);
...@@ -424,9 +424,8 @@ static int bfin_musb_init(struct musb *musb) ...@@ -424,9 +424,8 @@ static int bfin_musb_init(struct musb *musb)
static int bfin_musb_exit(struct musb *musb) static int bfin_musb_exit(struct musb *musb)
{ {
gpio_free(musb->config->gpio_vrsel); gpio_free(musb->config->gpio_vrsel);
usb_put_phy(musb->xceiv); usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0; return 0;
} }
...@@ -477,6 +476,9 @@ static int bfin_probe(struct platform_device *pdev) ...@@ -477,6 +476,9 @@ static int bfin_probe(struct platform_device *pdev)
pdata->platform_ops = &bfin_ops; pdata->platform_ops = &bfin_ops;
glue->phy = usb_phy_generic_register();
if (IS_ERR(glue->phy))
goto err2;
platform_set_drvdata(pdev, glue); platform_set_drvdata(pdev, glue);
memset(musb_resources, 0x00, sizeof(*musb_resources) * memset(musb_resources, 0x00, sizeof(*musb_resources) *
...@@ -514,6 +516,9 @@ static int bfin_probe(struct platform_device *pdev) ...@@ -514,6 +516,9 @@ static int bfin_probe(struct platform_device *pdev)
return 0; return 0;
err3: err3:
usb_phy_generic_unregister(glue->phy);
err2:
platform_device_put(musb); platform_device_put(musb);
err1: err1:
...@@ -528,6 +533,7 @@ static int bfin_remove(struct platform_device *pdev) ...@@ -528,6 +533,7 @@ static int bfin_remove(struct platform_device *pdev)
struct bfin_glue *glue = platform_get_drvdata(pdev); struct bfin_glue *glue = platform_get_drvdata(pdev);
platform_device_unregister(glue->musb); platform_device_unregister(glue->musb);
usb_phy_generic_unregister(glue->phy);
kfree(glue); kfree(glue);
return 0; return 0;
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include <mach/da8xx.h> #include <mach/da8xx.h>
#include <linux/platform_data/usb-davinci.h> #include <linux/platform_data/usb-davinci.h>
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
struct da8xx_glue { struct da8xx_glue {
struct device *dev; struct device *dev;
struct platform_device *musb; struct platform_device *musb;
struct platform_device *phy;
struct clk *clk; struct clk *clk;
}; };
...@@ -418,7 +419,6 @@ static int da8xx_musb_init(struct musb *musb) ...@@ -418,7 +419,6 @@ static int da8xx_musb_init(struct musb *musb)
if (!rev) if (!rev)
goto fail; goto fail;
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv)) { if (IS_ERR_OR_NULL(musb->xceiv)) {
ret = -EPROBE_DEFER; ret = -EPROBE_DEFER;
...@@ -453,7 +453,6 @@ static int da8xx_musb_exit(struct musb *musb) ...@@ -453,7 +453,6 @@ static int da8xx_musb_exit(struct musb *musb)
phy_off(); phy_off();
usb_put_phy(musb->xceiv); usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0; return 0;
} }
...@@ -512,6 +511,11 @@ static int da8xx_probe(struct platform_device *pdev) ...@@ -512,6 +511,11 @@ static int da8xx_probe(struct platform_device *pdev)
pdata->platform_ops = &da8xx_ops; pdata->platform_ops = &da8xx_ops;
glue->phy = usb_phy_generic_register();
if (IS_ERR(glue->phy)) {
ret = PTR_ERR(glue->phy);
goto err5;
}
platform_set_drvdata(pdev, glue); platform_set_drvdata(pdev, glue);
memset(musb_resources, 0x00, sizeof(*musb_resources) * memset(musb_resources, 0x00, sizeof(*musb_resources) *
...@@ -538,11 +542,14 @@ static int da8xx_probe(struct platform_device *pdev) ...@@ -538,11 +542,14 @@ static int da8xx_probe(struct platform_device *pdev)
if (IS_ERR(musb)) { if (IS_ERR(musb)) {
ret = PTR_ERR(musb); ret = PTR_ERR(musb);
dev_err(&pdev->dev, "failed to register musb device: %d\n", ret); dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
goto err5; goto err6;
} }
return 0; return 0;
err6:
usb_phy_generic_unregister(glue->phy);
err5: err5:
clk_disable(clk); clk_disable(clk);
...@@ -561,6 +568,7 @@ static int da8xx_remove(struct platform_device *pdev) ...@@ -561,6 +568,7 @@ static int da8xx_remove(struct platform_device *pdev)
struct da8xx_glue *glue = platform_get_drvdata(pdev); struct da8xx_glue *glue = platform_get_drvdata(pdev);
platform_device_unregister(glue->musb); platform_device_unregister(glue->musb);
usb_phy_generic_unregister(glue->phy);
clk_disable(glue->clk); clk_disable(glue->clk);
clk_put(glue->clk); clk_put(glue->clk);
kfree(glue); kfree(glue);
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include <mach/cputype.h> #include <mach/cputype.h>
#include <mach/hardware.h> #include <mach/hardware.h>
...@@ -381,7 +381,6 @@ static int davinci_musb_init(struct musb *musb) ...@@ -381,7 +381,6 @@ static int davinci_musb_init(struct musb *musb)
u32 revision; u32 revision;
int ret = -ENODEV; int ret = -ENODEV;
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv)) { if (IS_ERR_OR_NULL(musb->xceiv)) {
ret = -EPROBE_DEFER; ret = -EPROBE_DEFER;
...@@ -439,7 +438,7 @@ static int davinci_musb_init(struct musb *musb) ...@@ -439,7 +438,7 @@ static int davinci_musb_init(struct musb *musb)
fail: fail:
usb_put_phy(musb->xceiv); usb_put_phy(musb->xceiv);
unregister: unregister:
usb_nop_xceiv_unregister(); usb_phy_generic_unregister();
return ret; return ret;
} }
...@@ -487,7 +486,6 @@ static int davinci_musb_exit(struct musb *musb) ...@@ -487,7 +486,6 @@ static int davinci_musb_exit(struct musb *musb)
phy_off(); phy_off();
usb_put_phy(musb->xceiv); usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0; return 0;
} }
...@@ -545,6 +543,7 @@ static int davinci_probe(struct platform_device *pdev) ...@@ -545,6 +543,7 @@ static int davinci_probe(struct platform_device *pdev)
pdata->platform_ops = &davinci_ops; pdata->platform_ops = &davinci_ops;
usb_phy_generic_register();
platform_set_drvdata(pdev, glue); platform_set_drvdata(pdev, glue);
memset(musb_resources, 0x00, sizeof(*musb_resources) * memset(musb_resources, 0x00, sizeof(*musb_resources) *
...@@ -603,6 +602,7 @@ static int davinci_remove(struct platform_device *pdev) ...@@ -603,6 +602,7 @@ static int davinci_remove(struct platform_device *pdev)
struct davinci_glue *glue = platform_get_drvdata(pdev); struct davinci_glue *glue = platform_get_drvdata(pdev);
platform_device_unregister(glue->musb); platform_device_unregister(glue->musb);
usb_phy_generic_unregister();
clk_disable(glue->clk); clk_disable(glue->clk);
clk_put(glue->clk); clk_put(glue->clk);
kfree(glue); kfree(glue);
......
...@@ -848,6 +848,10 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -848,6 +848,10 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
} }
} }
/* handle babble condition */
if (int_usb & MUSB_INTR_BABBLE)
schedule_work(&musb->recover_work);
#if 0 #if 0
/* REVISIT ... this would be for multiplexing periodic endpoints, or /* REVISIT ... this would be for multiplexing periodic endpoints, or
* supporting transfer phasing to prevent exceeding ISO bandwidth * supporting transfer phasing to prevent exceeding ISO bandwidth
...@@ -1746,6 +1750,34 @@ static void musb_irq_work(struct work_struct *data) ...@@ -1746,6 +1750,34 @@ static void musb_irq_work(struct work_struct *data)
} }
} }
/* Recover from babble interrupt conditions */
static void musb_recover_work(struct work_struct *data)
{
struct musb *musb = container_of(data, struct musb, recover_work);
int status;
musb_platform_reset(musb);
usb_phy_vbus_off(musb->xceiv);
udelay(100);
usb_phy_vbus_on(musb->xceiv);
udelay(100);
/*
* When a babble condition occurs, the musb controller removes the
* session bit and the endpoint config is lost.
*/
if (musb->dyn_fifo)
status = ep_config_from_table(musb);
else
status = ep_config_from_hw(musb);
/* start the session again */
if (status == 0)
musb_start(musb);
}
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
* Init support * Init support
*/ */
...@@ -1913,6 +1945,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) ...@@ -1913,6 +1945,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
/* Init IRQ workqueue before request_irq */ /* Init IRQ workqueue before request_irq */
INIT_WORK(&musb->irq_work, musb_irq_work); INIT_WORK(&musb->irq_work, musb_irq_work);
INIT_WORK(&musb->recover_work, musb_recover_work);
INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset); INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset);
INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume); INIT_DELAYED_WORK(&musb->finish_resume_work, musb_host_finish_resume);
...@@ -2008,6 +2041,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) ...@@ -2008,6 +2041,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
fail3: fail3:
cancel_work_sync(&musb->irq_work); cancel_work_sync(&musb->irq_work);
cancel_work_sync(&musb->recover_work);
cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->finish_resume_work);
cancel_delayed_work_sync(&musb->deassert_reset_work); cancel_delayed_work_sync(&musb->deassert_reset_work);
if (musb->dma_controller) if (musb->dma_controller)
...@@ -2073,6 +2107,7 @@ static int musb_remove(struct platform_device *pdev) ...@@ -2073,6 +2107,7 @@ static int musb_remove(struct platform_device *pdev)
dma_controller_destroy(musb->dma_controller); dma_controller_destroy(musb->dma_controller);
cancel_work_sync(&musb->irq_work); cancel_work_sync(&musb->irq_work);
cancel_work_sync(&musb->recover_work);
cancel_delayed_work_sync(&musb->finish_resume_work); cancel_delayed_work_sync(&musb->finish_resume_work);
cancel_delayed_work_sync(&musb->deassert_reset_work); cancel_delayed_work_sync(&musb->deassert_reset_work);
musb_free(musb); musb_free(musb);
......
...@@ -192,6 +192,7 @@ struct musb_platform_ops { ...@@ -192,6 +192,7 @@ struct musb_platform_ops {
int (*set_mode)(struct musb *musb, u8 mode); int (*set_mode)(struct musb *musb, u8 mode);
void (*try_idle)(struct musb *musb, unsigned long timeout); void (*try_idle)(struct musb *musb, unsigned long timeout);
void (*reset)(struct musb *musb);
int (*vbus_status)(struct musb *musb); int (*vbus_status)(struct musb *musb);
void (*set_vbus)(struct musb *musb, int on); void (*set_vbus)(struct musb *musb, int on);
...@@ -296,6 +297,7 @@ struct musb { ...@@ -296,6 +297,7 @@ struct musb {
irqreturn_t (*isr)(int, void *); irqreturn_t (*isr)(int, void *);
struct work_struct irq_work; struct work_struct irq_work;
struct work_struct recover_work;
struct delayed_work deassert_reset_work; struct delayed_work deassert_reset_work;
struct delayed_work finish_resume_work; struct delayed_work finish_resume_work;
u16 hwvers; u16 hwvers;
...@@ -337,6 +339,7 @@ struct musb { ...@@ -337,6 +339,7 @@ struct musb {
dma_addr_t async; dma_addr_t async;
dma_addr_t sync; dma_addr_t sync;
void __iomem *sync_va; void __iomem *sync_va;
u8 tusb_revision;
#endif #endif
/* passed down from chip/board specific irq handlers */ /* passed down from chip/board specific irq handlers */
...@@ -552,6 +555,12 @@ static inline void musb_platform_try_idle(struct musb *musb, ...@@ -552,6 +555,12 @@ static inline void musb_platform_try_idle(struct musb *musb,
musb->ops->try_idle(musb, timeout); musb->ops->try_idle(musb, timeout);
} }
static inline void musb_platform_reset(struct musb *musb)
{
if (musb->ops->reset)
musb->ops->reset(musb);
}
static inline int musb_platform_get_vbus_status(struct musb *musb) static inline int musb_platform_get_vbus_status(struct musb *musb)
{ {
if (!musb->ops->vbus_status) if (!musb->ops->vbus_status)
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include <linux/platform_data/usb-omap.h> #include <linux/platform_data/usb-omap.h>
#include <linux/sizes.h> #include <linux/sizes.h>
...@@ -329,9 +329,21 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) ...@@ -329,9 +329,21 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
* value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set. * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
* Also, DRVVBUS pulses for SRP (but not at 5V) ... * Also, DRVVBUS pulses for SRP (but not at 5V) ...
*/ */
if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE) if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE) {
pr_info("CAUTION: musb: Babble Interrupt Occurred\n"); pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
/*
* When a babble condition occurs, the musb controller removes
* the session and is no longer in host mode. Hence, all
* devices connected to its root hub get disconnected.
*
* Hand this error down to the musb core isr, so it can
* recover.
*/
musb->int_usb = MUSB_INTR_BABBLE | MUSB_INTR_DISCONNECT;
musb->int_tx = musb->int_rx = 0;
}
if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) { if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
int drvvbus = dsps_readl(reg_base, wrp->status); int drvvbus = dsps_readl(reg_base, wrp->status);
void __iomem *mregs = musb->mregs; void __iomem *mregs = musb->mregs;
...@@ -524,6 +536,16 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) ...@@ -524,6 +536,16 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode)
return 0; return 0;
} }
static void dsps_musb_reset(struct musb *musb)
{
struct device *dev = musb->controller;
struct dsps_glue *glue = dev_get_drvdata(dev->parent);
const struct dsps_musb_wrapper *wrp = glue->wrp;
dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
udelay(100);
}
static struct musb_platform_ops dsps_ops = { static struct musb_platform_ops dsps_ops = {
.init = dsps_musb_init, .init = dsps_musb_init,
.exit = dsps_musb_exit, .exit = dsps_musb_exit,
...@@ -533,6 +555,7 @@ static struct musb_platform_ops dsps_ops = { ...@@ -533,6 +555,7 @@ static struct musb_platform_ops dsps_ops = {
.try_idle = dsps_musb_try_idle, .try_idle = dsps_musb_try_idle,
.set_mode = dsps_musb_set_mode, .set_mode = dsps_musb_set_mode,
.reset = dsps_musb_reset,
}; };
static u64 musb_dmamask = DMA_BIT_MASK(32); static u64 musb_dmamask = DMA_BIT_MASK(32);
...@@ -750,7 +773,7 @@ static const struct of_device_id musb_dsps_of_match[] = { ...@@ -750,7 +773,7 @@ static const struct of_device_id musb_dsps_of_match[] = {
}; };
MODULE_DEVICE_TABLE(of, musb_dsps_of_match); MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int dsps_suspend(struct device *dev) static int dsps_suspend(struct device *dev)
{ {
struct dsps_glue *glue = dev_get_drvdata(dev); struct dsps_glue *glue = dev_get_drvdata(dev);
......
...@@ -24,13 +24,14 @@ ...@@ -24,13 +24,14 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include "musb_core.h" #include "musb_core.h"
struct tusb6010_glue { struct tusb6010_glue {
struct device *dev; struct device *dev;
struct platform_device *musb; struct platform_device *musb;
struct platform_device *phy;
}; };
static void tusb_musb_set_vbus(struct musb *musb, int is_on); static void tusb_musb_set_vbus(struct musb *musb, int is_on);
...@@ -42,7 +43,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on); ...@@ -42,7 +43,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on);
* Checks the revision. We need to use the DMA register as 3.0 does not * Checks the revision. We need to use the DMA register as 3.0 does not
* have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV. * have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV.
*/ */
u8 tusb_get_revision(struct musb *musb) static u8 tusb_get_revision(struct musb *musb)
{ {
void __iomem *tbase = musb->ctrl_base; void __iomem *tbase = musb->ctrl_base;
u32 die_id; u32 die_id;
...@@ -58,14 +59,13 @@ u8 tusb_get_revision(struct musb *musb) ...@@ -58,14 +59,13 @@ u8 tusb_get_revision(struct musb *musb)
return rev; return rev;
} }
EXPORT_SYMBOL_GPL(tusb_get_revision);
static int tusb_print_revision(struct musb *musb) static void tusb_print_revision(struct musb *musb)
{ {
void __iomem *tbase = musb->ctrl_base; void __iomem *tbase = musb->ctrl_base;
u8 rev; u8 rev;
rev = tusb_get_revision(musb); rev = musb->tusb_revision;
pr_info("tusb: %s%i.%i %s%i.%i %s%i.%i %s%i.%i %s%i %s%i.%i\n", pr_info("tusb: %s%i.%i %s%i.%i %s%i.%i %s%i.%i %s%i %s%i.%i\n",
"prcm", "prcm",
...@@ -84,8 +84,6 @@ static int tusb_print_revision(struct musb *musb) ...@@ -84,8 +84,6 @@ static int tusb_print_revision(struct musb *musb)
TUSB_DIDR1_HI_CHIP_REV(musb_readl(tbase, TUSB_DIDR1_HI)), TUSB_DIDR1_HI_CHIP_REV(musb_readl(tbase, TUSB_DIDR1_HI)),
"rev", "rev",
TUSB_REV_MAJOR(rev), TUSB_REV_MINOR(rev)); TUSB_REV_MAJOR(rev), TUSB_REV_MINOR(rev));
return tusb_get_revision(musb);
} }
#define WBUS_QUIRK_MASK (TUSB_PHY_OTG_CTRL_TESTM2 | TUSB_PHY_OTG_CTRL_TESTM1 \ #define WBUS_QUIRK_MASK (TUSB_PHY_OTG_CTRL_TESTM2 | TUSB_PHY_OTG_CTRL_TESTM1 \
...@@ -349,7 +347,7 @@ static void tusb_allow_idle(struct musb *musb, u32 wakeup_enables) ...@@ -349,7 +347,7 @@ static void tusb_allow_idle(struct musb *musb, u32 wakeup_enables)
u32 reg; u32 reg;
if ((wakeup_enables & TUSB_PRCM_WBUS) if ((wakeup_enables & TUSB_PRCM_WBUS)
&& (tusb_get_revision(musb) == TUSB_REV_30)) && (musb->tusb_revision == TUSB_REV_30))
tusb_wbus_quirk(musb, 1); tusb_wbus_quirk(musb, 1);
tusb_set_clock_source(musb, 0); tusb_set_clock_source(musb, 0);
...@@ -797,7 +795,7 @@ static irqreturn_t tusb_musb_interrupt(int irq, void *__hci) ...@@ -797,7 +795,7 @@ static irqreturn_t tusb_musb_interrupt(int irq, void *__hci)
u32 reg; u32 reg;
u32 i; u32 i;
if (tusb_get_revision(musb) == TUSB_REV_30) if (musb->tusb_revision == TUSB_REV_30)
tusb_wbus_quirk(musb, 0); tusb_wbus_quirk(musb, 0);
/* there are issues re-locking the PLL on wakeup ... */ /* there are issues re-locking the PLL on wakeup ... */
...@@ -1011,10 +1009,11 @@ static int tusb_musb_start(struct musb *musb) ...@@ -1011,10 +1009,11 @@ static int tusb_musb_start(struct musb *musb)
goto err; goto err;
} }
ret = tusb_print_revision(musb); musb->tusb_revision = tusb_get_revision(musb);
if (ret < 2) { tusb_print_revision(musb);
if (musb->tusb_revision < 2) {
printk(KERN_ERR "tusb: Unsupported TUSB6010 revision %i\n", printk(KERN_ERR "tusb: Unsupported TUSB6010 revision %i\n",
ret); musb->tusb_revision);
goto err; goto err;
} }
...@@ -1065,7 +1064,6 @@ static int tusb_musb_init(struct musb *musb) ...@@ -1065,7 +1064,6 @@ static int tusb_musb_init(struct musb *musb)
void __iomem *sync = NULL; void __iomem *sync = NULL;
int ret; int ret;
usb_nop_xceiv_register();
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(musb->xceiv)) if (IS_ERR_OR_NULL(musb->xceiv))
return -EPROBE_DEFER; return -EPROBE_DEFER;
...@@ -1117,7 +1115,6 @@ static int tusb_musb_init(struct musb *musb) ...@@ -1117,7 +1115,6 @@ static int tusb_musb_init(struct musb *musb)
iounmap(sync); iounmap(sync);
usb_put_phy(musb->xceiv); usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
} }
return ret; return ret;
} }
...@@ -1133,7 +1130,6 @@ static int tusb_musb_exit(struct musb *musb) ...@@ -1133,7 +1130,6 @@ static int tusb_musb_exit(struct musb *musb)
iounmap(musb->sync_va); iounmap(musb->sync_va);
usb_put_phy(musb->xceiv); usb_put_phy(musb->xceiv);
usb_nop_xceiv_unregister();
return 0; return 0;
} }
...@@ -1176,6 +1172,7 @@ static int tusb_probe(struct platform_device *pdev) ...@@ -1176,6 +1172,7 @@ static int tusb_probe(struct platform_device *pdev)
pdata->platform_ops = &tusb_ops; pdata->platform_ops = &tusb_ops;
usb_phy_generic_register();
platform_set_drvdata(pdev, glue); platform_set_drvdata(pdev, glue);
memset(musb_resources, 0x00, sizeof(*musb_resources) * memset(musb_resources, 0x00, sizeof(*musb_resources) *
...@@ -1224,6 +1221,7 @@ static int tusb_remove(struct platform_device *pdev) ...@@ -1224,6 +1221,7 @@ static int tusb_remove(struct platform_device *pdev)
struct tusb6010_glue *glue = platform_get_drvdata(pdev); struct tusb6010_glue *glue = platform_get_drvdata(pdev);
platform_device_unregister(glue->musb); platform_device_unregister(glue->musb);
usb_phy_generic_unregister(glue->phy);
kfree(glue); kfree(glue);
return 0; return 0;
......
...@@ -12,14 +12,6 @@ ...@@ -12,14 +12,6 @@
#ifndef __TUSB6010_H__ #ifndef __TUSB6010_H__
#define __TUSB6010_H__ #define __TUSB6010_H__
extern u8 tusb_get_revision(struct musb *musb);
#ifdef CONFIG_USB_TUSB6010
#define musb_in_tusb() 1
#else
#define musb_in_tusb() 0
#endif
#ifdef CONFIG_USB_TUSB_OMAP_DMA #ifdef CONFIG_USB_TUSB_OMAP_DMA
#define tusb_dma_omap() 1 #define tusb_dma_omap() 1
#else #else
......
...@@ -677,7 +677,7 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba ...@@ -677,7 +677,7 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
tusb_dma->controller.channel_program = tusb_omap_dma_program; tusb_dma->controller.channel_program = tusb_omap_dma_program;
tusb_dma->controller.channel_abort = tusb_omap_dma_abort; tusb_dma->controller.channel_abort = tusb_omap_dma_abort;
if (tusb_get_revision(musb) >= TUSB_REV_30) if (musb->tusb_revision >= TUSB_REV_30)
tusb_dma->multichannel = 1; tusb_dma->multichannel = 1;
for (i = 0; i < MAX_DMAREQ; i++) { for (i = 0; i < MAX_DMAREQ; i++) {
......
...@@ -163,11 +163,12 @@ config USB_ISP1301 ...@@ -163,11 +163,12 @@ config USB_ISP1301
module will be called phy-isp1301. module will be called phy-isp1301.
config USB_MSM_OTG config USB_MSM_OTG
tristate "OTG support for Qualcomm on-chip USB controller" tristate "Qualcomm on-chip USB OTG controller support"
depends on (USB || USB_GADGET) && ARCH_MSM depends on (USB || USB_GADGET) && (ARCH_MSM || ARCH_QCOM || COMPILE_TEST)
depends on RESET_CONTROLLER
select USB_PHY select USB_PHY
help help
Enable this to support the USB OTG transceiver on MSM chips. It Enable this to support the USB OTG transceiver on Qualcomm chips. It
handles PHY initialization, clock management, and workarounds handles PHY initialization, clock management, and workarounds
required after resetting the hardware and power management. required after resetting the hardware and power management.
This driver is required even for peripheral only or host only This driver is required even for peripheral only or host only
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include "phy-generic.h" #include "phy-generic.h"
struct am335x_phy { struct am335x_phy {
struct usb_phy_gen_xceiv usb_phy_gen; struct usb_phy_generic usb_phy_gen;
struct phy_control *phy_ctrl; struct phy_control *phy_ctrl;
int id; int id;
}; };
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
...@@ -41,34 +41,25 @@ ...@@ -41,34 +41,25 @@
#include "phy-generic.h" #include "phy-generic.h"
static struct platform_device *pd; struct platform_device *usb_phy_generic_register(void)
void usb_nop_xceiv_register(void)
{ {
if (pd) return platform_device_register_simple("usb_phy_generic",
return; PLATFORM_DEVID_AUTO, NULL, 0);
pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0);
if (IS_ERR(pd)) {
pr_err("Unable to register generic usb transceiver\n");
pd = NULL;
return;
}
} }
EXPORT_SYMBOL(usb_nop_xceiv_register); EXPORT_SYMBOL_GPL(usb_phy_generic_register);
void usb_nop_xceiv_unregister(void) void usb_phy_generic_unregister(struct platform_device *pdev)
{ {
platform_device_unregister(pd); platform_device_unregister(pdev);
pd = NULL;
} }
EXPORT_SYMBOL(usb_nop_xceiv_unregister); EXPORT_SYMBOL_GPL(usb_phy_generic_unregister);
static int nop_set_suspend(struct usb_phy *x, int suspend) static int nop_set_suspend(struct usb_phy *x, int suspend)
{ {
return 0; return 0;
} }
static void nop_reset_set(struct usb_phy_gen_xceiv *nop, int asserted) static void nop_reset_set(struct usb_phy_generic *nop, int asserted)
{ {
int value; int value;
...@@ -87,7 +78,7 @@ static void nop_reset_set(struct usb_phy_gen_xceiv *nop, int asserted) ...@@ -87,7 +78,7 @@ static void nop_reset_set(struct usb_phy_gen_xceiv *nop, int asserted)
int usb_gen_phy_init(struct usb_phy *phy) int usb_gen_phy_init(struct usb_phy *phy)
{ {
struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev); struct usb_phy_generic *nop = dev_get_drvdata(phy->dev);
if (!IS_ERR(nop->vcc)) { if (!IS_ERR(nop->vcc)) {
if (regulator_enable(nop->vcc)) if (regulator_enable(nop->vcc))
...@@ -106,7 +97,7 @@ EXPORT_SYMBOL_GPL(usb_gen_phy_init); ...@@ -106,7 +97,7 @@ EXPORT_SYMBOL_GPL(usb_gen_phy_init);
void usb_gen_phy_shutdown(struct usb_phy *phy) void usb_gen_phy_shutdown(struct usb_phy *phy)
{ {
struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev); struct usb_phy_generic *nop = dev_get_drvdata(phy->dev);
/* Assert RESET */ /* Assert RESET */
nop_reset_set(nop, 1); nop_reset_set(nop, 1);
...@@ -150,8 +141,8 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) ...@@ -150,8 +141,8 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
return 0; return 0;
} }
int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
struct usb_phy_gen_xceiv_platform_data *pdata) struct usb_phy_generic_platform_data *pdata)
{ {
enum usb_phy_type type = USB_PHY_TYPE_USB2; enum usb_phy_type type = USB_PHY_TYPE_USB2;
int err; int err;
...@@ -245,10 +236,10 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, ...@@ -245,10 +236,10 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop,
} }
EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy); EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy);
static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) static int usb_phy_generic_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct usb_phy_gen_xceiv *nop; struct usb_phy_generic *nop;
int err; int err;
nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL); nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL);
...@@ -274,9 +265,9 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) ...@@ -274,9 +265,9 @@ static int usb_phy_gen_xceiv_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int usb_phy_gen_xceiv_remove(struct platform_device *pdev) static int usb_phy_generic_remove(struct platform_device *pdev)
{ {
struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev); struct usb_phy_generic *nop = platform_get_drvdata(pdev);
usb_remove_phy(&nop->phy); usb_remove_phy(&nop->phy);
...@@ -290,29 +281,29 @@ static const struct of_device_id nop_xceiv_dt_ids[] = { ...@@ -290,29 +281,29 @@ static const struct of_device_id nop_xceiv_dt_ids[] = {
MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids); MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
static struct platform_driver usb_phy_gen_xceiv_driver = { static struct platform_driver usb_phy_generic_driver = {
.probe = usb_phy_gen_xceiv_probe, .probe = usb_phy_generic_probe,
.remove = usb_phy_gen_xceiv_remove, .remove = usb_phy_generic_remove,
.driver = { .driver = {
.name = "usb_phy_gen_xceiv", .name = "usb_phy_generic",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = nop_xceiv_dt_ids, .of_match_table = nop_xceiv_dt_ids,
}, },
}; };
static int __init usb_phy_gen_xceiv_init(void) static int __init usb_phy_generic_init(void)
{ {
return platform_driver_register(&usb_phy_gen_xceiv_driver); return platform_driver_register(&usb_phy_generic_driver);
} }
subsys_initcall(usb_phy_gen_xceiv_init); subsys_initcall(usb_phy_generic_init);
static void __exit usb_phy_gen_xceiv_exit(void) static void __exit usb_phy_generic_exit(void)
{ {
platform_driver_unregister(&usb_phy_gen_xceiv_driver); platform_driver_unregister(&usb_phy_generic_driver);
} }
module_exit(usb_phy_gen_xceiv_exit); module_exit(usb_phy_generic_exit);
MODULE_ALIAS("platform:usb_phy_gen_xceiv"); MODULE_ALIAS("platform:usb_phy_generic");
MODULE_AUTHOR("Texas Instruments Inc"); MODULE_AUTHOR("Texas Instruments Inc");
MODULE_DESCRIPTION("NOP USB Transceiver driver"); MODULE_DESCRIPTION("NOP USB Transceiver driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifndef _PHY_GENERIC_H_ #ifndef _PHY_GENERIC_H_
#define _PHY_GENERIC_H_ #define _PHY_GENERIC_H_
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
struct usb_phy_gen_xceiv { struct usb_phy_generic {
struct usb_phy phy; struct usb_phy phy;
struct device *dev; struct device *dev;
struct clk *clk; struct clk *clk;
...@@ -15,7 +15,7 @@ struct usb_phy_gen_xceiv { ...@@ -15,7 +15,7 @@ struct usb_phy_gen_xceiv {
int usb_gen_phy_init(struct usb_phy *phy); int usb_gen_phy_init(struct usb_phy *phy);
void usb_gen_phy_shutdown(struct usb_phy *phy); void usb_gen_phy_shutdown(struct usb_phy *phy);
int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
struct usb_phy_gen_xceiv_platform_data *pdata); struct usb_phy_generic_platform_data *pdata);
#endif #endif
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/usb/usb_phy_gen_xceiv.h> #include <linux/usb/usb_phy_generic.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#define PHY_REF_SSP_EN BIT(29) #define PHY_REF_SSP_EN BIT(29)
struct keystone_usbphy { struct keystone_usbphy {
struct usb_phy_gen_xceiv usb_phy_gen; struct usb_phy_generic usb_phy_gen;
void __iomem *phy_ctrl; void __iomem *phy_ctrl;
}; };
......
此差异已折叠。
...@@ -48,6 +48,7 @@ static struct ulpi_info ulpi_ids[] = { ...@@ -48,6 +48,7 @@ static struct ulpi_info ulpi_ids[] = {
ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"), ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"),
ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"),
ULPI_INFO(ULPI_ID(0x0424, 0x0007), "SMSC USB3320"), ULPI_INFO(ULPI_ID(0x0424, 0x0007), "SMSC USB3320"),
ULPI_INFO(ULPI_ID(0x0424, 0x0009), "SMSC USB334x"),
ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"), ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"),
}; };
......
...@@ -56,6 +56,61 @@ ...@@ -56,6 +56,61 @@
#define USB_MS_TO_HS_INTERVAL(x) (ilog2((x * 1000 / 125)) + 1) #define USB_MS_TO_HS_INTERVAL(x) (ilog2((x * 1000 / 125)) + 1)
struct usb_configuration; struct usb_configuration;
/**
* struct usb_os_desc_ext_prop - describes one "Extended Property"
* @entry: used to keep a list of extended properties
* @type: Extended Property type
* @name_len: Extended Property unicode name length, including terminating '\0'
* @name: Extended Property name
* @data_len: Length of Extended Property blob (for unicode store double len)
* @data: Extended Property blob
* @item: Represents this Extended Property in configfs
*/
struct usb_os_desc_ext_prop {
struct list_head entry;
u8 type;
int name_len;
char *name;
int data_len;
char *data;
struct config_item item;
};
/**
* struct usb_os_desc - describes OS descriptors associated with one interface
* @ext_compat_id: 16 bytes of "Compatible ID" and "Subcompatible ID"
* @ext_prop: Extended Properties list
* @ext_prop_len: Total length of Extended Properties blobs
* @ext_prop_count: Number of Extended Properties
* @opts_mutex: Optional mutex protecting config data of a usb_function_instance
* @group: Represents OS descriptors associated with an interface in configfs
* @owner: Module associated with this OS descriptor
*/
struct usb_os_desc {
char *ext_compat_id;
struct list_head ext_prop;
int ext_prop_len;
int ext_prop_count;
struct mutex *opts_mutex;
struct config_group group;
struct module *owner;
};
/**
* struct usb_os_desc_table - describes OS descriptors associated with one
* interface of a usb_function
* @if_id: Interface id
* @os_desc: "Extended Compatibility ID" and "Extended Properties" of the
* interface
*
* Each interface can have at most one "Extended Compatibility ID" and a
* number of "Extended Properties".
*/
struct usb_os_desc_table {
int if_id;
struct usb_os_desc *os_desc;
};
/** /**
* struct usb_function - describes one function of a configuration * struct usb_function - describes one function of a configuration
* @name: For diagnostics, identifies the function. * @name: For diagnostics, identifies the function.
...@@ -73,6 +128,10 @@ struct usb_configuration; ...@@ -73,6 +128,10 @@ struct usb_configuration;
* be available at super speed. * be available at super speed.
* @config: assigned when @usb_add_function() is called; this is the * @config: assigned when @usb_add_function() is called; this is the
* configuration with which this function is associated. * configuration with which this function is associated.
* @os_desc_table: Table of (interface id, os descriptors) pairs. The function
* can expose more than one interface. If an interface is a member of
* an IAD, only the first interface of IAD has its entry in the table.
* @os_desc_n: Number of entries in os_desc_table
* @bind: Before the gadget can register, all of its functions bind() to the * @bind: Before the gadget can register, all of its functions bind() to the
* available resources including string and interface identifiers used * available resources including string and interface identifiers used
* in interface or class descriptors; endpoints; I/O buffers; and so on. * in interface or class descriptors; endpoints; I/O buffers; and so on.
...@@ -129,6 +188,9 @@ struct usb_function { ...@@ -129,6 +188,9 @@ struct usb_function {
struct usb_configuration *config; struct usb_configuration *config;
struct usb_os_desc_table *os_desc_table;
unsigned os_desc_n;
/* REVISIT: bind() functions can be marked __init, which /* REVISIT: bind() functions can be marked __init, which
* makes trouble for section mismatch analysis. See if * makes trouble for section mismatch analysis. See if
* we can't restructure things to avoid mismatching. * we can't restructure things to avoid mismatching.
...@@ -327,6 +389,8 @@ extern void usb_composite_unregister(struct usb_composite_driver *driver); ...@@ -327,6 +389,8 @@ extern void usb_composite_unregister(struct usb_composite_driver *driver);
extern void usb_composite_setup_continue(struct usb_composite_dev *cdev); extern void usb_composite_setup_continue(struct usb_composite_dev *cdev);
extern int composite_dev_prepare(struct usb_composite_driver *composite, extern int composite_dev_prepare(struct usb_composite_driver *composite,
struct usb_composite_dev *cdev); struct usb_composite_dev *cdev);
extern int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
struct usb_ep *ep0);
void composite_dev_cleanup(struct usb_composite_dev *cdev); void composite_dev_cleanup(struct usb_composite_dev *cdev);
static inline struct usb_composite_driver *to_cdriver( static inline struct usb_composite_driver *to_cdriver(
...@@ -335,11 +399,19 @@ static inline struct usb_composite_driver *to_cdriver( ...@@ -335,11 +399,19 @@ static inline struct usb_composite_driver *to_cdriver(
return container_of(gdrv, struct usb_composite_driver, gadget_driver); return container_of(gdrv, struct usb_composite_driver, gadget_driver);
} }
#define OS_STRING_QW_SIGN_LEN 14
#define OS_STRING_IDX 0xEE
/** /**
* struct usb_composite_device - represents one composite usb gadget * struct usb_composite_device - represents one composite usb gadget
* @gadget: read-only, abstracts the gadget's usb peripheral controller * @gadget: read-only, abstracts the gadget's usb peripheral controller
* @req: used for control responses; buffer is pre-allocated * @req: used for control responses; buffer is pre-allocated
* @os_desc_req: used for OS descriptors responses; buffer is pre-allocated
* @config: the currently active configuration * @config: the currently active configuration
* @qw_sign: qwSignature part of the OS string
* @b_vendor_code: bMS_VendorCode part of the OS string
* @use_os_string: false by default, interested gadgets set it
* @os_desc_config: the configuration to be used with OS descriptors
* *
* One of these devices is allocated and initialized before the * One of these devices is allocated and initialized before the
* associated device driver's bind() is called. * associated device driver's bind() is called.
...@@ -369,9 +441,16 @@ static inline struct usb_composite_driver *to_cdriver( ...@@ -369,9 +441,16 @@ static inline struct usb_composite_driver *to_cdriver(
struct usb_composite_dev { struct usb_composite_dev {
struct usb_gadget *gadget; struct usb_gadget *gadget;
struct usb_request *req; struct usb_request *req;
struct usb_request *os_desc_req;
struct usb_configuration *config; struct usb_configuration *config;
/* OS String is a custom (yet popular) extension to the USB standard. */
u8 qw_sign[OS_STRING_QW_SIGN_LEN];
u8 b_vendor_code;
struct usb_configuration *os_desc_config;
unsigned int use_os_string:1;
/* private: */ /* private: */
/* internals */ /* internals */
unsigned int suspended:1; unsigned int suspended:1;
......
...@@ -22,21 +22,6 @@ ...@@ -22,21 +22,6 @@
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/clk.h> #include <linux/clk.h>
/**
* Supported USB modes
*
* USB_PERIPHERAL Only peripheral mode is supported.
* USB_HOST Only host mode is supported.
* USB_OTG OTG mode is supported.
*
*/
enum usb_mode_type {
USB_NONE = 0,
USB_PERIPHERAL,
USB_HOST,
USB_OTG,
};
/** /**
* OTG control * OTG control
* *
...@@ -115,27 +100,23 @@ enum usb_chg_type { ...@@ -115,27 +100,23 @@ enum usb_chg_type {
/** /**
* struct msm_otg_platform_data - platform device data * struct msm_otg_platform_data - platform device data
* for msm_otg driver. * for msm_otg driver.
* @phy_init_seq: PHY configuration sequence. val, reg pairs * @phy_init_seq: PHY configuration sequence values. Value of -1 is reserved as
* terminated by -1. * "do not overwrite default vaule at this address".
* @phy_init_sz: PHY configuration sequence size.
* @vbus_power: VBUS power on/off routine. * @vbus_power: VBUS power on/off routine.
* @power_budget: VBUS power budget in mA (0 will be treated as 500mA). * @power_budget: VBUS power budget in mA (0 will be treated as 500mA).
* @mode: Supported mode (OTG/peripheral/host). * @mode: Supported mode (OTG/peripheral/host).
* @otg_control: OTG switch controlled by user/Id pin * @otg_control: OTG switch controlled by user/Id pin
* @default_mode: Default operational mode. Applicable only if
* OTG switch is controller by user.
* @pclk_src_name: pclk is derived from ebi1_usb_clk in case of 7x27 and 8k
* dfab_usb_hs_clk in case of 8660 and 8960.
*/ */
struct msm_otg_platform_data { struct msm_otg_platform_data {
int *phy_init_seq; int *phy_init_seq;
int phy_init_sz;
void (*vbus_power)(bool on); void (*vbus_power)(bool on);
unsigned power_budget; unsigned power_budget;
enum usb_mode_type mode; enum usb_dr_mode mode;
enum otg_control_type otg_control; enum otg_control_type otg_control;
enum usb_mode_type default_mode;
enum msm_usb_phy_type phy_type; enum msm_usb_phy_type phy_type;
void (*setup_gpio)(enum usb_otg_state state); void (*setup_gpio)(enum usb_otg_state state);
char *pclk_src_name;
int (*link_clk_reset)(struct clk *link_clk, bool assert); int (*link_clk_reset)(struct clk *link_clk, bool assert);
int (*phy_clk_reset)(struct clk *phy_clk); int (*phy_clk_reset)(struct clk *phy_clk);
}; };
...@@ -147,7 +128,6 @@ struct msm_otg_platform_data { ...@@ -147,7 +128,6 @@ struct msm_otg_platform_data {
* @irq: IRQ number assigned for HSUSB controller. * @irq: IRQ number assigned for HSUSB controller.
* @clk: clock struct of usb_hs_clk. * @clk: clock struct of usb_hs_clk.
* @pclk: clock struct of usb_hs_pclk. * @pclk: clock struct of usb_hs_pclk.
* @pclk_src: pclk source for voting.
* @phy_reset_clk: clock struct of usb_phy_clk. * @phy_reset_clk: clock struct of usb_phy_clk.
* @core_clk: clock struct of usb_hs_core_clk. * @core_clk: clock struct of usb_hs_core_clk.
* @regs: ioremapped register base address. * @regs: ioremapped register base address.
...@@ -168,7 +148,6 @@ struct msm_otg { ...@@ -168,7 +148,6 @@ struct msm_otg {
int irq; int irq;
struct clk *clk; struct clk *clk;
struct clk *pclk; struct clk *pclk;
struct clk *pclk_src;
struct clk *phy_reset_clk; struct clk *phy_reset_clk;
struct clk *core_clk; struct clk *core_clk;
void __iomem *regs; void __iomem *regs;
...@@ -179,10 +158,18 @@ struct msm_otg { ...@@ -179,10 +158,18 @@ struct msm_otg {
atomic_t in_lpm; atomic_t in_lpm;
int async_int; int async_int;
unsigned cur_power; unsigned cur_power;
int phy_number;
struct delayed_work chg_work; struct delayed_work chg_work;
enum usb_chg_state chg_state; enum usb_chg_state chg_state;
enum usb_chg_type chg_type; enum usb_chg_type chg_type;
u8 dcd_retries; u8 dcd_retries;
struct regulator *v3p3;
struct regulator *v1p8;
struct regulator *vddcx;
struct reset_control *phy_rst;
struct reset_control *link_rst;
int vdd_levels[3];
}; };
#endif #endif
此差异已折叠。
CC = gcc
LIBUSB_CFLAGS = $(shell pkg-config --cflags libusb-1.0)
LIBUSB_LIBS = $(shell pkg-config --libs libusb-1.0)
WARNINGS = -Wall -Wextra
CFLAGS = $(LIBUSB_CFLAGS) $(WARNINGS)
LDFLAGS = $(LIBUSB_LIBS)
all: test
%: %.c
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
clean:
$(RM) test
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册