usb: patches for v3.10 merge window

Here is the big Gadget & PHY pull request. Many of us have
 been really busy lately getting multiple drivers to a better
 position.
 
 Since this pull request is so large, I will divide it in sections
 so it's easier to grasp what's included.
 
 - cleanups:
 	. UDC drivers no longer touch gadget->dev, that's now udc-core
 		responsibility
 	. Many more UDC drivers converted to usb_gadget_map/unmap_request()
 	. UDC drivers no longer initialize DMA-related fields from gadget's
 		device structure
 	. UDC drivers don't touch gadget.dev.driver directly
 	. UDC drivers don't assign gadget.dev.release directly
 	. Removal of some unused DMA_ADDR_INVALID
 	. Introduction of CONFIG_USB_PHY
 	. All phy drivers have been moved to drivers/usb/phy and renamed to
 		a common naming scheme
 	. Fix PHY layer so it never returns a NULL pointer, also fix all
 		callers to avoid using IS_ERR_OR_NULL()
 	. Sparse fixes all over the place
 	. drivers/usb/otg/ has been deleted
 	. Marvel drivers (mv_udc, ehci-mv, mv_otg and mv_u3d) improved clock
 		usage
 
 - new features:
 	. UDC core now provides a generic way for tracking and reporting
 		UDC's state (not attached, resuming, suspended, addressed,
 		default, etc)
 	. twl4030-usb learned that it shouldn't be enabled during init
 	. Full DT support for DWC3 has been implemented
 	. ab8500-usb learned about pinctrl framework
 	. nop PHY learned about DeviceTree and regulators
 	. DWC3 learned about suspend/resume
 	. DWC3 can now be compiled in host-only and gadget-only (as well as
 		DRD) configurations
 	. UVC now enables streaming endpoint based on negotiated speed
 	. isp1301 now implements the PHY API properly
 	. configfs-based interface for gadget drivers which will lead to
 		the removal of all code which just combines functions together
 		to build functional gadget drivers.
 	. f_serial and f_obex were converted to new configfs interface while
 		maintaining old interface around.
 
 - non-critical fixes:
 	. UVC gadget driver got fixes for Endpoint usage and stream calculation
 	. ab8500-usb fixed unbalanced clock and regulator API usage
 	. twl4030-usb got a fix for when OMAP3 is booted with cable connected
 	. fusb300_udc got a fix for DMA usage
 	. UVC got fixes for two assertions of the USB Video Class Compliance
 		specification revision 1.1
 	. build warning issues caused by recent addition of __must_check to
 		regulator API
 
 These are all changes which deserve a mention, all other changes are related
 to these one or minor spelling fixes and other similar tasks.
 
 Signed-of-by: Felipe Balbi <balbi@ti.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJRXG8GAAoJEIaOsuA1yqREJzYQAKMLW3J/TKTWS1DDuf7qMtMz
 Ug6qChKZXgT1/QrNjsq2tx4jYIkNdSMtRKiUx0BnIptlUx6gM22gcsN8mXX/UJjC
 FYAiWl+tYe85e9uayqqt+qVCZjTZCc7St4wQalugDHefvA7yCbiZpSaJRGlJMK+x
 mePJ7MfrulDsYBXr0u+m2LOJ0qxMDi40k3/UN3aUu5yzrmBiRpVq1mySruvLwGFp
 Pr6vBnprEc6bW5sRdUR4SICKLvLk5sHwHpvpkzDLYBIb/jXQwbfQri/HKeh4VMk8
 trbsvHZyB7H8uuFsCHiBc6VtjcbZ4mxPUK+1PCq8hG077avdkm3ox0BERk9aRTeC
 jg4mdpyWjgovwi882woPEQXNZoaAXpVDyI8tBRx92a+rGJjXSHhLQI+4Ffi4ZvzV
 d+q1ZzrHxuzwa/BwcPETY76umXQqXWXg+ap1bHDY0RZFoPLdXMpl583NXGSn3gOD
 dUlD0UlgYwb75333tRIPNQn3qOx0HVd6MlYPMNzl9t9c9qqfX78AYRny6ZucupRg
 t9VZ6FO3D2yre9W7u3U3q2c9H7uSAKr/8xaNfvdsIWPncgvvYVIyE8MnR7AiHoPv
 ZYESs/Gs6w9vUsHa9K4J16Ape7D3AMcGpXUoPUxTBHrwBexzt4j27VWtcL4ns/9r
 0kcltUJ4Zq+PIjc7xgxe
 =aF4r
 -----END PGP SIGNATURE-----

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

Felipe writes:

usb: patches for v3.10 merge window

Here is the big Gadget & PHY pull request. Many of us have
been really busy lately getting multiple drivers to a better
position.

Since this pull request is so large, I will divide it in sections
so it's easier to grasp what's included.

- cleanups:
	. UDC drivers no longer touch gadget->dev, that's now udc-core
		responsibility
	. Many more UDC drivers converted to usb_gadget_map/unmap_request()
	. UDC drivers no longer initialize DMA-related fields from gadget's
		device structure
	. UDC drivers don't touch gadget.dev.driver directly
	. UDC drivers don't assign gadget.dev.release directly
	. Removal of some unused DMA_ADDR_INVALID
	. Introduction of CONFIG_USB_PHY
	. All phy drivers have been moved to drivers/usb/phy and renamed to
		a common naming scheme
	. Fix PHY layer so it never returns a NULL pointer, also fix all
		callers to avoid using IS_ERR_OR_NULL()
	. Sparse fixes all over the place
	. drivers/usb/otg/ has been deleted
	. Marvel drivers (mv_udc, ehci-mv, mv_otg and mv_u3d) improved clock
		usage

- new features:
	. UDC core now provides a generic way for tracking and reporting
		UDC's state (not attached, resuming, suspended, addressed,
		default, etc)
	. twl4030-usb learned that it shouldn't be enabled during init
	. Full DT support for DWC3 has been implemented
	. ab8500-usb learned about pinctrl framework
	. nop PHY learned about DeviceTree and regulators
	. DWC3 learned about suspend/resume
	. DWC3 can now be compiled in host-only and gadget-only (as well as
		DRD) configurations
	. UVC now enables streaming endpoint based on negotiated speed
	. isp1301 now implements the PHY API properly
	. configfs-based interface for gadget drivers which will lead to
		the removal of all code which just combines functions together
		to build functional gadget drivers.
	. f_serial and f_obex were converted to new configfs interface while
		maintaining old interface around.

- non-critical fixes:
	. UVC gadget driver got fixes for Endpoint usage and stream calculation
	. ab8500-usb fixed unbalanced clock and regulator API usage
	. twl4030-usb got a fix for when OMAP3 is booted with cable connected
	. fusb300_udc got a fix for DMA usage
	. UVC got fixes for two assertions of the USB Video Class Compliance
		specification revision 1.1
	. build warning issues caused by recent addition of __must_check to
		regulator API

These are all changes which deserve a mention, all other changes are related
to these one or minor spelling fixes and other similar tasks.

Signed-of-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
Greg Kroah-Hartman 2013-04-05 15:18:00 -07:00
commit 64dc9e2e73
159 changed files with 6868 additions and 4499 deletions

View File

@ -8,10 +8,10 @@ OMAP MUSB GLUE
and disconnect.
- multipoint : Should be "1" indicating the musb controller supports
multipoint. This is a MUSB configuration-specific setting.
- num_eps : Specifies the number of endpoints. This is also a
- num-eps : Specifies the number of endpoints. This is also a
MUSB configuration-specific setting. Should be set to "16"
- ram_bits : Specifies the ram address size. Should be set to "12"
- interface_type : This is a board specific setting to describe the type of
- ram-bits : Specifies the ram address size. Should be set to "12"
- interface-type : This is a board specific setting to describe the type of
interface between the controller and the phy. It should be "0" or "1"
specifying ULPI and UTMI respectively.
- mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
@ -29,18 +29,46 @@ usb_otg_hs: usb_otg_hs@4a0ab000 {
ti,hwmods = "usb_otg_hs";
ti,has-mailbox;
multipoint = <1>;
num_eps = <16>;
ram_bits = <12>;
num-eps = <16>;
ram-bits = <12>;
ctrl-module = <&omap_control_usb>;
};
Board specific device node entry
&usb_otg_hs {
interface_type = <1>;
interface-type = <1>;
mode = <3>;
power = <50>;
};
OMAP DWC3 GLUE
- compatible : Should be "ti,dwc3"
- ti,hwmods : Should be "usb_otg_ss"
- reg : Address and length of the register set for the device.
- interrupts : The irq number of this device that is used to interrupt the
MPU
- #address-cells, #size-cells : Must be present if the device has sub-nodes
- utmi-mode : controls the source of UTMI/PIPE status for VBUS and OTG ID.
It should be set to "1" for HW mode and "2" for SW mode.
- ranges: the child address space are mapped 1:1 onto the parent address space
Sub-nodes:
The dwc3 core should be added as subnode to omap dwc3 glue.
- dwc3 :
The binding details of dwc3 can be found in:
Documentation/devicetree/bindings/usb/dwc3.txt
omap_dwc3 {
compatible = "ti,dwc3";
ti,hwmods = "usb_otg_ss";
reg = <0x4a020000 0x1ff>;
interrupts = <0 93 4>;
#address-cells = <1>;
#size-cells = <1>;
utmi-mode = <2>;
ranges;
};
OMAP CONTROL USB
Required properties:

View File

@ -1,20 +1,25 @@
* Samsung's usb phy transceiver
SAMSUNG USB-PHY controllers
The Samsung's phy transceiver is used for controlling usb phy for
s3c-hsotg as well as ehci-s5p and ohci-exynos usb controllers
across Samsung SOCs.
** Samsung's usb 2.0 phy transceiver
The Samsung's usb 2.0 phy transceiver is used for controlling
usb 2.0 phy for s3c-hsotg as well as ehci-s5p and ohci-exynos
usb controllers across Samsung SOCs.
TODO: Adding the PHY binding with controller(s) according to the under
developement generic PHY driver.
Required properties:
Exynos4210:
- compatible : should be "samsung,exynos4210-usbphy"
- compatible : should be "samsung,exynos4210-usb2phy"
- reg : base physical address of the phy registers and length of memory mapped
region.
- clocks: Clock IDs array as required by the controller.
- clock-names: names of clock correseponding IDs clock property as requested
by the controller driver.
Exynos5250:
- compatible : should be "samsung,exynos5250-usbphy"
- compatible : should be "samsung,exynos5250-usb2phy"
- reg : base physical address of the phy registers and length of memory mapped
region.
@ -44,12 +49,69 @@ Example:
usbphy@125B0000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "samsung,exynos4210-usbphy";
compatible = "samsung,exynos4210-usb2phy";
reg = <0x125B0000 0x100>;
ranges;
clocks = <&clock 2>, <&clock 305>;
clock-names = "xusbxti", "otg";
usbphy-sys {
/* USB device and host PHY_CONTROL registers */
reg = <0x10020704 0x8>;
};
};
** Samsung's usb 3.0 phy transceiver
Starting exynso5250, Samsung's SoC have usb 3.0 phy transceiver
which is used for controlling usb 3.0 phy for dwc3-exynos usb 3.0
controllers across Samsung SOCs.
Required properties:
Exynos5250:
- compatible : should be "samsung,exynos5250-usb3phy"
- reg : base physical address of the phy registers and length of memory mapped
region.
- clocks: Clock IDs array as required by the controller.
- clock-names: names of clocks correseponding to IDs in the clock property
as requested by the controller driver.
Optional properties:
- #address-cells: should be '1' when usbphy node has a child node with 'reg'
property.
- #size-cells: should be '1' when usbphy node has a child node with 'reg'
property.
- ranges: allows valid translation between child's address space and parent's
address space.
- The child node 'usbphy-sys' to the node 'usbphy' is for the system controller
interface for usb-phy. It should provide the following information required by
usb-phy controller to control phy.
- reg : base physical address of PHY_CONTROL registers.
The size of this register is the total sum of size of all PHY_CONTROL
registers that the SoC has. For example, the size will be
'0x4' in case we have only one PHY_CONTROL register (e.g.
OTHERS register in S3C64XX or USB_PHY_CONTROL register in S5PV210)
and, '0x8' in case we have two PHY_CONTROL registers (e.g.
USBDEVICE_PHY_CONTROL and USBHOST_PHY_CONTROL registers in exynos4x).
and so on.
Example:
usbphy@12100000 {
compatible = "samsung,exynos5250-usb3phy";
reg = <0x12100000 0x100>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
clocks = <&clock 1>, <&clock 286>;
clock-names = "ext_xtal", "usbdrd30";
usbphy-sys {
/* USB device and host PHY_CONTROL registers */
reg = <0x10040704 0x8>;
};
};

View File

@ -0,0 +1,34 @@
USB NOP PHY
Required properties:
- compatible: should be usb-nop-xceiv
Optional properties:
- clocks: phandle to the PHY clock. Use as per Documentation/devicetree
/bindings/clock/clock-bindings.txt
This property is required if clock-frequency is specified.
- clock-names: Should be "main_clk"
- clock-frequency: the clock frequency (in Hz) that the PHY clock must
be configured to.
- vcc-supply: phandle to the regulator that provides RESET to the PHY.
- reset-supply: phandle to the regulator that provides power to the PHY.
Example:
hsusb1_phy {
compatible = "usb-nop-xceiv";
clock-frequency = <19200000>;
clocks = <&osc 0>;
clock-names = "main_clk";
vcc-supply = <&hsusb1_vcc_regulator>;
reset-supply = <&hsusb1_reset_regulator>;
};
hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator
and expects that clock to be configured to 19.2MHz by the NOP PHY driver.
hsusb1_vcc_regulator provides power to the PHY and hsusb1_reset_regulator
controls RESET.

View File

@ -223,13 +223,7 @@ static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
};
#if defined(CONFIG_USB_EHCI_MV)
static char *pxa168_sph_clock_name[] = {
[0] = "PXA168-USBCLK",
};
static struct mv_usb_platform_data pxa168_sph_pdata = {
.clknum = 1,
.clkname = pxa168_sph_clock_name,
.mode = MV_USB_MODE_HOST,
.phy_init = pxa_usb_phy_init,
.phy_deinit = pxa_usb_phy_deinit,

View File

@ -162,13 +162,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
#ifdef CONFIG_USB_SUPPORT
#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
static char *pxa910_usb_clock_name[] = {
[0] = "U2OCLK",
};
static struct mv_usb_platform_data ttc_usb_pdata = {
.clknum = 1,
.clkname = pxa910_usb_clock_name,
.vbus = NULL,
.mode = MV_USB_MODE_OTG,
.otg_force_a_bus_req = 1,

View File

@ -169,7 +169,7 @@ static int usbhsf_get_id(struct platform_device *pdev)
return USBHS_GADGET;
}
static void usbhsf_power_ctrl(struct platform_device *pdev,
static int usbhsf_power_ctrl(struct platform_device *pdev,
void __iomem *base, int enable)
{
struct usbhsf_private *priv = usbhsf_get_priv(pdev);
@ -223,6 +223,8 @@ static void usbhsf_power_ctrl(struct platform_device *pdev,
clk_disable(priv->pci); /* usb work around */
clk_disable(priv->usb24); /* usb work around */
}
return 0;
}
static int usbhsf_get_vbus(struct platform_device *pdev)
@ -239,7 +241,7 @@ static irqreturn_t usbhsf_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
static void usbhsf_hardware_exit(struct platform_device *pdev)
static int usbhsf_hardware_exit(struct platform_device *pdev)
{
struct usbhsf_private *priv = usbhsf_get_priv(pdev);
@ -264,6 +266,8 @@ static void usbhsf_hardware_exit(struct platform_device *pdev)
priv->usbh_base = NULL;
free_irq(IRQ7, pdev);
return 0;
}
static int usbhsf_hardware_init(struct platform_device *pdev)

View File

@ -155,12 +155,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
return !((1 << 7) & __raw_readw(priv->cr2));
}
static void usbhs_phy_reset(struct platform_device *pdev)
static int usbhs_phy_reset(struct platform_device *pdev)
{
struct usbhs_private *priv = usbhs_get_priv(pdev);
/* init phy */
__raw_writew(0x8a0a, priv->cr2);
return 0;
}
static int usbhs_get_id(struct platform_device *pdev)
@ -202,7 +204,7 @@ static int usbhs_hardware_init(struct platform_device *pdev)
return 0;
}
static void usbhs_hardware_exit(struct platform_device *pdev)
static int usbhs_hardware_exit(struct platform_device *pdev)
{
struct usbhs_private *priv = usbhs_get_priv(pdev);
@ -210,6 +212,8 @@ static void usbhs_hardware_exit(struct platform_device *pdev)
__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
free_irq(IRQ15, pdev);
return 0;
}
static u32 usbhs_pipe_cfg[] = {

View File

@ -596,12 +596,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
return usbhs_is_connected(usbhs_get_priv(pdev));
}
static void usbhs_phy_reset(struct platform_device *pdev)
static int usbhs_phy_reset(struct platform_device *pdev)
{
struct usbhs_private *priv = usbhs_get_priv(pdev);
/* init phy */
__raw_writew(0x8a0a, priv->usbcrcaddr);
return 0;
}
static int usbhs0_get_id(struct platform_device *pdev)
@ -628,11 +630,13 @@ static int usbhs0_hardware_init(struct platform_device *pdev)
return 0;
}
static void usbhs0_hardware_exit(struct platform_device *pdev)
static int usbhs0_hardware_exit(struct platform_device *pdev)
{
struct usbhs_private *priv = usbhs_get_priv(pdev);
cancel_delayed_work_sync(&priv->work);
return 0;
}
static struct usbhs_private usbhs0_private = {
@ -735,7 +739,7 @@ static int usbhs1_hardware_init(struct platform_device *pdev)
return 0;
}
static void usbhs1_hardware_exit(struct platform_device *pdev)
static int usbhs1_hardware_exit(struct platform_device *pdev)
{
struct usbhs_private *priv = usbhs_get_priv(pdev);
@ -743,6 +747,8 @@ static void usbhs1_hardware_exit(struct platform_device *pdev)
__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
free_irq(IRQ8, pdev);
return 0;
}
static int usbhs1_get_id(struct platform_device *pdev)

View File

@ -18,8 +18,8 @@ config ARCH_TEGRA_2x_SOC
select PL310_ERRATA_727915 if CACHE_L2X0
select PL310_ERRATA_769419 if CACHE_L2X0
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB
select USB_ULPI_VIEWPORT if USB_SUPPORT
select USB_ULPI if USB_PHY
select USB_ULPI_VIEWPORT if USB_PHY
help
Support for NVIDIA Tegra AP20 and T20 processors, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@ -37,8 +37,8 @@ config ARCH_TEGRA_3x_SOC
select PINCTRL_TEGRA30
select PL310_ERRATA_769419 if CACHE_L2X0
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB
select USB_ULPI_VIEWPORT if USB_SUPPORT
select USB_ULPI if USB_PHY
select USB_ULPI_VIEWPORT if USB_PHY
help
Support for NVIDIA Tegra T30 processor family, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller

View File

@ -254,11 +254,13 @@ static int usbhs_get_id(struct platform_device *pdev)
return gpio_get_value(GPIO_PTB3);
}
static void usbhs_phy_reset(struct platform_device *pdev)
static int usbhs_phy_reset(struct platform_device *pdev)
{
/* enable vbus if HOST */
if (!gpio_get_value(GPIO_PTB3))
gpio_set_value(GPIO_PTB5, 1);
return 0;
}
static struct renesas_usbhs_platform_info usbhs_info = {

View File

@ -79,7 +79,7 @@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/
obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_UWB) += uwb/
obj-$(CONFIG_USB_OTG_UTILS) += usb/
obj-$(CONFIG_USB_PHY) += usb/
obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_PCI) += usb/
obj-$(CONFIG_USB_GADGET) += usb/

View File

@ -254,7 +254,7 @@ config BATTERY_RX51
config CHARGER_ISP1704
tristate "ISP1704 USB Charger Detection"
depends on USB_OTG_UTILS
depends on USB_PHY
help
Say Y to enable support for USB Charger Detection with
ISP1707/ISP1704 USB transceivers.

View File

@ -35,7 +35,7 @@ static struct timer_list supply_timer;
static struct timer_list polling_timer;
static int polling;
#ifdef CONFIG_USB_OTG_UTILS
#if IS_ENABLED(CONFIG_USB_PHY)
static struct usb_phy *transceiver;
static struct notifier_block otg_nb;
#endif
@ -218,7 +218,7 @@ static void polling_timer_func(unsigned long unused)
jiffies + msecs_to_jiffies(pdata->polling_interval));
}
#ifdef CONFIG_USB_OTG_UTILS
#if IS_ENABLED(CONFIG_USB_PHY)
static int otg_is_usb_online(void)
{
return (transceiver->last_event == USB_EVENT_VBUS ||
@ -315,7 +315,7 @@ static int pda_power_probe(struct platform_device *pdev)
pda_psy_usb.num_supplicants = pdata->num_supplicants;
}
#ifdef CONFIG_USB_OTG_UTILS
#if IS_ENABLED(CONFIG_USB_PHY)
transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(transceiver)) {
if (!pdata->is_usb_online)
@ -367,7 +367,7 @@ static int pda_power_probe(struct platform_device *pdev)
}
}
#ifdef CONFIG_USB_OTG_UTILS
#if IS_ENABLED(CONFIG_USB_PHY)
if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
otg_nb.notifier_call = otg_handle_notification;
ret = usb_register_notifier(transceiver, &otg_nb);
@ -391,7 +391,7 @@ static int pda_power_probe(struct platform_device *pdev)
return 0;
#ifdef CONFIG_USB_OTG_UTILS
#if IS_ENABLED(CONFIG_USB_PHY)
otg_reg_notifier_failed:
if (pdata->is_usb_online && usb_irq)
free_irq(usb_irq->start, &pda_psy_usb);
@ -402,7 +402,7 @@ static int pda_power_probe(struct platform_device *pdev)
usb_supply_failed:
if (pdata->is_ac_online && ac_irq)
free_irq(ac_irq->start, &pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
#if IS_ENABLED(CONFIG_USB_PHY)
if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver);
#endif
@ -437,7 +437,7 @@ static int pda_power_remove(struct platform_device *pdev)
power_supply_unregister(&pda_psy_usb);
if (pdata->is_ac_online)
power_supply_unregister(&pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
#if IS_ENABLED(CONFIG_USB_PHY)
if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver);
#endif

View File

@ -186,6 +186,4 @@ source "drivers/usb/atm/Kconfig"
source "drivers/usb/gadget/Kconfig"
source "drivers/usb/otg/Kconfig"
endif # USB_SUPPORT

View File

@ -6,8 +6,6 @@
obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_OTG_UTILS) += otg/
obj-$(CONFIG_USB_DWC3) += dwc3/
obj-$(CONFIG_USB_MON) += mon/
@ -46,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/
obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB) += misc/
obj-$(CONFIG_USB_OTG_UTILS) += phy/
obj-$(CONFIG_USB_PHY) += phy/
obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/
obj-$(CONFIG_USB_ATM) += atm/

View File

@ -1638,16 +1638,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
return retval;
}
/**
* udc_release: driver release function
* @dev: device
*
* Currently does nothing
*/
static void udc_release(struct device *dev)
{
}
/**
* udc_start: initialize gadget role
* @ci: chipidea controller
@ -1667,12 +1657,6 @@ static int udc_start(struct ci13xxx *ci)
INIT_LIST_HEAD(&ci->gadget.ep_list);
dev_set_name(&ci->gadget.dev, "gadget");
ci->gadget.dev.dma_mask = dev->dma_mask;
ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
ci->gadget.dev.parent = dev;
ci->gadget.dev.release = udc_release;
/* alloc resources */
ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
sizeof(struct ci13xxx_qh),
@ -1710,17 +1694,11 @@ static int udc_start(struct ci13xxx *ci)
goto put_transceiver;
}
retval = device_register(&ci->gadget.dev);
if (retval) {
put_device(&ci->gadget.dev);
goto put_transceiver;
}
if (!IS_ERR_OR_NULL(ci->transceiver)) {
retval = otg_set_peripheral(ci->transceiver->otg,
&ci->gadget);
if (retval)
goto unreg_device;
goto put_transceiver;
}
retval = usb_add_gadget_udc(dev, &ci->gadget);
@ -1740,8 +1718,6 @@ static int udc_start(struct ci13xxx *ci)
}
dev_err(dev, "error = %i\n", retval);
unreg_device:
device_unregister(&ci->gadget.dev);
put_transceiver:
if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
usb_put_phy(ci->transceiver);
@ -1776,7 +1752,6 @@ static void udc_stop(struct ci13xxx *ci)
if (ci->global_phy)
usb_put_phy(ci->transceiver);
}
device_unregister(&ci->gadget.dev);
/* my kobject is dynamic, I swear! */
memset(&ci->gadget, 0, sizeof(ci->gadget));
}

View File

@ -1,7 +1,6 @@
config USB_DWC3
tristate "DesignWare USB3 DRD Core Support"
depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
select USB_OTG_UTILS
select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
help
Say Y or M here if your system has a Dual Role SuperSpeed

View File

@ -140,7 +140,8 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
* Returns a pointer to the allocated event buffer structure on success
* otherwise ERR_PTR(errno).
*/
static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
unsigned length)
{
struct dwc3_event_buffer *evt;
@ -259,6 +260,17 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
}
}
static void dwc3_core_num_eps(struct dwc3 *dwc)
{
struct dwc3_hwparams *parms = &dwc->hwparams;
dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
dwc->num_in_eps, dwc->num_out_eps);
}
static void dwc3_cache_hwparams(struct dwc3 *dwc)
{
struct dwc3_hwparams *parms = &dwc->hwparams;
@ -335,13 +347,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (dwc->revision < DWC3_REVISION_190A)
reg |= DWC3_GCTL_U2RSTECN;
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
dwc3_core_num_eps(dwc);
ret = dwc3_event_buffers_setup(dwc);
if (ret) {
dev_err(dwc->dev, "failed to setup event buffers\n");
goto err0;
}
dwc3_writel(dwc->regs, DWC3_GCTL, reg);
return 0;
@ -351,8 +359,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
static void dwc3_core_exit(struct dwc3 *dwc)
{
dwc3_event_buffers_cleanup(dwc);
usb_phy_shutdown(dwc->usb2_phy);
usb_phy_shutdown(dwc->usb3_phy);
}
@ -428,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
}
if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
if (IS_ERR(dwc->usb2_phy)) {
ret = PTR_ERR(dwc->usb2_phy);
/*
* if -ENXIO is returned, it means PHY layer wasn't
* enabled, so it makes no sense to return -EPROBE_DEFER
* in that case, since no PHY driver will ever probe.
*/
if (ret == -ENXIO)
return ret;
dev_err(dev, "no usb2 phy configured\n");
return -EPROBE_DEFER;
}
if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
if (IS_ERR(dwc->usb3_phy)) {
ret = PTR_ERR(dwc->usb2_phy);
/*
* if -ENXIO is returned, it means PHY layer wasn't
* enabled, so it makes no sense to return -EPROBE_DEFER
* in that case, since no PHY driver will ever probe.
*/
if (ret == -ENXIO)
return ret;
dev_err(dev, "no usb3 phy configured\n");
return -EPROBE_DEFER;
}
@ -448,6 +474,10 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->regs_size = resource_size(res);
dwc->dev = dev;
dev->dma_mask = dev->parent->dma_mask;
dev->dma_parms = dev->parent->dma_parms;
dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
if (!strncmp("super", maximum_speed, 5))
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
else if (!strncmp("high", maximum_speed, 4))
@ -480,7 +510,18 @@ static int dwc3_probe(struct platform_device *pdev)
goto err0;
}
mode = DWC3_MODE(dwc->hwparams.hwparams0);
ret = dwc3_event_buffers_setup(dwc);
if (ret) {
dev_err(dwc->dev, "failed to setup event buffers\n");
goto err1;
}
if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
mode = DWC3_MODE_HOST;
else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
mode = DWC3_MODE_DEVICE;
else
mode = DWC3_MODE_DRD;
switch (mode) {
case DWC3_MODE_DEVICE:
@ -488,7 +529,7 @@ static int dwc3_probe(struct platform_device *pdev)
ret = dwc3_gadget_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize gadget\n");
goto err1;
goto err2;
}
break;
case DWC3_MODE_HOST:
@ -496,7 +537,7 @@ static int dwc3_probe(struct platform_device *pdev)
ret = dwc3_host_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize host\n");
goto err1;
goto err2;
}
break;
case DWC3_MODE_DRD:
@ -504,32 +545,32 @@ static int dwc3_probe(struct platform_device *pdev)
ret = dwc3_host_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize host\n");
goto err1;
goto err2;
}
ret = dwc3_gadget_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize gadget\n");
goto err1;
goto err2;
}
break;
default:
dev_err(dev, "Unsupported mode of operation %d\n", mode);
goto err1;
goto err2;
}
dwc->mode = mode;
ret = dwc3_debugfs_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize debugfs\n");
goto err2;
goto err3;
}
pm_runtime_allow(dev);
return 0;
err2:
err3:
switch (mode) {
case DWC3_MODE_DEVICE:
dwc3_gadget_exit(dwc);
@ -546,6 +587,9 @@ static int dwc3_probe(struct platform_device *pdev)
break;
}
err2:
dwc3_event_buffers_cleanup(dwc);
err1:
dwc3_core_exit(dwc);
@ -583,12 +627,130 @@ static int dwc3_remove(struct platform_device *pdev)
break;
}
dwc3_event_buffers_cleanup(dwc);
dwc3_free_event_buffers(dwc);
dwc3_core_exit(dwc);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int dwc3_prepare(struct device *dev)
{
struct dwc3 *dwc = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&dwc->lock, flags);
switch (dwc->mode) {
case DWC3_MODE_DEVICE:
case DWC3_MODE_DRD:
dwc3_gadget_prepare(dwc);
/* FALLTHROUGH */
case DWC3_MODE_HOST:
default:
dwc3_event_buffers_cleanup(dwc);
break;
}
spin_unlock_irqrestore(&dwc->lock, flags);
return 0;
}
static void dwc3_complete(struct device *dev)
{
struct dwc3 *dwc = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&dwc->lock, flags);
switch (dwc->mode) {
case DWC3_MODE_DEVICE:
case DWC3_MODE_DRD:
dwc3_gadget_complete(dwc);
/* FALLTHROUGH */
case DWC3_MODE_HOST:
default:
dwc3_event_buffers_setup(dwc);
break;
}
spin_unlock_irqrestore(&dwc->lock, flags);
}
static int dwc3_suspend(struct device *dev)
{
struct dwc3 *dwc = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&dwc->lock, flags);
switch (dwc->mode) {
case DWC3_MODE_DEVICE:
case DWC3_MODE_DRD:
dwc3_gadget_suspend(dwc);
/* FALLTHROUGH */
case DWC3_MODE_HOST:
default:
/* do nothing */
break;
}
dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL);
spin_unlock_irqrestore(&dwc->lock, flags);
usb_phy_shutdown(dwc->usb3_phy);
usb_phy_shutdown(dwc->usb2_phy);
return 0;
}
static int dwc3_resume(struct device *dev)
{
struct dwc3 *dwc = dev_get_drvdata(dev);
unsigned long flags;
usb_phy_init(dwc->usb3_phy);
usb_phy_init(dwc->usb2_phy);
msleep(100);
spin_lock_irqsave(&dwc->lock, flags);
dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
switch (dwc->mode) {
case DWC3_MODE_DEVICE:
case DWC3_MODE_DRD:
dwc3_gadget_resume(dwc);
/* FALLTHROUGH */
case DWC3_MODE_HOST:
default:
/* do nothing */
break;
}
spin_unlock_irqrestore(&dwc->lock, flags);
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
return 0;
}
static const struct dev_pm_ops dwc3_dev_pm_ops = {
.prepare = dwc3_prepare,
.complete = dwc3_complete,
SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
};
#define DWC3_PM_OPS &(dwc3_dev_pm_ops)
#else
#define DWC3_PM_OPS NULL
#endif
#ifdef CONFIG_OF
static const struct of_device_id of_dwc3_match[] = {
{
@ -605,6 +767,7 @@ static struct platform_driver dwc3_driver = {
.driver = {
.name = "dwc3",
.of_match_table = of_match_ptr(of_dwc3_match),
.pm = DWC3_PM_OPS,
},
};

View File

@ -154,8 +154,9 @@
/* OTG Registers */
#define DWC3_OCFG 0xcc00
#define DWC3_OCTL 0xcc04
#define DWC3_OEVTEN 0xcc08
#define DWC3_OSTS 0xcc0C
#define DWC3_OEVT 0xcc08
#define DWC3_OEVTEN 0xcc0C
#define DWC3_OSTS 0xcc10
/* Bit fields */
@ -369,6 +370,9 @@ struct dwc3_trb;
* @list: a list of event buffers
* @buf: _THE_ buffer
* @length: size of this buffer
* @lpos: event offset
* @count: cache of last read event count register
* @flags: flags related to this event buffer
* @dma: dma_addr_t
* @dwc: pointer to DWC controller
*/
@ -376,6 +380,10 @@ struct dwc3_event_buffer {
void *buf;
unsigned length;
unsigned int lpos;
unsigned int count;
unsigned int flags;
#define DWC3_EVENT_PENDING BIT(0)
dma_addr_t dma;
@ -487,12 +495,6 @@ enum dwc3_link_state {
DWC3_LINK_STATE_MASK = 0x0f,
};
enum dwc3_device_state {
DWC3_DEFAULT_STATE,
DWC3_ADDRESS_STATE,
DWC3_CONFIGURED_STATE,
};
/* TRB Length, PCM and Status */
#define DWC3_TRB_SIZE_MASK (0x00ffffff)
#define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK)
@ -574,6 +576,14 @@ struct dwc3_hwparams {
/* HWPARAMS1 */
#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15)
/* HWPARAMS3 */
#define DWC3_NUM_IN_EPS_MASK (0x1f << 18)
#define DWC3_NUM_EPS_MASK (0x3f << 12)
#define DWC3_NUM_EPS(p) (((p)->hwparams3 & \
(DWC3_NUM_EPS_MASK)) >> 12)
#define DWC3_NUM_IN_EPS(p) (((p)->hwparams3 & \
(DWC3_NUM_IN_EPS_MASK)) >> 18)
/* HWPARAMS7 */
#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff)
@ -618,7 +628,6 @@ struct dwc3_scratchpad_array {
* @gadget_driver: pointer to the gadget driver
* @regs: base address for our registers
* @regs_size: address space size
* @irq: IRQ number
* @num_event_buffers: calculated number of event buffers
* @u1u2: only used on revisions <1.83a for workaround
* @maximum_speed: maximum speed requested (mainly for testing purposes)
@ -626,6 +635,8 @@ struct dwc3_scratchpad_array {
* @mode: mode of operation
* @usb2_phy: pointer to USB2 PHY
* @usb3_phy: pointer to USB3 PHY
* @dcfg: saved contents of DCFG register
* @gctl: saved contents of GCTL register
* @is_selfpowered: true when we are selfpowered
* @three_stage_setup: set if we perform a three phase setup
* @ep0_bounced: true when we used bounce buffer
@ -639,6 +650,8 @@ struct dwc3_scratchpad_array {
* @u2pel: parameter from Set SEL request.
* @u1sel: parameter from Set SEL request.
* @u1pel: parameter from Set SEL request.
* @num_out_eps: number of out endpoints
* @num_in_eps: number of in endpoints
* @ep0_next_event: hold the next expected event
* @ep0state: state of endpoint zero
* @link_state: link state
@ -656,8 +669,10 @@ struct dwc3 {
dma_addr_t ep0_trb_addr;
dma_addr_t ep0_bounce_addr;
struct dwc3_request ep0_usb_req;
/* device lock */
spinlock_t lock;
struct device *dev;
struct platform_device *xhci;
@ -675,6 +690,10 @@ struct dwc3 {
void __iomem *regs;
size_t regs_size;
/* used for suspend/resume */
u32 dcfg;
u32 gctl;
u32 num_event_buffers;
u32 u1u2;
u32 maximum_speed;
@ -694,6 +713,9 @@ struct dwc3 {
#define DWC3_REVISION_202A 0x5533202a
#define DWC3_REVISION_210A 0x5533210a
#define DWC3_REVISION_220A 0x5533220a
#define DWC3_REVISION_230A 0x5533230a
#define DWC3_REVISION_240A 0x5533240a
#define DWC3_REVISION_250A 0x5533250a
unsigned is_selfpowered:1;
unsigned three_stage_setup:1;
@ -704,11 +726,11 @@ struct dwc3 {
unsigned delayed_status:1;
unsigned needs_fifo_resize:1;
unsigned resize_fifos:1;
unsigned pullups_connected:1;
enum dwc3_ep0_next ep0_next_event;
enum dwc3_ep0_state ep0state;
enum dwc3_link_state link_state;
enum dwc3_device_state dev_state;
u16 isoch_delay;
u16 u2sel;
@ -718,6 +740,9 @@ struct dwc3 {
u8 speed;
u8 num_out_eps;
u8 num_in_eps;
void *mem;
struct dwc3_hwparams hwparams;
@ -884,4 +909,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc)
{ }
#endif
/* power management interface */
#if !IS_ENABLED(CONFIG_USB_DWC3_HOST)
int dwc3_gadget_prepare(struct dwc3 *dwc);
void dwc3_gadget_complete(struct dwc3 *dwc);
int dwc3_gadget_suspend(struct dwc3 *dwc);
int dwc3_gadget_resume(struct dwc3 *dwc);
#else
static inline int dwc3_gadget_prepare(struct dwc3 *dwc)
{
return 0;
}
static inline void dwc3_gadget_complete(struct dwc3 *dwc)
{
}
static inline int dwc3_gadget_suspend(struct dwc3 *dwc)
{
return 0;
}
static inline int dwc3_gadget_resume(struct dwc3 *dwc)
{
return 0;
}
#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */
#endif /* __DRIVERS_USB_DWC3_CORE_H */

View File

@ -59,7 +59,7 @@
.offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \
}
static struct debugfs_reg32 dwc3_regs[] = {
static const struct debugfs_reg32 dwc3_regs[] = {
dump_register(GSBUSCFG0),
dump_register(GSBUSCFG1),
dump_register(GTXTHRCFG),
@ -372,6 +372,7 @@ static struct debugfs_reg32 dwc3_regs[] = {
dump_register(OCFG),
dump_register(OCTL),
dump_register(OEVT),
dump_register(OEVTEN),
dump_register(OSTS),
};
@ -577,8 +578,14 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
case DWC3_LINK_STATE_LPBK:
seq_printf(s, "Loopback\n");
break;
case DWC3_LINK_STATE_RESET:
seq_printf(s, "Reset\n");
break;
case DWC3_LINK_STATE_RESUME:
seq_printf(s, "Resume\n");
break;
default:
seq_printf(s, "UNKNOWN %d\n", reg);
seq_printf(s, "UNKNOWN %d\n", state);
}
return 0;
@ -661,28 +668,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
goto err1;
}
#if IS_ENABLED(CONFIG_USB_DWC3_GADGET)
file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_mode_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_mode_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
}
}
file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_testmode_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
}
if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) ||
IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_testmode_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
}
file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_link_state_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_link_state_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
}
}
#endif
return 0;

View File

@ -22,9 +22,9 @@
#include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/of.h>
#include <linux/of_platform.h>
struct dwc3_exynos {
struct platform_device *dwc3;
struct platform_device *usb2_phy;
struct platform_device *usb3_phy;
struct device *dev;
@ -86,21 +86,30 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
return ret;
}
static int dwc3_exynos_remove_child(struct device *dev, void *unused)
{
struct platform_device *pdev = to_platform_device(dev);
platform_device_unregister(pdev);
return 0;
}
static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
static int dwc3_exynos_probe(struct platform_device *pdev)
{
struct platform_device *dwc3;
struct dwc3_exynos *exynos;
struct clk *clk;
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
int ret = -ENOMEM;
exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
if (!exynos) {
dev_err(dev, "not enough memory\n");
return -ENOMEM;
goto err1;
}
/*
@ -108,21 +117,15 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
* Since shared usb code relies on it, set it here for now.
* Once we move to full device tree support this will vanish off.
*/
if (!pdev->dev.dma_mask)
pdev->dev.dma_mask = &dwc3_exynos_dma_mask;
if (!dev->dma_mask)
dev->dma_mask = &dwc3_exynos_dma_mask;
platform_set_drvdata(pdev, exynos);
ret = dwc3_exynos_register_phys(exynos);
if (ret) {
dev_err(dev, "couldn't register PHYs\n");
return ret;
}
dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc3) {
dev_err(dev, "couldn't allocate dwc3 device\n");
return -ENOMEM;
goto err1;
}
clk = devm_clk_get(dev, "usbdrd30");
@ -132,37 +135,28 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
goto err1;
}
dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
dwc3->dev.parent = dev;
dwc3->dev.dma_mask = dev->dma_mask;
dwc3->dev.dma_parms = dev->dma_parms;
exynos->dwc3 = dwc3;
exynos->dev = dev;
exynos->clk = clk;
clk_enable(exynos->clk);
clk_prepare_enable(exynos->clk);
ret = platform_device_add_resources(dwc3, pdev->resource,
pdev->num_resources);
if (ret) {
dev_err(dev, "couldn't add resources to dwc3 device\n");
goto err2;
}
ret = platform_device_add(dwc3);
if (ret) {
dev_err(dev, "failed to register dwc3 device\n");
if (node) {
ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) {
dev_err(dev, "failed to add dwc3 core\n");
goto err2;
}
} else {
dev_err(dev, "no device node, failed to add dwc3 core\n");
ret = -ENODEV;
goto err2;
}
return 0;
err2:
clk_disable(clk);
clk_disable_unprepare(clk);
err1:
platform_device_put(dwc3);
return ret;
}
@ -170,11 +164,11 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
{
struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
platform_device_unregister(exynos->dwc3);
platform_device_unregister(exynos->usb2_phy);
platform_device_unregister(exynos->usb3_phy);
device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
clk_disable(exynos->clk);
clk_disable_unprepare(exynos->clk);
return 0;
}
@ -187,12 +181,46 @@ static const struct of_device_id exynos_dwc3_match[] = {
MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
#endif
#ifdef CONFIG_PM_SLEEP
static int dwc3_exynos_suspend(struct device *dev)
{
struct dwc3_exynos *exynos = dev_get_drvdata(dev);
clk_disable(exynos->clk);
return 0;
}
static int dwc3_exynos_resume(struct device *dev)
{
struct dwc3_exynos *exynos = dev_get_drvdata(dev);
clk_enable(exynos->clk);
/* runtime set active to reflect active state. */
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
return 0;
}
static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dwc3_exynos_suspend, dwc3_exynos_resume)
};
#define DEV_PM_OPS (&dwc3_exynos_dev_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
static struct platform_driver dwc3_exynos_driver = {
.probe = dwc3_exynos_probe,
.remove = dwc3_exynos_remove,
.driver = {
.name = "exynos-dwc3",
.of_match_table = of_match_ptr(exynos_dwc3_match),
.pm = DEV_PM_OPS,
},
};

View File

@ -52,7 +52,6 @@
#include <linux/of_platform.h>
#include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
/*
* All these registers belong to OMAP's Wrapper around the
@ -117,20 +116,17 @@ struct dwc3_omap {
/* device lock */
spinlock_t lock;
struct platform_device *usb2_phy;
struct platform_device *usb3_phy;
struct device *dev;
int irq;
void __iomem *base;
void *context;
u32 resource_size;
u32 utmi_otg_status;
u32 dma_status:1;
};
struct dwc3_omap *_omap;
static struct dwc3_omap *_omap;
static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
{
@ -142,11 +138,14 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
writel(value, base + offset);
}
void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
{
u32 val;
struct dwc3_omap *omap = _omap;
if (!omap)
return -EPROBE_DEFER;
switch (status) {
case OMAP_DWC3_ID_GROUND:
dev_dbg(omap->dev, "ID GND\n");
@ -189,64 +188,10 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
dev_dbg(omap->dev, "ID float\n");
}
return;
return 0;
}
EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
static int dwc3_omap_register_phys(struct dwc3_omap *omap)
{
struct nop_usb_xceiv_platform_data pdata;
struct platform_device *pdev;
int ret;
memset(&pdata, 0x00, sizeof(pdata));
pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
if (!pdev)
return -ENOMEM;
omap->usb2_phy = pdev;
pdata.type = USB_PHY_TYPE_USB2;
ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata));
if (ret)
goto err1;
pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
if (!pdev) {
ret = -ENOMEM;
goto err1;
}
omap->usb3_phy = pdev;
pdata.type = USB_PHY_TYPE_USB3;
ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata));
if (ret)
goto err2;
ret = platform_device_add(omap->usb2_phy);
if (ret)
goto err2;
ret = platform_device_add(omap->usb3_phy);
if (ret)
goto err3;
return 0;
err3:
platform_device_del(omap->usb2_phy);
err2:
platform_device_put(omap->usb3_phy);
err1:
platform_device_put(omap->usb2_phy);
return ret;
}
static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
{
struct dwc3_omap *omap = _omap;
@ -307,121 +252,10 @@ static int dwc3_omap_remove_core(struct device *dev, void *c)
return 0;
}
static int dwc3_omap_probe(struct platform_device *pdev)
static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
{
struct dwc3_omap_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node;
struct dwc3_omap *omap;
struct resource *res;
struct device *dev = &pdev->dev;
int size;
int ret = -ENOMEM;
int irq;
const u32 *utmi_mode;
u32 reg;
void __iomem *base;
void *context;
omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
if (!omap) {
dev_err(dev, "not enough memory\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, omap);
irq = platform_get_irq(pdev, 1);
if (irq < 0) {
dev_err(dev, "missing IRQ resource\n");
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (!res) {
dev_err(dev, "missing memory base resource\n");
return -EINVAL;
}
base = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!base) {
dev_err(dev, "ioremap failed\n");
return -ENOMEM;
}
ret = dwc3_omap_register_phys(omap);
if (ret) {
dev_err(dev, "couldn't register PHYs\n");
return ret;
}
context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
if (!context) {
dev_err(dev, "couldn't allocate dwc3 context memory\n");
return -ENOMEM;
}
spin_lock_init(&omap->lock);
omap->resource_size = resource_size(res);
omap->context = context;
omap->dev = dev;
omap->irq = irq;
omap->base = base;
/*
* REVISIT if we ever have two instances of the wrapper, we will be
* in big trouble
*/
_omap = omap;
pm_runtime_enable(dev);
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
dev_err(dev, "get_sync failed with err %d\n", ret);
return ret;
}
reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
utmi_mode = of_get_property(node, "utmi-mode", &size);
if (utmi_mode && size == sizeof(*utmi_mode)) {
reg |= *utmi_mode;
} else {
if (!pdata) {
dev_dbg(dev, "missing platform data\n");
} else {
switch (pdata->utmi_mode) {
case DWC3_OMAP_UTMI_MODE_SW:
reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
break;
case DWC3_OMAP_UTMI_MODE_HW:
reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
break;
default:
dev_dbg(dev, "UNKNOWN utmi mode %d\n",
pdata->utmi_mode);
}
}
}
dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
/* check the DMA Status */
reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
"dwc3-omap", omap);
if (ret) {
dev_err(dev, "failed to request IRQ #%d --> %d\n",
omap->irq, ret);
return ret;
}
/* enable all IRQs */
reg = USBOTGSS_IRQO_COREIRQ_ST;
dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
@ -437,14 +271,120 @@ static int dwc3_omap_probe(struct platform_device *pdev)
USBOTGSS_IRQ1_IDPULLUP_FALL);
dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
}
if (node) {
ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) {
dev_err(&pdev->dev,
"failed to add create dwc3 core\n");
return ret;
}
static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
{
/* disable all IRQs */
dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, 0x00);
dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x00);
}
static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
static int dwc3_omap_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct dwc3_omap *omap;
struct resource *res;
struct device *dev = &pdev->dev;
int ret = -ENOMEM;
int irq;
int utmi_mode = 0;
u32 reg;
void __iomem *base;
if (!node) {
dev_err(dev, "device node not found\n");
return -EINVAL;
}
omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
if (!omap) {
dev_err(dev, "not enough memory\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, omap);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "missing IRQ resource\n");
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "missing memory base resource\n");
return -EINVAL;
}
base = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!base) {
dev_err(dev, "ioremap failed\n");
return -ENOMEM;
}
spin_lock_init(&omap->lock);
omap->dev = dev;
omap->irq = irq;
omap->base = base;
dev->dma_mask = &dwc3_omap_dma_mask;
/*
* REVISIT if we ever have two instances of the wrapper, we will be
* in big trouble
*/
_omap = omap;
pm_runtime_enable(dev);
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
dev_err(dev, "get_sync failed with err %d\n", ret);
return ret;
}
reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
of_property_read_u32(node, "utmi-mode", &utmi_mode);
switch (utmi_mode) {
case DWC3_OMAP_UTMI_MODE_SW:
reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
break;
case DWC3_OMAP_UTMI_MODE_HW:
reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
break;
default:
dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
}
dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
/* check the DMA Status */
reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG);
omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE);
ret = devm_request_irq(dev, omap->irq, dwc3_omap_interrupt, 0,
"dwc3-omap", omap);
if (ret) {
dev_err(dev, "failed to request IRQ #%d --> %d\n",
omap->irq, ret);
return ret;
}
dwc3_omap_enable_irqs(omap);
ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) {
dev_err(&pdev->dev, "failed to create dwc3 core\n");
return ret;
}
return 0;
@ -454,8 +394,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
{
struct dwc3_omap *omap = platform_get_drvdata(pdev);
platform_device_unregister(omap->usb2_phy);
platform_device_unregister(omap->usb3_phy);
dwc3_omap_disable_irqs(omap);
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
@ -465,18 +404,72 @@ static int dwc3_omap_remove(struct platform_device *pdev)
static const struct of_device_id of_dwc3_match[] = {
{
"ti,dwc3",
.compatible = "ti,dwc3"
},
{ },
};
MODULE_DEVICE_TABLE(of, of_dwc3_match);
#ifdef CONFIG_PM_SLEEP
static int dwc3_omap_prepare(struct device *dev)
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
dwc3_omap_disable_irqs(omap);
return 0;
}
static void dwc3_omap_complete(struct device *dev)
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
dwc3_omap_enable_irqs(omap);
}
static int dwc3_omap_suspend(struct device *dev)
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
omap->utmi_otg_status = dwc3_omap_readl(omap->base,
USBOTGSS_UTMI_OTG_STATUS);
return 0;
}
static int dwc3_omap_resume(struct device *dev)
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS,
omap->utmi_otg_status);
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
return 0;
}
static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
.prepare = dwc3_omap_prepare,
.complete = dwc3_omap_complete,
SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
};
#define DEV_PM_OPS (&dwc3_omap_dev_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM_SLEEP */
static struct platform_driver dwc3_omap_driver = {
.probe = dwc3_omap_probe,
.remove = dwc3_omap_remove,
.driver = {
.name = "omap-dwc3",
.of_match_table = of_dwc3_match,
.pm = DEV_PM_OPS,
},
};

View File

@ -212,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
};
MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
#ifdef CONFIG_PM
static int dwc3_pci_suspend(struct device *dev)
{
struct pci_dev *pci = to_pci_dev(dev);
pci_disable_device(pci);
return 0;
}
static int dwc3_pci_resume(struct device *dev)
{
struct pci_dev *pci = to_pci_dev(dev);
int ret;
ret = pci_enable_device(pci);
if (ret) {
dev_err(dev, "can't re-enable device --> %d\n", ret);
return ret;
}
pci_set_master(pci);
return 0;
}
static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
};
#define DEV_PM_OPS (&dwc3_pci_dev_pm_ops)
#else
#define DEV_PM_OPS NULL
#endif /* CONFIG_PM */
static struct pci_driver dwc3_pci_driver = {
.name = "dwc3-pci",
.id_table = dwc3_pci_id_table,
.probe = dwc3_pci_probe,
.remove = dwc3_pci_remove,
.driver = {
.pm = DEV_PM_OPS,
},
};
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");

View File

@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
u32 wIndex;
u32 reg;
int ret;
enum usb_device_state state;
wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex);
recip = ctrl->bRequestType & USB_RECIP_MASK;
state = dwc->gadget.state;
switch (recip) {
case USB_RECIP_DEVICE:
@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
* default control pipe
*/
case USB_DEVICE_U1_ENABLE:
if (dwc->dev_state != DWC3_CONFIGURED_STATE)
if (state != USB_STATE_CONFIGURED)
return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL;
@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
break;
case USB_DEVICE_U2_ENABLE:
if (dwc->dev_state != DWC3_CONFIGURED_STATE)
if (state != USB_STATE_CONFIGURED)
return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL;
@ -493,6 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
enum usb_device_state state = dwc->gadget.state;
u32 addr;
u32 reg;
@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
return -EINVAL;
}
if (dwc->dev_state == DWC3_CONFIGURED_STATE) {
if (state == USB_STATE_CONFIGURED) {
dev_dbg(dwc->dev, "trying to set address when configured\n");
return -EINVAL;
}
@ -513,9 +517,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
if (addr)
dwc->dev_state = DWC3_ADDRESS_STATE;
usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
else
dwc->dev_state = DWC3_DEFAULT_STATE;
usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
return 0;
}
@ -532,6 +536,7 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
enum usb_device_state state = dwc->gadget.state;
u32 cfg;
int ret;
u32 reg;
@ -539,16 +544,18 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc->start_config_issued = false;
cfg = le16_to_cpu(ctrl->wValue);
switch (dwc->dev_state) {
case DWC3_DEFAULT_STATE:
switch (state) {
case USB_STATE_DEFAULT:
return -EINVAL;
break;
case DWC3_ADDRESS_STATE:
case USB_STATE_ADDRESS:
ret = dwc3_ep0_delegate_req(dwc, ctrl);
/* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
dwc->dev_state = DWC3_CONFIGURED_STATE;
usb_gadget_set_state(&dwc->gadget,
USB_STATE_CONFIGURED);
/*
* Enable transition to U1/U2 state when
* nothing is pending from application.
@ -562,10 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
}
break;
case DWC3_CONFIGURED_STATE:
case USB_STATE_CONFIGURED:
ret = dwc3_ep0_delegate_req(dwc, ctrl);
if (!cfg)
dwc->dev_state = DWC3_ADDRESS_STATE;
usb_gadget_set_state(&dwc->gadget,
USB_STATE_ADDRESS);
break;
default:
ret = -EINVAL;
@ -620,10 +628,11 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
struct dwc3_ep *dep;
enum usb_device_state state = dwc->gadget.state;
u16 wLength;
u16 wValue;
if (dwc->dev_state == DWC3_DEFAULT_STATE)
if (state == USB_STATE_DEFAULT)
return -EINVAL;
wValue = le16_to_cpu(ctrl->wValue);

View File

@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
if (dwc->revision >= DWC3_REVISION_194A)
reg &= ~DWC3_DCTL_KEEP_CONNECT;
reg |= DWC3_DCTL_RUN_STOP;
dwc->pullups_connected = true;
} else {
reg &= ~DWC3_DCTL_RUN_STOP;
dwc->pullups_connected = false;
}
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
@ -1469,6 +1471,33 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
return ret;
}
static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
{
u32 reg;
/* Enable all but Start and End of Frame IRQs */
reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
DWC3_DEVTEN_EVNTOVERFLOWEN |
DWC3_DEVTEN_CMDCMPLTEN |
DWC3_DEVTEN_ERRTICERREN |
DWC3_DEVTEN_WKUPEVTEN |
DWC3_DEVTEN_ULSTCNGEN |
DWC3_DEVTEN_CONNECTDONEEN |
DWC3_DEVTEN_USBRSTEN |
DWC3_DEVTEN_DISCONNEVTEN);
dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
}
static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
{
/* mask all interrupts */
dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
}
static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
static int dwc3_gadget_start(struct usb_gadget *g,
struct usb_gadget_driver *driver)
{
@ -1476,6 +1505,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
struct dwc3_ep *dep;
unsigned long flags;
int ret = 0;
int irq;
u32 reg;
spin_lock_irqsave(&dwc->lock, flags);
@ -1489,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
}
dwc->gadget_driver = driver;
dwc->gadget.dev.driver = &driver->driver;
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg &= ~(DWC3_DCFG_SPEED_MASK);
@ -1536,6 +1565,17 @@ static int dwc3_gadget_start(struct usb_gadget *g,
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
if (ret) {
dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
irq, ret);
goto err1;
}
dwc3_gadget_enable_irq(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);
return 0;
@ -1554,14 +1594,18 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
{
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long flags;
int irq;
spin_lock_irqsave(&dwc->lock, flags);
dwc3_gadget_disable_irq(dwc);
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
free_irq(irq, dwc);
__dwc3_gadget_ep_disable(dwc->eps[0]);
__dwc3_gadget_ep_disable(dwc->eps[1]);
dwc->gadget_driver = NULL;
dwc->gadget.dev.driver = NULL;
spin_unlock_irqrestore(&dwc->lock, flags);
@ -1579,14 +1623,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
/* -------------------------------------------------------------------------- */
static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
u8 num, u32 direction)
{
struct dwc3_ep *dep;
u8 epnum;
u8 i;
INIT_LIST_HEAD(&dwc->gadget.ep_list);
for (i = 0; i < num; i++) {
u8 epnum = (i << 1) | (!!direction);
for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
dep = kzalloc(sizeof(*dep), GFP_KERNEL);
if (!dep) {
dev_err(dwc->dev, "can't allocate endpoint %d\n",
@ -1600,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
(epnum & 1) ? "in" : "out");
dep->endpoint.name = dep->name;
dep->direction = (epnum & 1);
@ -1630,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
return 0;
}
static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
{
int ret;
INIT_LIST_HEAD(&dwc->gadget.ep_list);
ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0);
if (ret < 0) {
dev_vdbg(dwc->dev, "failed to allocate OUT endpoints\n");
return ret;
}
ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1);
if (ret < 0) {
dev_vdbg(dwc->dev, "failed to allocate IN endpoints\n");
return ret;
}
return 0;
}
static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
@ -1637,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
dep = dwc->eps[epnum];
if (!dep)
continue;
dwc3_free_trb_pool(dep);
if (epnum != 0 && epnum != 1)
@ -1646,12 +1716,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
}
}
static void dwc3_gadget_release(struct device *dev)
{
dev_dbg(dev, "%s\n", __func__);
}
/* -------------------------------------------------------------------------- */
static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
struct dwc3_request *req, struct dwc3_trb *trb,
const struct dwc3_event_depevt *event, int status)
@ -1975,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
struct dwc3_ep *dep;
dep = dwc->eps[epnum];
if (!dep)
continue;
if (!(dep->flags & DWC3_EP_ENABLED))
continue;
@ -1992,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
int ret;
dep = dwc->eps[epnum];
if (!dep)
continue;
if (!(dep->flags & DWC3_EP_STALL))
continue;
@ -2091,7 +2162,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
}
/* after reset -> Default State */
dwc->dev_state = DWC3_DEFAULT_STATE;
usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
/* Recent versions support automatic phy suspend and don't need this */
if (dwc->revision < DWC3_REVISION_194A) {
@ -2277,6 +2348,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
unsigned int evtinfo)
{
enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK;
unsigned int pwropt;
/*
* WORKAROUND: DWC3 < 2.50a have an issue when configured without
* Hibernation mode enabled which would show up when device detects
* host-initiated U3 exit.
*
* In that case, device will generate a Link State Change Interrupt
* from U3 to RESUME which is only necessary if Hibernation is
* configured in.
*
* There are no functional changes due to such spurious event and we
* just need to ignore it.
*
* Refers to:
*
* STAR#9000570034 RTL: SS Resume event generated in non-Hibernation
* operational mode
*/
pwropt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1);
if ((dwc->revision < DWC3_REVISION_250A) &&
(pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) {
if ((dwc->link_state == DWC3_LINK_STATE_U3) &&
(next == DWC3_LINK_STATE_RESUME)) {
dev_vdbg(dwc->dev, "ignoring transition U3 -> Resume\n");
return;
}
}
/*
* WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending
@ -2387,40 +2486,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
}
}
static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
{
struct dwc3 *dwc = _dwc;
unsigned long flags;
irqreturn_t ret = IRQ_NONE;
int i;
spin_lock_irqsave(&dwc->lock, flags);
for (i = 0; i < dwc->num_event_buffers; i++) {
struct dwc3_event_buffer *evt;
int left;
evt = dwc->ev_buffs[i];
left = evt->count;
if (!(evt->flags & DWC3_EVENT_PENDING))
continue;
while (left > 0) {
union dwc3_event event;
event.raw = *(u32 *) (evt->buf + evt->lpos);
dwc3_process_event_entry(dwc, &event);
/*
* FIXME we wrap around correctly to the next entry as
* almost all entries are 4 bytes in size. There is one
* entry which has 12 bytes which is a regular entry
* followed by 8 bytes data. ATM I don't know how
* things are organized if we get next to the a
* boundary so I worry about that once we try to handle
* that.
*/
evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
left -= 4;
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4);
}
evt->count = 0;
evt->flags &= ~DWC3_EVENT_PENDING;
ret = IRQ_HANDLED;
}
spin_unlock_irqrestore(&dwc->lock, flags);
return ret;
}
static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
{
struct dwc3_event_buffer *evt;
int left;
u32 count;
evt = dwc->ev_buffs[buf];
count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));
count &= DWC3_GEVNTCOUNT_MASK;
if (!count)
return IRQ_NONE;
evt = dwc->ev_buffs[buf];
left = count;
evt->count = count;
evt->flags |= DWC3_EVENT_PENDING;
while (left > 0) {
union dwc3_event event;
event.raw = *(u32 *) (evt->buf + evt->lpos);
dwc3_process_event_entry(dwc, &event);
/*
* XXX we wrap around correctly to the next entry as almost all
* entries are 4 bytes in size. There is one entry which has 12
* bytes which is a regular entry followed by 8 bytes data. ATM
* I don't know how things are organized if were get next to the
* a boundary so I worry about that once we try to handle that.
*/
evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
left -= 4;
dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
}
return IRQ_HANDLED;
return IRQ_WAKE_THREAD;
}
static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
@ -2435,7 +2567,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
irqreturn_t status;
status = dwc3_process_event_buf(dwc, i);
if (status == IRQ_HANDLED)
if (status == IRQ_WAKE_THREAD)
ret = status;
}
@ -2454,7 +2586,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
{
u32 reg;
int ret;
int irq;
dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
&dwc->ctrl_req_addr, GFP_KERNEL);
@ -2488,19 +2619,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err3;
}
dev_set_name(&dwc->gadget.dev, "gadget");
dwc->gadget.ops = &dwc3_gadget_ops;
dwc->gadget.max_speed = USB_SPEED_SUPER;
dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->gadget.dev.parent = dwc->dev;
dwc->gadget.sg_supported = true;
dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask);
dwc->gadget.dev.dma_parms = dwc->dev->dma_parms;
dwc->gadget.dev.dma_mask = dwc->dev->dma_mask;
dwc->gadget.dev.release = dwc3_gadget_release;
dwc->gadget.name = "dwc3-gadget";
/*
@ -2512,60 +2634,24 @@ int dwc3_gadget_init(struct dwc3 *dwc)
if (ret)
goto err4;
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED,
"dwc3", dwc);
if (ret) {
dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
irq, ret);
goto err5;
}
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg |= DWC3_DCFG_LPM_CAP;
dwc3_writel(dwc->regs, DWC3_DCFG, reg);
/* Enable all but Start and End of Frame IRQs */
reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
DWC3_DEVTEN_EVNTOVERFLOWEN |
DWC3_DEVTEN_CMDCMPLTEN |
DWC3_DEVTEN_ERRTICERREN |
DWC3_DEVTEN_WKUPEVTEN |
DWC3_DEVTEN_ULSTCNGEN |
DWC3_DEVTEN_CONNECTDONEEN |
DWC3_DEVTEN_USBRSTEN |
DWC3_DEVTEN_DISCONNEVTEN);
dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
/* automatic phy suspend only on recent versions */
/* Enable USB2 LPM and automatic phy suspend only on recent versions */
if (dwc->revision >= DWC3_REVISION_194A) {
dwc3_gadget_usb2_phy_suspend(dwc, false);
dwc3_gadget_usb3_phy_suspend(dwc, false);
}
ret = device_register(&dwc->gadget.dev);
if (ret) {
dev_err(dwc->dev, "failed to register gadget device\n");
put_device(&dwc->gadget.dev);
goto err6;
}
ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
if (ret) {
dev_err(dwc->dev, "failed to register udc\n");
goto err7;
goto err5;
}
return 0;
err7:
device_unregister(&dwc->gadget.dev);
err6:
dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
free_irq(irq, dwc);
err5:
dwc3_gadget_free_endpoints(dwc);
@ -2588,15 +2674,11 @@ int dwc3_gadget_init(struct dwc3 *dwc)
return ret;
}
/* -------------------------------------------------------------------------- */
void dwc3_gadget_exit(struct dwc3 *dwc)
{
int irq;
usb_del_gadget_udc(&dwc->gadget);
irq = platform_get_irq(to_platform_device(dwc->dev), 0);
dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
free_irq(irq, dwc);
dwc3_gadget_free_endpoints(dwc);
@ -2610,6 +2692,63 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
dwc->ctrl_req, dwc->ctrl_req_addr);
device_unregister(&dwc->gadget.dev);
}
int dwc3_gadget_prepare(struct dwc3 *dwc)
{
if (dwc->pullups_connected)
dwc3_gadget_disable_irq(dwc);
return 0;
}
void dwc3_gadget_complete(struct dwc3 *dwc)
{
if (dwc->pullups_connected) {
dwc3_gadget_enable_irq(dwc);
dwc3_gadget_run_stop(dwc, true);
}
}
int dwc3_gadget_suspend(struct dwc3 *dwc)
{
__dwc3_gadget_ep_disable(dwc->eps[0]);
__dwc3_gadget_ep_disable(dwc->eps[1]);
dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG);
return 0;
}
int dwc3_gadget_resume(struct dwc3 *dwc)
{
struct dwc3_ep *dep;
int ret;
/* Start with SuperSpeed Default */
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
dep = dwc->eps[0];
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
if (ret)
goto err0;
dep = dwc->eps[1];
ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
if (ret)
goto err1;
/* begin to receive SETUP packets */
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
return 0;
err1:
__dwc3_gadget_ep_disable(dwc->eps[0]);
err0:
return ret;
}

View File

@ -196,7 +196,6 @@ config USB_OMAP
tristate "OMAP USB Device Controller"
depends on ARCH_OMAP1
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
select USB_OTG_UTILS if ARCH_OMAP
help
Many Texas Instruments OMAP processors have flexible full
speed USB device controllers, with support for up to 30
@ -211,7 +210,6 @@ config USB_OMAP
config USB_PXA25X
tristate "PXA 25x or IXP 4xx"
depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
select USB_OTG_UTILS
help
Intel's PXA 25x series XScale ARM-5TE processors include
an integrated full speed USB 1.1 device controller. The
@ -259,8 +257,6 @@ config USB_RENESAS_USBHS_UDC
config USB_PXA27X
tristate "PXA 27x"
depends on ARCH_PXA && (PXA27x || PXA3xx)
select USB_OTG_UTILS
help
Intel's PXA 27x series XScale ARM v5TE processors include
an integrated full speed USB 1.1 device controller.
@ -329,9 +325,6 @@ config USB_MV_UDC
config USB_MV_U3D
tristate "MARVELL PXA2128 USB 3.0 controller"
depends on CPU_MMP3
select USB_GADGET_DUALSPEED
select USB_GADGET_SUPERSPEED
help
MARVELL PXA2128 Processor series include a super speed USB3.0 device
controller, which support super speed USB peripheral.
@ -501,6 +494,7 @@ endmenu
# composite based drivers
config USB_LIBCOMPOSITE
tristate
select CONFIGFS_FS
depends on USB_GADGET
config USB_F_ACM
@ -512,6 +506,12 @@ config USB_F_SS_LB
config USB_U_SERIAL
tristate
config USB_F_SERIAL
tristate
config USB_F_OBEX
tristate
choice
tristate "USB Gadget Drivers"
default USB_ETH
@ -766,6 +766,8 @@ config USB_G_SERIAL
depends on TTY
select USB_U_SERIAL
select USB_F_ACM
select USB_F_SERIAL
select USB_F_OBEX
select USB_LIBCOMPOSITE
help
The Serial Gadget talks to the Linux-USB generic serial driver.
@ -839,6 +841,7 @@ config USB_G_NOKIA
depends on PHONET
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_F_ACM
help
The Nokia composite gadget provides support for acm, obex
and phonet in only one composite gadget driver.
@ -957,6 +960,7 @@ config USB_G_WEBCAM
tristate "USB Webcam Gadget"
depends on VIDEO_DEV
select USB_LIBCOMPOSITE
select VIDEOBUF2_VMALLOC
help
The Webcam Gadget acts as a composite USB Audio and Video Class
device. It provides a userspace API to process UVC control requests

View File

@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_GADGET) += udc-core.o
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
libcomposite-y := usbstring.o config.o epautoconf.o
libcomposite-y += composite.o functions.o
libcomposite-y += composite.o functions.o configfs.o
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2272) += net2272.o
obj-$(CONFIG_USB_NET2280) += net2280.o
@ -36,10 +36,15 @@ obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
# USB Functions
obj-$(CONFIG_USB_F_ACM) += f_acm.o
f_ss_lb-y := f_loopback.o f_sourcesink.o
obj-$(CONFIG_USB_F_SS_LB) += f_ss_lb.o
usb_f_acm-y := f_acm.o
obj-$(CONFIG_USB_F_ACM) += usb_f_acm.o
usb_f_ss_lb-y := f_loopback.o f_sourcesink.o
obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o
obj-$(CONFIG_USB_U_SERIAL) += u_serial.o
usb_f_serial-y := f_serial.o
obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o
usb_f_obex-y := f_obex.o
obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o
#
# USB gadget drivers

View File

@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
static struct fsg_common fsg_common;
/*-------------------------------------------------------------------------*/
static unsigned char tty_line;
static struct usb_function *f_acm;
static struct usb_function_instance *f_acm_inst;
/*
@ -117,7 +116,6 @@ static struct usb_function_instance *f_acm_inst;
*/
static int __init acm_ms_do_config(struct usb_configuration *c)
{
struct f_serial_opts *opts;
int status;
if (gadget_is_otg(c->cdev->gadget)) {
@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
if (IS_ERR(f_acm_inst))
return PTR_ERR(f_acm_inst);
opts = container_of(f_acm_inst, struct f_serial_opts, func_inst);
opts->port_num = tty_line;
f_acm = usb_get_function(f_acm_inst);
if (IS_ERR(f_acm)) {
status = PTR_ERR(f_acm);
@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
int status;
void *retp;
/* set up serial link layer */
status = gserial_alloc_line(&tty_line);
if (status < 0)
return status;
/* set up mass storage function */
retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
if (IS_ERR(retp)) {
status = PTR_ERR(retp);
goto fail0;
return PTR_ERR(retp);
}
/*
@ -207,8 +197,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
/* error recovery */
fail1:
fsg_common_put(&fsg_common);
fail0:
gserial_free_line(tty_line);
return status;
}
@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
{
usb_put_function(f_acm);
usb_put_function_instance(f_acm_inst);
gserial_free_line(tty_line);
return 0;
}

View File

@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g,
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
/* Some gadget drivers use both ep0 directions.
* NOTE: to gadget driver, ep0 is just one endpoint...
@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g,
shutdown(dev, driver);
spin_unlock_irqrestore(&dev->lock, flags);
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
/* set SD */
@ -3080,7 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev)
if (dev->active)
pci_disable_device(pdev);
device_unregister(&dev->gadget.dev);
pci_set_drvdata(pdev, NULL);
udc_remove(dev);
@ -3245,8 +3242,6 @@ static int udc_pci_probe(
dev->phys_addr = resource;
dev->irq = pdev->irq;
dev->pdev = pdev;
dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
/* general probing */
if (udc_probe(dev) == 0)
@ -3273,7 +3268,6 @@ static int udc_probe(struct udc *dev)
dev->gadget.ops = &udc_ops;
dev_set_name(&dev->gadget.dev, "gadget");
dev->gadget.dev.release = gadget_release;
dev->gadget.name = name;
dev->gadget.max_speed = USB_SPEED_HIGH;
@ -3297,17 +3291,11 @@ static int udc_probe(struct udc *dev)
"driver version: %s(for Geode5536 B1)\n", tmp);
udc = dev;
retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget);
retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
gadget_release);
if (retval)
goto finished;
retval = device_register(&dev->gadget.dev);
if (retval) {
usb_del_gadget_udc(&dev->gadget);
put_device(&dev->gadget.dev);
goto finished;
}
/* timer init */
init_timer(&udc_timer);
udc_timer.function = udc_timer_function;

View File

@ -472,7 +472,6 @@ struct udc_request {
/* flags */
unsigned dma_going : 1,
dma_mapping : 1,
dma_done : 1;
/* phys. address */
dma_addr_t td_phys;

View File

@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget,
udc = container_of(gadget, struct at91_udc, gadget);
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
udc->gadget.dev.of_node = udc->pdev->dev.of_node;
udc->enabled = 1;
udc->selfpowered = 1;
@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget,
at91_udp_write(udc, AT91_UDP_IDR, ~0);
spin_unlock_irqrestore(&udc->lock, flags);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
DBG("unbound from %s\n", driver->driver.name);
@ -1780,13 +1778,7 @@ static int at91udc_probe(struct platform_device *pdev)
DBG("clocks missing\n");
retval = -ENODEV;
/* NOTE: we "know" here that refcounts on these are NOPs */
goto fail0b;
}
retval = device_register(&udc->gadget.dev);
if (retval < 0) {
put_device(&udc->gadget.dev);
goto fail0b;
goto fail1;
}
/* don't do anything until we have both gadget driver and VBUS */
@ -1857,8 +1849,6 @@ static int at91udc_probe(struct platform_device *pdev)
fail2:
free_irq(udc->udp_irq, udc);
fail1:
device_unregister(&udc->gadget.dev);
fail0b:
iounmap(udc->udp_baseaddr);
fail0a:
if (cpu_is_at91rm9200())
@ -1892,8 +1882,6 @@ static int __exit at91udc_remove(struct platform_device *pdev)
gpio_free(udc->board.vbus_pin);
}
free_irq(udc->udp_irq, udc);
device_unregister(&udc->gadget.dev);
iounmap(udc->udp_baseaddr);
if (cpu_is_at91rm9200())

View File

@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status)
if (req->req.status == -EINPROGRESS)
req->req.status = status;
if (req->mapped) {
dma_unmap_single(
&udc->pdev->dev, req->req.dma, req->req.length,
ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
}
if (req->using_dma)
usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
DBG(DBG_GADGET | DBG_REQ,
"%s: req %p complete: status %d, actual %u\n",
@ -684,7 +679,6 @@ usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
return NULL;
INIT_LIST_HEAD(&req->queue);
req->req.dma = DMA_ADDR_INVALID;
return &req->req;
}
@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
return -EINVAL;
}
ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in);
if (ret)
return ret;
req->using_dma = 1;
if (req->req.dma == DMA_ADDR_INVALID) {
req->req.dma = dma_map_single(
&udc->pdev->dev, req->req.buf, req->req.length,
ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 1;
} else {
dma_sync_single_for_device(
&udc->pdev->dev, req->req.dma, req->req.length,
ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 0;
}
req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
@ -1799,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget,
udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc->lock, flags);
clk_enable(udc->pclk);
@ -1841,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
toggle_bias(0);
usba_writel(udc, CTRL, USBA_DISABLE_MASK);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
clk_disable(udc->hclk);
@ -1900,10 +1883,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
(unsigned long)fifo->start, udc->fifo);
device_initialize(&udc->gadget.dev);
udc->gadget.dev.parent = &pdev->dev;
udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
platform_set_drvdata(pdev, udc);
/* Make sure we start from a clean slate */
@ -1962,12 +1941,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
}
udc->irq = irq;
ret = device_add(&udc->gadget.dev);
if (ret) {
dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret);
goto err_device_add;
}
if (gpio_is_valid(pdata->vbus_pin)) {
if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
udc->vbus_pin = pdata->vbus_pin;
@ -2007,9 +1980,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
gpio_free(udc->vbus_pin);
}
device_unregister(&udc->gadget.dev);
err_device_add:
free_irq(irq, udc);
err_request_irq:
kfree(usba_ep);
@ -2053,8 +2023,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
clk_put(udc->hclk);
clk_put(udc->pclk);
device_unregister(&udc->gadget.dev);
return 0;
}

View File

@ -216,12 +216,6 @@
#define EP0_EPT_SIZE USBA_EPT_SIZE_64
#define EP0_NR_BANKS 1
/*
* REVISIT: Try to eliminate this value. Can we rely on req->mapped to
* provide this information?
*/
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define FIFO_IOMEM_ID 0
#define CTRL_IOMEM_ID 1

View File

@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget,
udc->driver = driver;
driver->driver.bus = NULL;
udc->gadget.dev.driver = &driver->driver;
udc->gadget.dev.of_node = udc->dev->of_node;
spin_unlock_irqrestore(&udc->lock, flags);
@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget,
spin_lock_irqsave(&udc->lock, flags);
udc->driver = NULL;
udc->gadget.dev.driver = NULL;
/*
* If we switch the PHY too abruptly after dropping D+, the host
@ -2305,17 +2303,6 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
* Driver init/exit
***********************************************************************/
/**
* bcm63xx_udc_gadget_release - Called from device_release().
* @dev: Unused.
*
* We get a warning if this function doesn't exist, but it's empty because
* we don't have to free any of the memory allocated with the devm_* APIs.
*/
static void bcm63xx_udc_gadget_release(struct device *dev)
{
}
/**
* bcm63xx_udc_probe - Initialize a new instance of the UDC.
* @pdev: Platform device struct from the bcm63xx BSP code.
@ -2368,13 +2355,9 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
spin_lock_init(&udc->lock);
INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
dev_set_name(&udc->gadget.dev, "gadget");
udc->gadget.ops = &bcm63xx_udc_ops;
udc->gadget.name = dev_name(dev);
udc->gadget.dev.parent = dev;
udc->gadget.dev.release = bcm63xx_udc_gadget_release;
udc->gadget.dev.dma_mask = dev->dma_mask;
if (!pd->use_fullspeed && !use_fullspeed)
udc->gadget.max_speed = USB_SPEED_HIGH;
@ -2414,17 +2397,12 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
}
}
rc = device_register(&udc->gadget.dev);
if (rc)
goto out_uninit;
bcm63xx_udc_init_debugfs(udc);
rc = usb_add_gadget_udc(dev, &udc->gadget);
if (!rc)
return 0;
bcm63xx_udc_cleanup_debugfs(udc);
device_unregister(&udc->gadget.dev);
out_uninit:
bcm63xx_uninit_udc_hw(udc);
return rc;
@ -2440,7 +2418,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)
bcm63xx_udc_cleanup_debugfs(udc);
usb_del_gadget_udc(&udc->gadget);
device_unregister(&udc->gadget.dev);
BUG_ON(udc->driver);
platform_set_drvdata(pdev, NULL);

View File

@ -103,18 +103,16 @@ static struct usb_gadget_strings *dev_strings[] = {
};
static u8 hostaddr[ETH_ALEN];
static struct eth_dev *the_dev;
/*-------------------------------------------------------------------------*/
static struct usb_function *f_acm;
static struct usb_function_instance *fi_serial;
static unsigned char tty_line;
/*
* We _always_ have both CDC ECM and CDC ACM functions.
*/
static int __init cdc_do_config(struct usb_configuration *c)
{
struct f_serial_opts *opts;
int status;
if (gadget_is_otg(c->cdev->gadget)) {
@ -122,7 +120,7 @@ static int __init cdc_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
status = ecm_bind_config(c, hostaddr);
status = ecm_bind_config(c, hostaddr, the_dev);
if (status < 0)
return status;
@ -130,9 +128,6 @@ static int __init cdc_do_config(struct usb_configuration *c)
if (IS_ERR(fi_serial))
return PTR_ERR(fi_serial);
opts = container_of(fi_serial, struct f_serial_opts, func_inst);
opts->port_num = tty_line;
f_acm = usb_get_function(fi_serial);
if (IS_ERR(f_acm))
goto err_func_acm;
@ -169,14 +164,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
}
/* set up network link layer */
status = gether_setup(cdev->gadget, hostaddr);
if (status < 0)
return status;
/* set up serial link layer */
status = gserial_alloc_line(&tty_line);
if (status < 0)
goto fail0;
the_dev = gether_setup(cdev->gadget, hostaddr);
if (IS_ERR(the_dev))
return PTR_ERR(the_dev);
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
@ -200,9 +190,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
return 0;
fail1:
gserial_free_line(tty_line);
fail0:
gether_cleanup();
gether_cleanup(the_dev);
return status;
}
@ -210,8 +198,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)
{
usb_put_function(f_acm);
usb_put_function_instance(fi_serial);
gserial_free_line(tty_line);
gether_cleanup();
gether_cleanup(the_dev);
return 0;
}

View File

@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
kfree(cdev->req->buf);
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
}
cdev->next_string_id = 0;
device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
}

File diff suppressed because it is too large Load Diff

View File

@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g,
dum->devstatus = 0;
dum->driver = driver;
dum->gadget.dev.driver = &driver->driver;
dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
driver->driver.name);
return 0;
@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
driver->driver.name);
dum->gadget.dev.driver = NULL;
dum->driver = NULL;
return 0;
@ -937,11 +935,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
/* The gadget structure is stored inside the hcd structure and will be
* released along with it. */
static void dummy_gadget_release(struct device *dev)
{
return;
}
static void init_dummy_udc_hw(struct dummy *dum)
{
int i;
@ -984,15 +977,7 @@ static int dummy_udc_probe(struct platform_device *pdev)
dum->gadget.ops = &dummy_ops;
dum->gadget.max_speed = USB_SPEED_SUPER;
dev_set_name(&dum->gadget.dev, "gadget");
dum->gadget.dev.parent = &pdev->dev;
dum->gadget.dev.release = dummy_gadget_release;
rc = device_register(&dum->gadget.dev);
if (rc < 0) {
put_device(&dum->gadget.dev);
return rc;
}
init_dummy_udc_hw(dum);
rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
@ -1008,7 +993,6 @@ static int dummy_udc_probe(struct platform_device *pdev)
err_dev:
usb_del_gadget_udc(&dum->gadget);
err_udc:
device_unregister(&dum->gadget.dev);
return rc;
}
@ -1019,7 +1003,6 @@ static int dummy_udc_remove(struct platform_device *pdev)
usb_del_gadget_udc(&dum->gadget);
platform_set_drvdata(pdev, NULL);
device_remove_file(&dum->gadget.dev, &dev_attr_function);
device_unregister(&dum->gadget.dev);
return 0;
}
@ -1923,7 +1906,7 @@ static int dummy_hub_status(struct usb_hcd *hcd, char *buf)
}
/* usb 3.0 root hub device descriptor */
struct {
static struct {
struct usb_bos_descriptor bos;
struct usb_ss_cap_descriptor ss_cap;
} __packed usb3_bos_desc = {

View File

@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = {
};
static u8 hostaddr[ETH_ALEN];
static struct eth_dev *the_dev;
/*-------------------------------------------------------------------------*/
/*
@ -224,7 +224,7 @@ static int __init rndis_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
return rndis_bind_config(c, hostaddr);
return rndis_bind_config(c, hostaddr, the_dev);
}
static struct usb_configuration rndis_config_driver = {
@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c)
}
if (use_eem)
return eem_bind_config(c);
return eem_bind_config(c, the_dev);
else if (can_support_ecm(c->cdev->gadget))
return ecm_bind_config(c, hostaddr);
return ecm_bind_config(c, hostaddr, the_dev);
else
return geth_bind_config(c, hostaddr);
return geth_bind_config(c, hostaddr, the_dev);
}
static struct usb_configuration eth_config_driver = {
@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
int status;
/* set up network link layer */
status = gether_setup(cdev->gadget, hostaddr);
if (status < 0)
return status;
the_dev = gether_setup(cdev->gadget, hostaddr);
if (IS_ERR(the_dev))
return PTR_ERR(the_dev);
/* set up main config label and device descriptor */
if (use_eem) {
@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
return 0;
fail:
gether_cleanup();
gether_cleanup(the_dev);
return status;
}
static int __exit eth_unbind(struct usb_composite_dev *cdev)
{
gether_cleanup();
gether_cleanup(the_dev);
return 0;
}

View File

@ -715,72 +715,6 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
static struct f_acm *acm_alloc_basic_func(void)
{
struct f_acm *acm;
acm = kzalloc(sizeof(*acm), GFP_KERNEL);
if (!acm)
return NULL;
spin_lock_init(&acm->lock);
acm->port.connect = acm_connect;
acm->port.disconnect = acm_disconnect;
acm->port.send_break = acm_send_break;
acm->port.func.name = "acm";
/* descriptors are per-instance copies */
acm->port.func.bind = acm_bind;
acm->port.func.set_alt = acm_set_alt;
acm->port.func.setup = acm_setup;
acm->port.func.disable = acm_disable;
return acm;
}
#ifdef USB_FACM_INCLUDED
static void
acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
usb_free_all_descriptors(f);
if (acm->notify_req)
gs_free_req(acm->notify, acm->notify_req);
kfree(acm);
}
/**
* acm_bind_config - add a CDC ACM function to a configuration
* @c: the configuration to support the CDC ACM instance
* @port_num: /dev/ttyGS* port this interface will use
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
*
*/
int acm_bind_config(struct usb_configuration *c, u8 port_num)
{
struct f_acm *acm;
int status;
/* allocate and initialize one new instance */
acm = acm_alloc_basic_func();
if (!acm)
return -ENOMEM;
acm->port_num = port_num;
acm->port.func.unbind = acm_old_unbind;
status = usb_add_function(c, &acm->port.func);
if (status)
kfree(acm);
return status;
}
#else
static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
@ -803,10 +737,24 @@ static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
struct f_serial_opts *opts;
struct f_acm *acm;
acm = acm_alloc_basic_func();
acm = kzalloc(sizeof(*acm), GFP_KERNEL);
if (!acm)
return ERR_PTR(-ENOMEM);
spin_lock_init(&acm->lock);
acm->port.connect = acm_connect;
acm->port.disconnect = acm_disconnect;
acm->port.send_break = acm_send_break;
acm->port.func.name = "acm";
acm->port.func.strings = acm_strings;
/* descriptors are per-instance copies */
acm->port.func.bind = acm_bind;
acm->port.func.set_alt = acm_set_alt;
acm->port.func.setup = acm_setup;
acm->port.func.disable = acm_disable;
opts = container_of(fi, struct f_serial_opts, func_inst);
acm->port_num = opts->port_num;
acm->port.func.unbind = acm_unbind;
@ -815,24 +763,85 @@ static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
return &acm->port.func;
}
static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_serial_opts,
func_inst.group);
}
CONFIGFS_ATTR_STRUCT(f_serial_opts);
static ssize_t f_acm_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
struct f_serial_opts_attribute *f_serial_opts_attr =
container_of(attr, struct f_serial_opts_attribute, attr);
ssize_t ret = 0;
if (f_serial_opts_attr->show)
ret = f_serial_opts_attr->show(opts, page);
return ret;
}
static void acm_attr_release(struct config_item *item)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
usb_put_function_instance(&opts->func_inst);
}
static struct configfs_item_operations acm_item_ops = {
.release = acm_attr_release,
.show_attribute = f_acm_attr_show,
};
static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
{
return sprintf(page, "%u\n", opts->port_num);
}
static struct f_serial_opts_attribute f_acm_port_num =
__CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
static struct configfs_attribute *acm_attrs[] = {
&f_acm_port_num.attr,
NULL,
};
static struct config_item_type acm_func_type = {
.ct_item_ops = &acm_item_ops,
.ct_attrs = acm_attrs,
.ct_owner = THIS_MODULE,
};
static void acm_free_instance(struct usb_function_instance *fi)
{
struct f_serial_opts *opts;
opts = container_of(fi, struct f_serial_opts, func_inst);
gserial_free_line(opts->port_num);
kfree(opts);
}
static struct usb_function_instance *acm_alloc_instance(void)
{
struct f_serial_opts *opts;
int ret;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
opts->func_inst.free_func_inst = acm_free_instance;
ret = gserial_alloc_line(&opts->port_num);
if (ret) {
kfree(opts);
return ERR_PTR(ret);
}
config_group_init_type_name(&opts->func_inst.group, "",
&acm_func_type);
return &opts->func_inst;
}
DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
MODULE_LICENSE("GPL");
#endif

View File

@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
* for calling @gether_cleanup() before module unload.
*/
int
ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev)
{
struct f_ecm *ecm;
int status;
@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
ecm_string_defs[1].s = ecm->ethaddr;
ecm->port.ioport = dev;
ecm->port.cdc_filter = DEFAULT_FILTER;
ecm->port.func.name = "cdc_ethernet";

View File

@ -528,7 +528,7 @@ static int eem_unwrap(struct gether *port,
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
int __init eem_bind_config(struct usb_configuration *c)
int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev)
{
struct f_eem *eem;
int status;
@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c)
if (!eem)
return -ENOMEM;
eem->port.ioport = dev;
eem->port.cdc_filter = DEFAULT_FILTER;
eem->port.func.name = "cdc_eem";

View File

@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev)
{
struct f_ncm *ncm;
int status;
@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
spin_lock_init(&ncm->lock);
ncm_reset_values(ncm);
ncm->port.ioport = dev;
ncm->port.is_fixed = true;
ncm->port.func.name = "cdc_network";

View File

@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = {
/*-------------------------------------------------------------------------*/
static struct usb_interface_descriptor obex_control_intf __initdata = {
static struct usb_interface_descriptor obex_control_intf = {
.bLength = sizeof(obex_control_intf),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = {
.bInterfaceSubClass = USB_CDC_SUBCLASS_OBEX,
};
static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
static struct usb_interface_descriptor obex_data_nop_intf = {
.bLength = sizeof(obex_data_nop_intf),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 1,
@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
.bInterfaceClass = USB_CLASS_CDC_DATA,
};
static struct usb_interface_descriptor obex_data_intf __initdata = {
static struct usb_interface_descriptor obex_data_intf = {
.bLength = sizeof(obex_data_intf),
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 2,
@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = {
.bInterfaceClass = USB_CLASS_CDC_DATA,
};
static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
static struct usb_cdc_header_desc obex_cdc_header_desc = {
.bLength = sizeof(obex_cdc_header_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = cpu_to_le16(0x0120),
};
static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
static struct usb_cdc_union_desc obex_cdc_union_desc = {
.bLength = sizeof(obex_cdc_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_UNION_TYPE,
@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
.bSlaveInterface0 = 2,
};
static struct usb_cdc_obex_desc obex_desc __initdata = {
static struct usb_cdc_obex_desc obex_desc = {
.bLength = sizeof(obex_desc),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_OBEX_TYPE,
@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = {
/* High-Speed Support */
static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
static struct usb_endpoint_descriptor obex_hs_ep_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
static struct usb_endpoint_descriptor obex_hs_ep_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *hs_function[] __initdata = {
static struct usb_descriptor_header *hs_function[] = {
(struct usb_descriptor_header *) &obex_control_intf,
(struct usb_descriptor_header *) &obex_cdc_header_desc,
(struct usb_descriptor_header *) &obex_desc,
@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = {
/* Full-Speed Support */
static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
static struct usb_endpoint_descriptor obex_fs_ep_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
static struct usb_endpoint_descriptor obex_fs_ep_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_descriptor_header *fs_function[] __initdata = {
static struct usb_descriptor_header *fs_function[] = {
(struct usb_descriptor_header *) &obex_control_intf,
(struct usb_descriptor_header *) &obex_cdc_header_desc,
(struct usb_descriptor_header *) &obex_desc,
@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g)
/*-------------------------------------------------------------------------*/
static int __init
obex_bind(struct usb_configuration *c, struct usb_function *f)
/* Some controllers can't support CDC OBEX ... */
static inline bool can_support_obex(struct usb_configuration *c)
{
/* Since the first interface is a NOP, we can ignore the
* issue of multi-interface support on most controllers.
*
* Altsettings are mandatory, however...
*/
if (!gadget_supports_altsettings(c->cdev->gadget))
return false;
/* everything else is *probably* fine ... */
return true;
}
static int obex_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_obex *obex = func_to_obex(f);
int status;
struct usb_ep *ep;
if (!can_support_obex(c))
return -EINVAL;
if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
status = usb_string_ids_tab(c->cdev, obex_string_defs);
if (status < 0)
return status;
obex_control_intf.iInterface =
obex_string_defs[OBEX_CTRL_IDX].id;
status = obex_string_defs[OBEX_DATA_IDX].id;
obex_data_nop_intf.iInterface = status;
obex_data_intf.iInterface = status;
}
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
@ -376,29 +405,16 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
#ifdef USBF_OBEX_INCLUDED
static void
obex_unbind(struct usb_configuration *c, struct usb_function *f)
obex_old_unbind(struct usb_configuration *c, struct usb_function *f)
{
obex_string_defs[OBEX_CTRL_IDX].id = 0;
usb_free_all_descriptors(f);
kfree(func_to_obex(f));
}
/* Some controllers can't support CDC OBEX ... */
static inline bool can_support_obex(struct usb_configuration *c)
{
/* Since the first interface is a NOP, we can ignore the
* issue of multi-interface support on most controllers.
*
* Altsettings are mandatory, however...
*/
if (!gadget_supports_altsettings(c->cdev->gadget))
return false;
/* everything else is *probably* fine ... */
return true;
}
/**
* obex_bind_config - add a CDC OBEX function to a configuration
* @c: the configuration to support the CDC OBEX instance
@ -412,21 +428,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
struct f_obex *obex;
int status;
if (!can_support_obex(c))
return -EINVAL;
if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
status = usb_string_ids_tab(c->cdev, obex_string_defs);
if (status < 0)
return status;
obex_control_intf.iInterface =
obex_string_defs[OBEX_CTRL_IDX].id;
status = obex_string_defs[OBEX_DATA_IDX].id;
obex_data_nop_intf.iInterface = status;
obex_data_intf.iInterface = status;
}
/* allocate and initialize one new instance */
obex = kzalloc(sizeof *obex, GFP_KERNEL);
if (!obex)
@ -441,7 +442,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
obex->port.func.strings = obex_strings;
/* descriptors are per-instance copies */
obex->port.func.bind = obex_bind;
obex->port.func.unbind = obex_unbind;
obex->port.func.unbind = obex_old_unbind;
obex->port.func.set_alt = obex_set_alt;
obex->port.func.get_alt = obex_get_alt;
obex->port.func.disable = obex_disable;
@ -453,5 +454,138 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
return status;
}
#else
static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_serial_opts,
func_inst.group);
}
CONFIGFS_ATTR_STRUCT(f_serial_opts);
static ssize_t f_obex_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
struct f_serial_opts_attribute *f_serial_opts_attr =
container_of(attr, struct f_serial_opts_attribute, attr);
ssize_t ret = 0;
if (f_serial_opts_attr->show)
ret = f_serial_opts_attr->show(opts, page);
return ret;
}
static void obex_attr_release(struct config_item *item)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
usb_put_function_instance(&opts->func_inst);
}
static struct configfs_item_operations obex_item_ops = {
.release = obex_attr_release,
.show_attribute = f_obex_attr_show,
};
static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page)
{
return sprintf(page, "%u\n", opts->port_num);
}
static struct f_serial_opts_attribute f_obex_port_num =
__CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show);
static struct configfs_attribute *acm_attrs[] = {
&f_obex_port_num.attr,
NULL,
};
static struct config_item_type obex_func_type = {
.ct_item_ops = &obex_item_ops,
.ct_attrs = acm_attrs,
.ct_owner = THIS_MODULE,
};
static void obex_free_inst(struct usb_function_instance *f)
{
struct f_serial_opts *opts;
opts = container_of(f, struct f_serial_opts, func_inst);
gserial_free_line(opts->port_num);
kfree(opts);
}
static struct usb_function_instance *obex_alloc_inst(void)
{
struct f_serial_opts *opts;
int ret;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
opts->func_inst.free_func_inst = obex_free_inst;
ret = gserial_alloc_line(&opts->port_num);
if (ret) {
kfree(opts);
return ERR_PTR(ret);
}
config_group_init_type_name(&opts->func_inst.group, "",
&obex_func_type);
return &opts->func_inst;
}
static void obex_free(struct usb_function *f)
{
struct f_obex *obex;
obex = func_to_obex(f);
kfree(obex);
}
static void obex_unbind(struct usb_configuration *c, struct usb_function *f)
{
obex_string_defs[OBEX_CTRL_IDX].id = 0;
usb_free_all_descriptors(f);
}
struct usb_function *obex_alloc(struct usb_function_instance *fi)
{
struct f_obex *obex;
struct f_serial_opts *opts;
/* allocate and initialize one new instance */
obex = kzalloc(sizeof(*obex), GFP_KERNEL);
if (!obex)
return ERR_PTR(-ENOMEM);
opts = container_of(fi, struct f_serial_opts, func_inst);
obex->port_num = opts->port_num;
obex->port.connect = obex_connect;
obex->port.disconnect = obex_disconnect;
obex->port.func.name = "obex";
obex->port.func.strings = obex_strings;
/* descriptors are per-instance copies */
obex->port.func.bind = obex_bind;
obex->port.func.unbind = obex_unbind;
obex->port.func.set_alt = obex_set_alt;
obex->port.func.get_alt = obex_get_alt;
obex->port.func.disable = obex_disable;
obex->port.func.free_func = obex_free;
return &obex->port.func;
}
DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc);
#endif
MODULE_AUTHOR("Felipe Balbi");
MODULE_LICENSE("GPL");

View File

@ -813,7 +813,7 @@ static inline bool can_support_rndis(struct usb_configuration *c)
int
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer)
u32 vendorID, const char *manufacturer, struct eth_dev *dev)
{
struct f_rndis *rndis;
int status;
@ -846,6 +846,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
rndis->vendorID = vendorID;
rndis->manufacturer = manufacturer;
rndis->port.ioport = dev;
/* RNDIS activates when the host changes this filter */
rndis->port.cdc_filter = 0;

View File

@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h>
#include "u_serial.h"
@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f)
/* interface descriptor: */
static struct usb_interface_descriptor gser_interface_desc __initdata = {
static struct usb_interface_descriptor gser_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */
@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = {
/* full speed support: */
static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
static struct usb_endpoint_descriptor gser_fs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
static struct usb_endpoint_descriptor gser_fs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
static struct usb_descriptor_header *gser_fs_function[] __initdata = {
static struct usb_descriptor_header *gser_fs_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
(struct usb_descriptor_header *) &gser_fs_in_desc,
(struct usb_descriptor_header *) &gser_fs_out_desc,
@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = {
/* high speed support: */
static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
static struct usb_endpoint_descriptor gser_hs_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
static struct usb_endpoint_descriptor gser_hs_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
};
static struct usb_descriptor_header *gser_hs_function[] __initdata = {
static struct usb_descriptor_header *gser_hs_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
(struct usb_descriptor_header *) &gser_hs_in_desc,
(struct usb_descriptor_header *) &gser_hs_out_desc,
NULL,
};
static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
static struct usb_endpoint_descriptor gser_ss_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
static struct usb_endpoint_descriptor gser_ss_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = {
static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = {
.bLength = sizeof gser_ss_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
};
static struct usb_descriptor_header *gser_ss_function[] __initdata = {
static struct usb_descriptor_header *gser_ss_function[] = {
(struct usb_descriptor_header *) &gser_interface_desc,
(struct usb_descriptor_header *) &gser_ss_in_desc,
(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f)
/* serial function driver setup/binding */
static int __init
gser_bind(struct usb_configuration *c, struct usb_function *f)
static int gser_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct f_gser *gser = func_to_gser(f);
int status;
struct usb_ep *ep;
/* REVISIT might want instance-specific strings to help
* distinguish instances ...
*/
/* maybe allocate device-global string ID */
if (gser_string_defs[0].id == 0) {
status = usb_string_id(c->cdev);
if (status < 0)
return status;
gser_string_defs[0].id = status;
}
/* allocate instance-specific interface IDs */
status = usb_interface_id(c, f);
if (status < 0)
@ -246,44 +258,115 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
return status;
}
static void
gser_unbind(struct usb_configuration *c, struct usb_function *f)
static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
{
usb_free_all_descriptors(f);
kfree(func_to_gser(f));
return container_of(to_config_group(item), struct f_serial_opts,
func_inst.group);
}
/**
* gser_bind_config - add a generic serial function to a configuration
* @c: the configuration to support the serial instance
* @port_num: /dev/ttyGS* port this interface will use
* Context: single threaded during gadget setup
*
* Returns zero on success, else negative errno.
*/
int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
CONFIGFS_ATTR_STRUCT(f_serial_opts);
static ssize_t f_serial_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
struct f_serial_opts_attribute *f_serial_opts_attr =
container_of(attr, struct f_serial_opts_attribute, attr);
ssize_t ret = 0;
if (f_serial_opts_attr->show)
ret = f_serial_opts_attr->show(opts, page);
return ret;
}
static void serial_attr_release(struct config_item *item)
{
struct f_serial_opts *opts = to_f_serial_opts(item);
usb_put_function_instance(&opts->func_inst);
}
static struct configfs_item_operations serial_item_ops = {
.release = serial_attr_release,
.show_attribute = f_serial_attr_show,
};
static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page)
{
return sprintf(page, "%u\n", opts->port_num);
}
static struct f_serial_opts_attribute f_serial_port_num =
__CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show);
static struct configfs_attribute *acm_attrs[] = {
&f_serial_port_num.attr,
NULL,
};
static struct config_item_type serial_func_type = {
.ct_item_ops = &serial_item_ops,
.ct_attrs = acm_attrs,
.ct_owner = THIS_MODULE,
};
static void gser_free_inst(struct usb_function_instance *f)
{
struct f_serial_opts *opts;
opts = container_of(f, struct f_serial_opts, func_inst);
gserial_free_line(opts->port_num);
kfree(opts);
}
static struct usb_function_instance *gser_alloc_inst(void)
{
struct f_serial_opts *opts;
int ret;
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
opts->func_inst.free_func_inst = gser_free_inst;
ret = gserial_alloc_line(&opts->port_num);
if (ret) {
kfree(opts);
return ERR_PTR(ret);
}
config_group_init_type_name(&opts->func_inst.group, "",
&serial_func_type);
return &opts->func_inst;
}
static void gser_free(struct usb_function *f)
{
struct f_gser *serial;
serial = func_to_gser(f);
kfree(serial);
}
static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
{
usb_free_all_descriptors(f);
}
struct usb_function *gser_alloc(struct usb_function_instance *fi)
{
struct f_gser *gser;
int status;
/* REVISIT might want instance-specific strings to help
* distinguish instances ...
*/
/* maybe allocate device-global string ID */
if (gser_string_defs[0].id == 0) {
status = usb_string_id(c->cdev);
if (status < 0)
return status;
gser_string_defs[0].id = status;
}
struct f_serial_opts *opts;
/* allocate and initialize one new instance */
gser = kzalloc(sizeof *gser, GFP_KERNEL);
gser = kzalloc(sizeof(*gser), GFP_KERNEL);
if (!gser)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
gser->port_num = port_num;
opts = container_of(fi, struct f_serial_opts, func_inst);
gser->port_num = opts->port_num;
gser->port.func.name = "gser";
gser->port.func.strings = gser_strings;
@ -291,9 +374,12 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
gser->port.func.unbind = gser_unbind;
gser->port.func.set_alt = gser_set_alt;
gser->port.func.disable = gser_disable;
gser->port.func.free_func = gser_free;
status = usb_add_function(c, &gser->port.func);
if (status)
kfree(gser);
return status;
return &gser->port.func;
}
DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Al Borchers");
MODULE_AUTHOR("David Brownell");

View File

@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev)
{
struct f_gether *geth;
int status;
@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
geth_string_defs[1].s = geth->ethaddr;
geth->port.ioport = dev;
geth->port.cdc_filter = DEFAULT_FILTER;
geth->port.func.name = "cdc_subset";

View File

@ -33,19 +33,15 @@ unsigned int uvc_gadget_trace_param;
/*-------------------------------------------------------------------------*/
/* module parameters specific to the Video streaming endpoint */
static unsigned streaming_interval = 1;
static unsigned int streaming_interval = 1;
module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_interval, "1 - 16");
static unsigned streaming_maxpacket = 1024;
static unsigned int streaming_maxpacket = 1024;
module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
static unsigned streaming_mult;
module_param(streaming_mult, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)");
static unsigned streaming_maxburst;
static unsigned int streaming_maxburst;
module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
@ -55,13 +51,11 @@ MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
/* string IDs are assigned dynamically */
#define UVC_STRING_ASSOCIATION_IDX 0
#define UVC_STRING_CONTROL_IDX 1
#define UVC_STRING_STREAMING_IDX 2
#define UVC_STRING_CONTROL_IDX 0
#define UVC_STRING_STREAMING_IDX 1
static struct usb_string uvc_en_us_strings[] = {
[UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera",
[UVC_STRING_CONTROL_IDX].s = "Video Control",
[UVC_STRING_CONTROL_IDX].s = "UVC Camera",
[UVC_STRING_STREAMING_IDX].s = "Video Streaming",
{ }
};
@ -79,7 +73,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = {
#define UVC_INTF_VIDEO_CONTROL 0
#define UVC_INTF_VIDEO_STREAMING 1
#define STATUS_BYTECOUNT 16 /* 16 bytes status */
#define UVC_STATUS_MAX_PACKET_SIZE 16 /* 16 bytes status */
static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
.bLength = sizeof(uvc_iad),
@ -104,20 +98,29 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = {
.iInterface = 0,
};
static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = {
static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
.bInterval = 8,
};
static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
.bLength = sizeof(uvc_ss_control_comp),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* The following 3 values can be tweaked if necessary. */
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
};
static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
.bLength = UVC_DT_CONTROL_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubType = UVC_EP_INTERRUPT,
.wMaxTransferSize = cpu_to_le16(STATUS_BYTECOUNT),
.wMaxTransferSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
};
static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
@ -144,63 +147,53 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {
.iInterface = 0,
};
static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = cpu_to_le16(512),
.bInterval = 1,
.bmAttributes = USB_ENDPOINT_SYNC_ASYNC
| USB_ENDPOINT_XFER_ISOC,
/* The wMaxPacketSize and bInterval values will be initialized from
* module parameters.
*/
.wMaxPacketSize = 0,
.bInterval = 0,
};
static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = cpu_to_le16(1024),
.bInterval = 1,
};
/* super speed support */
static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
.bInterval = 8,
};
static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
.bLength = sizeof uvc_ss_control_comp,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* the following 3 values can be tweaked if necessary */
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
.wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT),
.bmAttributes = USB_ENDPOINT_SYNC_ASYNC
| USB_ENDPOINT_XFER_ISOC,
/* The wMaxPacketSize and bInterval values will be initialized from
* module parameters.
*/
.wMaxPacketSize = 0,
.bInterval = 0,
};
static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_ISOC,
.wMaxPacketSize = cpu_to_le16(1024),
.bInterval = 4,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_SYNC_ASYNC
| USB_ENDPOINT_XFER_ISOC,
/* The wMaxPacketSize and bInterval values will be initialized from
* module parameters.
*/
.wMaxPacketSize = 0,
.bInterval = 0,
};
static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
.bLength = sizeof uvc_ss_streaming_comp,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* the following 3 values can be tweaked if necessary */
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = cpu_to_le16(1024),
static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = {
.bLength = sizeof(uvc_ss_streaming_comp),
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
/* The following 3 values can be tweaked if necessary. */
.bMaxBurst = 0,
.bmAttributes = 0,
.wBytesPerInterval = cpu_to_le16(1024),
};
static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
@ -273,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
return 0;
}
void uvc_function_setup_continue(struct uvc_device *uvc)
{
struct usb_composite_dev *cdev = uvc->func.config->cdev;
usb_composite_setup_continue(cdev);
}
static int
uvc_function_get_alt(struct usb_function *f, unsigned interface)
{
@ -335,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_CONNECTED;
break;
return 0;
case 1:
if (uvc->state != UVC_STATE_CONNECTED)
@ -352,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMON;
v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_STREAMING;
break;
return USB_GADGET_DELAYED_STATUS;
default:
return -EINVAL;
}
return 0;
}
static void
@ -454,7 +450,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
const struct uvc_descriptor_header * const *uvc_streaming_cls;
const struct usb_descriptor_header * const *uvc_streaming_std;
const struct usb_descriptor_header * const *src;
static struct usb_endpoint_descriptor *uvc_control_ep;
struct usb_descriptor_header **dst;
struct usb_descriptor_header **hdr;
unsigned int control_size;
@ -468,14 +463,12 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
uvc_control_desc = uvc->desc.ss_control;
uvc_streaming_cls = uvc->desc.ss_streaming;
uvc_streaming_std = uvc_ss_streaming;
uvc_control_ep = &uvc_ss_control_ep;
break;
case USB_SPEED_HIGH:
uvc_control_desc = uvc->desc.fs_control;
uvc_streaming_cls = uvc->desc.hs_streaming;
uvc_streaming_std = uvc_hs_streaming;
uvc_control_ep = &uvc_fs_control_ep;
break;
case USB_SPEED_FULL:
@ -483,7 +476,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
uvc_control_desc = uvc->desc.fs_control;
uvc_streaming_cls = uvc->desc.fs_streaming;
uvc_streaming_std = uvc_fs_streaming;
uvc_control_ep = &uvc_fs_control_ep;
break;
}
@ -494,6 +486,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
* Class-specific UVC control descriptors
* uvc_control_ep
* uvc_control_cs_ep
* uvc_ss_control_comp (for SS only)
* uvc_streaming_intf_alt0
* Class-specific UVC streaming descriptors
* uvc_{fs|hs}_streaming
@ -503,7 +496,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
control_size = 0;
streaming_size = 0;
bytes = uvc_iad.bLength + uvc_control_intf.bLength
+ uvc_control_ep->bLength + uvc_control_cs_ep.bLength
+ uvc_control_ep.bLength + uvc_control_cs_ep.bLength
+ uvc_streaming_intf_alt0.bLength;
if (speed == USB_SPEED_SUPER) {
@ -514,13 +507,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
}
for (src = (const struct usb_descriptor_header **)uvc_control_desc;
*src; ++src) {
*src; ++src) {
control_size += (*src)->bLength;
bytes += (*src)->bLength;
n_desc++;
}
for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
*src; ++src) {
*src; ++src) {
streaming_size += (*src)->bLength;
bytes += (*src)->bLength;
n_desc++;
@ -549,7 +542,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
uvc_control_header->bInCollection = 1;
uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep);
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
if (speed == USB_SPEED_SUPER)
UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
@ -560,8 +553,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
UVC_COPY_DESCRIPTORS(mem, dst,
(const struct usb_descriptor_header**)uvc_streaming_cls);
uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
uvc_streaming_header->bEndpointAddress =
uvc_fs_streaming_ep.bEndpointAddress;
uvc_streaming_header->bEndpointAddress = uvc->video.ep->address;
UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
@ -581,7 +573,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
uvc->control_ep->driver_data = NULL;
uvc->video.ep->driver_data = NULL;
uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0;
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf);
@ -595,31 +587,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
struct uvc_device *uvc = to_uvc(f);
unsigned int max_packet_mult;
unsigned int max_packet_size;
struct usb_ep *ep;
int ret = -EINVAL;
INFO(cdev, "uvc_function_bind\n");
/* sanity check the streaming endpoint module parameters */
if (streaming_interval < 1)
streaming_interval = 1;
if (streaming_interval > 16)
streaming_interval = 16;
if (streaming_mult > 2)
streaming_mult = 2;
if (streaming_maxburst > 15)
streaming_maxburst = 15;
/*
* fill in the FS video streaming specific descriptors from the
* module parameters
/* Sanity check the streaming endpoint module parameters.
*/
uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ?
1023 : streaming_maxpacket;
streaming_interval = clamp(streaming_interval, 1U, 16U);
streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U);
streaming_maxburst = min(streaming_maxburst, 15U);
/* Fill in the FS/HS/SS Video Streaming specific descriptors from the
* module parameters.
*
* NOTE: We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
if (streaming_maxpacket <= 1024) {
max_packet_mult = 1;
max_packet_size = streaming_maxpacket;
} else if (streaming_maxpacket <= 2048) {
max_packet_mult = 2;
max_packet_size = streaming_maxpacket / 2;
} else {
max_packet_mult = 3;
max_packet_size = streaming_maxpacket / 3;
}
uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U);
uvc_fs_streaming_ep.bInterval = streaming_interval;
uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size;
uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11);
uvc_hs_streaming_ep.bInterval = streaming_interval;
uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size;
uvc_ss_streaming_ep.bInterval = streaming_interval;
uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
uvc_ss_streaming_comp.wBytesPerInterval =
max_packet_size * max_packet_mult * streaming_maxburst;
/* Allocate endpoints. */
ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep);
ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
if (!ep) {
INFO(cdev, "Unable to allocate control EP\n");
goto error;
@ -627,7 +640,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc->control_ep = ep;
ep->driver_data = uvc;
ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
if (gadget_is_superspeed(c->cdev->gadget))
ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
&uvc_ss_streaming_comp);
else if (gadget_is_dualspeed(cdev->gadget))
ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep);
else
ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
if (!ep) {
INFO(cdev, "Unable to allocate streaming EP\n");
goto error;
@ -635,6 +655,10 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc->video.ep = ep;
ep->driver_data = uvc;
uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
/* Allocate interface IDs. */
if ((ret = usb_interface_id(c, f)) < 0)
goto error;
@ -648,37 +672,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc_streaming_intf_alt1.bInterfaceNumber = ret;
uvc->streaming_intf = ret;
/* sanity check the streaming endpoint module parameters */
if (streaming_maxpacket > 1024)
streaming_maxpacket = 1024;
/*
* Fill in the HS descriptors from the module parameters for the Video
* Streaming endpoint.
* NOTE: We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
uvc_hs_streaming_ep.bInterval = streaming_interval;
uvc_hs_streaming_ep.bEndpointAddress =
uvc_fs_streaming_ep.bEndpointAddress;
/*
* Fill in the SS descriptors from the module parameters for the Video
* Streaming endpoint.
* NOTE: We assume that the user knows what they are doing and won't
* give parameters that their UDC doesn't support.
*/
uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
uvc_ss_streaming_ep.bInterval = streaming_interval;
uvc_ss_streaming_comp.bmAttributes = streaming_mult;
uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
uvc_ss_streaming_comp.wBytesPerInterval =
streaming_maxpacket * (streaming_mult + 1) *
(streaming_maxburst + 1);
uvc_ss_streaming_ep.bEndpointAddress =
uvc_fs_streaming_ep.bEndpointAddress;
/* Copy descriptors */
f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
if (gadget_is_dualspeed(cdev->gadget))
@ -775,23 +768,23 @@ uvc_bind_config(struct usb_configuration *c,
/* Validate the descriptors. */
if (fs_control == NULL || fs_control[0] == NULL ||
fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
goto error;
if (ss_control == NULL || ss_control[0] == NULL ||
ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
goto error;
if (fs_streaming == NULL || fs_streaming[0] == NULL ||
fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
goto error;
if (hs_streaming == NULL || hs_streaming[0] == NULL ||
hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
goto error;
if (ss_streaming == NULL || ss_streaming[0] == NULL ||
ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
goto error;
uvc->desc.fs_control = fs_control;
@ -800,13 +793,16 @@ uvc_bind_config(struct usb_configuration *c,
uvc->desc.hs_streaming = hs_streaming;
uvc->desc.ss_streaming = ss_streaming;
/* Allocate string descriptor numbers. */
if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
/* String descriptors are global, we only need to allocate string IDs
* for the first UVC function. UVC functions beyond the first (if any)
* will reuse the same IDs.
*/
if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {
ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
if (ret)
goto error;
uvc_iad.iFunction =
uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
uvc_control_intf.iInterface =
uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;

View File

@ -16,12 +16,12 @@
#include <linux/usb/composite.h>
#include <linux/usb/video.h>
extern int uvc_bind_config(struct usb_configuration *c,
const struct uvc_descriptor_header * const *fs_control,
const struct uvc_descriptor_header * const *hs_control,
const struct uvc_descriptor_header * const *fs_streaming,
const struct uvc_descriptor_header * const *hs_streaming,
const struct uvc_descriptor_header * const *ss_streaming);
int uvc_bind_config(struct usb_configuration *c,
const struct uvc_descriptor_header * const *fs_control,
const struct uvc_descriptor_header * const *hs_control,
const struct uvc_descriptor_header * const *fs_streaming,
const struct uvc_descriptor_header * const *hs_streaming,
const struct uvc_descriptor_header * const *ss_streaming);
#endif /* _F_UVC_H_ */

View File

@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget,
driver->driver.bus = NULL;
/* hook up the driver */
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
udc->gadget.speed = driver->max_speed;
/* Enable IRQ reg and Set usbcmd reg EN bit */
@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc->lock, flags);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
@ -2523,12 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev)
/* name: Identifies the controller hardware type. */
udc->gadget.name = driver_name;
device_initialize(&udc->gadget.dev);
dev_set_name(&udc->gadget.dev, "gadget");
udc->gadget.dev.release = qe_udc_release;
udc->gadget.dev.parent = &ofdev->dev;
/* initialize qe_ep struct */
@ -2592,22 +2584,17 @@ static int qe_udc_probe(struct platform_device *ofdev)
goto err5;
}
ret = device_add(&udc->gadget.dev);
ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
qe_udc_release);
if (ret)
goto err6;
ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget);
if (ret)
goto err7;
dev_set_drvdata(&ofdev->dev, udc);
dev_info(udc->dev,
"%s USB controller initialized as device\n",
(udc->soc_type == PORT_QE) ? "QE" : "CPM");
return 0;
err7:
device_unregister(&udc->gadget.dev);
err6:
free_irq(udc->usb_irq, udc);
err5:
@ -2702,7 +2689,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
iounmap(udc->usb_regs);
device_unregister(&udc->gadget.dev);
/* wait for release() of gadget.dev to free udc */
wait_for_completion(&done);

View File

@ -185,20 +185,7 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
}
if (req->mapped) {
dma_unmap_single(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
ep_is_in(ep)
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
} else
dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
ep_is_in(ep)
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
if (status && (status != -ESHUTDOWN))
VDBG("complete %s req %p stat %d len %u/%u",
@ -888,6 +875,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
struct fsl_req *req = container_of(_req, struct fsl_req, req);
struct fsl_udc *udc;
unsigned long flags;
int ret;
/* catch various bogus parameters */
if (!_req || !req->req.complete || !req->req.buf
@ -910,22 +898,9 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
req->ep = ep;
/* map virtual address to hardware */
if (req->req.dma == DMA_ADDR_INVALID) {
req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
req->req.buf,
req->req.length, ep_is_in(ep)
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
req->mapped = 1;
} else {
dma_sync_single_for_device(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
ep_is_in(ep)
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
req->mapped = 0;
}
ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
if (ret)
return ret;
req->req.status = -EINPROGRESS;
req->req.actual = 0;
@ -1290,6 +1265,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
{
struct fsl_req *req = udc->status_req;
struct fsl_ep *ep;
int ret;
if (direction == EP_DIR_IN)
udc->ep0_dir = USB_DIR_IN;
@ -1307,10 +1283,9 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
req->req.complete = NULL;
req->dtd_count = 0;
req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
req->req.buf, req->req.length,
ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 1;
ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
if (ret)
return ret;
if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
fsl_queue_td(ep, req);
@ -1353,6 +1328,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
u16 tmp = 0; /* Status, cpu endian */
struct fsl_req *req;
struct fsl_ep *ep;
int ret;
ep = &udc->eps[0];
@ -1390,10 +1366,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
req->req.complete = NULL;
req->dtd_count = 0;
req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
req->req.buf, req->req.length,
ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 1;
ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
if (ret)
goto stall;
/* prime the data phase */
if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
@ -1964,7 +1939,6 @@ static int fsl_udc_start(struct usb_gadget *g,
driver->driver.bus = NULL;
/* hook up the driver */
udc_controller->driver = driver;
udc_controller->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc_controller->lock, flags);
if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
@ -1980,7 +1954,6 @@ static int fsl_udc_start(struct usb_gadget *g,
if (retval < 0) {
ERR("can't bind to transceiver\n");
driver->unbind(&udc_controller->gadget);
udc_controller->gadget.dev.driver = 0;
udc_controller->driver = 0;
return retval;
}
@ -2023,7 +1996,6 @@ static int fsl_udc_stop(struct usb_gadget *g,
nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc_controller->lock, flags);
udc_controller->gadget.dev.driver = NULL;
udc_controller->driver = NULL;
return 0;
@ -2521,12 +2493,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
/* Setup gadget.dev and register with kernel */
dev_set_name(&udc_controller->gadget.dev, "gadget");
udc_controller->gadget.dev.release = fsl_udc_release;
udc_controller->gadget.dev.parent = &pdev->dev;
udc_controller->gadget.dev.of_node = pdev->dev.of_node;
ret = device_register(&udc_controller->gadget.dev);
if (ret < 0)
goto err_free_irq;
if (!IS_ERR_OR_NULL(udc_controller->transceiver))
udc_controller->gadget.is_otg = 1;
@ -2559,10 +2526,11 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
if (udc_controller->td_pool == NULL) {
ret = -ENOMEM;
goto err_unregister;
goto err_free_irq;
}
ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget,
fsl_udc_release);
if (ret)
goto err_del_udc;
@ -2571,8 +2539,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
err_del_udc:
dma_pool_destroy(udc_controller->td_pool);
err_unregister:
device_unregister(&udc_controller->gadget.dev);
err_free_irq:
free_irq(udc_controller->irq, udc_controller);
err_iounmap:
@ -2622,7 +2588,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
release_mem_region(res->start, resource_size(res));
device_unregister(&udc_controller->gadget.dev);
/* free udc --wait for the release() finished */
wait_for_completion(&done);
@ -2747,21 +2712,7 @@ static struct platform_driver udc_driver = {
},
};
static int __init udc_init(void)
{
printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION);
return platform_driver_probe(&udc_driver, fsl_udc_probe);
}
module_init(udc_init);
static void __exit udc_exit(void)
{
platform_driver_unregister(&udc_driver);
printk(KERN_WARNING "%s unregistered\n", driver_desc);
}
module_exit(udc_exit);
module_platform_driver_probe(udc_driver, fsl_udc_probe);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);

View File

@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
if (reg & FUSB300_EPSET0_STL) {
printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
reg &= ~FUSB300_EPSET0_STL;
reg |= FUSB300_EPSET0_STL_CLR;
iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
}
}
@ -930,33 +930,33 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
return;
IDMA_RESET:
fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0,
FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0);
reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum);
iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0);
}
static void fusb300_set_idma(struct fusb300_ep *ep,
static void fusb300_set_idma(struct fusb300_ep *ep,
struct fusb300_request *req)
{
dma_addr_t d;
int ret;
d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
if (dma_mapping_error(NULL, d)) {
printk(KERN_DEBUG "dma_mapping_error\n");
ret = usb_gadget_map_request(&ep->fusb300->gadget,
&req->req, DMA_TO_DEVICE);
if (ret)
return;
}
dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
fusb300_fill_idma_prdtbl(ep, d, req->req.length);
fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length);
/* check idma is done */
fusb300_wait_idma_finished(ep);
dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
usb_gadget_unmap_request(&ep->fusb300->gadget,
&req->req, DMA_TO_DEVICE);
}
static void in_ep_fifo_handler(struct fusb300_ep *ep)
@ -1316,7 +1316,6 @@ static int fusb300_udc_start(struct usb_gadget *g,
/* hook up the driver */
driver->driver.bus = NULL;
fusb300->driver = driver;
fusb300->gadget.dev.driver = &driver->driver;
return 0;
}
@ -1327,7 +1326,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
struct fusb300 *fusb300 = to_fusb300(g);
driver->unbind(&fusb300->gadget);
fusb300->gadget.dev.driver = NULL;
init_controller(fusb300);
fusb300->driver = NULL;
@ -1422,14 +1420,7 @@ static int __init fusb300_probe(struct platform_device *pdev)
fusb300->gadget.ops = &fusb300_gadget_ops;
device_initialize(&fusb300->gadget.dev);
dev_set_name(&fusb300->gadget.dev, "gadget");
fusb300->gadget.max_speed = USB_SPEED_HIGH;
fusb300->gadget.dev.parent = &pdev->dev;
fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask;
fusb300->gadget.dev.release = pdev->dev.release;
fusb300->gadget.name = udc_name;
fusb300->reg = reg;
@ -1478,19 +1469,10 @@ static int __init fusb300_probe(struct platform_device *pdev)
if (ret)
goto err_add_udc;
ret = device_add(&fusb300->gadget.dev);
if (ret) {
pr_err("device_add error (%d)\n", ret);
goto err_add_device;
}
dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
return 0;
err_add_device:
usb_del_gadget_udc(&fusb300->gadget);
err_add_udc:
fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);

View File

@ -111,8 +111,8 @@
/*
* * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
* */
#define FUSB300_EPSET0_STL_CLR (1 << 3)
#define FUSB300_EPSET0_CLRSEQNUM (1 << 2)
#define FUSB300_EPSET0_EPn_TX0BYTE (1 << 1)
#define FUSB300_EPSET0_STL (1 << 0)
/*

View File

@ -13,7 +13,6 @@
#define pr_fmt(fmt) "g_ffs: " fmt
#include <linux/module.h>
/*
* kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
@ -38,13 +37,16 @@
# include "u_ether.c"
static u8 gfs_hostaddr[ETH_ALEN];
static struct eth_dev *the_dev;
# ifdef CONFIG_USB_FUNCTIONFS_ETH
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev);
# endif
#else
# define gether_cleanup() do { } while (0)
# define gether_setup(gadget, hostaddr) ((int)0)
# define the_dev NULL
# define gether_cleanup(dev) do { } while (0)
# define gfs_hostaddr NULL
struct eth_dev;
#endif
#include "f_fs.c"
@ -137,7 +139,8 @@ static struct usb_gadget_strings *gfs_dev_strings[] = {
struct gfs_configuration {
struct usb_configuration c;
int (*eth)(struct usb_configuration *c, u8 *ethaddr);
int (*eth)(struct usb_configuration *c, u8 *ethaddr,
struct eth_dev *dev);
} gfs_configurations[] = {
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
{
@ -346,10 +349,13 @@ static int gfs_bind(struct usb_composite_dev *cdev)
if (missing_funcs)
return -ENODEV;
ret = gether_setup(cdev->gadget, gfs_hostaddr);
if (unlikely(ret < 0))
#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
the_dev = gether_setup(cdev->gadget, gfs_hostaddr);
#endif
if (IS_ERR(the_dev)) {
ret = PTR_ERR(the_dev);
goto error_quick;
}
gfs_ether_setup = true;
ret = usb_string_ids_tab(cdev, gfs_strings);
@ -386,7 +392,7 @@ static int gfs_bind(struct usb_composite_dev *cdev)
for (i = 0; i < func_num; i++)
functionfs_unbind(ffs_tab[i].ffs_data);
error:
gether_cleanup();
gether_cleanup(the_dev);
error_quick:
gfs_ether_setup = false;
return ret;
@ -410,7 +416,7 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
* do...?
*/
if (gfs_ether_setup)
gether_cleanup();
gether_cleanup(the_dev);
gfs_ether_setup = false;
for (i = func_num; i--; )
@ -440,7 +446,7 @@ static int gfs_do_config(struct usb_configuration *c)
}
if (gc->eth) {
ret = gc->eth(c, gfs_hostaddr);
ret = gc->eth(c, gfs_hostaddr, the_dev);
if (unlikely(ret < 0))
return ret;
}
@ -469,11 +475,12 @@ static int gfs_do_config(struct usb_configuration *c)
#ifdef CONFIG_USB_FUNCTIONFS_ETH
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev)
{
return can_support_ecm(c->cdev->gadget)
? ecm_bind_config(c, ethaddr)
: geth_bind_config(c, ethaddr);
? ecm_bind_config(c, ethaddr, dev)
: geth_bind_config(c, ethaddr, dev);
}
#endif

View File

@ -51,8 +51,6 @@
#define DRIVER_DESC "TC86C001 USB Device Controller"
#define DRIVER_VERSION "30-Oct 2003"
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
static const char driver_name [] = "goku_udc";
static const char driver_desc [] = DRIVER_DESC;
@ -275,7 +273,6 @@ goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
if (!req)
return NULL;
req->req.dma = DMA_ADDR_INVALID;
INIT_LIST_HEAD(&req->queue);
return &req->req;
}
@ -1354,7 +1351,6 @@ static int goku_udc_start(struct usb_gadget *g,
/* hook up the driver */
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
/*
* then enable host detection and ep0; and we're ready
@ -1394,7 +1390,6 @@ static int goku_udc_stop(struct usb_gadget *g,
dev->driver = NULL;
stop_activity(dev, driver);
spin_unlock_irqrestore(&dev->lock, flags);
dev->gadget.dev.driver = NULL;
return 0;
}
@ -1716,8 +1711,6 @@ static void goku_remove(struct pci_dev *pdev)
pci_resource_len (pdev, 0));
if (dev->enabled)
pci_disable_device(pdev);
if (dev->registered)
device_unregister(&dev->gadget.dev);
pci_set_drvdata(pdev, NULL);
dev->regs = NULL;
@ -1756,10 +1749,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dev->gadget.max_speed = USB_SPEED_FULL;
/* the "gadget" abstracts/virtualizes the controller */
dev_set_name(&dev->gadget.dev, "gadget");
dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
dev->gadget.dev.release = gadget_release;
dev->gadget.name = driver_name;
/* now all the pci goodies ... */
@ -1810,13 +1799,8 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
#endif
retval = device_register(&dev->gadget.dev);
if (retval) {
put_device(&dev->gadget.dev);
goto err;
}
dev->registered = 1;
retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
gadget_release);
if (retval)
goto err;

View File

@ -250,8 +250,7 @@ struct goku_udc {
got_region:1,
req_config:1,
configured:1,
enabled:1,
registered:1;
enabled:1;
/* pci state used to access those endpoints */
struct pci_dev *pdev;

View File

@ -1338,7 +1338,6 @@ static int imx_udc_start(struct usb_gadget *gadget,
imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
/* first hook up the driver ... */
imx_usb->driver = driver;
imx_usb->gadget.dev.driver = &driver->driver;
D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
__func__, driver->driver.name);
@ -1358,7 +1357,6 @@ static int imx_udc_stop(struct usb_gadget *gadget,
imx_udc_disable(imx_usb);
del_timer(&imx_usb->timer);
imx_usb->gadget.dev.driver = NULL;
imx_usb->driver = NULL;
D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
@ -1461,15 +1459,6 @@ static int __init imx_udc_probe(struct platform_device *pdev)
imx_usb->clk = clk;
imx_usb->dev = &pdev->dev;
device_initialize(&imx_usb->gadget.dev);
imx_usb->gadget.dev.parent = &pdev->dev;
imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask;
ret = device_add(&imx_usb->gadget.dev);
if (retval)
goto fail4;
platform_set_drvdata(pdev, imx_usb);
usb_init_data(imx_usb);
@ -1481,11 +1470,9 @@ static int __init imx_udc_probe(struct platform_device *pdev)
ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
if (ret)
goto fail5;
goto fail4;
return 0;
fail5:
device_unregister(&imx_usb->gadget.dev);
fail4:
for (i = 0; i < IMX_USB_NB_EP + 1; i++)
free_irq(imx_usb->usbd_int[i], imx_usb);
@ -1509,7 +1496,6 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
int i;
usb_del_gadget_udc(&imx_usb->gadget);
device_unregister(&imx_usb->gadget.dev);
imx_udc_disable(imx_usb);
del_timer(&imx_usb->timer);

View File

@ -1469,23 +1469,7 @@ static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
status = req->req.status;
if (ep->lep) {
enum dma_data_direction direction;
if (ep->is_in)
direction = DMA_TO_DEVICE;
else
direction = DMA_FROM_DEVICE;
if (req->mapped) {
dma_unmap_single(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
direction);
req->req.dma = 0;
req->mapped = 0;
} else
dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
direction);
usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
/* Free DDs */
udc_dd_free(udc, req->dd_desc_ptr);
@ -1841,26 +1825,11 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep,
}
if (ep->lep) {
enum dma_data_direction direction;
struct lpc32xx_usbd_dd_gad *dd;
/* Map DMA pointer */
if (ep->is_in)
direction = DMA_TO_DEVICE;
else
direction = DMA_FROM_DEVICE;
if (req->req.dma == 0) {
req->req.dma = dma_map_single(
ep->udc->gadget.dev.parent,
req->req.buf, req->req.length, direction);
req->mapped = 1;
} else {
dma_sync_single_for_device(
ep->udc->gadget.dev.parent, req->req.dma,
req->req.length, direction);
req->mapped = 0;
}
status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
if (status)
return status;
/* For the request, build a list of DDs */
dd = udc_dd_alloc(udc);
@ -2977,7 +2946,6 @@ static int lpc32xx_start(struct usb_gadget *gadget,
}
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
udc->gadget.dev.of_node = udc->dev->of_node;
udc->enabled = 1;
udc->selfpowered = 1;
@ -3026,7 +2994,6 @@ static int lpc32xx_stop(struct usb_gadget *gadget,
}
udc->enabled = 0;
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
return 0;
@ -3248,12 +3215,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
udc_disable(udc);
udc_reinit(udc);
retval = device_register(&udc->gadget.dev);
if (retval < 0) {
dev_err(udc->dev, "Device registration failure\n");
goto dev_register_fail;
}
/* Request IRQs - low and high priority USB device IRQs are routed to
* the same handler, while the DMA interrupt is routed elsewhere */
retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
@ -3320,8 +3281,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
irq_hp_fail:
free_irq(udc->udp_irq[IRQ_USB_LP], udc);
irq_lp_fail:
device_unregister(&udc->gadget.dev);
dev_register_fail:
dma_pool_destroy(udc->dd_cache);
dma_alloc_fail:
dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
@ -3376,8 +3335,6 @@ static int lpc32xx_udc_remove(struct platform_device *pdev)
free_irq(udc->udp_irq[IRQ_USB_HP], udc);
free_irq(udc->udp_irq[IRQ_USB_LP], udc);
device_unregister(&udc->gadget.dev);
clk_disable(udc->usb_otg_clk);
clk_put(udc->usb_otg_clk);
clk_disable(udc->usb_slv_clk);

View File

@ -1471,7 +1471,6 @@ static int m66592_udc_start(struct usb_gadget *g,
/* hook up the driver */
driver->driver.bus = NULL;
m66592->driver = driver;
m66592->gadget.dev.driver = &driver->driver;
m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
@ -1494,7 +1493,6 @@ static int m66592_udc_stop(struct usb_gadget *g,
m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
driver->unbind(&m66592->gadget);
m66592->gadget.dev.driver = NULL;
init_controller(m66592);
disable_controller(m66592);
@ -1538,7 +1536,6 @@ static int __exit m66592_remove(struct platform_device *pdev)
struct m66592 *m66592 = dev_get_drvdata(&pdev->dev);
usb_del_gadget_udc(&m66592->gadget);
device_del(&m66592->gadget.dev);
del_timer_sync(&m66592->timer);
iounmap(m66592->reg);
@ -1608,12 +1605,7 @@ static int __init m66592_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, m66592);
m66592->gadget.ops = &m66592_gadget_ops;
device_initialize(&m66592->gadget.dev);
dev_set_name(&m66592->gadget.dev, "gadget");
m66592->gadget.max_speed = USB_SPEED_HIGH;
m66592->gadget.dev.parent = &pdev->dev;
m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
m66592->gadget.dev.release = pdev->dev.release;
m66592->gadget.name = udc_name;
init_timer(&m66592->timer);
@ -1674,12 +1666,6 @@ static int __init m66592_probe(struct platform_device *pdev)
init_controller(m66592);
ret = device_add(&m66592->gadget.dev);
if (ret) {
pr_err("device_add error (%d)\n", ret);
goto err_device_add;
}
ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
if (ret)
goto err_add_udc;
@ -1688,9 +1674,6 @@ static int __init m66592_probe(struct platform_device *pdev)
return 0;
err_add_udc:
device_del(&m66592->gadget.dev);
err_device_add:
m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
clean_up3:

View File

@ -135,8 +135,8 @@ static struct fsg_common fsg_common;
static u8 hostaddr[ETH_ALEN];
static unsigned char tty_line;
static struct usb_function_instance *fi_acm;
static struct eth_dev *the_dev;
/********** RNDIS **********/
@ -152,7 +152,7 @@ static __init int rndis_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
ret = rndis_bind_config(c, hostaddr);
ret = rndis_bind_config(c, hostaddr, the_dev);
if (ret < 0)
return ret;
@ -214,7 +214,7 @@ static __init int cdc_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
ret = ecm_bind_config(c, hostaddr);
ret = ecm_bind_config(c, hostaddr, the_dev);
if (ret < 0)
return ret;
@ -269,7 +269,6 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
static int __ref multi_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct f_serial_opts *opts;
int status;
if (!can_support_ecm(cdev->gadget)) {
@ -279,24 +278,17 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
}
/* set up network link layer */
status = gether_setup(cdev->gadget, hostaddr);
if (status < 0)
return status;
the_dev = gether_setup(cdev->gadget, hostaddr);
if (IS_ERR(the_dev))
return PTR_ERR(the_dev);
/* set up serial link layer */
status = gserial_alloc_line(&tty_line);
if (status < 0)
goto fail0;
fi_acm = usb_get_function_instance("acm");
if (IS_ERR(fi_acm)) {
status = PTR_ERR(fi_acm);
goto fail0dot5;
goto fail0;
}
opts = container_of(fi_acm, struct f_serial_opts, func_inst);
opts->port_num = tty_line;
/* set up mass storage function */
{
void *retp;
@ -334,10 +326,8 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
fsg_common_put(&fsg_common);
fail1:
usb_put_function_instance(fi_acm);
fail0dot5:
gserial_free_line(tty_line);
fail0:
gether_cleanup();
gether_cleanup(the_dev);
return status;
}
@ -350,8 +340,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_acm_rndis);
#endif
usb_put_function_instance(fi_acm);
gserial_free_line(tty_line);
gether_cleanup();
gether_cleanup(the_dev);
return 0;
}

View File

@ -30,9 +30,6 @@
#include <linux/platform_device.h>
#include <linux/platform_data/mv_usb.h>
#include <linux/clk.h>
#include <asm/system.h>
#include <asm/unaligned.h>
#include <asm/byteorder.h>
#include "mv_u3d.h"
@ -125,7 +122,7 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
struct mv_u3d_trb *curr_trb;
dma_addr_t cur_deq_lo;
struct mv_u3d_ep_context *curr_ep_context;
int trb_complete, actual, remaining_length;
int trb_complete, actual, remaining_length = 0;
int direction, ep_num;
int retval = 0;
u32 tmp, status, length;
@ -189,6 +186,8 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
*/
static
void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
__releases(&ep->udc->lock)
__acquires(&ep->udc->lock)
{
struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
@ -812,19 +811,19 @@ mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return 0;
}
dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n",
__func__, _ep->name, (u32)req);
dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n",
__func__, _ep->name, req);
/* catch various bogus parameters */
if (!req->req.complete || !req->req.buf
|| !list_empty(&req->queue)) {
dev_err(u3d->dev,
"%s, bad params, _req: 0x%x,"
"req->req.complete: 0x%x, req->req.buf: 0x%x,"
"%s, bad params, _req: 0x%p,"
"req->req.complete: 0x%p, req->req.buf: 0x%p,"
"list_empty: 0x%x\n",
__func__, (u32)_req,
(u32)req->req.complete, (u32)req->req.buf,
(u32)list_empty(&req->queue));
__func__, _req,
req->req.complete, req->req.buf,
list_empty(&req->queue));
return -EINVAL;
}
if (unlikely(!ep->ep.desc)) {
@ -905,7 +904,7 @@ static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
struct mv_u3d_req, queue);
/* Point first TRB of next request to the EP context. */
iowrite32((u32) next_req->trb_head,
iowrite32((unsigned long) next_req->trb_head,
&ep_context->trb_addr_lo);
} else {
struct mv_u3d_ep_context *ep_context;
@ -1264,7 +1263,6 @@ static int mv_u3d_start(struct usb_gadget *g,
/* hook up the driver ... */
driver->driver.bus = NULL;
u3d->driver = driver;
u3d->gadget.dev.driver = &driver->driver;
u3d->ep0_dir = USB_DIR_OUT;
@ -1302,7 +1300,6 @@ static int mv_u3d_stop(struct usb_gadget *g,
spin_unlock_irqrestore(&u3d->lock, flags);
u3d->gadget.dev.driver = NULL;
u3d->driver = NULL;
return 0;
@ -1525,6 +1522,8 @@ static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)
static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
struct usb_ctrlrequest *setup)
__releases(&u3c->lock)
__acquires(&u3c->lock)
{
bool delegate = false;
@ -1758,11 +1757,6 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev)
return IRQ_HANDLED;
}
static void mv_u3d_gadget_release(struct device *dev)
{
dev_dbg(dev, "%s\n", __func__);
}
static int mv_u3d_remove(struct platform_device *dev)
{
struct mv_u3d *u3d = platform_get_drvdata(dev);
@ -1792,8 +1786,6 @@ static int mv_u3d_remove(struct platform_device *dev)
clk_put(u3d->clk);
device_unregister(&u3d->gadget.dev);
platform_set_drvdata(dev, NULL);
kfree(u3d);
@ -1829,7 +1821,7 @@ static int mv_u3d_probe(struct platform_device *dev)
u3d->dev = &dev->dev;
u3d->vbus = pdata->vbus;
u3d->clk = clk_get(&dev->dev, pdata->clkname[0]);
u3d->clk = clk_get(&dev->dev, NULL);
if (IS_ERR(u3d->clk)) {
retval = PTR_ERR(u3d->clk);
goto err_get_clk;
@ -1849,8 +1841,9 @@ static int mv_u3d_probe(struct platform_device *dev)
retval = -EBUSY;
goto err_map_cap_regs;
} else {
dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n",
(unsigned int)r->start, (unsigned int)u3d->cap_regs);
dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n",
(unsigned long) r->start,
(unsigned long) u3d->cap_regs);
}
/* we will access controller register, so enable the u3d controller */
@ -1864,10 +1857,10 @@ static int mv_u3d_probe(struct platform_device *dev)
}
}
u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs
u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs
+ MV_U3D_USB3_OP_REGS_OFFSET);
u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs
u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs
+ ioread32(&u3d->cap_regs->vuoff));
u3d->max_eps = 16;
@ -1957,16 +1950,8 @@ static int mv_u3d_probe(struct platform_device *dev)
u3d->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
/* the "gadget" abstracts/virtualizes the controller */
dev_set_name(&u3d->gadget.dev, "gadget");
u3d->gadget.dev.parent = &dev->dev;
u3d->gadget.dev.dma_mask = dev->dev.dma_mask;
u3d->gadget.dev.release = mv_u3d_gadget_release;
u3d->gadget.name = driver_name; /* gadget name */
retval = device_register(&u3d->gadget.dev);
if (retval)
goto err_register_gadget_device;
mv_u3d_eps_init(u3d);
/* external vbus detection */
@ -1991,8 +1976,6 @@ static int mv_u3d_probe(struct platform_device *dev)
return 0;
err_unregister:
device_unregister(&u3d->gadget.dev);
err_register_gadget_device:
free_irq(u3d->irq, &dev->dev);
err_request_irq:
err_get_irq:
@ -2021,7 +2004,7 @@ static int mv_u3d_probe(struct platform_device *dev)
return retval;
}
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int mv_u3d_suspend(struct device *dev)
{
struct mv_u3d *u3d = dev_get_drvdata(dev);
@ -2064,10 +2047,10 @@ static int mv_u3d_resume(struct device *dev)
return 0;
}
SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
#endif
static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
static void mv_u3d_shutdown(struct platform_device *dev)
{
struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
@ -2080,14 +2063,12 @@ static void mv_u3d_shutdown(struct platform_device *dev)
static struct platform_driver mv_u3d_driver = {
.probe = mv_u3d_probe,
.remove = __exit_p(mv_u3d_remove),
.remove = mv_u3d_remove,
.shutdown = mv_u3d_shutdown,
.driver = {
.owner = THIS_MODULE,
.name = "mv-u3d",
#ifdef CONFIG_PM
.pm = &mv_u3d_pm_ops,
#endif
},
};

View File

@ -222,8 +222,7 @@ struct mv_udc {
struct mv_usb_platform_data *pdata;
/* some SOC has mutiple clock sources for USB*/
unsigned int clknum;
struct clk *clk[0];
struct clk *clk;
};
/* endpoint data structure */

View File

@ -212,6 +212,8 @@ static int process_ep_req(struct mv_udc *udc, int index,
* request is still in progress.
*/
static void done(struct mv_ep *ep, struct mv_req *req, int status)
__releases(&ep->udc->lock)
__acquires(&ep->udc->lock)
{
struct mv_udc *udc = NULL;
unsigned char stopped = ep->stopped;
@ -237,18 +239,7 @@ static void done(struct mv_ep *ep, struct mv_req *req, int status)
dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
}
if (req->mapped) {
dma_unmap_single(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
((ep_dir(ep) == EP_DIR_IN) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE));
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
} else
dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
((ep_dir(ep) == EP_DIR_IN) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE));
usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
if (status && (status != -ESHUTDOWN))
dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
@ -732,21 +723,9 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
req->ep = ep;
/* map virtual address to hardware */
if (req->req.dma == DMA_ADDR_INVALID) {
req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
req->req.buf,
req->req.length, ep_dir(ep)
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
req->mapped = 1;
} else {
dma_sync_single_for_device(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
ep_dir(ep)
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
req->mapped = 0;
}
retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep));
if (retval)
return retval;
req->req.status = -EINPROGRESS;
req->req.actual = 0;
@ -780,18 +759,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return 0;
err_unmap_dma:
if (req->mapped) {
dma_unmap_single(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
((ep_dir(ep) == EP_DIR_IN) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE));
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
} else
dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
((ep_dir(ep) == EP_DIR_IN) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE));
usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep));
return retval;
}
@ -1006,18 +974,12 @@ static struct usb_ep_ops mv_ep_ops = {
static void udc_clock_enable(struct mv_udc *udc)
{
unsigned int i;
for (i = 0; i < udc->clknum; i++)
clk_prepare_enable(udc->clk[i]);
clk_prepare_enable(udc->clk);
}
static void udc_clock_disable(struct mv_udc *udc)
{
unsigned int i;
for (i = 0; i < udc->clknum; i++)
clk_disable_unprepare(udc->clk[i]);
clk_disable_unprepare(udc->clk);
}
static void udc_stop(struct mv_udc *udc)
@ -1386,7 +1348,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
/* hook up the driver ... */
driver->driver.bus = NULL;
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
udc->usb_state = USB_STATE_ATTACHED;
udc->ep0_state = WAIT_FOR_SETUP;
@ -1401,7 +1362,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
dev_err(&udc->dev->dev,
"unable to register peripheral to otg\n");
udc->driver = NULL;
udc->gadget.dev.driver = NULL;
return retval;
}
}
@ -1437,7 +1397,6 @@ static int mv_udc_stop(struct usb_gadget *gadget,
spin_unlock_irqrestore(&udc->lock, flags);
/* unbind gadget driver */
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
return 0;
@ -1528,14 +1487,7 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
return 0;
out:
if (req->mapped) {
dma_unmap_single(ep->udc->gadget.dev.parent,
req->req.dma, req->req.length,
((ep_dir(ep) == EP_DIR_IN) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE));
req->req.dma = DMA_ADDR_INVALID;
req->mapped = 0;
}
usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
return retval;
}
@ -1695,6 +1647,8 @@ static void ch9setfeature(struct mv_udc *udc, struct usb_ctrlrequest *setup)
static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
struct usb_ctrlrequest *setup)
__releases(&ep->udc->lock)
__acquires(&ep->udc->lock)
{
bool delegate = false;
@ -1891,7 +1845,7 @@ static void irq_process_tr_complete(struct mv_udc *udc)
}
}
void irq_process_reset(struct mv_udc *udc)
static void irq_process_reset(struct mv_udc *udc)
{
u32 tmp;
unsigned int loops;
@ -2138,8 +2092,6 @@ static int mv_udc_remove(struct platform_device *pdev)
mv_udc_disable(udc);
device_unregister(&udc->gadget.dev);
/* free dev, wait for the release() finished */
wait_for_completion(udc->done);
@ -2151,7 +2103,6 @@ static int mv_udc_probe(struct platform_device *pdev)
struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
struct mv_udc *udc;
int retval = 0;
int clk_i = 0;
struct resource *r;
size_t size;
@ -2160,8 +2111,7 @@ static int mv_udc_probe(struct platform_device *pdev)
return -ENODEV;
}
size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
if (udc == NULL) {
dev_err(&pdev->dev, "failed to allocate memory for udc\n");
return -ENOMEM;
@ -2173,27 +2123,25 @@ static int mv_udc_probe(struct platform_device *pdev)
udc->dev = pdev;
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->mode == MV_USB_MODE_OTG) {
udc->transceiver = devm_usb_get_phy(&pdev->dev,
USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(udc->transceiver)) {
udc->transceiver = NULL;
return -ENODEV;
}
}
#endif
if (IS_ERR(udc->transceiver)) {
retval = PTR_ERR(udc->transceiver);
udc->clknum = pdata->clknum;
for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
udc->clk[clk_i] = devm_clk_get(&pdev->dev,
pdata->clkname[clk_i]);
if (IS_ERR(udc->clk[clk_i])) {
retval = PTR_ERR(udc->clk[clk_i]);
return retval;
if (retval == -ENXIO)
return retval;
udc->transceiver = NULL;
return -EPROBE_DEFER;
}
}
/* udc only have one sysclk. */
udc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(udc->clk))
return PTR_ERR(udc->clk);
r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
if (r == NULL) {
dev_err(&pdev->dev, "no I/O memory resource defined\n");
@ -2311,16 +2259,8 @@ static int mv_udc_probe(struct platform_device *pdev)
udc->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
/* the "gadget" abstracts/virtualizes the controller */
dev_set_name(&udc->gadget.dev, "gadget");
udc->gadget.dev.parent = &pdev->dev;
udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
udc->gadget.dev.release = gadget_release;
udc->gadget.name = driver_name; /* gadget name */
retval = device_register(&udc->gadget.dev);
if (retval)
goto err_destroy_dma;
eps_init(udc);
/* VBUS detect: we can disable/enable clock on demand.*/
@ -2342,7 +2282,7 @@ static int mv_udc_probe(struct platform_device *pdev)
if (!udc->qwork) {
dev_err(&pdev->dev, "cannot create workqueue\n");
retval = -ENOMEM;
goto err_unregister;
goto err_destroy_dma;
}
INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
@ -2358,7 +2298,8 @@ static int mv_udc_probe(struct platform_device *pdev)
else
udc->vbus_active = 1;
retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
gadget_release);
if (retval)
goto err_create_workqueue;
@ -2370,8 +2311,6 @@ static int mv_udc_probe(struct platform_device *pdev)
err_create_workqueue:
destroy_workqueue(udc->qwork);
err_unregister:
device_unregister(&udc->gadget.dev);
err_destroy_dma:
dma_pool_destroy(udc->dtd_pool);
err_free_dma:

View File

@ -111,6 +111,7 @@ static struct usb_gadget_strings *dev_strings[] = {
NULL,
};
struct eth_dev *the_dev;
static u8 hostaddr[ETH_ALEN];
/*-------------------------------------------------------------------------*/
@ -124,7 +125,7 @@ static int __init ncm_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
return ncm_bind_config(c, hostaddr);
return ncm_bind_config(c, hostaddr, the_dev);
}
static struct usb_configuration ncm_config_driver = {
@ -143,9 +144,9 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
int status;
/* set up network link layer */
status = gether_setup(cdev->gadget, hostaddr);
if (status < 0)
return status;
the_dev = gether_setup(cdev->gadget, hostaddr);
if (IS_ERR(the_dev))
return PTR_ERR(the_dev);
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
@ -168,13 +169,13 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
return 0;
fail:
gether_cleanup();
gether_cleanup(the_dev);
return status;
}
static int __exit gncm_unbind(struct usb_composite_dev *cdev)
{
gether_cleanup();
gether_cleanup(the_dev);
return 0;
}

View File

@ -58,7 +58,6 @@ static const char * const ep_name[] = {
"ep-a", "ep-b", "ep-c",
};
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#ifdef CONFIG_USB_NET2272_DMA
/*
* use_dma: the NET2272 can use an external DMA controller.
@ -341,7 +340,6 @@ net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
if (!req)
return NULL;
req->req.dma = DMA_ADDR_INVALID;
INIT_LIST_HEAD(&req->queue);
return &req->req;
@ -913,7 +911,7 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
}
}
}
if (likely(req != 0))
if (likely(req))
list_add_tail(&req->queue, &ep->queue);
if (likely(!list_empty(&ep->queue)))
@ -1467,7 +1465,6 @@ static int net2272_start(struct usb_gadget *_gadget,
dev->softconnect = 1;
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
/* ... then enable host detection and ep0; and we're ready
* for set_configuration as well as eventual disconnect.
@ -1517,7 +1514,6 @@ static int net2272_stop(struct usb_gadget *_gadget,
stop_activity(dev, driver);
spin_unlock_irqrestore(&dev->lock, flags);
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
@ -1549,7 +1545,7 @@ net2272_handle_dma(struct net2272_ep *ep)
| (ep->dev->dma_eot_polarity << EOT_POLARITY)
| (ep->dev->dma_dack_polarity << DACK_POLARITY)
| (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
| ((ep->dma >> 1) << DMA_ENDPOINT_SELECT));
| (ep->dma << DMA_ENDPOINT_SELECT));
ep->dev->dma_busy = 0;
@ -1622,7 +1618,7 @@ net2272_handle_ep(struct net2272_ep *ep)
ep->irqs++;
dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
ep->ep.name, stat0, stat1, req ? &req->req : 0);
ep->ep.name, stat0, stat1, req ? &req->req : NULL);
net2272_ep_write(ep, EP_STAT0, stat0 &
~((1 << NAK_OUT_PACKETS)
@ -2216,7 +2212,6 @@ net2272_remove(struct net2272 *dev)
free_irq(dev->irq, dev);
iounmap(dev->base_addr);
device_unregister(&dev->gadget.dev);
device_remove_file(dev->dev, &dev_attr_registers);
dev_info(dev->dev, "unbind\n");
@ -2243,10 +2238,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
ret->gadget.max_speed = USB_SPEED_HIGH;
/* the "gadget" abstracts/virtualizes the controller */
dev_set_name(&ret->gadget.dev, "gadget");
ret->gadget.dev.parent = dev;
ret->gadget.dev.dma_mask = dev->dma_mask;
ret->gadget.dev.release = net2272_gadget_release;
ret->gadget.name = driver_name;
return ret;
@ -2282,14 +2273,12 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
dma_mode_string());
dev_info(dev->dev, "version: %s\n", driver_vers);
ret = device_register(&dev->gadget.dev);
if (ret)
goto err_irq;
ret = device_create_file(dev->dev, &dev_attr_registers);
if (ret)
goto err_dev_reg;
goto err_irq;
ret = usb_add_gadget_udc(dev->dev, &dev->gadget);
ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget,
net2272_gadget_release);
if (ret)
goto err_add_udc;
@ -2297,8 +2286,6 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
err_add_udc:
device_remove_file(dev->dev, &dev_attr_registers);
err_dev_reg:
device_unregister(&dev->gadget.dev);
err_irq:
free_irq(dev->irq, dev);
err:

View File

@ -65,7 +65,6 @@
#define DRIVER_DESC "PLX NET228x USB Peripheral Controller"
#define DRIVER_VERSION "2005 Sept 27"
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define EP_DONTUSE 13 /* nonzero */
#define USE_RDK_LEDS /* GPIO pins control three LEDs */
@ -406,7 +405,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
if (!req)
return NULL;
req->req.dma = DMA_ADDR_INVALID;
INIT_LIST_HEAD (&req->queue);
/* this dma descriptor may be swapped with the previous dummy */
@ -420,7 +418,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
return NULL;
}
td->dmacount = 0; /* not VALID */
td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
td->dmadesc = td->dmaaddr;
req->td = td;
}
@ -1896,7 +1893,6 @@ static int net2280_start(struct usb_gadget *_gadget,
dev->softconnect = 1;
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
if (retval) goto err_unbind;
@ -1924,7 +1920,6 @@ static int net2280_start(struct usb_gadget *_gadget,
err_func:
device_remove_file (&dev->pdev->dev, &dev_attr_function);
err_unbind:
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
return retval;
}
@ -1967,7 +1962,6 @@ static int net2280_stop(struct usb_gadget *_gadget,
stop_activity (dev, driver);
spin_unlock_irqrestore (&dev->lock, flags);
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
net2280_led_active (dev, 0);
@ -2072,7 +2066,7 @@ static void handle_ep_small (struct net2280_ep *ep)
return;
/* manual DMA queue advance after short OUT */
if (likely (ep->dma != 0)) {
if (likely (ep->dma)) {
if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
u32 count;
int stopped = ep->stopped;
@ -2330,7 +2324,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
/* hw handles device and interface status */
if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
goto delegate;
if ((e = get_ep_by_addr (dev, w_index)) == 0
if ((e = get_ep_by_addr (dev, w_index)) == NULL
|| w_length > 2)
goto do_stall;
@ -2358,7 +2352,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
if (w_value != USB_ENDPOINT_HALT
|| w_length != 0)
goto do_stall;
if ((e = get_ep_by_addr (dev, w_index)) == 0)
if ((e = get_ep_by_addr (dev, w_index)) == NULL)
goto do_stall;
if (e->wedged) {
VDEBUG(dev, "%s wedged, halt not cleared\n",
@ -2380,7 +2374,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
if (w_value != USB_ENDPOINT_HALT
|| w_length != 0)
goto do_stall;
if ((e = get_ep_by_addr (dev, w_index)) == 0)
if ((e = get_ep_by_addr (dev, w_index)) == NULL)
goto do_stall;
if (e->ep.name == ep0name)
goto do_stall;
@ -2685,7 +2679,6 @@ static void net2280_remove (struct pci_dev *pdev)
pci_resource_len (pdev, 0));
if (dev->enabled)
pci_disable_device (pdev);
device_unregister (&dev->gadget.dev);
device_remove_file (&pdev->dev, &dev_attr_registers);
pci_set_drvdata (pdev, NULL);
@ -2717,10 +2710,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
dev->gadget.max_speed = USB_SPEED_HIGH;
/* the "gadget" abstracts/virtualizes the controller */
dev_set_name(&dev->gadget.dev, "gadget");
dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
dev->gadget.dev.release = gadget_release;
dev->gadget.name = driver_name;
/* now all the pci goodies ... */
@ -2802,7 +2791,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
goto done;
}
td->dmacount = 0; /* not VALID */
td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
td->dmadesc = td->dmaaddr;
dev->ep [i].dummy = td;
}
@ -2829,12 +2817,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
use_dma
? (use_dma_chaining ? "chaining" : "enabled")
: "disabled");
retval = device_register (&dev->gadget.dev);
if (retval) goto done;
retval = device_create_file (&pdev->dev, &dev_attr_registers);
if (retval) goto done;
retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
gadget_release);
if (retval)
goto done;
return 0;

View File

@ -37,11 +37,9 @@
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#define USB_FACM_INCLUDED
#include "f_acm.c"
#define USBF_OBEX_INCLUDED
#include "f_ecm.c"
#include "f_obex.c"
#include "f_serial.c"
#include "f_phonet.c"
#include "u_ether.c"
@ -98,45 +96,19 @@ MODULE_AUTHOR("Felipe Balbi");
MODULE_LICENSE("GPL");
/*-------------------------------------------------------------------------*/
static struct usb_function *f_acm_cfg1;
static struct usb_function *f_acm_cfg2;
static u8 hostaddr[ETH_ALEN];
static struct eth_dev *the_dev;
enum {
TTY_PORT_OBEX0,
TTY_PORT_OBEX1,
TTY_PORT_ACM,
TTY_PORTS_MAX,
};
static unsigned char tty_lines[TTY_PORTS_MAX];
static int __init nokia_bind_config(struct usb_configuration *c)
{
int status = 0;
status = phonet_bind_config(c);
if (status)
printk(KERN_DEBUG "could not bind phonet config\n");
status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]);
if (status)
printk(KERN_DEBUG "could not bind obex config %d\n", 0);
status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]);
if (status)
printk(KERN_DEBUG "could not bind obex config %d\n", 0);
status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
if (status)
printk(KERN_DEBUG "could not bind acm config\n");
status = ecm_bind_config(c, hostaddr);
if (status)
printk(KERN_DEBUG "could not bind ecm config\n");
return status;
}
static struct usb_configuration nokia_config_500ma_driver = {
.label = "Bus Powered",
.bConfigurationValue = 1,
@ -153,6 +125,51 @@ static struct usb_configuration nokia_config_100ma_driver = {
.MaxPower = 100,
};
static struct usb_function_instance *fi_acm;
static int __init nokia_bind_config(struct usb_configuration *c)
{
struct usb_function *f_acm;
int status = 0;
status = phonet_bind_config(c);
if (status)
printk(KERN_DEBUG "could not bind phonet config\n");
status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]);
if (status)
printk(KERN_DEBUG "could not bind obex config %d\n", 0);
status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]);
if (status)
printk(KERN_DEBUG "could not bind obex config %d\n", 0);
f_acm = usb_get_function(fi_acm);
if (IS_ERR(f_acm))
return PTR_ERR(f_acm);
status = usb_add_function(c, f_acm);
if (status)
goto err_conf;
status = ecm_bind_config(c, hostaddr, the_dev);
if (status) {
pr_debug("could not bind ecm config %d\n", status);
goto err_ecm;
}
if (c == &nokia_config_500ma_driver)
f_acm_cfg1 = f_acm;
else
f_acm_cfg2 = f_acm;
return status;
err_ecm:
usb_remove_function(c, f_acm);
err_conf:
usb_put_function(f_acm);
return status;
}
static int __init nokia_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
@ -169,9 +186,11 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
goto err_ether;
}
status = gether_setup(cdev->gadget, hostaddr);
if (status < 0)
the_dev = gether_setup(cdev->gadget, hostaddr);
if (IS_ERR(the_dev)) {
status = PTR_ERR(the_dev);
goto err_ether;
}
status = usb_string_ids_tab(cdev, strings_dev);
if (status < 0)
@ -185,24 +204,32 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
if (!gadget_supports_altsettings(gadget))
goto err_usb;
fi_acm = usb_get_function_instance("acm");
if (IS_ERR(fi_acm))
goto err_usb;
/* finally register the configuration */
status = usb_add_config(cdev, &nokia_config_500ma_driver,
nokia_bind_config);
if (status < 0)
goto err_usb;
goto err_acm_inst;
status = usb_add_config(cdev, &nokia_config_100ma_driver,
nokia_bind_config);
if (status < 0)
goto err_usb;
goto err_put_cfg1;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
return 0;
err_put_cfg1:
usb_put_function(f_acm_cfg1);
err_acm_inst:
usb_put_function_instance(fi_acm);
err_usb:
gether_cleanup();
gether_cleanup(the_dev);
err_ether:
cur_line--;
while (cur_line >= 0)
@ -217,12 +244,15 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev)
{
int i;
usb_put_function(f_acm_cfg1);
usb_put_function(f_acm_cfg2);
usb_put_function_instance(fi_acm);
gphonet_cleanup();
for (i = 0; i < TTY_PORTS_MAX; i++)
gserial_free_line(tty_lines[i]);
gether_cleanup();
gether_cleanup(the_dev);
return 0;
}
@ -247,4 +277,3 @@ static void __exit nokia_cleanup(void)
usb_composite_unregister(&nokia_driver);
}
module_exit(nokia_cleanup);

View File

@ -2067,7 +2067,6 @@ static int omap_udc_start(struct usb_gadget *g,
/* hook up the driver */
driver->driver.bus = NULL;
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc->lock, flags);
if (udc->dc_clk != NULL)
@ -2083,7 +2082,6 @@ static int omap_udc_start(struct usb_gadget *g,
ERR("can't bind to transceiver\n");
if (driver->unbind) {
driver->unbind(&udc->gadget);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
}
goto done;
@ -2129,7 +2127,6 @@ static int omap_udc_stop(struct usb_gadget *g,
udc_quiesce(udc);
spin_unlock_irqrestore(&udc->lock, flags);
udc->gadget.dev.driver = NULL;
udc->driver = NULL;
if (udc->dc_clk != NULL)
@ -2631,14 +2628,6 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
udc->gadget.speed = USB_SPEED_UNKNOWN;
udc->gadget.max_speed = USB_SPEED_FULL;
udc->gadget.name = driver_name;
device_initialize(&udc->gadget.dev);
dev_set_name(&udc->gadget.dev, "gadget");
udc->gadget.dev.release = omap_udc_release;
udc->gadget.dev.parent = &odev->dev;
if (use_dma)
udc->gadget.dev.dma_mask = odev->dev.dma_mask;
udc->transceiver = xceiv;
/* ep0 is special; put it right after the SETUP buffer */
@ -2912,14 +2901,13 @@ static int omap_udc_probe(struct platform_device *pdev)
}
create_proc_file();
status = device_add(&udc->gadget.dev);
status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
omap_udc_release);
if (status)
goto cleanup4;
status = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (!status)
return status;
/* If fail, fall through */
return 0;
cleanup4:
remove_proc_file();
@ -2990,7 +2978,6 @@ static int omap_udc_remove(struct platform_device *pdev)
release_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1);
device_unregister(&udc->gadget.dev);
wait_for_completion(&done);
return 0;

View File

@ -358,7 +358,6 @@ struct pch_udc_dev {
prot_stall:1,
irq_registered:1,
mem_region:1,
registered:1,
suspended:1,
connected:1,
vbus_session:1,
@ -1441,6 +1440,8 @@ static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
*/
static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
int status)
__releases(&dev->lock)
__acquires(&dev->lock)
{
struct pch_udc_dev *dev;
unsigned halted = ep->halted;
@ -2382,6 +2383,8 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
* @dev: Reference to the device structure
*/
static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
__releases(&dev->lock)
__acquires(&dev->lock)
{
u32 stat;
int setup_supported;
@ -2989,7 +2992,6 @@ static int pch_udc_start(struct usb_gadget *g,
driver->driver.bus = NULL;
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
/* get ready for ep0 traffic */
pch_udc_setup_ep0(dev);
@ -3010,7 +3012,6 @@ static int pch_udc_stop(struct usb_gadget *g,
pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
/* Assures that there are no pending requests with this driver */
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
dev->connected = 0;
@ -3078,8 +3079,6 @@ static void pch_udc_remove(struct pci_dev *pdev)
pci_resource_len(pdev, PCH_UDC_PCI_BAR));
if (dev->active)
pci_disable_device(pdev);
if (dev->registered)
device_unregister(&dev->gadget.dev);
kfree(dev);
pci_set_drvdata(pdev, NULL);
}
@ -3196,21 +3195,13 @@ static int pch_udc_probe(struct pci_dev *pdev,
if (retval)
goto finished;
dev_set_name(&dev->gadget.dev, "gadget");
dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
dev->gadget.dev.release = gadget_release;
dev->gadget.name = KBUILD_MODNAME;
dev->gadget.max_speed = USB_SPEED_HIGH;
retval = device_register(&dev->gadget.dev);
if (retval)
goto finished;
dev->registered = 1;
/* Put the device in disconnected state till a driver is bound */
pch_udc_set_disconnect(dev);
retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
gadget_release);
if (retval)
goto finished;
return 0;

View File

@ -1263,7 +1263,6 @@ static int pxa25x_udc_start(struct usb_gadget *g,
/* first hook up the driver ... */
dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
dev->pullup = 1;
/* ... then enable host detection and ep0; and we're ready
@ -1325,7 +1324,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g,
if (!IS_ERR_OR_NULL(dev->transceiver))
(void) otg_set_peripheral(dev->transceiver->otg, NULL);
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
dump_state(dev);
@ -2138,17 +2136,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
dev->timer.function = udc_watchdog;
dev->timer.data = (unsigned long) dev;
device_initialize(&dev->gadget.dev);
dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
retval = device_add(&dev->gadget.dev);
if (retval) {
dev->driver = NULL;
dev->gadget.dev.driver = NULL;
goto err_device_add;
}
the_controller = dev;
platform_set_drvdata(pdev, dev);
@ -2199,8 +2186,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
free_irq(irq, dev);
#endif
err_irq1:
device_unregister(&dev->gadget.dev);
err_device_add:
if (gpio_is_valid(dev->mach->gpio_pullup))
gpio_free(dev->mach->gpio_pullup);
err_gpio_pullup:
@ -2226,7 +2211,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
return -EBUSY;
usb_del_gadget_udc(&dev->gadget);
device_unregister(&dev->gadget.dev);
dev->pullup = 0;
pullup(dev);

View File

@ -24,14 +24,12 @@
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/prefetch.h>
#include <asm/byteorder.h>
#include <mach/hardware.h>
#include <linux/byteorder/generic.h>
#include <linux/platform_data/pxa2xx_udc.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <mach/udc.h>
#include "pxa27x_udc.h"
@ -611,7 +609,7 @@ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
*
* Find the physical pxa27x ep, and setup its UDCCR
*/
static __init void pxa_ep_setup(struct pxa_ep *ep)
static void pxa_ep_setup(struct pxa_ep *ep)
{
u32 new_udccr;
@ -633,7 +631,7 @@ static __init void pxa_ep_setup(struct pxa_ep *ep)
*
* Setup all pxa physical endpoints, except ep0
*/
static __init void pxa_eps_setup(struct pxa_udc *dev)
static void pxa_eps_setup(struct pxa_udc *dev)
{
unsigned int i;
@ -1718,7 +1716,7 @@ static void udc_disable(struct pxa_udc *udc)
* Initializes gadget endpoint list, endpoints locks. No action is taken
* on the hardware.
*/
static __init void udc_init_data(struct pxa_udc *dev)
static void udc_init_data(struct pxa_udc *dev)
{
int i;
struct pxa_ep *ep;
@ -1811,7 +1809,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
/* first hook up the driver ... */
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
dplus_pullup(udc, 1);
if (!IS_ERR_OR_NULL(udc->transceiver)) {
@ -1829,7 +1826,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
fail:
udc->driver = NULL;
udc->gadget.dev.driver = NULL;
return retval;
}
@ -1871,7 +1867,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,
udc->driver = NULL;
if (!IS_ERR_OR_NULL(udc->transceiver))
return otg_set_peripheral(udc->transceiver->otg, NULL);
return 0;
@ -2413,7 +2408,7 @@ static struct pxa_udc memory = {
* Perform basic init : allocates udc clock, creates sysfs files, requests
* irq.
*/
static int __init pxa_udc_probe(struct platform_device *pdev)
static int pxa_udc_probe(struct platform_device *pdev)
{
struct resource *regs;
struct pxa_udc *udc = &memory;
@ -2456,9 +2451,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
goto err_map;
}
device_initialize(&udc->gadget.dev);
udc->gadget.dev.parent = &pdev->dev;
udc->gadget.dev.dma_mask = NULL;
udc->vbus_sensed = 0;
the_controller = udc;
@ -2475,12 +2467,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
goto err_irq;
}
retval = device_add(&udc->gadget.dev);
if (retval) {
dev_err(udc->dev, "device_add error %d\n", retval);
goto err_dev_add;
}
retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (retval)
goto err_add_udc;
@ -2490,8 +2476,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
return 0;
err_add_udc:
device_unregister(&udc->gadget.dev);
err_dev_add:
free_irq(udc->irq, udc);
err_irq:
iounmap(udc->regs);
@ -2506,13 +2490,12 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
* pxa_udc_remove - removes the udc device driver
* @_dev: platform device
*/
static int __exit pxa_udc_remove(struct platform_device *_dev)
static int pxa_udc_remove(struct platform_device *_dev)
{
struct pxa_udc *udc = platform_get_drvdata(_dev);
int gpio = udc->mach->gpio_pullup;
usb_del_gadget_udc(&udc->gadget);
device_del(&udc->gadget.dev);
usb_gadget_unregister_driver(udc->driver);
free_irq(udc->irq, udc);
pxa_cleanup_debugfs(udc);
@ -2625,7 +2608,8 @@ static struct platform_driver udc_driver = {
.name = "pxa27x-udc",
.owner = THIS_MODULE,
},
.remove = __exit_p(pxa_udc_remove),
.probe = pxa_udc_probe,
.remove = pxa_udc_remove,
.shutdown = pxa_udc_shutdown,
#ifdef CONFIG_PM
.suspend = pxa_udc_suspend,
@ -2633,22 +2617,7 @@ static struct platform_driver udc_driver = {
#endif
};
static int __init udc_init(void)
{
if (!cpu_is_pxa27x() && !cpu_is_pxa3xx())
return -ENODEV;
printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
return platform_driver_probe(&udc_driver, pxa_udc_probe);
}
module_init(udc_init);
static void __exit udc_exit(void)
{
platform_driver_unregister(&udc_driver);
}
module_exit(udc_exit);
module_platform_driver(udc_driver);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Robert Jarzmik");

View File

@ -1837,7 +1837,6 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
clk_put(r8a66597->clk);
}
device_unregister(&r8a66597->gadget.dev);
kfree(r8a66597);
return 0;
}
@ -1915,17 +1914,8 @@ static int __init r8a66597_probe(struct platform_device *pdev)
r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
r8a66597->gadget.ops = &r8a66597_gadget_ops;
dev_set_name(&r8a66597->gadget.dev, "gadget");
r8a66597->gadget.max_speed = USB_SPEED_HIGH;
r8a66597->gadget.dev.parent = &pdev->dev;
r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
r8a66597->gadget.dev.release = pdev->dev.release;
r8a66597->gadget.name = udc_name;
ret = device_register(&r8a66597->gadget.dev);
if (ret < 0) {
dev_err(&pdev->dev, "device_register failed\n");
goto clean_up;
}
init_timer(&r8a66597->timer);
r8a66597->timer.function = r8a66597_timer;
@ -1939,7 +1929,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
clk_name);
ret = PTR_ERR(r8a66597->clk);
goto clean_up_dev;
goto clean_up;
}
clk_enable(r8a66597->clk);
}
@ -2007,8 +1997,6 @@ static int __init r8a66597_probe(struct platform_device *pdev)
clk_disable(r8a66597->clk);
clk_put(r8a66597->clk);
}
clean_up_dev:
device_unregister(&r8a66597->gadget.dev);
clean_up:
if (r8a66597) {
if (r8a66597->sudmac_reg)

View File

@ -39,8 +39,6 @@
#include "s3c-hsotg.h"
#define DMA_ADDR_INVALID (~((dma_addr_t)0))
static const char * const s3c_hsotg_supply_names[] = {
"vusb_d", /* digital USB supply, 1.2V */
"vusb_a", /* analog USB supply, 1.1V */
@ -405,7 +403,6 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
INIT_LIST_HEAD(&req->queue);
req->req.dma = DMA_ADDR_INVALID;
return &req->req;
}
@ -435,24 +432,12 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
struct s3c_hsotg_req *hs_req)
{
struct usb_request *req = &hs_req->req;
enum dma_data_direction dir;
dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
/* ignore this if we're not moving any data */
if (hs_req->req.length == 0)
return;
if (hs_req->mapped) {
/* we mapped this, so unmap and remove the dma */
dma_unmap_single(hsotg->dev, req->dma, req->length, dir);
req->dma = DMA_ADDR_INVALID;
hs_req->mapped = 0;
} else {
dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
}
usb_gadget_unmap_request(&hsotg->gadget, hs_req, hs_ep->dir_in);
}
/**
@ -852,37 +837,16 @@ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep,
struct usb_request *req)
{
enum dma_data_direction dir;
struct s3c_hsotg_req *hs_req = our_req(req);
dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
int ret;
/* if the length is zero, ignore the DMA data */
if (hs_req->req.length == 0)
return 0;
if (req->dma == DMA_ADDR_INVALID) {
dma_addr_t dma;
dma = dma_map_single(hsotg->dev, req->buf, req->length, dir);
if (unlikely(dma_mapping_error(hsotg->dev, dma)))
goto dma_error;
if (dma & 3) {
dev_err(hsotg->dev, "%s: unaligned dma buffer\n",
__func__);
dma_unmap_single(hsotg->dev, dma, req->length, dir);
return -EINVAL;
}
hs_req->mapped = 1;
req->dma = dma;
} else {
dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
hs_req->mapped = 0;
}
ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in);
if (ret)
goto dma_error;
return 0;
@ -2961,9 +2925,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
driver->driver.bus = NULL;
hsotg->driver = driver;
hsotg->gadget.dev.driver = &driver->driver;
hsotg->gadget.dev.of_node = hsotg->dev->of_node;
hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
@ -2979,7 +2941,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
err:
hsotg->driver = NULL;
hsotg->gadget.dev.driver = NULL;
return ret;
}
@ -3014,7 +2975,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
hsotg->driver = NULL;
hsotg->gadget.speed = USB_SPEED_UNKNOWN;
hsotg->gadget.dev.driver = NULL;
spin_unlock_irqrestore(&hsotg->lock, flags);
@ -3483,16 +3443,6 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
debugfs_remove(hsotg->debug_root);
}
/**
* s3c_hsotg_release - release callback for hsotg device
* @dev: Device to for which release is called
*
* Nothing to do as the resource is allocated using devm_ API.
*/
static void s3c_hsotg_release(struct device *dev)
{
}
/**
* s3c_hsotg_probe - probe function for hsotg driver
* @pdev: The platform information for the driver
@ -3517,7 +3467,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
}
phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(phy)) {
if (IS_ERR(phy)) {
/* Fallback for pdata */
plat = pdev->dev.platform_data;
if (!plat) {
@ -3567,18 +3517,10 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
device_initialize(&hsotg->gadget.dev);
dev_set_name(&hsotg->gadget.dev, "gadget");
hsotg->gadget.max_speed = USB_SPEED_HIGH;
hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
hsotg->gadget.name = dev_name(dev);
hsotg->gadget.dev.parent = dev;
hsotg->gadget.dev.dma_mask = dev->dma_mask;
hsotg->gadget.dev.release = s3c_hsotg_release;
/* reset the system */
clk_prepare_enable(hsotg->clk);
@ -3658,12 +3600,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
s3c_hsotg_phy_disable(hsotg);
ret = device_add(&hsotg->gadget.dev);
if (ret) {
put_device(&hsotg->gadget.dev);
goto err_ep_mem;
}
ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
if (ret)
goto err_ep_mem;
@ -3702,10 +3638,8 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
}
s3c_hsotg_phy_disable(hsotg);
clk_disable_unprepare(hsotg->clk);
device_unregister(&hsotg->gadget.dev);
return 0;
}

View File

@ -283,7 +283,6 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)
/**
* s3c_hsudc_stop_activity - Stop activity on all endpoints.
* @hsudc: Device controller for which EP activity is to be stopped.
* @driver: Reference to the gadget driver which is currently active.
*
* All the endpoints are stopped and any pending transfer requests if any on
* the endpoint are terminated.
@ -1154,7 +1153,6 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
return -EBUSY;
hsudc->driver = driver;
hsudc->gadget.dev.driver = &driver->driver;
ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
hsudc->supplies);
@ -1190,7 +1188,6 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
err_supplies:
hsudc->driver = NULL;
hsudc->gadget.dev.driver = NULL;
return ret;
}
@ -1208,7 +1205,6 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
spin_lock_irqsave(&hsudc->lock, flags);
hsudc->driver = NULL;
hsudc->gadget.dev.driver = NULL;
hsudc->gadget.speed = USB_SPEED_UNKNOWN;
s3c_hsudc_uninit_phy();
@ -1303,15 +1299,10 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
spin_lock_init(&hsudc->lock);
dev_set_name(&hsudc->gadget.dev, "gadget");
hsudc->gadget.max_speed = USB_SPEED_HIGH;
hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
hsudc->gadget.name = dev_name(dev);
hsudc->gadget.dev.parent = dev;
hsudc->gadget.dev.dma_mask = dev->dma_mask;
hsudc->gadget.ep0 = &hsudc->ep[0].ep;
hsudc->gadget.is_otg = 0;
hsudc->gadget.is_a_peripheral = 0;
hsudc->gadget.speed = USB_SPEED_UNKNOWN;
@ -1345,12 +1336,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
disable_irq(hsudc->irq);
local_irq_enable();
ret = device_register(&hsudc->gadget.dev);
if (ret) {
put_device(&hsudc->gadget.dev);
goto err_add_device;
}
ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
if (ret)
goto err_add_udc;
@ -1359,7 +1344,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
return 0;
err_add_udc:
device_unregister(&hsudc->gadget.dev);
err_add_device:
clk_disable(hsudc->uclk);
err_res:

View File

@ -1674,7 +1674,6 @@ static int s3c2410_udc_start(struct usb_gadget *g,
/* Hook the driver */
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
/* Enable udc */
s3c2410_udc_enable(udc);
@ -1824,17 +1823,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
goto err_mem;
}
device_initialize(&udc->gadget.dev);
udc->gadget.dev.parent = &pdev->dev;
udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
/* Bind the driver */
retval = device_add(&udc->gadget.dev);
if (retval) {
dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
goto err_device_add;
}
the_controller = udc;
platform_set_drvdata(pdev, udc);
@ -1923,8 +1911,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
err_int:
free_irq(IRQ_USBD, udc);
err_map:
device_unregister(&udc->gadget.dev);
err_device_add:
iounmap(base_addr);
err_mem:
release_mem_region(rsrc_start, rsrc_len);
@ -1946,7 +1932,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
return -EBUSY;
usb_del_gadget_udc(&udc->gadget);
device_unregister(&udc->gadget.dev);
debugfs_remove(udc->regs_info);
if (udc_info && !udc_info->udc_command &&

View File

@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
@ -27,18 +28,6 @@
#define GS_LONG_NAME "Gadget Serial"
#define GS_VERSION_NAME GS_LONG_NAME " " GS_VERSION_STR
/*-------------------------------------------------------------------------*/
/*
* Kbuild is not very cooperative with respect to linking separately
* compiled library objects into one module. So for now we won't use
* separate compilation ... ensuring init/exit sections work to shrink
* the runtime footprint, and giving us at least some parts of what
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
*/
#include "f_obex.c"
#include "f_serial.c"
/*-------------------------------------------------------------------------*/
USB_GADGET_COMPOSITE_OPTIONS();
@ -126,27 +115,6 @@ module_param(n_ports, uint, 0);
MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
/*-------------------------------------------------------------------------*/
static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
static int __init serial_bind_obex_config(struct usb_configuration *c)
{
unsigned i;
int status = 0;
for (i = 0; i < n_ports && status == 0; i++)
status = obex_bind_config(c, tty_lines[i]);
return status;
}
static int __init serial_bind_gser_config(struct usb_configuration *c)
{
unsigned i;
int status = 0;
for (i = 0; i < n_ports && status == 0; i++)
status = gser_bind_config(c, tty_lines[i]);
return status;
}
static struct usb_configuration serial_config_driver = {
/* .label = f(use_acm) */
@ -169,15 +137,12 @@ static int serial_register_ports(struct usb_composite_dev *cdev,
goto out;
for (i = 0; i < n_ports; i++) {
struct f_serial_opts *opts;
fi_serial[i] = usb_get_function_instance(f_name);
if (IS_ERR(fi_serial[i])) {
ret = PTR_ERR(fi_serial[i]);
goto fail;
}
opts = container_of(fi_serial[i], struct f_serial_opts, func_inst);
opts->port_num = tty_lines[i];
f_serial[i] = usb_get_function(fi_serial[i]);
if (IS_ERR(f_serial[i])) {
@ -212,13 +177,6 @@ static int serial_register_ports(struct usb_composite_dev *cdev,
static int __init gs_bind(struct usb_composite_dev *cdev)
{
int status;
int cur_line;
for (cur_line = 0; cur_line < n_ports; cur_line++) {
status = gserial_alloc_line(&tty_lines[cur_line]);
if (status)
goto fail;
}
/* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue.
@ -243,11 +201,12 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
"acm");
usb_ep_autoconfig_reset(cdev->gadget);
} else if (use_obex)
status = usb_add_config(cdev, &serial_config_driver,
serial_bind_obex_config);
else
status = usb_add_config(cdev, &serial_config_driver,
serial_bind_gser_config);
status = serial_register_ports(cdev, &serial_config_driver,
"obex");
else {
status = serial_register_ports(cdev, &serial_config_driver,
"gser");
}
if (status < 0)
goto fail;
@ -257,9 +216,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
return 0;
fail:
cur_line--;
while (cur_line >= 0)
gserial_free_line(tty_lines[cur_line--]);
return status;
}
@ -270,7 +226,6 @@ static int gs_unbind(struct usb_composite_dev *cdev)
for (i = 0; i < n_ports; i++) {
usb_put_function(f_serial[i]);
usb_put_function_instance(fi_serial[i]);
gserial_free_line(tty_lines[i]);
}
return 0;
}

View File

@ -50,7 +50,6 @@
struct eth_dev {
/* lock is held while accessing port_usb
* or updating its backlink port_usb->ioport
*/
spinlock_t lock;
struct gether *port_usb;
@ -729,8 +728,6 @@ static int get_ether_addr(const char *str, u8 *dev_addr)
return 1;
}
static struct eth_dev *the_dev;
static const struct net_device_ops eth_netdev_ops = {
.ndo_open = eth_open,
.ndo_stop = eth_stop,
@ -758,19 +755,16 @@ static struct device_type gadget_type = {
*
* Returns negative errno, or zero on success
*/
int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
const char *netname)
{
struct eth_dev *dev;
struct net_device *net;
int status;
if (the_dev)
return -EBUSY;
net = alloc_etherdev(sizeof *dev);
if (!net)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
dev = netdev_priv(net);
spin_lock_init(&dev->lock);
@ -807,12 +801,11 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
if (status < 0) {
dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
free_netdev(net);
dev = ERR_PTR(status);
} else {
INFO(dev, "MAC %pM\n", net->dev_addr);
INFO(dev, "HOST MAC %pM\n", dev->host_mac);
the_dev = dev;
/* two kinds of host-initiated state changes:
* - iff DATA transfer is active, carrier is "on"
* - tx queueing enabled if open *and* carrier is "on"
@ -820,7 +813,7 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
netif_carrier_off(net);
}
return status;
return dev;
}
/**
@ -829,19 +822,16 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
*
* This is called to free all resources allocated by @gether_setup().
*/
void gether_cleanup(void)
void gether_cleanup(struct eth_dev *dev)
{
if (!the_dev)
if (!dev)
return;
unregister_netdev(the_dev->net);
flush_work(&the_dev->work);
free_netdev(the_dev->net);
the_dev = NULL;
unregister_netdev(dev->net);
flush_work(&dev->work);
free_netdev(dev->net);
}
/**
* gether_connect - notify network layer that USB link is active
* @link: the USB link, set up with endpoints, descriptors matching
@ -860,7 +850,7 @@ void gether_cleanup(void)
*/
struct net_device *gether_connect(struct gether *link)
{
struct eth_dev *dev = the_dev;
struct eth_dev *dev = link->ioport;
int result = 0;
if (!dev)
@ -895,7 +885,6 @@ struct net_device *gether_connect(struct gether *link)
spin_lock(&dev->lock);
dev->port_usb = link;
link->ioport = dev;
if (netif_running(dev->net)) {
if (link->open)
link->open(link);
@ -989,6 +978,5 @@ void gether_disconnect(struct gether *link)
spin_lock(&dev->lock);
dev->port_usb = NULL;
link->ioport = NULL;
spin_unlock(&dev->lock);
}

View File

@ -21,6 +21,7 @@
#include "gadget_chips.h"
struct eth_dev;
/*
* This represents the USB side of an "ethernet" link, managed by a USB
@ -70,7 +71,7 @@ struct gether {
|USB_CDC_PACKET_TYPE_DIRECTED)
/* variant of gether_setup that allows customizing network device name */
int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
const char *netname);
/* netdev setup/teardown as directed by the gadget driver */
@ -86,12 +87,13 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
*
* Returns negative errno, or zero on success
*/
static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
static inline struct eth_dev *gether_setup(struct usb_gadget *g,
u8 ethaddr[ETH_ALEN])
{
return gether_setup_name(g, ethaddr, "usb");
}
void gether_cleanup(void);
void gether_cleanup(struct eth_dev *dev);
/* connect/disconnect is handled by individual functions */
struct net_device *gether_connect(struct gether *);
@ -111,21 +113,24 @@ static inline bool can_support_ecm(struct usb_gadget *gadget)
}
/* each configuration may bind one instance of an ethernet link */
int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
int eem_bind_config(struct usb_configuration *c);
int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev);
int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev);
int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
struct eth_dev *dev);
int eem_bind_config(struct usb_configuration *c, struct eth_dev *dev);
#ifdef USB_ETH_RNDIS
int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer);
u32 vendorID, const char *manufacturer, struct eth_dev *dev);
#else
static inline int
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
u32 vendorID, const char *manufacturer)
u32 vendorID, const char *manufacturer, struct eth_dev *dev)
{
return 0;
}
@ -145,9 +150,9 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
* for calling @gether_cleanup() before module unload.
*/
static inline int rndis_bind_config(struct usb_configuration *c,
u8 ethaddr[ETH_ALEN])
u8 ethaddr[ETH_ALEN], struct eth_dev *dev)
{
return rndis_bind_config_vendor(c, ethaddr, 0, NULL);
return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);
}

View File

@ -65,7 +65,6 @@ int gserial_connect(struct gserial *, u8 port_num);
void gserial_disconnect(struct gserial *);
/* functions are bound to configurations by a config or gadget driver */
int acm_bind_config(struct usb_configuration *c, u8 port_num);
int gser_bind_config(struct usb_configuration *c, u8 port_num);
int obex_bind_config(struct usb_configuration *c, u8 port_num);

View File

@ -101,6 +101,16 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
/* ------------------------------------------------------------------------- */
void usb_gadget_set_state(struct usb_gadget *gadget,
enum usb_device_state state)
{
gadget->state = state;
sysfs_notify(&gadget->dev.kobj, NULL, "status");
}
EXPORT_SYMBOL_GPL(usb_gadget_set_state);
/* ------------------------------------------------------------------------- */
/**
* usb_gadget_udc_start - tells usb device controller to start up
* @gadget: The gadget we want to get started
@ -156,6 +166,87 @@ static void usb_udc_release(struct device *dev)
}
static const struct attribute_group *usb_udc_attr_groups[];
static void usb_udc_nop_release(struct device *dev)
{
dev_vdbg(dev, "%s\n", __func__);
}
/**
* usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
* @parent: the parent device to this udc. Usually the controller driver's
* device.
* @gadget: the gadget to be added to the list.
* @release: a gadget release function.
*
* Returns zero on success, negative errno otherwise.
*/
int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
void (*release)(struct device *dev))
{
struct usb_udc *udc;
int ret = -ENOMEM;
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
if (!udc)
goto err1;
dev_set_name(&gadget->dev, "gadget");
gadget->dev.parent = parent;
dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
gadget->dev.dma_parms = parent->dma_parms;
gadget->dev.dma_mask = parent->dma_mask;
if (release)
gadget->dev.release = release;
else
gadget->dev.release = usb_udc_nop_release;
ret = device_register(&gadget->dev);
if (ret)
goto err2;
device_initialize(&udc->dev);
udc->dev.release = usb_udc_release;
udc->dev.class = udc_class;
udc->dev.groups = usb_udc_attr_groups;
udc->dev.parent = parent;
ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
if (ret)
goto err3;
udc->gadget = gadget;
mutex_lock(&udc_lock);
list_add_tail(&udc->list, &udc_list);
ret = device_add(&udc->dev);
if (ret)
goto err4;
usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
mutex_unlock(&udc_lock);
return 0;
err4:
list_del(&udc->list);
mutex_unlock(&udc_lock);
err3:
put_device(&udc->dev);
err2:
put_device(&gadget->dev);
kfree(udc);
err1:
return ret;
}
EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
/**
* usb_add_gadget_udc - adds a new gadget to the udc class driver list
* @parent: the parent device to this udc. Usually the controller
@ -166,43 +257,7 @@ static const struct attribute_group *usb_udc_attr_groups[];
*/
int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
{
struct usb_udc *udc;
int ret = -ENOMEM;
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
if (!udc)
goto err1;
device_initialize(&udc->dev);
udc->dev.release = usb_udc_release;
udc->dev.class = udc_class;
udc->dev.groups = usb_udc_attr_groups;
udc->dev.parent = parent;
ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
if (ret)
goto err2;
udc->gadget = gadget;
mutex_lock(&udc_lock);
list_add_tail(&udc->list, &udc_list);
ret = device_add(&udc->dev);
if (ret)
goto err3;
mutex_unlock(&udc_lock);
return 0;
err3:
list_del(&udc->list);
mutex_unlock(&udc_lock);
err2:
put_device(&udc->dev);
err1:
return ret;
return usb_add_gadget_udc_release(parent, gadget, NULL);
}
EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
@ -220,6 +275,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
udc->driver = NULL;
udc->dev.driver = NULL;
udc->gadget->dev.driver = NULL;
}
/**
@ -254,6 +310,7 @@ void usb_del_gadget_udc(struct usb_gadget *gadget)
kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
device_unregister(&udc->dev);
device_unregister(&gadget->dev);
}
EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
@ -268,6 +325,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
udc->driver = driver;
udc->dev.driver = &driver->driver;
udc->gadget->dev.driver = &driver->driver;
ret = driver->bind(udc->gadget, driver);
if (ret)
@ -286,6 +344,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
udc->driver->function, ret);
udc->driver = NULL;
udc->dev.driver = NULL;
udc->gadget->dev.driver = NULL;
return ret;
}
@ -395,6 +454,16 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
}
static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
static ssize_t usb_gadget_state_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
struct usb_gadget *gadget = udc->gadget;
return sprintf(buf, "%s\n", usb_state_string(gadget->state));
}
static DEVICE_ATTR(state, S_IRUGO, usb_gadget_state_show, NULL);
#define USB_UDC_SPEED_ATTR(name, param) \
ssize_t usb_udc_##param##_show(struct device *dev, \
struct device_attribute *attr, char *buf) \
@ -403,7 +472,7 @@ ssize_t usb_udc_##param##_show(struct device *dev, \
return snprintf(buf, PAGE_SIZE, "%s\n", \
usb_speed_string(udc->gadget->param)); \
} \
static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
static DEVICE_ATTR(name, S_IRUGO, usb_udc_##param##_show, NULL)
static USB_UDC_SPEED_ATTR(current_speed, speed);
static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
@ -428,6 +497,7 @@ static USB_UDC_ATTR(a_alt_hnp_support);
static struct attribute *usb_udc_attrs[] = {
&dev_attr_srp.attr,
&dev_attr_soft_connect.attr,
&dev_attr_state.attr,
&dev_attr_current_speed.attr,
&dev_attr_maximum_speed.attr,

View File

@ -98,8 +98,6 @@ extern unsigned int uvc_gadget_trace_param;
#define DRIVER_VERSION "0.1.0"
#define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0)
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
#define UVC_NUM_REQUESTS 4
#define UVC_MAX_REQUEST_SIZE 64
#define UVC_MAX_EVENTS 4
@ -190,6 +188,7 @@ struct uvc_file_handle
* Functions
*/
extern void uvc_function_setup_continue(struct uvc_device *uvc);
extern void uvc_endpoint_stream(struct uvc_device *dev);
extern void uvc_function_connect(struct uvc_device *uvc);

View File

@ -10,6 +10,7 @@
* (at your option) any later version.
*/
#include <linux/atomic.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/list.h>
@ -18,7 +19,8 @@
#include <linux/videodev2.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/atomic.h>
#include <media/videobuf2-vmalloc.h>
#include "uvc.h"
@ -28,330 +30,175 @@
* Video queues is initialized by uvc_queue_init(). The function performs
* basic initialization of the uvc_video_queue struct and never fails.
*
* Video buffer allocation and freeing are performed by uvc_alloc_buffers and
* uvc_free_buffers respectively. The former acquires the video queue lock,
* while the later must be called with the lock held (so that allocation can
* free previously allocated buffers). Trying to free buffers that are mapped
* to user space will return -EBUSY.
*
* Video buffers are managed using two queues. However, unlike most USB video
* drivers that use an in queue and an out queue, we use a main queue to hold
* all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
* hold empty buffers. This design (copied from video-buf) minimizes locking
* in interrupt, as only one queue is shared between interrupt and user
* contexts.
*
* Use cases
* ---------
*
* Unless stated otherwise, all operations that modify the irq buffers queue
* are protected by the irq spinlock.
*
* 1. The user queues the buffers, starts streaming and dequeues a buffer.
*
* The buffers are added to the main and irq queues. Both operations are
* protected by the queue lock, and the later is protected by the irq
* spinlock as well.
*
* The completion handler fetches a buffer from the irq queue and fills it
* with video data. If no buffer is available (irq queue empty), the handler
* returns immediately.
*
* When the buffer is full, the completion handler removes it from the irq
* queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
* At that point, any process waiting on the buffer will be woken up. If a
* process tries to dequeue a buffer after it has been marked ready, the
* dequeing will succeed immediately.
*
* 2. Buffers are queued, user is waiting on a buffer and the device gets
* disconnected.
*
* When the device is disconnected, the kernel calls the completion handler
* with an appropriate status code. The handler marks all buffers in the
* irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
* that any process waiting on a buffer gets woken up.
*
* Waking up up the first buffer on the irq list is not enough, as the
* process waiting on the buffer might restart the dequeue operation
* immediately.
*
* Video buffers are managed by videobuf2. The driver uses a mutex to protect
* the videobuf2 queue operations by serializing calls to videobuf2 and a
* spinlock to protect the IRQ queue that holds the buffers to be processed by
* the driver.
*/
static void
uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
/* -----------------------------------------------------------------------------
* videobuf2 queue operations
*/
static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock);
INIT_LIST_HEAD(&queue->mainqueue);
INIT_LIST_HEAD(&queue->irqqueue);
queue->type = type;
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
struct uvc_video *video = container_of(queue, struct uvc_video, queue);
if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
*nbuffers = UVC_MAX_VIDEO_BUFFERS;
*nplanes = 1;
sizes[0] = video->imagesize;
return 0;
}
/*
* Free the video buffers.
*
* This function must be called with the queue lock held.
*/
static int uvc_free_buffers(struct uvc_video_queue *queue)
static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
unsigned int i;
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
for (i = 0; i < queue->count; ++i) {
if (queue->buffer[i].vma_use_count != 0)
return -EBUSY;
if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
return -EINVAL;
}
if (queue->count) {
vfree(queue->mem);
queue->count = 0;
if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
return -ENODEV;
buf->state = UVC_BUF_STATE_QUEUED;
buf->mem = vb2_plane_vaddr(vb, 0);
buf->length = vb2_plane_size(vb, 0);
if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->bytesused = 0;
else
buf->bytesused = vb2_get_plane_payload(vb, 0);
return 0;
}
static void uvc_buffer_queue(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
list_add_tail(&buf->queue, &queue->irqqueue);
} else {
/* If the device is disconnected return the buffer to userspace
* directly. The next QBUF call will fail with -ENODEV.
*/
buf->state = UVC_BUF_STATE_ERROR;
vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
}
spin_unlock_irqrestore(&queue->irqlock, flags);
}
static struct vb2_ops uvc_queue_qops = {
.queue_setup = uvc_queue_setup,
.buf_prepare = uvc_buffer_prepare,
.buf_queue = uvc_buffer_queue,
};
static int uvc_queue_init(struct uvc_video_queue *queue,
enum v4l2_buf_type type)
{
int ret;
queue->queue.type = type;
queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
queue->queue.drv_priv = queue;
queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
queue->queue.ops = &uvc_queue_qops;
queue->queue.mem_ops = &vb2_vmalloc_memops;
ret = vb2_queue_init(&queue->queue);
if (ret)
return ret;
mutex_init(&queue->mutex);
spin_lock_init(&queue->irqlock);
INIT_LIST_HEAD(&queue->irqqueue);
queue->flags = 0;
return 0;
}
/*
* Allocate the video buffers.
*
* Pages are reserved to make sure they will not be swapped, as they will be
* filled in the URB completion handler.
*
* Buffers will be individually mapped, so they must all be page aligned.
* Free the video buffers.
*/
static int
uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
unsigned int buflength)
static void uvc_free_buffers(struct uvc_video_queue *queue)
{
unsigned int bufsize = PAGE_ALIGN(buflength);
unsigned int i;
void *mem = NULL;
int ret;
if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
nbuffers = UVC_MAX_VIDEO_BUFFERS;
mutex_lock(&queue->mutex);
if ((ret = uvc_free_buffers(queue)) < 0)
goto done;
/* Bail out if no buffers should be allocated. */
if (nbuffers == 0)
goto done;
/* Decrement the number of buffers until allocation succeeds. */
for (; nbuffers > 0; --nbuffers) {
mem = vmalloc_32(nbuffers * bufsize);
if (mem != NULL)
break;
}
if (mem == NULL) {
ret = -ENOMEM;
goto done;
}
for (i = 0; i < nbuffers; ++i) {
memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
queue->buffer[i].buf.index = i;
queue->buffer[i].buf.m.offset = i * bufsize;
queue->buffer[i].buf.length = buflength;
queue->buffer[i].buf.type = queue->type;
queue->buffer[i].buf.sequence = 0;
queue->buffer[i].buf.field = V4L2_FIELD_NONE;
queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
queue->buffer[i].buf.flags = 0;
init_waitqueue_head(&queue->buffer[i].wait);
}
queue->mem = mem;
queue->count = nbuffers;
queue->buf_size = bufsize;
ret = nbuffers;
done:
vb2_queue_release(&queue->queue);
mutex_unlock(&queue->mutex);
return ret;
}
static void __uvc_query_buffer(struct uvc_buffer *buf,
struct v4l2_buffer *v4l2_buf)
{
memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
if (buf->vma_use_count)
v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
switch (buf->state) {
case UVC_BUF_STATE_ERROR:
case UVC_BUF_STATE_DONE:
v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
break;
case UVC_BUF_STATE_QUEUED:
case UVC_BUF_STATE_ACTIVE:
v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
break;
case UVC_BUF_STATE_IDLE:
default:
break;
}
}
static int
uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
{
int ret = 0;
mutex_lock(&queue->mutex);
if (v4l2_buf->index >= queue->count) {
ret = -EINVAL;
goto done;
}
__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
done:
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Queue a video buffer. Attempting to queue a buffer that has already been
* queued will return -EINVAL.
* Allocate the video buffers.
*/
static int
uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
static int uvc_alloc_buffers(struct uvc_video_queue *queue,
struct v4l2_requestbuffers *rb)
{
struct uvc_buffer *buf;
unsigned long flags;
int ret = 0;
uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
if (v4l2_buf->type != queue->type ||
v4l2_buf->memory != V4L2_MEMORY_MMAP) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
"and/or memory (%u).\n", v4l2_buf->type,
v4l2_buf->memory);
return -EINVAL;
}
int ret;
mutex_lock(&queue->mutex);
if (v4l2_buf->index >= queue->count) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
ret = -EINVAL;
goto done;
}
buf = &queue->buffer[v4l2_buf->index];
if (buf->state != UVC_BUF_STATE_IDLE) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
"(%u).\n", buf->state);
ret = -EINVAL;
goto done;
}
if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
v4l2_buf->bytesused > buf->buf.length) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
ret = -EINVAL;
goto done;
}
if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
buf->buf.bytesused = 0;
else
buf->buf.bytesused = v4l2_buf->bytesused;
spin_lock_irqsave(&queue->irqlock, flags);
if (queue->flags & UVC_QUEUE_DISCONNECTED) {
spin_unlock_irqrestore(&queue->irqlock, flags);
ret = -ENODEV;
goto done;
}
buf->state = UVC_BUF_STATE_QUEUED;
ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
queue->flags &= ~UVC_QUEUE_PAUSED;
list_add_tail(&buf->stream, &queue->mainqueue);
list_add_tail(&buf->queue, &queue->irqqueue);
spin_unlock_irqrestore(&queue->irqlock, flags);
done:
ret = vb2_reqbufs(&queue->queue, rb);
mutex_unlock(&queue->mutex);
return ret ? ret : rb->count;
}
static int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *buf)
{
int ret;
mutex_lock(&queue->mutex);
ret = vb2_querybuf(&queue->queue, buf);
mutex_unlock(&queue->mutex);
return ret;
}
static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
static int uvc_queue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *buf)
{
if (nonblocking) {
return (buf->state != UVC_BUF_STATE_QUEUED &&
buf->state != UVC_BUF_STATE_ACTIVE)
? 0 : -EAGAIN;
}
unsigned long flags;
int ret;
return wait_event_interruptible(buf->wait,
buf->state != UVC_BUF_STATE_QUEUED &&
buf->state != UVC_BUF_STATE_ACTIVE);
mutex_lock(&queue->mutex);
ret = vb2_qbuf(&queue->queue, buf);
spin_lock_irqsave(&queue->irqlock, flags);
ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
queue->flags &= ~UVC_QUEUE_PAUSED;
spin_unlock_irqrestore(&queue->irqlock, flags);
mutex_unlock(&queue->mutex);
return ret;
}
/*
* Dequeue a video buffer. If nonblocking is false, block until a buffer is
* available.
*/
static int
uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
int nonblocking)
static int uvc_dequeue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *buf, int nonblocking)
{
struct uvc_buffer *buf;
int ret = 0;
if (v4l2_buf->type != queue->type ||
v4l2_buf->memory != V4L2_MEMORY_MMAP) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
"and/or memory (%u).\n", v4l2_buf->type,
v4l2_buf->memory);
return -EINVAL;
}
int ret;
mutex_lock(&queue->mutex);
if (list_empty(&queue->mainqueue)) {
uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
ret = -EINVAL;
goto done;
}
buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
goto done;
uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
buf->buf.index, buf->state, buf->buf.bytesused);
switch (buf->state) {
case UVC_BUF_STATE_ERROR:
uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
"(transmission error).\n");
ret = -EIO;
case UVC_BUF_STATE_DONE:
buf->state = UVC_BUF_STATE_IDLE;
break;
case UVC_BUF_STATE_IDLE:
case UVC_BUF_STATE_QUEUED:
case UVC_BUF_STATE_ACTIVE:
default:
uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
"(driver bug?).\n", buf->state);
ret = -EINVAL;
goto done;
}
list_del(&buf->stream);
__uvc_query_buffer(buf, v4l2_buf);
done:
ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
mutex_unlock(&queue->mutex);
return ret;
}
@ -361,105 +208,47 @@ uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
* This function implements video queue polling and is intended to be used by
* the device poll handler.
*/
static unsigned int
uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
poll_table *wait)
static unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
struct file *file, poll_table *wait)
{
struct uvc_buffer *buf;
unsigned int mask = 0;
unsigned int ret;
mutex_lock(&queue->mutex);
if (list_empty(&queue->mainqueue))
goto done;
buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
poll_wait(file, &buf->wait, wait);
if (buf->state == UVC_BUF_STATE_DONE ||
buf->state == UVC_BUF_STATE_ERROR)
mask |= POLLOUT | POLLWRNORM;
done:
ret = vb2_poll(&queue->queue, file, wait);
mutex_unlock(&queue->mutex);
return mask;
return ret;
}
/*
* VMA operations.
*/
static void uvc_vm_open(struct vm_area_struct *vma)
static int uvc_queue_mmap(struct uvc_video_queue *queue,
struct vm_area_struct *vma)
{
struct uvc_buffer *buffer = vma->vm_private_data;
buffer->vma_use_count++;
}
static void uvc_vm_close(struct vm_area_struct *vma)
{
struct uvc_buffer *buffer = vma->vm_private_data;
buffer->vma_use_count--;
}
static struct vm_operations_struct uvc_vm_ops = {
.open = uvc_vm_open,
.close = uvc_vm_close,
};
/*
* Memory-map a buffer.
*
* This function implements video buffer memory mapping and is intended to be
* used by the device mmap handler.
*/
static int
uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
{
struct uvc_buffer *uninitialized_var(buffer);
struct page *page;
unsigned long addr, start, size;
unsigned int i;
int ret = 0;
start = vma->vm_start;
size = vma->vm_end - vma->vm_start;
int ret;
mutex_lock(&queue->mutex);
ret = vb2_mmap(&queue->queue, vma);
mutex_unlock(&queue->mutex);
for (i = 0; i < queue->count; ++i) {
buffer = &queue->buffer[i];
if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
break;
}
return ret;
}
if (i == queue->count || size != queue->buf_size) {
ret = -EINVAL;
goto done;
}
#ifndef CONFIG_MMU
/*
* Get unmapped area.
*
* NO-MMU arch need this function to make mmap() work correctly.
*/
static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
unsigned long pgoff)
{
unsigned long ret;
/*
* VM_IO marks the area as being an mmaped region for I/O to a
* device. It also prevents the region from being core dumped.
*/
vma->vm_flags |= VM_IO;
addr = (unsigned long)queue->mem + buffer->buf.m.offset;
while (size > 0) {
page = vmalloc_to_page((void *)addr);
if ((ret = vm_insert_page(vma, start, page)) < 0)
goto done;
start += PAGE_SIZE;
addr += PAGE_SIZE;
size -= PAGE_SIZE;
}
vma->vm_ops = &uvc_vm_ops;
vma->vm_private_data = buffer;
uvc_vm_open(vma);
done:
mutex_lock(&queue->mutex);
ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
mutex_unlock(&queue->mutex);
return ret;
}
#endif
/*
* Cancel the video buffers queue.
@ -484,7 +273,7 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
queue);
list_del(&buf->queue);
buf->state = UVC_BUF_STATE_ERROR;
wake_up(&buf->wait);
vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
}
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_queue_buffer and the disconnection event that
@ -516,26 +305,33 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
*/
static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
{
unsigned int i;
unsigned long flags;
int ret = 0;
mutex_lock(&queue->mutex);
if (enable) {
if (uvc_queue_streaming(queue)) {
ret = -EBUSY;
ret = vb2_streamon(&queue->queue, queue->queue.type);
if (ret < 0)
goto done;
}
queue->sequence = 0;
queue->flags |= UVC_QUEUE_STREAMING;
queue->buf_used = 0;
} else {
uvc_queue_cancel(queue, 0);
INIT_LIST_HEAD(&queue->mainqueue);
ret = vb2_streamoff(&queue->queue, queue->queue.type);
if (ret < 0)
goto done;
for (i = 0; i < queue->count; ++i)
queue->buffer[i].state = UVC_BUF_STATE_IDLE;
spin_lock_irqsave(&queue->irqlock, flags);
INIT_LIST_HEAD(&queue->irqqueue);
queue->flags &= ~UVC_QUEUE_STREAMING;
/*
* FIXME: We need to clear the DISCONNECTED flag to ensure that
* applications will be able to queue buffers for the next
* streaming run. However, clearing it here doesn't guarantee
* that the device will be reconnected in the meantime.
*/
queue->flags &= ~UVC_QUEUE_DISCONNECTED;
spin_unlock_irqrestore(&queue->irqlock, flags);
}
done:
@ -544,15 +340,15 @@ static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
}
/* called with &queue_irqlock held.. */
static struct uvc_buffer *
uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf)
{
struct uvc_buffer *nextbuf;
if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
buf->buf.length != buf->buf.bytesused) {
buf->length != buf->bytesused) {
buf->state = UVC_BUF_STATE_QUEUED;
buf->buf.bytesused = 0;
vb2_set_plane_payload(&buf->buf, 0, 0);
return buf;
}
@ -563,10 +359,18 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
else
nextbuf = NULL;
buf->buf.sequence = queue->sequence++;
do_gettimeofday(&buf->buf.timestamp);
/*
* 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++;
do_gettimeofday(&buf->buf.v4l2_buf.timestamp);
vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
wake_up(&buf->wait);
return nextbuf;
}

View File

@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/videodev2.h>
#include <media/videobuf2-core.h>
/* Maximum frame size in bytes, for sanity checking. */
#define UVC_MAX_FRAME_SIZE (16*1024*1024)
@ -25,42 +26,35 @@ enum uvc_buffer_state {
};
struct uvc_buffer {
unsigned long vma_use_count;
struct list_head stream;
/* Touched by interrupt handler. */
struct v4l2_buffer buf;
struct vb2_buffer buf;
struct list_head queue;
wait_queue_head_t wait;
enum uvc_buffer_state state;
void *mem;
unsigned int length;
unsigned int bytesused;
};
#define UVC_QUEUE_STREAMING (1 << 0)
#define UVC_QUEUE_DISCONNECTED (1 << 1)
#define UVC_QUEUE_DROP_INCOMPLETE (1 << 2)
#define UVC_QUEUE_PAUSED (1 << 3)
#define UVC_QUEUE_DISCONNECTED (1 << 0)
#define UVC_QUEUE_DROP_INCOMPLETE (1 << 1)
#define UVC_QUEUE_PAUSED (1 << 2)
struct uvc_video_queue {
enum v4l2_buf_type type;
struct vb2_queue queue;
struct mutex mutex; /* Protects queue */
void *mem;
unsigned int flags;
__u32 sequence;
unsigned int count;
unsigned int buf_size;
unsigned int buf_used;
struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
struct mutex mutex; /* protects buffers and mainqueue */
spinlock_t irqlock; /* protects irqqueue */
struct list_head mainqueue;
spinlock_t irqlock; /* Protects flags and irqqueue */
struct list_head irqqueue;
};
static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
{
return queue->flags & UVC_QUEUE_STREAMING;
return vb2_is_streaming(&queue->queue);
}
#endif /* __KERNEL__ */

View File

@ -41,9 +41,8 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
req->length = min_t(unsigned int, uvc->event_length, data->length);
req->zero = data->length < uvc->event_length;
req->dma = DMA_ADDR_INVALID;
memcpy(req->buf, data->data, data->length);
memcpy(req->buf, data->data, req->length);
return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
}
@ -148,16 +147,13 @@ uvc_v4l2_release(struct file *file)
uvc_function_disconnect(uvc);
uvc_video_enable(video, 0);
mutex_lock(&video->queue.mutex);
if (uvc_free_buffers(&video->queue) < 0)
printk(KERN_ERR "uvc_v4l2_release: Unable to free "
"buffers.\n");
mutex_unlock(&video->queue.mutex);
uvc_free_buffers(&video->queue);
file->private_data = NULL;
v4l2_fh_del(&handle->vfh);
v4l2_fh_exit(&handle->vfh);
kfree(handle);
return 0;
}
@ -178,9 +174,9 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_capability *cap = arg;
memset(cap, 0, sizeof *cap);
strncpy(cap->driver, "g_uvc", sizeof(cap->driver));
strncpy(cap->card, cdev->gadget->name, sizeof(cap->card));
strncpy(cap->bus_info, dev_name(&cdev->gadget->dev),
strlcpy(cap->driver, "g_uvc", sizeof(cap->driver));
strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card));
strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),
sizeof cap->bus_info);
cap->version = DRIVER_VERSION_NUMBER;
cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
@ -192,7 +188,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct v4l2_format *fmt = arg;
if (fmt->type != video->queue.type)
if (fmt->type != video->queue.queue.type)
return -EINVAL;
return uvc_v4l2_get_format(video, fmt);
@ -202,7 +198,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct v4l2_format *fmt = arg;
if (fmt->type != video->queue.type)
if (fmt->type != video->queue.queue.type)
return -EINVAL;
return uvc_v4l2_set_format(video, fmt);
@ -213,16 +209,13 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct v4l2_requestbuffers *rb = arg;
if (rb->type != video->queue.type ||
rb->memory != V4L2_MEMORY_MMAP)
if (rb->type != video->queue.queue.type)
return -EINVAL;
ret = uvc_alloc_buffers(&video->queue, rb->count,
video->imagesize);
ret = uvc_alloc_buffers(&video->queue, rb);
if (ret < 0)
return ret;
rb->count = ret;
ret = 0;
break;
}
@ -231,9 +224,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct v4l2_buffer *buf = arg;
if (buf->type != video->queue.type)
return -EINVAL;
return uvc_query_buffer(&video->queue, buf);
}
@ -251,24 +241,36 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
int *type = arg;
if (*type != video->queue.type)
if (*type != video->queue.queue.type)
return -EINVAL;
return uvc_video_enable(video, 1);
/* Enable UVC video. */
ret = uvc_video_enable(video, 1);
if (ret < 0)
return ret;
/*
* Complete the alternate setting selection setup phase now that
* userspace is ready to provide video frames.
*/
uvc_function_setup_continue(uvc);
uvc->state = UVC_STATE_STREAMING;
return 0;
}
case VIDIOC_STREAMOFF:
{
int *type = arg;
if (*type != video->queue.type)
if (*type != video->queue.queue.type)
return -EINVAL;
return uvc_video_enable(video, 0);
}
/* Events */
case VIDIOC_DQEVENT:
case VIDIOC_DQEVENT:
{
struct v4l2_event *event = arg;
@ -333,18 +335,22 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
{
struct video_device *vdev = video_devdata(file);
struct uvc_device *uvc = video_get_drvdata(vdev);
struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
unsigned int mask = 0;
poll_wait(file, &handle->vfh.wait, wait);
if (v4l2_event_pending(&handle->vfh))
mask |= POLLPRI;
mask |= uvc_queue_poll(&uvc->video.queue, file, wait);
return mask;
return uvc_queue_poll(&uvc->video.queue, file, wait);
}
#ifndef CONFIG_MMU
static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
unsigned long addr, unsigned long len, unsigned long pgoff,
unsigned long flags)
{
struct video_device *vdev = video_devdata(file);
struct uvc_device *uvc = video_get_drvdata(vdev);
return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff);
}
#endif
static struct v4l2_file_operations uvc_v4l2_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
@ -352,5 +358,8 @@ static struct v4l2_file_operations uvc_v4l2_fops = {
.ioctl = uvc_v4l2_ioctl,
.mmap = uvc_v4l2_mmap,
.poll = uvc_v4l2_poll,
#ifndef CONFIG_MMU
.get_unmapped_area = uvc_v4l2_get_unmapped_area,
#endif
};

View File

@ -32,7 +32,7 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
data[0] = 2;
data[1] = UVC_STREAM_EOH | video->fid;
if (buf->buf.bytesused - video->queue.buf_used <= len - 2)
if (buf->bytesused - video->queue.buf_used <= len - 2)
data[1] |= UVC_STREAM_EOF;
return 2;
@ -47,8 +47,8 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
void *mem;
/* Copy video data to the USB buffer. */
mem = queue->mem + buf->buf.m.offset + queue->buf_used;
nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
mem = buf->mem + queue->buf_used;
nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
memcpy(data, mem, nbytes);
queue->buf_used += nbytes;
@ -82,7 +82,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
req->length = video->req_size - len;
req->zero = video->payload_size == video->max_payload_size;
if (buf->buf.bytesused == video->queue.buf_used) {
if (buf->bytesused == video->queue.buf_used) {
video->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_DONE;
uvc_queue_next_buffer(&video->queue, buf);
@ -92,7 +92,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
}
if (video->payload_size == video->max_payload_size ||
buf->buf.bytesused == video->queue.buf_used)
buf->bytesused == video->queue.buf_used)
video->payload_size = 0;
}
@ -115,7 +115,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
req->length = video->req_size - len;
if (buf->buf.bytesused == video->queue.buf_used) {
if (buf->bytesused == video->queue.buf_used) {
video->queue.buf_used = 0;
buf->state = UVC_BUF_STATE_DONE;
uvc_queue_next_buffer(&video->queue, buf);
@ -161,6 +161,7 @@ static void
uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
{
struct uvc_video *video = req->context;
struct uvc_video_queue *queue = &video->queue;
struct uvc_buffer *buf;
unsigned long flags;
int ret;
@ -169,13 +170,15 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
case 0:
break;
case -ESHUTDOWN:
case -ESHUTDOWN: /* disconnect from host. */
printk(KERN_INFO "VS request cancelled.\n");
uvc_queue_cancel(queue, 1);
goto requeue;
default:
printk(KERN_INFO "VS request completed with status %d.\n",
req->status);
uvc_queue_cancel(queue, 0);
goto requeue;
}
@ -229,13 +232,18 @@ uvc_video_free_requests(struct uvc_video *video)
static int
uvc_video_alloc_requests(struct uvc_video *video)
{
unsigned int req_size;
unsigned int i;
int ret = -ENOMEM;
BUG_ON(video->req_size);
req_size = video->ep->maxpacket
* max_t(unsigned int, video->ep->maxburst, 1)
* (video->ep->mult + 1);
for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL);
video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
if (video->req_buffer[i] == NULL)
goto error;
@ -245,14 +253,14 @@ uvc_video_alloc_requests(struct uvc_video *video)
video->req[i]->buf = video->req_buffer[i];
video->req[i]->length = 0;
video->req[i]->dma = DMA_ADDR_INVALID;
video->req[i]->complete = uvc_video_complete;
video->req[i]->context = video;
list_add_tail(&video->req[i]->list, &video->req_free);
}
video->req_size = video->ep->maxpacket;
video->req_size = req_size;
return 0;
error:
@ -309,7 +317,8 @@ uvc_video_pump(struct uvc_video *video)
video->encode(req, video, buf);
/* Queue the USB request */
if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) {
ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
if (ret < 0) {
printk(KERN_INFO "Failed to queue request (%d)\n", ret);
usb_ep_set_halt(video->ep);
spin_unlock_irqrestore(&video->queue.irqlock, flags);

View File

@ -180,6 +180,7 @@ config USB_EHCI_TEGRA
boolean "NVIDIA Tegra HCD support"
depends on USB_EHCI_HCD && ARCH_TEGRA
select USB_EHCI_ROOT_HUB_TT
select USB_PHY
help
This driver enables support for the internal USB Host Controllers
found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
@ -301,7 +302,6 @@ config USB_OHCI_HCD
tristate "OHCI HCD support"
depends on USB && USB_ARCH_HAS_OHCI
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
select USB_OTG_UTILS if ARCH_OMAP
depends on USB_ISP1301 || !ARCH_LPC32XX
---help---
The Open Host Controller Interface (OHCI) is a standard for accessing

View File

@ -145,7 +145,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
* management.
*/
phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(phy)) {
if (IS_ERR(phy)) {
dev_err(&pdev->dev, "unable to find transceiver\n");
ret = -ENODEV;
goto put_hcd;

View File

@ -33,25 +33,17 @@ struct ehci_hcd_mv {
struct mv_usb_platform_data *pdata;
/* clock source and total clock number */
unsigned int clknum;
struct clk *clk[0];
struct clk *clk;
};
static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
{
unsigned int i;
for (i = 0; i < ehci_mv->clknum; i++)
clk_prepare_enable(ehci_mv->clk[i]);
clk_prepare_enable(ehci_mv->clk);
}
static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
{
unsigned int i;
for (i = 0; i < ehci_mv->clknum; i++)
clk_disable_unprepare(ehci_mv->clk[i]);
clk_disable_unprepare(ehci_mv->clk);
}
static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
@ -144,9 +136,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
struct ehci_hcd *ehci;
struct ehci_hcd_mv *ehci_mv;
struct resource *r;
int clk_i, retval = -ENODEV;
int retval = -ENODEV;
u32 offset;
size_t size;
if (!pdata) {
dev_err(&pdev->dev, "missing platform_data\n");
@ -160,8 +151,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
if (!hcd)
return -ENOMEM;
size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum;
ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL);
if (ehci_mv == NULL) {
dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
retval = -ENOMEM;
@ -172,16 +162,11 @@ static int mv_ehci_probe(struct platform_device *pdev)
ehci_mv->pdata = pdata;
ehci_mv->hcd = hcd;
ehci_mv->clknum = pdata->clknum;
for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
ehci_mv->clk[clk_i] =
devm_clk_get(&pdev->dev, pdata->clkname[clk_i]);
if (IS_ERR(ehci_mv->clk[clk_i])) {
dev_err(&pdev->dev, "error get clck \"%s\"\n",
pdata->clkname[clk_i]);
retval = PTR_ERR(ehci_mv->clk[clk_i]);
goto err_clear_drvdata;
}
ehci_mv->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(ehci_mv->clk)) {
dev_err(&pdev->dev, "error getting clock\n");
retval = PTR_ERR(ehci_mv->clk);
goto err_clear_drvdata;
}
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
@ -240,12 +225,16 @@ static int mv_ehci_probe(struct platform_device *pdev)
ehci_mv->mode = pdata->mode;
if (ehci_mv->mode == MV_USB_MODE_OTG) {
#ifdef CONFIG_USB_OTG_UTILS
ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(ehci_mv->otg)) {
dev_err(&pdev->dev,
"unable to find transceiver\n");
retval = -ENODEV;
if (IS_ERR(ehci_mv->otg)) {
retval = PTR_ERR(ehci_mv->otg);
if (retval == -ENXIO)
dev_info(&pdev->dev, "MV_USB_MODE_OTG "
"must have CONFIG_USB_PHY enabled\n");
else
dev_err(&pdev->dev,
"unable to find transceiver\n");
goto err_disable_clk;
}
@ -258,11 +247,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
}
/* otg will enable clock before use as host */
mv_ehci_disable(ehci_mv);
#else
dev_info(&pdev->dev, "MV_USB_MODE_OTG "
"must have CONFIG_USB_OTG_UTILS enabled\n");
goto err_disable_clk;
#endif
} else {
if (pdata->set_vbus)
pdata->set_vbus(1);

View File

@ -140,7 +140,7 @@ static int s5p_ehci_probe(struct platform_device *pdev)
return -ENOMEM;
phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(phy)) {
if (IS_ERR(phy)) {
/* Fallback to pdata */
if (!pdata) {
dev_warn(&pdev->dev, "no platform data or transceiver defined\n");

View File

@ -773,16 +773,14 @@ static int tegra_ehci_probe(struct platform_device *pdev)
goto fail_phy;
}
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->operating_mode == TEGRA_USB_OTG) {
tegra->transceiver =
devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(tegra->transceiver))
if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, &hcd->self);
} else {
tegra->transceiver = ERR_PTR(-ENODEV);
}
#endif
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err) {
@ -801,10 +799,8 @@ static int tegra_ehci_probe(struct platform_device *pdev)
return err;
fail:
#ifdef CONFIG_USB_OTG_UTILS
if (!IS_ERR_OR_NULL(tegra->transceiver))
if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, NULL);
#endif
fail_phy:
usb_phy_shutdown(hcd->phy);
fail_io:
@ -823,10 +819,8 @@ static int tegra_ehci_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
#ifdef CONFIG_USB_OTG_UTILS
if (!IS_ERR_OR_NULL(tegra->transceiver))
if (!IS_ERR(tegra->transceiver))
otg_set_host(tegra->transceiver->otg, NULL);
#endif
usb_phy_shutdown(hcd->phy);
usb_remove_hcd(hcd);

View File

@ -128,7 +128,7 @@ static int exynos_ohci_probe(struct platform_device *pdev)
return -ENOMEM;
phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(phy)) {
if (IS_ERR(phy)) {
/* Fallback to pdata */
if (!pdata) {
dev_warn(&pdev->dev, "no platform data or transceiver defined\n");

View File

@ -7,7 +7,6 @@
config USB_MUSB_HDRC
tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
depends on USB && USB_GADGET
select USB_OTG_UTILS
help
Say Y here if your system has a dual role high speed USB
controller based on the Mentor Graphics silicon IP. Then
@ -34,10 +33,12 @@ choice
config USB_MUSB_DAVINCI
tristate "DaVinci"
depends on ARCH_DAVINCI_DMx
depends on BROKEN
config USB_MUSB_DA8XX
tristate "DA8xx/OMAP-L1x"
depends on ARCH_DAVINCI_DA8XX
depends on BROKEN
config USB_MUSB_TUSB6010
tristate "TUSB6010"
@ -53,7 +54,6 @@ config USB_MUSB_AM35X
config USB_MUSB_DSPS
tristate "TI DSPS platforms"
depends on SOC_TI81XX || SOC_AM33XX
config USB_MUSB_BLACKFIN
tristate "Blackfin"
@ -61,12 +61,12 @@ config USB_MUSB_BLACKFIN
config USB_MUSB_UX500
tristate "U8500 and U5500"
depends on (ARCH_U8500 && AB8500_USB)
endchoice
choice
prompt 'MUSB DMA mode'
default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM
default USB_UX500_DMA if USB_MUSB_UX500
default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI

View File

@ -149,7 +149,7 @@ static void otg_timer(unsigned long _musb)
*/
devctl = musb_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv->state) {
@ -195,7 +195,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
if (musb->is_active || (musb->a_wait_bcon == 0 &&
musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
del_timer(&otg_workaround);
last_timer = jiffies;
return;
@ -208,7 +208,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&otg_workaround, timeout);
}
@ -298,7 +298,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
/* NOTE: this must complete power-on within 100 ms. */
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;

View File

@ -280,13 +280,13 @@ static void musb_conn_timer_handler(unsigned long _musb)
break;
default:
dev_dbg(musb->controller, "%s state not handled\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
break;
}
spin_unlock_irqrestore(&musb->lock, flags);
dev_dbg(musb->controller, "state is %s\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
}
static void bfin_musb_enable(struct musb *musb)
@ -307,7 +307,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on)
dev_dbg(musb->controller, "VBUS %s, devctl %02x "
/* otg %3x conf %08x prcm %08x */ "\n",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
musb_readb(musb->mregs, MUSB_DEVCTL));
}

View File

@ -435,7 +435,6 @@ cppi_rndis_update(struct cppi_channel *c, int is_rx,
}
}
#ifdef CONFIG_USB_MUSB_DEBUG
static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
{
pr_debug("RXBD/%s %08x: "
@ -444,21 +443,16 @@ static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
bd->hw_next, bd->hw_bufp, bd->hw_off_len,
bd->hw_options);
}
#endif
static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)
{
#ifdef CONFIG_USB_MUSB_DEBUG
struct cppi_descriptor *bd;
if (!_dbg_level(level))
return;
cppi_dump_rx(level, rx, tag);
if (rx->last_processed)
cppi_dump_rxbd("last", rx->last_processed);
for (bd = rx->head; bd; bd = bd->next)
cppi_dump_rxbd("active", bd);
#endif
}
@ -784,6 +778,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
void __iomem *tibase = musb->ctrl_base;
int is_rndis = 0;
struct cppi_rx_stateram __iomem *rx_ram = rx->state_ram;
struct cppi_descriptor *d;
if (onepacket) {
/* almost every USB driver, host or peripheral side */
@ -897,14 +892,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
bd->hw_options |= CPPI_SOP_SET;
tail->hw_options |= CPPI_EOP_SET;
#ifdef CONFIG_USB_MUSB_DEBUG
if (_dbg_level(5)) {
struct cppi_descriptor *d;
for (d = rx->head; d; d = d->next)
cppi_dump_rxbd("S", d);
}
#endif
for (d = rx->head; d; d = d->next)
cppi_dump_rxbd("S", d);
/* in case the preceding transfer left some state... */
tail = rx->last_processed;

View File

@ -198,7 +198,7 @@ static void otg_timer(unsigned long _musb)
*/
devctl = musb_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv->state) {
@ -267,7 +267,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
if (musb->is_active || (musb->a_wait_bcon == 0 &&
musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
del_timer(&otg_workaround);
last_timer = jiffies;
return;
@ -280,7 +280,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
last_timer = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&otg_workaround, timeout);
}
@ -360,7 +360,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;

View File

@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb)
*/
devctl = musb_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv->state) {
@ -349,7 +349,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
davinci_musb_source_power(musb, drvvbus, 0);
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
err ? " ERROR" : "",
devctl);
retval = IRQ_HANDLED;

View File

@ -372,13 +372,13 @@ static void musb_otg_timer_func(unsigned long data)
case OTG_STATE_A_SUSPEND:
case OTG_STATE_A_WAIT_BCON:
dev_dbg(musb->controller, "HNP: %s timeout\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
musb_platform_set_vbus(musb, 0);
musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
break;
default:
dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
}
musb->ignore_disconnect = 0;
spin_unlock_irqrestore(&musb->lock, flags);
@ -393,13 +393,14 @@ void musb_hnp_stop(struct musb *musb)
void __iomem *mbase = musb->mregs;
u8 reg;
dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state));
dev_dbg(musb->controller, "HNP: stop from %s\n",
usb_otg_state_string(musb->xceiv->state));
switch (musb->xceiv->state) {
case OTG_STATE_A_PERIPHERAL:
musb_g_disconnect(musb);
dev_dbg(musb->controller, "HNP: back to %s\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
break;
case OTG_STATE_B_HOST:
dev_dbg(musb->controller, "HNP: Disabling HR\n");
@ -413,7 +414,7 @@ void musb_hnp_stop(struct musb *musb)
break;
default:
dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
}
/*
@ -451,7 +452,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
*/
if (int_usb & MUSB_INTR_RESUME) {
handled = IRQ_HANDLED;
dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state));
dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->state));
if (devctl & MUSB_DEVCTL_HM) {
void __iomem *mbase = musb->mregs;
@ -493,7 +494,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
default:
WARNING("bogus %s RESUME (%s)\n",
"host",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
}
} else {
switch (musb->xceiv->state) {
@ -522,7 +523,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
default:
WARNING("bogus %s RESUME (%s)\n",
"peripheral",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
}
}
}
@ -538,7 +539,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
/* IRQ arrives from ID pin sense or (later, if VBUS power
* is removed) SRP. responses are time critical:
@ -602,8 +603,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
break;
}
dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
otg_state_string(musb->xceiv->state),
dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller,
"VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
usb_otg_state_string(musb->xceiv->state),
devctl,
({ char *s;
switch (devctl & MUSB_DEVCTL_VBUS) {
@ -628,7 +630,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (int_usb & MUSB_INTR_SUSPEND) {
dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
otg_state_string(musb->xceiv->state), devctl);
usb_otg_state_string(musb->xceiv->state), devctl);
handled = IRQ_HANDLED;
switch (musb->xceiv->state) {
@ -745,12 +747,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
usb_hcd_resume_root_hub(hcd);
dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
otg_state_string(musb->xceiv->state), devctl);
usb_otg_state_string(musb->xceiv->state), devctl);
}
if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
MUSB_MODE(musb), devctl);
handled = IRQ_HANDLED;
@ -787,7 +789,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
break;
default:
WARNING("unhandled DISCONNECT transition (%s)\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
break;
}
}
@ -813,7 +815,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
}
} else {
dev_dbg(musb->controller, "BUS RESET as %s\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
switch (musb->xceiv->state) {
case OTG_STATE_A_SUSPEND:
/* We need to ignore disconnect on suspend
@ -826,7 +828,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */
/* never use invalid T(a_wait_bcon) */
dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
TA_WAIT_BCON(musb));
mod_timer(&musb->otg_timer, jiffies
+ msecs_to_jiffies(TA_WAIT_BCON(musb)));
@ -838,7 +840,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
break;
case OTG_STATE_B_WAIT_ACON:
dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
musb_g_reset(musb);
break;
@ -850,7 +852,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
break;
default:
dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
}
}
}
@ -1632,7 +1634,7 @@ musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
int ret = -EINVAL;
spin_lock_irqsave(&musb->lock, flags);
ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state));
ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->state));
spin_unlock_irqrestore(&musb->lock, flags);
return ret;
@ -1951,9 +1953,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb_write_ulpi_buscontrol(musb->mregs, busctl);
}
MUSB_DEV_MODE(musb);
musb->xceiv->otg->default_a = 0;
musb->xceiv->state = OTG_STATE_B_IDLE;
if (musb->xceiv->otg->default_a) {
MUSB_HST_MODE(musb);
musb->xceiv->state = OTG_STATE_A_IDLE;
} else {
MUSB_DEV_MODE(musb);
musb->xceiv->state = OTG_STATE_B_IDLE;
}
status = musb_gadget_setup(musb);
@ -2008,7 +2014,6 @@ static int musb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
int irq = platform_get_irq_byname(pdev, "mc");
int status;
struct resource *iomem;
void __iomem *base;
@ -2016,24 +2021,17 @@ static int musb_probe(struct platform_device *pdev)
if (!iomem || irq <= 0)
return -ENODEV;
base = ioremap(iomem->start, resource_size(iomem));
if (!base) {
dev_err(dev, "ioremap failed\n");
return -ENOMEM;
}
base = devm_ioremap_resource(dev, iomem);
if (IS_ERR(base))
return PTR_ERR(base);
status = musb_init_controller(dev, irq, base);
if (status < 0)
iounmap(base);
return status;
return musb_init_controller(dev, irq, base);
}
static int musb_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct musb *musb = dev_to_musb(dev);
void __iomem *ctrl_base = musb->ctrl_base;
/* this gets called on rmmod.
* - Host mode: host may still be active
@ -2044,7 +2042,6 @@ static int musb_remove(struct platform_device *pdev)
musb_shutdown(pdev);
musb_free(musb);
iounmap(ctrl_base);
device_init_wakeup(dev, 0);
#ifndef CONFIG_MUSB_PIO_ONLY
dma_set_mask(dev, *dev->parent->dma_mask);
@ -2293,8 +2290,6 @@ static int __init musb_init(void)
if (usb_disabled())
return 0;
pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
musb_driver_name);
return platform_driver_register(&musb_driver);
}
module_init(musb_init);

View File

@ -38,6 +38,7 @@
#include <linux/module.h>
#include <linux/usb/nop-usb-xceiv.h>
#include <linux/platform_data/usb-omap.h>
#include <linux/sizes.h>
#include <linux/of.h>
#include <linux/of_device.h>
@ -224,7 +225,7 @@ static void otg_timer(unsigned long _musb)
*/
devctl = dsps_readb(mregs, MUSB_DEVCTL);
dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
spin_lock_irqsave(&musb->lock, flags);
switch (musb->xceiv->state) {
@ -273,7 +274,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
if (musb->is_active || (musb->a_wait_bcon == 0 &&
musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
dev_dbg(musb->controller, "%s active, deleting timer\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
del_timer(&glue->timer[pdev->id]);
glue->last_timer[pdev->id] = jiffies;
return;
@ -288,7 +289,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
glue->last_timer[pdev->id] = timeout;
dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
jiffies_to_msecs(timeout - jiffies));
mod_timer(&glue->timer[pdev->id], timeout);
}
@ -334,7 +335,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
* value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
* Also, DRVVBUS pulses for SRP (but not at 5V) ...
*/
if (usbintr & MUSB_INTR_BABBLE)
if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE)
pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
@ -377,7 +378,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
/* NOTE: this must complete power-on within 100 ms. */
dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
drvvbus ? "on" : "off",
otg_state_string(musb->xceiv->state),
usb_otg_state_string(musb->xceiv->state),
err ? " ERROR" : "",
devctl);
ret = IRQ_HANDLED;
@ -596,14 +597,13 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
static int dsps_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match;
const struct dsps_musb_wrapper *wrp;
struct dsps_glue *glue;
struct resource *iomem;
int ret, i;
match = of_match_node(musb_dsps_of_match, np);
match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
if (!match) {
dev_err(&pdev->dev, "fail to get matching of_match struct\n");
ret = -EINVAL;

View File

@ -46,48 +46,6 @@
#include "musb_core.h"
/* MUSB PERIPHERAL status 3-mar-2006:
*
* - EP0 seems solid. It passes both USBCV and usbtest control cases.
* Minor glitches:
*
* + remote wakeup to Linux hosts work, but saw USBCV failures;
* in one test run (operator error?)
* + endpoint halt tests -- in both usbtest and usbcv -- seem
* to break when dma is enabled ... is something wrongly
* clearing SENDSTALL?
*
* - Mass storage behaved ok when last tested. Network traffic patterns
* (with lots of short transfers etc) need retesting; they turn up the
* worst cases of the DMA, since short packets are typical but are not
* required.
*
* - TX/IN
* + both pio and dma behave in with network and g_zero tests
* + no cppi throughput issues other than no-hw-queueing
* + failed with FLAT_REG (DaVinci)
* + seems to behave with double buffering, PIO -and- CPPI
* + with gadgetfs + AIO, requests got lost?
*
* - RX/OUT
* + both pio and dma behave in with network and g_zero tests
* + dma is slow in typical case (short_not_ok is clear)
* + double buffering ok with PIO
* + double buffering *FAILS* with CPPI, wrong data bytes sometimes
* + request lossage observed with gadgetfs
*
* - ISO not tested ... might work, but only weakly isochronous
*
* - Gadget driver disabling of softconnect during bind() is ignored; so
* drivers can't hold off host requests until userspace is ready.
* (Workaround: they can turn it off later.)
*
* - PORTABILITY (assumes PIO works):
* + DaVinci, basically works with cppi dma
* + OMAP 2430, ditto with mentor dma
* + TUSB 6010, platform-specific dma in the works
*/
/* ----------------------------------------------------------------------- */
#define is_buffer_mapped(req) (is_dma_capable() && \
@ -280,41 +238,6 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
return ep->packet_sz;
}
#ifdef CONFIG_USB_INVENTRA_DMA
/* Peripheral tx (IN) using Mentor DMA works as follows:
Only mode 0 is used for transfers <= wPktSize,
mode 1 is used for larger transfers,
One of the following happens:
- Host sends IN token which causes an endpoint interrupt
-> TxAvail
-> if DMA is currently busy, exit.
-> if queue is non-empty, txstate().
- Request is queued by the gadget driver.
-> if queue was previously empty, txstate()
txstate()
-> start
/\ -> setup DMA
| (data is transferred to the FIFO, then sent out when
| IN token(s) are recd from Host.
| -> DMA interrupt on completion
| calls TxAvail.
| -> stop DMA, ~DMAENAB,
| -> set TxPktRdy for last short pkt or zlp
| -> Complete Request
| -> Continue next request (call txstate)
|___________________________________|
* Non-Mentor DMA engines can of course work differently, such as by
* upleveling from irq-per-packet to irq-per-buffer.
*/
#endif
/*
* An endpoint is transmitting data. This can be called either from
* the IRQ routine or from ep.queue() to kickstart a request on an
@ -621,37 +544,6 @@ void musb_g_tx(struct musb *musb, u8 epnum)
/* ------------------------------------------------------------ */
#ifdef CONFIG_USB_INVENTRA_DMA
/* Peripheral rx (OUT) using Mentor DMA works as follows:
- Only mode 0 is used.
- Request is queued by the gadget class driver.
-> if queue was previously empty, rxstate()
- Host sends OUT token which causes an endpoint interrupt
/\ -> RxReady
| -> if request queued, call rxstate
| /\ -> setup DMA
| | -> DMA interrupt on completion
| | -> RxReady
| | -> stop DMA
| | -> ack the read
| | -> if data recd = max expected
| | by the request, or host
| | sent a short packet,
| | complete the request,
| | and start the next one.
| |_____________________________________|
| else just wait for the host
| to send the next OUT token.
|__________________________________________________|
* Non-Mentor DMA engines can of course work differently.
*/
#endif
/*
* Context: controller locked, IRQs blocked, endpoint selected
*/
@ -740,7 +632,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
struct dma_controller *c;
struct dma_channel *channel;
int use_dma = 0;
int transfer_size;
unsigned int transfer_size;
c = musb->dma_controller;
channel = musb_ep->dma;
@ -782,10 +674,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)
csr | MUSB_RXCSR_DMAMODE);
musb_writew(epio, MUSB_RXCSR, csr);
transfer_size = min(request->length - request->actual,
transfer_size = min_t(unsigned int,
request->length -
request->actual,
channel->max_len);
musb_ep->dma->desired_mode = 1;
} else {
if (!musb_ep->hb_mult &&
musb_ep->hw_ep->rx_double_buffered)
@ -815,7 +708,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
struct dma_controller *c;
struct dma_channel *channel;
int transfer_size = 0;
unsigned int transfer_size = 0;
c = musb->dma_controller;
channel = musb_ep->dma;
@ -824,11 +717,13 @@ static void rxstate(struct musb *musb, struct musb_request *req)
if (fifo_count < musb_ep->packet_sz)
transfer_size = fifo_count;
else if (request->short_not_ok)
transfer_size = min(request->length -
transfer_size = min_t(unsigned int,
request->length -
request->actual,
channel->max_len);
else
transfer_size = min(request->length -
transfer_size = min_t(unsigned int,
request->length -
request->actual,
(unsigned)fifo_count);
@ -1681,7 +1576,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
goto done;
default:
dev_dbg(musb->controller, "Unhandled wake: %s\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
goto done;
}
@ -1801,13 +1696,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
* all peripheral ports are external...
*/
static void musb_gadget_release(struct device *dev)
{
/* kref_put(WHAT) */
dev_dbg(dev, "%s\n", __func__);
}
static void
init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
{
@ -1892,12 +1780,7 @@ int musb_gadget_setup(struct musb *musb)
musb->g.speed = USB_SPEED_UNKNOWN;
/* this "gadget" abstracts/virtualizes the controller */
dev_set_name(&musb->g.dev, "gadget");
musb->g.dev.parent = musb->controller;
musb->g.dev.dma_mask = musb->controller->dma_mask;
musb->g.dev.release = musb_gadget_release;
musb->g.name = musb_driver_name;
musb->g.is_otg = 1;
musb_g_init_endpoints(musb);
@ -1905,11 +1788,6 @@ int musb_gadget_setup(struct musb *musb)
musb->is_active = 0;
musb_platform_try_idle(musb, 0);
status = device_register(&musb->g.dev);
if (status != 0) {
put_device(&musb->g.dev);
return status;
}
status = usb_add_gadget_udc(musb->controller, &musb->g);
if (status)
goto err;
@ -1924,8 +1802,6 @@ int musb_gadget_setup(struct musb *musb)
void musb_gadget_cleanup(struct musb *musb)
{
usb_del_gadget_udc(&musb->g);
if (musb->g.dev.parent)
device_unregister(&musb->g.dev);
}
/*
@ -1977,9 +1853,8 @@ static int musb_gadget_start(struct usb_gadget *g,
goto err;
}
if ((musb->xceiv->last_event == USB_EVENT_ID)
&& otg->set_vbus)
otg_set_vbus(otg, 1);
if (musb->xceiv->last_event == USB_EVENT_ID)
musb_platform_set_vbus(musb, 1);
hcd->self.uses_pio_for_control = 1;
@ -2063,6 +1938,7 @@ static int musb_gadget_stop(struct usb_gadget *g,
dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
musb->is_active = 0;
musb->gadget_driver = NULL;
musb_platform_try_idle(musb, 0);
spin_unlock_irqrestore(&musb->lock, flags);
@ -2099,7 +1975,7 @@ void musb_g_resume(struct musb *musb)
break;
default:
WARNING("unhandled RESUME transition (%s)\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
}
}
@ -2129,7 +2005,7 @@ void musb_g_suspend(struct musb *musb)
* A_PERIPHERAL may need care too
*/
WARNING("unhandled SUSPEND transition (%s)\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
}
}
@ -2163,7 +2039,7 @@ void musb_g_disconnect(struct musb *musb)
switch (musb->xceiv->state) {
default:
dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
otg_state_string(musb->xceiv->state));
usb_otg_state_string(musb->xceiv->state));
musb->xceiv->state = OTG_STATE_A_IDLE;
MUSB_HST_MODE(musb);
break;

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