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

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: NFelipe Balbi <balbi@ti.com>
...@@ -8,10 +8,10 @@ OMAP MUSB GLUE ...@@ -8,10 +8,10 @@ OMAP MUSB GLUE
and disconnect. and disconnect.
- multipoint : Should be "1" indicating the musb controller supports - multipoint : Should be "1" indicating the musb controller supports
multipoint. This is a MUSB configuration-specific setting. 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" MUSB configuration-specific setting. Should be set to "16"
- ram_bits : Specifies the ram address size. Should be set to "12" - 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-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" interface between the controller and the phy. It should be "0" or "1"
specifying ULPI and UTMI respectively. specifying ULPI and UTMI respectively.
- mode : Should be "3" to represent OTG. "1" signifies HOST and "2" - mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
...@@ -29,18 +29,46 @@ usb_otg_hs: usb_otg_hs@4a0ab000 { ...@@ -29,18 +29,46 @@ usb_otg_hs: usb_otg_hs@4a0ab000 {
ti,hwmods = "usb_otg_hs"; ti,hwmods = "usb_otg_hs";
ti,has-mailbox; ti,has-mailbox;
multipoint = <1>; multipoint = <1>;
num_eps = <16>; num-eps = <16>;
ram_bits = <12>; ram-bits = <12>;
ctrl-module = <&omap_control_usb>; ctrl-module = <&omap_control_usb>;
}; };
Board specific device node entry Board specific device node entry
&usb_otg_hs { &usb_otg_hs {
interface_type = <1>; interface-type = <1>;
mode = <3>; mode = <3>;
power = <50>; 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 OMAP CONTROL USB
Required properties: Required properties:
......
* Samsung's usb phy transceiver SAMSUNG USB-PHY controllers
The Samsung's phy transceiver is used for controlling usb phy for ** Samsung's usb 2.0 phy transceiver
s3c-hsotg as well as ehci-s5p and ohci-exynos usb controllers
across Samsung SOCs. 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 TODO: Adding the PHY binding with controller(s) according to the under
developement generic PHY driver. developement generic PHY driver.
Required properties: Required properties:
Exynos4210: 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 - reg : base physical address of the phy registers and length of memory mapped
region. 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: 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 - reg : base physical address of the phy registers and length of memory mapped
region. region.
...@@ -44,12 +49,69 @@ Example: ...@@ -44,12 +49,69 @@ Example:
usbphy@125B0000 { usbphy@125B0000 {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
compatible = "samsung,exynos4210-usbphy"; compatible = "samsung,exynos4210-usb2phy";
reg = <0x125B0000 0x100>; reg = <0x125B0000 0x100>;
ranges; ranges;
clocks = <&clock 2>, <&clock 305>;
clock-names = "xusbxti", "otg";
usbphy-sys { usbphy-sys {
/* USB device and host PHY_CONTROL registers */ /* USB device and host PHY_CONTROL registers */
reg = <0x10020704 0x8>; 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>;
};
};
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.
...@@ -223,13 +223,7 @@ static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = { ...@@ -223,13 +223,7 @@ static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
}; };
#if defined(CONFIG_USB_EHCI_MV) #if defined(CONFIG_USB_EHCI_MV)
static char *pxa168_sph_clock_name[] = {
[0] = "PXA168-USBCLK",
};
static struct mv_usb_platform_data pxa168_sph_pdata = { static struct mv_usb_platform_data pxa168_sph_pdata = {
.clknum = 1,
.clkname = pxa168_sph_clock_name,
.mode = MV_USB_MODE_HOST, .mode = MV_USB_MODE_HOST,
.phy_init = pxa_usb_phy_init, .phy_init = pxa_usb_phy_init,
.phy_deinit = pxa_usb_phy_deinit, .phy_deinit = pxa_usb_phy_deinit,
......
...@@ -162,13 +162,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = { ...@@ -162,13 +162,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
#ifdef CONFIG_USB_SUPPORT #ifdef CONFIG_USB_SUPPORT
#if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O) #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 = { static struct mv_usb_platform_data ttc_usb_pdata = {
.clknum = 1,
.clkname = pxa910_usb_clock_name,
.vbus = NULL, .vbus = NULL,
.mode = MV_USB_MODE_OTG, .mode = MV_USB_MODE_OTG,
.otg_force_a_bus_req = 1, .otg_force_a_bus_req = 1,
......
...@@ -169,7 +169,7 @@ static int usbhsf_get_id(struct platform_device *pdev) ...@@ -169,7 +169,7 @@ static int usbhsf_get_id(struct platform_device *pdev)
return USBHS_GADGET; 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) void __iomem *base, int enable)
{ {
struct usbhsf_private *priv = usbhsf_get_priv(pdev); struct usbhsf_private *priv = usbhsf_get_priv(pdev);
...@@ -223,6 +223,8 @@ static void usbhsf_power_ctrl(struct platform_device *pdev, ...@@ -223,6 +223,8 @@ static void usbhsf_power_ctrl(struct platform_device *pdev,
clk_disable(priv->pci); /* usb work around */ clk_disable(priv->pci); /* usb work around */
clk_disable(priv->usb24); /* usb work around */ clk_disable(priv->usb24); /* usb work around */
} }
return 0;
} }
static int usbhsf_get_vbus(struct platform_device *pdev) static int usbhsf_get_vbus(struct platform_device *pdev)
...@@ -239,7 +241,7 @@ static irqreturn_t usbhsf_interrupt(int irq, void *data) ...@@ -239,7 +241,7 @@ static irqreturn_t usbhsf_interrupt(int irq, void *data)
return IRQ_HANDLED; 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); struct usbhsf_private *priv = usbhsf_get_priv(pdev);
...@@ -264,6 +266,8 @@ static void usbhsf_hardware_exit(struct platform_device *pdev) ...@@ -264,6 +266,8 @@ static void usbhsf_hardware_exit(struct platform_device *pdev)
priv->usbh_base = NULL; priv->usbh_base = NULL;
free_irq(IRQ7, pdev); free_irq(IRQ7, pdev);
return 0;
} }
static int usbhsf_hardware_init(struct platform_device *pdev) static int usbhsf_hardware_init(struct platform_device *pdev)
......
...@@ -155,12 +155,14 @@ static int usbhs_get_vbus(struct platform_device *pdev) ...@@ -155,12 +155,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
return !((1 << 7) & __raw_readw(priv->cr2)); 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); struct usbhs_private *priv = usbhs_get_priv(pdev);
/* init phy */ /* init phy */
__raw_writew(0x8a0a, priv->cr2); __raw_writew(0x8a0a, priv->cr2);
return 0;
} }
static int usbhs_get_id(struct platform_device *pdev) static int usbhs_get_id(struct platform_device *pdev)
...@@ -202,7 +204,7 @@ static int usbhs_hardware_init(struct platform_device *pdev) ...@@ -202,7 +204,7 @@ static int usbhs_hardware_init(struct platform_device *pdev)
return 0; 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); struct usbhs_private *priv = usbhs_get_priv(pdev);
...@@ -210,6 +212,8 @@ static void usbhs_hardware_exit(struct platform_device *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); __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
free_irq(IRQ15, pdev); free_irq(IRQ15, pdev);
return 0;
} }
static u32 usbhs_pipe_cfg[] = { static u32 usbhs_pipe_cfg[] = {
......
...@@ -596,12 +596,14 @@ static int usbhs_get_vbus(struct platform_device *pdev) ...@@ -596,12 +596,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
return usbhs_is_connected(usbhs_get_priv(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); struct usbhs_private *priv = usbhs_get_priv(pdev);
/* init phy */ /* init phy */
__raw_writew(0x8a0a, priv->usbcrcaddr); __raw_writew(0x8a0a, priv->usbcrcaddr);
return 0;
} }
static int usbhs0_get_id(struct platform_device *pdev) static int usbhs0_get_id(struct platform_device *pdev)
...@@ -628,11 +630,13 @@ static int usbhs0_hardware_init(struct platform_device *pdev) ...@@ -628,11 +630,13 @@ static int usbhs0_hardware_init(struct platform_device *pdev)
return 0; 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); struct usbhs_private *priv = usbhs_get_priv(pdev);
cancel_delayed_work_sync(&priv->work); cancel_delayed_work_sync(&priv->work);
return 0;
} }
static struct usbhs_private usbhs0_private = { static struct usbhs_private usbhs0_private = {
...@@ -735,7 +739,7 @@ static int usbhs1_hardware_init(struct platform_device *pdev) ...@@ -735,7 +739,7 @@ static int usbhs1_hardware_init(struct platform_device *pdev)
return 0; 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); struct usbhs_private *priv = usbhs_get_priv(pdev);
...@@ -743,6 +747,8 @@ static void usbhs1_hardware_exit(struct platform_device *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); __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
free_irq(IRQ8, pdev); free_irq(IRQ8, pdev);
return 0;
} }
static int usbhs1_get_id(struct platform_device *pdev) static int usbhs1_get_id(struct platform_device *pdev)
......
...@@ -18,8 +18,8 @@ config ARCH_TEGRA_2x_SOC ...@@ -18,8 +18,8 @@ config ARCH_TEGRA_2x_SOC
select PL310_ERRATA_727915 if CACHE_L2X0 select PL310_ERRATA_727915 if CACHE_L2X0
select PL310_ERRATA_769419 if CACHE_L2X0 select PL310_ERRATA_769419 if CACHE_L2X0
select USB_ARCH_HAS_EHCI if USB_SUPPORT select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB select USB_ULPI if USB_PHY
select USB_ULPI_VIEWPORT if USB_SUPPORT select USB_ULPI_VIEWPORT if USB_PHY
help help
Support for NVIDIA Tegra AP20 and T20 processors, based on the Support for NVIDIA Tegra AP20 and T20 processors, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
...@@ -37,8 +37,8 @@ config ARCH_TEGRA_3x_SOC ...@@ -37,8 +37,8 @@ config ARCH_TEGRA_3x_SOC
select PINCTRL_TEGRA30 select PINCTRL_TEGRA30
select PL310_ERRATA_769419 if CACHE_L2X0 select PL310_ERRATA_769419 if CACHE_L2X0
select USB_ARCH_HAS_EHCI if USB_SUPPORT select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB select USB_ULPI if USB_PHY
select USB_ULPI_VIEWPORT if USB_SUPPORT select USB_ULPI_VIEWPORT if USB_PHY
help help
Support for NVIDIA Tegra T30 processor family, based on the Support for NVIDIA Tegra T30 processor family, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
......
...@@ -254,11 +254,13 @@ static int usbhs_get_id(struct platform_device *pdev) ...@@ -254,11 +254,13 @@ static int usbhs_get_id(struct platform_device *pdev)
return gpio_get_value(GPIO_PTB3); 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 */ /* enable vbus if HOST */
if (!gpio_get_value(GPIO_PTB3)) if (!gpio_get_value(GPIO_PTB3))
gpio_set_value(GPIO_PTB5, 1); gpio_set_value(GPIO_PTB5, 1);
return 0;
} }
static struct renesas_usbhs_platform_info usbhs_info = { static struct renesas_usbhs_platform_info usbhs_info = {
......
...@@ -79,7 +79,7 @@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ ...@@ -79,7 +79,7 @@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/
obj-$(CONFIG_PARIDE) += block/paride/ obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC) += tc/ obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_UWB) += uwb/ obj-$(CONFIG_UWB) += uwb/
obj-$(CONFIG_USB_OTG_UTILS) += usb/ obj-$(CONFIG_USB_PHY) += usb/
obj-$(CONFIG_USB) += usb/ obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_PCI) += usb/ obj-$(CONFIG_PCI) += usb/
obj-$(CONFIG_USB_GADGET) += usb/ obj-$(CONFIG_USB_GADGET) += usb/
......
...@@ -254,7 +254,7 @@ config BATTERY_RX51 ...@@ -254,7 +254,7 @@ config BATTERY_RX51
config CHARGER_ISP1704 config CHARGER_ISP1704
tristate "ISP1704 USB Charger Detection" tristate "ISP1704 USB Charger Detection"
depends on USB_OTG_UTILS depends on USB_PHY
help help
Say Y to enable support for USB Charger Detection with Say Y to enable support for USB Charger Detection with
ISP1707/ISP1704 USB transceivers. ISP1707/ISP1704 USB transceivers.
......
...@@ -35,7 +35,7 @@ static struct timer_list supply_timer; ...@@ -35,7 +35,7 @@ static struct timer_list supply_timer;
static struct timer_list polling_timer; static struct timer_list polling_timer;
static int polling; static int polling;
#ifdef CONFIG_USB_OTG_UTILS #if IS_ENABLED(CONFIG_USB_PHY)
static struct usb_phy *transceiver; static struct usb_phy *transceiver;
static struct notifier_block otg_nb; static struct notifier_block otg_nb;
#endif #endif
...@@ -218,7 +218,7 @@ static void polling_timer_func(unsigned long unused) ...@@ -218,7 +218,7 @@ static void polling_timer_func(unsigned long unused)
jiffies + msecs_to_jiffies(pdata->polling_interval)); 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) static int otg_is_usb_online(void)
{ {
return (transceiver->last_event == USB_EVENT_VBUS || return (transceiver->last_event == USB_EVENT_VBUS ||
...@@ -315,7 +315,7 @@ static int pda_power_probe(struct platform_device *pdev) ...@@ -315,7 +315,7 @@ static int pda_power_probe(struct platform_device *pdev)
pda_psy_usb.num_supplicants = pdata->num_supplicants; 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); transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (!IS_ERR_OR_NULL(transceiver)) { if (!IS_ERR_OR_NULL(transceiver)) {
if (!pdata->is_usb_online) if (!pdata->is_usb_online)
...@@ -367,7 +367,7 @@ static int pda_power_probe(struct platform_device *pdev) ...@@ -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) { if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
otg_nb.notifier_call = otg_handle_notification; otg_nb.notifier_call = otg_handle_notification;
ret = usb_register_notifier(transceiver, &otg_nb); ret = usb_register_notifier(transceiver, &otg_nb);
...@@ -391,7 +391,7 @@ static int pda_power_probe(struct platform_device *pdev) ...@@ -391,7 +391,7 @@ static int pda_power_probe(struct platform_device *pdev)
return 0; return 0;
#ifdef CONFIG_USB_OTG_UTILS #if IS_ENABLED(CONFIG_USB_PHY)
otg_reg_notifier_failed: otg_reg_notifier_failed:
if (pdata->is_usb_online && usb_irq) if (pdata->is_usb_online && usb_irq)
free_irq(usb_irq->start, &pda_psy_usb); free_irq(usb_irq->start, &pda_psy_usb);
...@@ -402,7 +402,7 @@ static int pda_power_probe(struct platform_device *pdev) ...@@ -402,7 +402,7 @@ static int pda_power_probe(struct platform_device *pdev)
usb_supply_failed: usb_supply_failed:
if (pdata->is_ac_online && ac_irq) if (pdata->is_ac_online && ac_irq)
free_irq(ac_irq->start, &pda_psy_ac); 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)) if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver); usb_put_phy(transceiver);
#endif #endif
...@@ -437,7 +437,7 @@ static int pda_power_remove(struct platform_device *pdev) ...@@ -437,7 +437,7 @@ static int pda_power_remove(struct platform_device *pdev)
power_supply_unregister(&pda_psy_usb); power_supply_unregister(&pda_psy_usb);
if (pdata->is_ac_online) if (pdata->is_ac_online)
power_supply_unregister(&pda_psy_ac); power_supply_unregister(&pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS #if IS_ENABLED(CONFIG_USB_PHY)
if (!IS_ERR_OR_NULL(transceiver)) if (!IS_ERR_OR_NULL(transceiver))
usb_put_phy(transceiver); usb_put_phy(transceiver);
#endif #endif
......
...@@ -186,6 +186,4 @@ source "drivers/usb/atm/Kconfig" ...@@ -186,6 +186,4 @@ source "drivers/usb/atm/Kconfig"
source "drivers/usb/gadget/Kconfig" source "drivers/usb/gadget/Kconfig"
source "drivers/usb/otg/Kconfig"
endif # USB_SUPPORT endif # USB_SUPPORT
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
obj-$(CONFIG_USB) += core/ obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_OTG_UTILS) += otg/
obj-$(CONFIG_USB_DWC3) += dwc3/ obj-$(CONFIG_USB_DWC3) += dwc3/
obj-$(CONFIG_USB_MON) += mon/ obj-$(CONFIG_USB_MON) += mon/
...@@ -46,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ ...@@ -46,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/
obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB) += misc/ obj-$(CONFIG_USB) += misc/
obj-$(CONFIG_USB_OTG_UTILS) += phy/ obj-$(CONFIG_USB_PHY) += phy/
obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/
obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_ATM) += atm/
......
...@@ -1638,16 +1638,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci) ...@@ -1638,16 +1638,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
return retval; return retval;
} }
/**
* udc_release: driver release function
* @dev: device
*
* Currently does nothing
*/
static void udc_release(struct device *dev)
{
}
/** /**
* udc_start: initialize gadget role * udc_start: initialize gadget role
* @ci: chipidea controller * @ci: chipidea controller
...@@ -1667,12 +1657,6 @@ static int udc_start(struct ci13xxx *ci) ...@@ -1667,12 +1657,6 @@ static int udc_start(struct ci13xxx *ci)
INIT_LIST_HEAD(&ci->gadget.ep_list); 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 */ /* alloc resources */
ci->qh_pool = dma_pool_create("ci13xxx_qh", dev, ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
sizeof(struct ci13xxx_qh), sizeof(struct ci13xxx_qh),
...@@ -1710,17 +1694,11 @@ static int udc_start(struct ci13xxx *ci) ...@@ -1710,17 +1694,11 @@ static int udc_start(struct ci13xxx *ci)
goto put_transceiver; 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)) { if (!IS_ERR_OR_NULL(ci->transceiver)) {
retval = otg_set_peripheral(ci->transceiver->otg, retval = otg_set_peripheral(ci->transceiver->otg,
&ci->gadget); &ci->gadget);
if (retval) if (retval)
goto unreg_device; goto put_transceiver;
} }
retval = usb_add_gadget_udc(dev, &ci->gadget); retval = usb_add_gadget_udc(dev, &ci->gadget);
...@@ -1740,8 +1718,6 @@ static int udc_start(struct ci13xxx *ci) ...@@ -1740,8 +1718,6 @@ static int udc_start(struct ci13xxx *ci)
} }
dev_err(dev, "error = %i\n", retval); dev_err(dev, "error = %i\n", retval);
unreg_device:
device_unregister(&ci->gadget.dev);
put_transceiver: put_transceiver:
if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
usb_put_phy(ci->transceiver); usb_put_phy(ci->transceiver);
...@@ -1776,7 +1752,6 @@ static void udc_stop(struct ci13xxx *ci) ...@@ -1776,7 +1752,6 @@ static void udc_stop(struct ci13xxx *ci)
if (ci->global_phy) if (ci->global_phy)
usb_put_phy(ci->transceiver); usb_put_phy(ci->transceiver);
} }
device_unregister(&ci->gadget.dev);
/* my kobject is dynamic, I swear! */ /* my kobject is dynamic, I swear! */
memset(&ci->gadget, 0, sizeof(ci->gadget)); memset(&ci->gadget, 0, sizeof(ci->gadget));
} }
......
config USB_DWC3 config USB_DWC3
tristate "DesignWare USB3 DRD Core Support" tristate "DesignWare USB3 DRD Core Support"
depends on (USB || USB_GADGET) && GENERIC_HARDIRQS depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
select USB_OTG_UTILS
select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
help help
Say Y or M here if your system has a Dual Role SuperSpeed Say Y or M here if your system has a Dual Role SuperSpeed
......
...@@ -140,7 +140,8 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc, ...@@ -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 * Returns a pointer to the allocated event buffer structure on success
* otherwise ERR_PTR(errno). * 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; struct dwc3_event_buffer *evt;
...@@ -259,6 +260,17 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) ...@@ -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) static void dwc3_cache_hwparams(struct dwc3 *dwc)
{ {
struct dwc3_hwparams *parms = &dwc->hwparams; struct dwc3_hwparams *parms = &dwc->hwparams;
...@@ -335,13 +347,9 @@ static int dwc3_core_init(struct dwc3 *dwc) ...@@ -335,13 +347,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (dwc->revision < DWC3_REVISION_190A) if (dwc->revision < DWC3_REVISION_190A)
reg |= DWC3_GCTL_U2RSTECN; reg |= DWC3_GCTL_U2RSTECN;
dwc3_writel(dwc->regs, DWC3_GCTL, reg); dwc3_core_num_eps(dwc);
ret = dwc3_event_buffers_setup(dwc); dwc3_writel(dwc->regs, DWC3_GCTL, reg);
if (ret) {
dev_err(dwc->dev, "failed to setup event buffers\n");
goto err0;
}
return 0; return 0;
...@@ -351,8 +359,6 @@ static int dwc3_core_init(struct dwc3 *dwc) ...@@ -351,8 +359,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
static void dwc3_core_exit(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->usb2_phy);
usb_phy_shutdown(dwc->usb3_phy); usb_phy_shutdown(dwc->usb3_phy);
} }
...@@ -428,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -428,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 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"); dev_err(dev, "no usb2 phy configured\n");
return -EPROBE_DEFER; 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"); dev_err(dev, "no usb3 phy configured\n");
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
...@@ -448,6 +474,10 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -448,6 +474,10 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->regs_size = resource_size(res); dwc->regs_size = resource_size(res);
dwc->dev = dev; 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)) if (!strncmp("super", maximum_speed, 5))
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
else if (!strncmp("high", maximum_speed, 4)) else if (!strncmp("high", maximum_speed, 4))
...@@ -480,7 +510,18 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -480,7 +510,18 @@ static int dwc3_probe(struct platform_device *pdev)
goto err0; 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) { switch (mode) {
case DWC3_MODE_DEVICE: case DWC3_MODE_DEVICE:
...@@ -488,7 +529,7 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -488,7 +529,7 @@ static int dwc3_probe(struct platform_device *pdev)
ret = dwc3_gadget_init(dwc); ret = dwc3_gadget_init(dwc);
if (ret) { if (ret) {
dev_err(dev, "failed to initialize gadget\n"); dev_err(dev, "failed to initialize gadget\n");
goto err1; goto err2;
} }
break; break;
case DWC3_MODE_HOST: case DWC3_MODE_HOST:
...@@ -496,7 +537,7 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -496,7 +537,7 @@ static int dwc3_probe(struct platform_device *pdev)
ret = dwc3_host_init(dwc); ret = dwc3_host_init(dwc);
if (ret) { if (ret) {
dev_err(dev, "failed to initialize host\n"); dev_err(dev, "failed to initialize host\n");
goto err1; goto err2;
} }
break; break;
case DWC3_MODE_DRD: case DWC3_MODE_DRD:
...@@ -504,32 +545,32 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -504,32 +545,32 @@ static int dwc3_probe(struct platform_device *pdev)
ret = dwc3_host_init(dwc); ret = dwc3_host_init(dwc);
if (ret) { if (ret) {
dev_err(dev, "failed to initialize host\n"); dev_err(dev, "failed to initialize host\n");
goto err1; goto err2;
} }
ret = dwc3_gadget_init(dwc); ret = dwc3_gadget_init(dwc);
if (ret) { if (ret) {
dev_err(dev, "failed to initialize gadget\n"); dev_err(dev, "failed to initialize gadget\n");
goto err1; goto err2;
} }
break; break;
default: default:
dev_err(dev, "Unsupported mode of operation %d\n", mode); dev_err(dev, "Unsupported mode of operation %d\n", mode);
goto err1; goto err2;
} }
dwc->mode = mode; dwc->mode = mode;
ret = dwc3_debugfs_init(dwc); ret = dwc3_debugfs_init(dwc);
if (ret) { if (ret) {
dev_err(dev, "failed to initialize debugfs\n"); dev_err(dev, "failed to initialize debugfs\n");
goto err2; goto err3;
} }
pm_runtime_allow(dev); pm_runtime_allow(dev);
return 0; return 0;
err2: err3:
switch (mode) { switch (mode) {
case DWC3_MODE_DEVICE: case DWC3_MODE_DEVICE:
dwc3_gadget_exit(dwc); dwc3_gadget_exit(dwc);
...@@ -546,6 +587,9 @@ static int dwc3_probe(struct platform_device *pdev) ...@@ -546,6 +587,9 @@ static int dwc3_probe(struct platform_device *pdev)
break; break;
} }
err2:
dwc3_event_buffers_cleanup(dwc);
err1: err1:
dwc3_core_exit(dwc); dwc3_core_exit(dwc);
...@@ -583,12 +627,130 @@ static int dwc3_remove(struct platform_device *pdev) ...@@ -583,12 +627,130 @@ static int dwc3_remove(struct platform_device *pdev)
break; break;
} }
dwc3_event_buffers_cleanup(dwc);
dwc3_free_event_buffers(dwc); dwc3_free_event_buffers(dwc);
dwc3_core_exit(dwc); dwc3_core_exit(dwc);
return 0; 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 #ifdef CONFIG_OF
static const struct of_device_id of_dwc3_match[] = { static const struct of_device_id of_dwc3_match[] = {
{ {
...@@ -605,6 +767,7 @@ static struct platform_driver dwc3_driver = { ...@@ -605,6 +767,7 @@ static struct platform_driver dwc3_driver = {
.driver = { .driver = {
.name = "dwc3", .name = "dwc3",
.of_match_table = of_match_ptr(of_dwc3_match), .of_match_table = of_match_ptr(of_dwc3_match),
.pm = DWC3_PM_OPS,
}, },
}; };
......
...@@ -154,8 +154,9 @@ ...@@ -154,8 +154,9 @@
/* OTG Registers */ /* OTG Registers */
#define DWC3_OCFG 0xcc00 #define DWC3_OCFG 0xcc00
#define DWC3_OCTL 0xcc04 #define DWC3_OCTL 0xcc04
#define DWC3_OEVTEN 0xcc08 #define DWC3_OEVT 0xcc08
#define DWC3_OSTS 0xcc0C #define DWC3_OEVTEN 0xcc0C
#define DWC3_OSTS 0xcc10
/* Bit fields */ /* Bit fields */
...@@ -369,6 +370,9 @@ struct dwc3_trb; ...@@ -369,6 +370,9 @@ struct dwc3_trb;
* @list: a list of event buffers * @list: a list of event buffers
* @buf: _THE_ buffer * @buf: _THE_ buffer
* @length: size of this 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 * @dma: dma_addr_t
* @dwc: pointer to DWC controller * @dwc: pointer to DWC controller
*/ */
...@@ -376,6 +380,10 @@ struct dwc3_event_buffer { ...@@ -376,6 +380,10 @@ struct dwc3_event_buffer {
void *buf; void *buf;
unsigned length; unsigned length;
unsigned int lpos; unsigned int lpos;
unsigned int count;
unsigned int flags;
#define DWC3_EVENT_PENDING BIT(0)
dma_addr_t dma; dma_addr_t dma;
...@@ -487,12 +495,6 @@ enum dwc3_link_state { ...@@ -487,12 +495,6 @@ enum dwc3_link_state {
DWC3_LINK_STATE_MASK = 0x0f, DWC3_LINK_STATE_MASK = 0x0f,
}; };
enum dwc3_device_state {
DWC3_DEFAULT_STATE,
DWC3_ADDRESS_STATE,
DWC3_CONFIGURED_STATE,
};
/* TRB Length, PCM and Status */ /* TRB Length, PCM and Status */
#define DWC3_TRB_SIZE_MASK (0x00ffffff) #define DWC3_TRB_SIZE_MASK (0x00ffffff)
#define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK) #define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK)
...@@ -574,6 +576,14 @@ struct dwc3_hwparams { ...@@ -574,6 +576,14 @@ struct dwc3_hwparams {
/* HWPARAMS1 */ /* HWPARAMS1 */
#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15) #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 */ /* HWPARAMS7 */
#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff) #define DWC3_RAM1_DEPTH(n) ((n) & 0xffff)
...@@ -618,7 +628,6 @@ struct dwc3_scratchpad_array { ...@@ -618,7 +628,6 @@ struct dwc3_scratchpad_array {
* @gadget_driver: pointer to the gadget driver * @gadget_driver: pointer to the gadget driver
* @regs: base address for our registers * @regs: base address for our registers
* @regs_size: address space size * @regs_size: address space size
* @irq: IRQ number
* @num_event_buffers: calculated number of event buffers * @num_event_buffers: calculated number of event buffers
* @u1u2: only used on revisions <1.83a for workaround * @u1u2: only used on revisions <1.83a for workaround
* @maximum_speed: maximum speed requested (mainly for testing purposes) * @maximum_speed: maximum speed requested (mainly for testing purposes)
...@@ -626,6 +635,8 @@ struct dwc3_scratchpad_array { ...@@ -626,6 +635,8 @@ struct dwc3_scratchpad_array {
* @mode: mode of operation * @mode: mode of operation
* @usb2_phy: pointer to USB2 PHY * @usb2_phy: pointer to USB2 PHY
* @usb3_phy: pointer to USB3 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 * @is_selfpowered: true when we are selfpowered
* @three_stage_setup: set if we perform a three phase setup * @three_stage_setup: set if we perform a three phase setup
* @ep0_bounced: true when we used bounce buffer * @ep0_bounced: true when we used bounce buffer
...@@ -639,6 +650,8 @@ struct dwc3_scratchpad_array { ...@@ -639,6 +650,8 @@ struct dwc3_scratchpad_array {
* @u2pel: parameter from Set SEL request. * @u2pel: parameter from Set SEL request.
* @u1sel: parameter from Set SEL request. * @u1sel: parameter from Set SEL request.
* @u1pel: 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 * @ep0_next_event: hold the next expected event
* @ep0state: state of endpoint zero * @ep0state: state of endpoint zero
* @link_state: link state * @link_state: link state
...@@ -656,8 +669,10 @@ struct dwc3 { ...@@ -656,8 +669,10 @@ struct dwc3 {
dma_addr_t ep0_trb_addr; dma_addr_t ep0_trb_addr;
dma_addr_t ep0_bounce_addr; dma_addr_t ep0_bounce_addr;
struct dwc3_request ep0_usb_req; struct dwc3_request ep0_usb_req;
/* device lock */ /* device lock */
spinlock_t lock; spinlock_t lock;
struct device *dev; struct device *dev;
struct platform_device *xhci; struct platform_device *xhci;
...@@ -675,6 +690,10 @@ struct dwc3 { ...@@ -675,6 +690,10 @@ struct dwc3 {
void __iomem *regs; void __iomem *regs;
size_t regs_size; size_t regs_size;
/* used for suspend/resume */
u32 dcfg;
u32 gctl;
u32 num_event_buffers; u32 num_event_buffers;
u32 u1u2; u32 u1u2;
u32 maximum_speed; u32 maximum_speed;
...@@ -694,6 +713,9 @@ struct dwc3 { ...@@ -694,6 +713,9 @@ struct dwc3 {
#define DWC3_REVISION_202A 0x5533202a #define DWC3_REVISION_202A 0x5533202a
#define DWC3_REVISION_210A 0x5533210a #define DWC3_REVISION_210A 0x5533210a
#define DWC3_REVISION_220A 0x5533220a #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 is_selfpowered:1;
unsigned three_stage_setup:1; unsigned three_stage_setup:1;
...@@ -704,11 +726,11 @@ struct dwc3 { ...@@ -704,11 +726,11 @@ struct dwc3 {
unsigned delayed_status:1; unsigned delayed_status:1;
unsigned needs_fifo_resize:1; unsigned needs_fifo_resize:1;
unsigned resize_fifos:1; unsigned resize_fifos:1;
unsigned pullups_connected:1;
enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_next ep0_next_event;
enum dwc3_ep0_state ep0state; enum dwc3_ep0_state ep0state;
enum dwc3_link_state link_state; enum dwc3_link_state link_state;
enum dwc3_device_state dev_state;
u16 isoch_delay; u16 isoch_delay;
u16 u2sel; u16 u2sel;
...@@ -718,6 +740,9 @@ struct dwc3 { ...@@ -718,6 +740,9 @@ struct dwc3 {
u8 speed; u8 speed;
u8 num_out_eps;
u8 num_in_eps;
void *mem; void *mem;
struct dwc3_hwparams hwparams; struct dwc3_hwparams hwparams;
...@@ -884,4 +909,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc) ...@@ -884,4 +909,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc)
{ } { }
#endif #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 */ #endif /* __DRIVERS_USB_DWC3_CORE_H */
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
.offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \ .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(GSBUSCFG0),
dump_register(GSBUSCFG1), dump_register(GSBUSCFG1),
dump_register(GTXTHRCFG), dump_register(GTXTHRCFG),
...@@ -372,6 +372,7 @@ static struct debugfs_reg32 dwc3_regs[] = { ...@@ -372,6 +372,7 @@ static struct debugfs_reg32 dwc3_regs[] = {
dump_register(OCFG), dump_register(OCFG),
dump_register(OCTL), dump_register(OCTL),
dump_register(OEVT),
dump_register(OEVTEN), dump_register(OEVTEN),
dump_register(OSTS), dump_register(OSTS),
}; };
...@@ -577,8 +578,14 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) ...@@ -577,8 +578,14 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
case DWC3_LINK_STATE_LPBK: case DWC3_LINK_STATE_LPBK:
seq_printf(s, "Loopback\n"); seq_printf(s, "Loopback\n");
break; break;
case DWC3_LINK_STATE_RESET:
seq_printf(s, "Reset\n");
break;
case DWC3_LINK_STATE_RESUME:
seq_printf(s, "Resume\n");
break;
default: default:
seq_printf(s, "UNKNOWN %d\n", reg); seq_printf(s, "UNKNOWN %d\n", state);
} }
return 0; return 0;
...@@ -661,28 +668,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc) ...@@ -661,28 +668,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
goto err1; goto err1;
} }
#if IS_ENABLED(CONFIG_USB_DWC3_GADGET) if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_mode_fops); dwc, &dwc3_mode_fops);
if (!file) { if (!file) {
ret = -ENOMEM; ret = -ENOMEM;
goto err1; goto err1;
} }
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, if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) ||
dwc, &dwc3_link_state_fops); IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
if (!file) { file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
ret = -ENOMEM; dwc, &dwc3_testmode_fops);
goto err1; 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; return 0;
......
...@@ -22,9 +22,9 @@ ...@@ -22,9 +22,9 @@
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h> #include <linux/usb/nop-usb-xceiv.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_platform.h>
struct dwc3_exynos { struct dwc3_exynos {
struct platform_device *dwc3;
struct platform_device *usb2_phy; struct platform_device *usb2_phy;
struct platform_device *usb3_phy; struct platform_device *usb3_phy;
struct device *dev; struct device *dev;
...@@ -86,21 +86,30 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos) ...@@ -86,21 +86,30 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
return ret; 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 u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
static int dwc3_exynos_probe(struct platform_device *pdev) static int dwc3_exynos_probe(struct platform_device *pdev)
{ {
struct platform_device *dwc3;
struct dwc3_exynos *exynos; struct dwc3_exynos *exynos;
struct clk *clk; struct clk *clk;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
int ret = -ENOMEM; int ret = -ENOMEM;
exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL); exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
if (!exynos) { if (!exynos) {
dev_err(dev, "not enough memory\n"); dev_err(dev, "not enough memory\n");
return -ENOMEM; goto err1;
} }
/* /*
...@@ -108,21 +117,15 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -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. * Since shared usb code relies on it, set it here for now.
* Once we move to full device tree support this will vanish off. * Once we move to full device tree support this will vanish off.
*/ */
if (!pdev->dev.dma_mask) if (!dev->dma_mask)
pdev->dev.dma_mask = &dwc3_exynos_dma_mask; dev->dma_mask = &dwc3_exynos_dma_mask;
platform_set_drvdata(pdev, exynos); platform_set_drvdata(pdev, exynos);
ret = dwc3_exynos_register_phys(exynos); ret = dwc3_exynos_register_phys(exynos);
if (ret) { if (ret) {
dev_err(dev, "couldn't register PHYs\n"); dev_err(dev, "couldn't register PHYs\n");
return ret; goto err1;
}
dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc3) {
dev_err(dev, "couldn't allocate dwc3 device\n");
return -ENOMEM;
} }
clk = devm_clk_get(dev, "usbdrd30"); clk = devm_clk_get(dev, "usbdrd30");
...@@ -132,37 +135,28 @@ static int dwc3_exynos_probe(struct platform_device *pdev) ...@@ -132,37 +135,28 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
goto err1; 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->dev = dev;
exynos->clk = clk; exynos->clk = clk;
clk_enable(exynos->clk); clk_prepare_enable(exynos->clk);
ret = platform_device_add_resources(dwc3, pdev->resource, if (node) {
pdev->num_resources); ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) { if (ret) {
dev_err(dev, "couldn't add resources to dwc3 device\n"); dev_err(dev, "failed to add dwc3 core\n");
goto err2; goto err2;
} }
} else {
ret = platform_device_add(dwc3); dev_err(dev, "no device node, failed to add dwc3 core\n");
if (ret) { ret = -ENODEV;
dev_err(dev, "failed to register dwc3 device\n");
goto err2; goto err2;
} }
return 0; return 0;
err2: err2:
clk_disable(clk); clk_disable_unprepare(clk);
err1: err1:
platform_device_put(dwc3);
return ret; return ret;
} }
...@@ -170,11 +164,11 @@ static int dwc3_exynos_remove(struct platform_device *pdev) ...@@ -170,11 +164,11 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
{ {
struct dwc3_exynos *exynos = platform_get_drvdata(pdev); struct dwc3_exynos *exynos = platform_get_drvdata(pdev);
platform_device_unregister(exynos->dwc3);
platform_device_unregister(exynos->usb2_phy); platform_device_unregister(exynos->usb2_phy);
platform_device_unregister(exynos->usb3_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; return 0;
} }
...@@ -187,12 +181,46 @@ static const struct of_device_id exynos_dwc3_match[] = { ...@@ -187,12 +181,46 @@ static const struct of_device_id exynos_dwc3_match[] = {
MODULE_DEVICE_TABLE(of, exynos_dwc3_match); MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
#endif #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 = { static struct platform_driver dwc3_exynos_driver = {
.probe = dwc3_exynos_probe, .probe = dwc3_exynos_probe,
.remove = dwc3_exynos_remove, .remove = dwc3_exynos_remove,
.driver = { .driver = {
.name = "exynos-dwc3", .name = "exynos-dwc3",
.of_match_table = of_match_ptr(exynos_dwc3_match), .of_match_table = of_match_ptr(exynos_dwc3_match),
.pm = DEV_PM_OPS,
}, },
}; };
......
...@@ -52,7 +52,6 @@ ...@@ -52,7 +52,6 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/nop-usb-xceiv.h>
/* /*
* All these registers belong to OMAP's Wrapper around the * All these registers belong to OMAP's Wrapper around the
...@@ -117,20 +116,17 @@ struct dwc3_omap { ...@@ -117,20 +116,17 @@ struct dwc3_omap {
/* device lock */ /* device lock */
spinlock_t lock; spinlock_t lock;
struct platform_device *usb2_phy;
struct platform_device *usb3_phy;
struct device *dev; struct device *dev;
int irq; int irq;
void __iomem *base; void __iomem *base;
void *context; u32 utmi_otg_status;
u32 resource_size;
u32 dma_status:1; u32 dma_status:1;
}; };
struct dwc3_omap *_omap; static struct dwc3_omap *_omap;
static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset) 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) ...@@ -142,11 +138,14 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
writel(value, base + offset); 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; u32 val;
struct dwc3_omap *omap = _omap; struct dwc3_omap *omap = _omap;
if (!omap)
return -EPROBE_DEFER;
switch (status) { switch (status) {
case OMAP_DWC3_ID_GROUND: case OMAP_DWC3_ID_GROUND:
dev_dbg(omap->dev, "ID GND\n"); dev_dbg(omap->dev, "ID GND\n");
...@@ -189,63 +188,9 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) ...@@ -189,63 +188,9 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
dev_dbg(omap->dev, "ID float\n"); dev_dbg(omap->dev, "ID float\n");
} }
return;
}
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; 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;
} }
EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
{ {
...@@ -307,24 +252,57 @@ static int dwc3_omap_remove_core(struct device *dev, void *c) ...@@ -307,24 +252,57 @@ static int dwc3_omap_remove_core(struct device *dev, void *c)
return 0; return 0;
} }
static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
{
u32 reg;
/* enable all IRQs */
reg = USBOTGSS_IRQO_COREIRQ_ST;
dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
reg = (USBOTGSS_IRQ1_OEVT |
USBOTGSS_IRQ1_DRVVBUS_RISE |
USBOTGSS_IRQ1_CHRGVBUS_RISE |
USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
USBOTGSS_IRQ1_IDPULLUP_RISE |
USBOTGSS_IRQ1_DRVVBUS_FALL |
USBOTGSS_IRQ1_CHRGVBUS_FALL |
USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
USBOTGSS_IRQ1_IDPULLUP_FALL);
dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
}
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) static int dwc3_omap_probe(struct platform_device *pdev)
{ {
struct dwc3_omap_data *pdata = pdev->dev.platform_data;
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
struct dwc3_omap *omap; struct dwc3_omap *omap;
struct resource *res; struct resource *res;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
int size;
int ret = -ENOMEM; int ret = -ENOMEM;
int irq; int irq;
const u32 *utmi_mode; int utmi_mode = 0;
u32 reg; u32 reg;
void __iomem *base; void __iomem *base;
void *context;
if (!node) {
dev_err(dev, "device node not found\n");
return -EINVAL;
}
omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL); omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
if (!omap) { if (!omap) {
...@@ -334,13 +312,13 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -334,13 +312,13 @@ static int dwc3_omap_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, omap); platform_set_drvdata(pdev, omap);
irq = platform_get_irq(pdev, 1); irq = platform_get_irq(pdev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(dev, "missing IRQ resource\n"); dev_err(dev, "missing IRQ resource\n");
return -EINVAL; return -EINVAL;
} }
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
dev_err(dev, "missing memory base resource\n"); dev_err(dev, "missing memory base resource\n");
return -EINVAL; return -EINVAL;
...@@ -352,25 +330,12 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -352,25 +330,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
return -ENOMEM; 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); spin_lock_init(&omap->lock);
omap->resource_size = resource_size(res);
omap->context = context;
omap->dev = dev; omap->dev = dev;
omap->irq = irq; omap->irq = irq;
omap->base = base; omap->base = base;
dev->dma_mask = &dwc3_omap_dma_mask;
/* /*
* REVISIT if we ever have two instances of the wrapper, we will be * REVISIT if we ever have two instances of the wrapper, we will be
...@@ -387,25 +352,17 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -387,25 +352,17 @@ static int dwc3_omap_probe(struct platform_device *pdev)
reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
utmi_mode = of_get_property(node, "utmi-mode", &size); of_property_read_u32(node, "utmi-mode", &utmi_mode);
if (utmi_mode && size == sizeof(*utmi_mode)) {
reg |= *utmi_mode; switch (utmi_mode) {
} else { case DWC3_OMAP_UTMI_MODE_SW:
if (!pdata) { reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
dev_dbg(dev, "missing platform data\n"); break;
} else { case DWC3_OMAP_UTMI_MODE_HW:
switch (pdata->utmi_mode) { reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
case DWC3_OMAP_UTMI_MODE_SW: break;
reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; default:
break; dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
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); dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
...@@ -422,29 +379,12 @@ static int dwc3_omap_probe(struct platform_device *pdev) ...@@ -422,29 +379,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
return ret; return ret;
} }
/* enable all IRQs */ dwc3_omap_enable_irqs(omap);
reg = USBOTGSS_IRQO_COREIRQ_ST;
dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
reg = (USBOTGSS_IRQ1_OEVT | ret = of_platform_populate(node, NULL, NULL, dev);
USBOTGSS_IRQ1_DRVVBUS_RISE | if (ret) {
USBOTGSS_IRQ1_CHRGVBUS_RISE | dev_err(&pdev->dev, "failed to create dwc3 core\n");
USBOTGSS_IRQ1_DISCHRGVBUS_RISE | return ret;
USBOTGSS_IRQ1_IDPULLUP_RISE |
USBOTGSS_IRQ1_DRVVBUS_FALL |
USBOTGSS_IRQ1_CHRGVBUS_FALL |
USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
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;
}
} }
return 0; return 0;
...@@ -454,8 +394,7 @@ static int dwc3_omap_remove(struct platform_device *pdev) ...@@ -454,8 +394,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
{ {
struct dwc3_omap *omap = platform_get_drvdata(pdev); struct dwc3_omap *omap = platform_get_drvdata(pdev);
platform_device_unregister(omap->usb2_phy); dwc3_omap_disable_irqs(omap);
platform_device_unregister(omap->usb3_phy);
pm_runtime_put_sync(&pdev->dev); pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
...@@ -465,18 +404,72 @@ static int dwc3_omap_remove(struct platform_device *pdev) ...@@ -465,18 +404,72 @@ static int dwc3_omap_remove(struct platform_device *pdev)
static const struct of_device_id of_dwc3_match[] = { static const struct of_device_id of_dwc3_match[] = {
{ {
"ti,dwc3", .compatible = "ti,dwc3"
}, },
{ }, { },
}; };
MODULE_DEVICE_TABLE(of, of_dwc3_match); 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 = { static struct platform_driver dwc3_omap_driver = {
.probe = dwc3_omap_probe, .probe = dwc3_omap_probe,
.remove = dwc3_omap_remove, .remove = dwc3_omap_remove,
.driver = { .driver = {
.name = "omap-dwc3", .name = "omap-dwc3",
.of_match_table = of_dwc3_match, .of_match_table = of_dwc3_match,
.pm = DEV_PM_OPS,
}, },
}; };
......
...@@ -212,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { ...@@ -212,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
}; };
MODULE_DEVICE_TABLE(pci, 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 = { static struct pci_driver dwc3_pci_driver = {
.name = "dwc3-pci", .name = "dwc3-pci",
.id_table = dwc3_pci_id_table, .id_table = dwc3_pci_id_table,
.probe = dwc3_pci_probe, .probe = dwc3_pci_probe,
.remove = dwc3_pci_remove, .remove = dwc3_pci_remove,
.driver = {
.pm = DEV_PM_OPS,
},
}; };
MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
......
...@@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, ...@@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
u32 wIndex; u32 wIndex;
u32 reg; u32 reg;
int ret; int ret;
enum usb_device_state state;
wValue = le16_to_cpu(ctrl->wValue); wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex); wIndex = le16_to_cpu(ctrl->wIndex);
recip = ctrl->bRequestType & USB_RECIP_MASK; recip = ctrl->bRequestType & USB_RECIP_MASK;
state = dwc->gadget.state;
switch (recip) { switch (recip) {
case USB_RECIP_DEVICE: case USB_RECIP_DEVICE:
...@@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, ...@@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
* default control pipe * default control pipe
*/ */
case USB_DEVICE_U1_ENABLE: case USB_DEVICE_U1_ENABLE:
if (dwc->dev_state != DWC3_CONFIGURED_STATE) if (state != USB_STATE_CONFIGURED)
return -EINVAL; return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED) if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL; return -EINVAL;
...@@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, ...@@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
break; break;
case USB_DEVICE_U2_ENABLE: case USB_DEVICE_U2_ENABLE:
if (dwc->dev_state != DWC3_CONFIGURED_STATE) if (state != USB_STATE_CONFIGURED)
return -EINVAL; return -EINVAL;
if (dwc->speed != DWC3_DSTS_SUPERSPEED) if (dwc->speed != DWC3_DSTS_SUPERSPEED)
return -EINVAL; return -EINVAL;
...@@ -493,6 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, ...@@ -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) static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{ {
enum usb_device_state state = dwc->gadget.state;
u32 addr; u32 addr;
u32 reg; u32 reg;
...@@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) ...@@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
return -EINVAL; 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"); dev_dbg(dwc->dev, "trying to set address when configured\n");
return -EINVAL; return -EINVAL;
} }
...@@ -513,9 +517,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) ...@@ -513,9 +517,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc3_writel(dwc->regs, DWC3_DCFG, reg); dwc3_writel(dwc->regs, DWC3_DCFG, reg);
if (addr) if (addr)
dwc->dev_state = DWC3_ADDRESS_STATE; usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
else else
dwc->dev_state = DWC3_DEFAULT_STATE; usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
return 0; return 0;
} }
...@@ -532,6 +536,7 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) ...@@ -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) static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{ {
enum usb_device_state state = dwc->gadget.state;
u32 cfg; u32 cfg;
int ret; int ret;
u32 reg; u32 reg;
...@@ -539,16 +544,18 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) ...@@ -539,16 +544,18 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
dwc->start_config_issued = false; dwc->start_config_issued = false;
cfg = le16_to_cpu(ctrl->wValue); cfg = le16_to_cpu(ctrl->wValue);
switch (dwc->dev_state) { switch (state) {
case DWC3_DEFAULT_STATE: case USB_STATE_DEFAULT:
return -EINVAL; return -EINVAL;
break; break;
case DWC3_ADDRESS_STATE: case USB_STATE_ADDRESS:
ret = dwc3_ep0_delegate_req(dwc, ctrl); ret = dwc3_ep0_delegate_req(dwc, ctrl);
/* if the cfg matches and the cfg is non zero */ /* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { 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 * Enable transition to U1/U2 state when
* nothing is pending from application. * nothing is pending from application.
...@@ -562,10 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) ...@@ -562,10 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
} }
break; break;
case DWC3_CONFIGURED_STATE: case USB_STATE_CONFIGURED:
ret = dwc3_ep0_delegate_req(dwc, ctrl); ret = dwc3_ep0_delegate_req(dwc, ctrl);
if (!cfg) if (!cfg)
dwc->dev_state = DWC3_ADDRESS_STATE; usb_gadget_set_state(&dwc->gadget,
USB_STATE_ADDRESS);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
...@@ -620,10 +628,11 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req) ...@@ -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) static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{ {
struct dwc3_ep *dep; struct dwc3_ep *dep;
enum usb_device_state state = dwc->gadget.state;
u16 wLength; u16 wLength;
u16 wValue; u16 wValue;
if (dwc->dev_state == DWC3_DEFAULT_STATE) if (state == USB_STATE_DEFAULT)
return -EINVAL; return -EINVAL;
wValue = le16_to_cpu(ctrl->wValue); wValue = le16_to_cpu(ctrl->wValue);
......
...@@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) ...@@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
if (dwc->revision >= DWC3_REVISION_194A) if (dwc->revision >= DWC3_REVISION_194A)
reg &= ~DWC3_DCTL_KEEP_CONNECT; reg &= ~DWC3_DCTL_KEEP_CONNECT;
reg |= DWC3_DCTL_RUN_STOP; reg |= DWC3_DCTL_RUN_STOP;
dwc->pullups_connected = true;
} else { } else {
reg &= ~DWC3_DCTL_RUN_STOP; reg &= ~DWC3_DCTL_RUN_STOP;
dwc->pullups_connected = false;
} }
dwc3_writel(dwc->regs, DWC3_DCTL, reg); dwc3_writel(dwc->regs, DWC3_DCTL, reg);
...@@ -1469,6 +1471,33 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) ...@@ -1469,6 +1471,33 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
return ret; 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, static int dwc3_gadget_start(struct usb_gadget *g,
struct usb_gadget_driver *driver) struct usb_gadget_driver *driver)
{ {
...@@ -1476,6 +1505,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, ...@@ -1476,6 +1505,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
struct dwc3_ep *dep; struct dwc3_ep *dep;
unsigned long flags; unsigned long flags;
int ret = 0; int ret = 0;
int irq;
u32 reg; u32 reg;
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
...@@ -1489,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g, ...@@ -1489,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
} }
dwc->gadget_driver = driver; dwc->gadget_driver = driver;
dwc->gadget.dev.driver = &driver->driver;
reg = dwc3_readl(dwc->regs, DWC3_DCFG); reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg &= ~(DWC3_DCFG_SPEED_MASK); reg &= ~(DWC3_DCFG_SPEED_MASK);
...@@ -1536,6 +1565,17 @@ static int dwc3_gadget_start(struct usb_gadget *g, ...@@ -1536,6 +1565,17 @@ static int dwc3_gadget_start(struct usb_gadget *g,
dwc->ep0state = EP0_SETUP_PHASE; dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc); 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); spin_unlock_irqrestore(&dwc->lock, flags);
return 0; return 0;
...@@ -1554,14 +1594,18 @@ static int dwc3_gadget_stop(struct usb_gadget *g, ...@@ -1554,14 +1594,18 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
{ {
struct dwc3 *dwc = gadget_to_dwc(g); struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long flags; unsigned long flags;
int irq;
spin_lock_irqsave(&dwc->lock, flags); 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[0]);
__dwc3_gadget_ep_disable(dwc->eps[1]); __dwc3_gadget_ep_disable(dwc->eps[1]);
dwc->gadget_driver = NULL; dwc->gadget_driver = NULL;
dwc->gadget.dev.driver = NULL;
spin_unlock_irqrestore(&dwc->lock, flags); spin_unlock_irqrestore(&dwc->lock, flags);
...@@ -1579,14 +1623,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { ...@@ -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; 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); dep = kzalloc(sizeof(*dep), GFP_KERNEL);
if (!dep) { if (!dep) {
dev_err(dwc->dev, "can't allocate endpoint %d\n", dev_err(dwc->dev, "can't allocate endpoint %d\n",
...@@ -1600,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) ...@@ -1600,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1, snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
(epnum & 1) ? "in" : "out"); (epnum & 1) ? "in" : "out");
dep->endpoint.name = dep->name; dep->endpoint.name = dep->name;
dep->direction = (epnum & 1); dep->direction = (epnum & 1);
...@@ -1630,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) ...@@ -1630,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
return 0; 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) static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
{ {
struct dwc3_ep *dep; struct dwc3_ep *dep;
...@@ -1637,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) ...@@ -1637,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) { for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
dep = dwc->eps[epnum]; dep = dwc->eps[epnum];
if (!dep)
continue;
dwc3_free_trb_pool(dep); dwc3_free_trb_pool(dep);
if (epnum != 0 && epnum != 1) if (epnum != 0 && epnum != 1)
...@@ -1646,12 +1716,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) ...@@ -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, static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
struct dwc3_request *req, struct dwc3_trb *trb, struct dwc3_request *req, struct dwc3_trb *trb,
const struct dwc3_event_depevt *event, int status) const struct dwc3_event_depevt *event, int status)
...@@ -1975,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc) ...@@ -1975,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
struct dwc3_ep *dep; struct dwc3_ep *dep;
dep = dwc->eps[epnum]; dep = dwc->eps[epnum];
if (!dep)
continue;
if (!(dep->flags & DWC3_EP_ENABLED)) if (!(dep->flags & DWC3_EP_ENABLED))
continue; continue;
...@@ -1992,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) ...@@ -1992,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
int ret; int ret;
dep = dwc->eps[epnum]; dep = dwc->eps[epnum];
if (!dep)
continue;
if (!(dep->flags & DWC3_EP_STALL)) if (!(dep->flags & DWC3_EP_STALL))
continue; continue;
...@@ -2091,7 +2162,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) ...@@ -2091,7 +2162,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
} }
/* after reset -> Default State */ /* 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 */ /* Recent versions support automatic phy suspend and don't need this */
if (dwc->revision < DWC3_REVISION_194A) { if (dwc->revision < DWC3_REVISION_194A) {
...@@ -2277,6 +2348,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, ...@@ -2277,6 +2348,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
unsigned int evtinfo) unsigned int evtinfo)
{ {
enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; 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 * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending
...@@ -2387,40 +2486,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc, ...@@ -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) static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
{ {
struct dwc3_event_buffer *evt; struct dwc3_event_buffer *evt;
int left;
u32 count; u32 count;
evt = dwc->ev_buffs[buf];
count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf)); count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));
count &= DWC3_GEVNTCOUNT_MASK; count &= DWC3_GEVNTCOUNT_MASK;
if (!count) if (!count)
return IRQ_NONE; return IRQ_NONE;
evt = dwc->ev_buffs[buf]; evt->count = count;
left = 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); return IRQ_WAKE_THREAD;
/*
* 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;
} }
static irqreturn_t dwc3_interrupt(int irq, void *_dwc) static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
...@@ -2435,7 +2567,7 @@ 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; irqreturn_t status;
status = dwc3_process_event_buf(dwc, i); status = dwc3_process_event_buf(dwc, i);
if (status == IRQ_HANDLED) if (status == IRQ_WAKE_THREAD)
ret = status; ret = status;
} }
...@@ -2454,7 +2586,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) ...@@ -2454,7 +2586,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
{ {
u32 reg; u32 reg;
int ret; int ret;
int irq;
dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
&dwc->ctrl_req_addr, GFP_KERNEL); &dwc->ctrl_req_addr, GFP_KERNEL);
...@@ -2488,19 +2619,10 @@ int dwc3_gadget_init(struct dwc3 *dwc) ...@@ -2488,19 +2619,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err3; goto err3;
} }
dev_set_name(&dwc->gadget.dev, "gadget");
dwc->gadget.ops = &dwc3_gadget_ops; dwc->gadget.ops = &dwc3_gadget_ops;
dwc->gadget.max_speed = USB_SPEED_SUPER; dwc->gadget.max_speed = USB_SPEED_SUPER;
dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->gadget.dev.parent = dwc->dev;
dwc->gadget.sg_supported = true; 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"; dwc->gadget.name = "dwc3-gadget";
/* /*
...@@ -2512,60 +2634,24 @@ int dwc3_gadget_init(struct dwc3 *dwc) ...@@ -2512,60 +2634,24 @@ int dwc3_gadget_init(struct dwc3 *dwc)
if (ret) if (ret)
goto err4; 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_readl(dwc->regs, DWC3_DCFG);
reg |= DWC3_DCFG_LPM_CAP; reg |= DWC3_DCFG_LPM_CAP;
dwc3_writel(dwc->regs, DWC3_DCFG, reg); dwc3_writel(dwc->regs, DWC3_DCFG, reg);
/* Enable all but Start and End of Frame IRQs */ /* Enable USB2 LPM and automatic phy suspend only on recent versions */
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 */
if (dwc->revision >= DWC3_REVISION_194A) { if (dwc->revision >= DWC3_REVISION_194A) {
dwc3_gadget_usb2_phy_suspend(dwc, false); dwc3_gadget_usb2_phy_suspend(dwc, false);
dwc3_gadget_usb3_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); ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
if (ret) { if (ret) {
dev_err(dwc->dev, "failed to register udc\n"); dev_err(dwc->dev, "failed to register udc\n");
goto err7; goto err5;
} }
return 0; return 0;
err7:
device_unregister(&dwc->gadget.dev);
err6:
dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
free_irq(irq, dwc);
err5: err5:
dwc3_gadget_free_endpoints(dwc); dwc3_gadget_free_endpoints(dwc);
...@@ -2588,15 +2674,11 @@ int dwc3_gadget_init(struct dwc3 *dwc) ...@@ -2588,15 +2674,11 @@ int dwc3_gadget_init(struct dwc3 *dwc)
return ret; return ret;
} }
/* -------------------------------------------------------------------------- */
void dwc3_gadget_exit(struct dwc3 *dwc) void dwc3_gadget_exit(struct dwc3 *dwc)
{ {
int irq;
usb_del_gadget_udc(&dwc->gadget); 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); dwc3_gadget_free_endpoints(dwc);
...@@ -2610,6 +2692,63 @@ void dwc3_gadget_exit(struct dwc3 *dwc) ...@@ -2610,6 +2692,63 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
dwc->ctrl_req, dwc->ctrl_req_addr); 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;
} }
...@@ -196,7 +196,6 @@ config USB_OMAP ...@@ -196,7 +196,6 @@ config USB_OMAP
tristate "OMAP USB Device Controller" tristate "OMAP USB Device Controller"
depends on ARCH_OMAP1 depends on ARCH_OMAP1
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
select USB_OTG_UTILS if ARCH_OMAP
help help
Many Texas Instruments OMAP processors have flexible full Many Texas Instruments OMAP processors have flexible full
speed USB device controllers, with support for up to 30 speed USB device controllers, with support for up to 30
...@@ -211,7 +210,6 @@ config USB_OMAP ...@@ -211,7 +210,6 @@ config USB_OMAP
config USB_PXA25X config USB_PXA25X
tristate "PXA 25x or IXP 4xx" tristate "PXA 25x or IXP 4xx"
depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
select USB_OTG_UTILS
help help
Intel's PXA 25x series XScale ARM-5TE processors include Intel's PXA 25x series XScale ARM-5TE processors include
an integrated full speed USB 1.1 device controller. The an integrated full speed USB 1.1 device controller. The
...@@ -259,8 +257,6 @@ config USB_RENESAS_USBHS_UDC ...@@ -259,8 +257,6 @@ config USB_RENESAS_USBHS_UDC
config USB_PXA27X config USB_PXA27X
tristate "PXA 27x" tristate "PXA 27x"
depends on ARCH_PXA && (PXA27x || PXA3xx)
select USB_OTG_UTILS
help help
Intel's PXA 27x series XScale ARM v5TE processors include Intel's PXA 27x series XScale ARM v5TE processors include
an integrated full speed USB 1.1 device controller. an integrated full speed USB 1.1 device controller.
...@@ -329,9 +325,6 @@ config USB_MV_UDC ...@@ -329,9 +325,6 @@ config USB_MV_UDC
config USB_MV_U3D config USB_MV_U3D
tristate "MARVELL PXA2128 USB 3.0 controller" tristate "MARVELL PXA2128 USB 3.0 controller"
depends on CPU_MMP3
select USB_GADGET_DUALSPEED
select USB_GADGET_SUPERSPEED
help help
MARVELL PXA2128 Processor series include a super speed USB3.0 device MARVELL PXA2128 Processor series include a super speed USB3.0 device
controller, which support super speed USB peripheral. controller, which support super speed USB peripheral.
...@@ -501,6 +494,7 @@ endmenu ...@@ -501,6 +494,7 @@ endmenu
# composite based drivers # composite based drivers
config USB_LIBCOMPOSITE config USB_LIBCOMPOSITE
tristate tristate
select CONFIGFS_FS
depends on USB_GADGET depends on USB_GADGET
config USB_F_ACM config USB_F_ACM
...@@ -512,6 +506,12 @@ config USB_F_SS_LB ...@@ -512,6 +506,12 @@ config USB_F_SS_LB
config USB_U_SERIAL config USB_U_SERIAL
tristate tristate
config USB_F_SERIAL
tristate
config USB_F_OBEX
tristate
choice choice
tristate "USB Gadget Drivers" tristate "USB Gadget Drivers"
default USB_ETH default USB_ETH
...@@ -766,6 +766,8 @@ config USB_G_SERIAL ...@@ -766,6 +766,8 @@ config USB_G_SERIAL
depends on TTY depends on TTY
select USB_U_SERIAL select USB_U_SERIAL
select USB_F_ACM select USB_F_ACM
select USB_F_SERIAL
select USB_F_OBEX
select USB_LIBCOMPOSITE select USB_LIBCOMPOSITE
help help
The Serial Gadget talks to the Linux-USB generic serial driver. The Serial Gadget talks to the Linux-USB generic serial driver.
...@@ -839,6 +841,7 @@ config USB_G_NOKIA ...@@ -839,6 +841,7 @@ config USB_G_NOKIA
depends on PHONET depends on PHONET
select USB_LIBCOMPOSITE select USB_LIBCOMPOSITE
select USB_U_SERIAL select USB_U_SERIAL
select USB_F_ACM
help help
The Nokia composite gadget provides support for acm, obex The Nokia composite gadget provides support for acm, obex
and phonet in only one composite gadget driver. and phonet in only one composite gadget driver.
...@@ -957,6 +960,7 @@ config USB_G_WEBCAM ...@@ -957,6 +960,7 @@ config USB_G_WEBCAM
tristate "USB Webcam Gadget" tristate "USB Webcam Gadget"
depends on VIDEO_DEV depends on VIDEO_DEV
select USB_LIBCOMPOSITE select USB_LIBCOMPOSITE
select VIDEOBUF2_VMALLOC
help help
The Webcam Gadget acts as a composite USB Audio and Video Class The Webcam Gadget acts as a composite USB Audio and Video Class
device. It provides a userspace API to process UVC control requests device. It provides a userspace API to process UVC control requests
......
...@@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG ...@@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
obj-$(CONFIG_USB_GADGET) += udc-core.o obj-$(CONFIG_USB_GADGET) += udc-core.o
obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
libcomposite-y := usbstring.o config.o epautoconf.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_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2272) += net2272.o obj-$(CONFIG_USB_NET2272) += net2272.o
obj-$(CONFIG_USB_NET2280) += net2280.o obj-$(CONFIG_USB_NET2280) += net2280.o
...@@ -36,10 +36,15 @@ obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o ...@@ -36,10 +36,15 @@ obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o
# USB Functions # USB Functions
obj-$(CONFIG_USB_F_ACM) += f_acm.o usb_f_acm-y := f_acm.o
f_ss_lb-y := f_loopback.o f_sourcesink.o obj-$(CONFIG_USB_F_ACM) += usb_f_acm.o
obj-$(CONFIG_USB_F_SS_LB) += f_ss_lb.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 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 # USB gadget drivers
......
...@@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); ...@@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
static struct fsg_common fsg_common; static struct fsg_common fsg_common;
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static unsigned char tty_line;
static struct usb_function *f_acm; static struct usb_function *f_acm;
static struct usb_function_instance *f_acm_inst; static struct usb_function_instance *f_acm_inst;
/* /*
...@@ -117,7 +116,6 @@ 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) static int __init acm_ms_do_config(struct usb_configuration *c)
{ {
struct f_serial_opts *opts;
int status; int status;
if (gadget_is_otg(c->cdev->gadget)) { if (gadget_is_otg(c->cdev->gadget)) {
...@@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c) ...@@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
if (IS_ERR(f_acm_inst)) if (IS_ERR(f_acm_inst))
return PTR_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); f_acm = usb_get_function(f_acm_inst);
if (IS_ERR(f_acm)) { if (IS_ERR(f_acm)) {
status = PTR_ERR(f_acm); status = PTR_ERR(f_acm);
...@@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev) ...@@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
int status; int status;
void *retp; void *retp;
/* set up serial link layer */
status = gserial_alloc_line(&tty_line);
if (status < 0)
return status;
/* set up mass storage function */ /* set up mass storage function */
retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
if (IS_ERR(retp)) { if (IS_ERR(retp)) {
status = PTR_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) ...@@ -207,8 +197,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
/* error recovery */ /* error recovery */
fail1: fail1:
fsg_common_put(&fsg_common); fsg_common_put(&fsg_common);
fail0:
gserial_free_line(tty_line);
return status; return status;
} }
...@@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev) ...@@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
{ {
usb_put_function(f_acm); usb_put_function(f_acm);
usb_put_function_instance(f_acm_inst); usb_put_function_instance(f_acm_inst);
gserial_free_line(tty_line);
return 0; return 0;
} }
......
...@@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g, ...@@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g,
driver->driver.bus = NULL; driver->driver.bus = NULL;
dev->driver = driver; dev->driver = driver;
dev->gadget.dev.driver = &driver->driver;
/* Some gadget drivers use both ep0 directions. /* Some gadget drivers use both ep0 directions.
* NOTE: to gadget driver, ep0 is just one endpoint... * NOTE: to gadget driver, ep0 is just one endpoint...
...@@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g, ...@@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g,
shutdown(dev, driver); shutdown(dev, driver);
spin_unlock_irqrestore(&dev->lock, flags); spin_unlock_irqrestore(&dev->lock, flags);
dev->gadget.dev.driver = NULL;
dev->driver = NULL; dev->driver = NULL;
/* set SD */ /* set SD */
...@@ -3080,7 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev) ...@@ -3080,7 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev)
if (dev->active) if (dev->active)
pci_disable_device(pdev); pci_disable_device(pdev);
device_unregister(&dev->gadget.dev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
udc_remove(dev); udc_remove(dev);
...@@ -3245,8 +3242,6 @@ static int udc_pci_probe( ...@@ -3245,8 +3242,6 @@ static int udc_pci_probe(
dev->phys_addr = resource; dev->phys_addr = resource;
dev->irq = pdev->irq; dev->irq = pdev->irq;
dev->pdev = pdev; dev->pdev = pdev;
dev->gadget.dev.parent = &pdev->dev;
dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
/* general probing */ /* general probing */
if (udc_probe(dev) == 0) if (udc_probe(dev) == 0)
...@@ -3273,7 +3268,6 @@ static int udc_probe(struct udc *dev) ...@@ -3273,7 +3268,6 @@ static int udc_probe(struct udc *dev)
dev->gadget.ops = &udc_ops; dev->gadget.ops = &udc_ops;
dev_set_name(&dev->gadget.dev, "gadget"); dev_set_name(&dev->gadget.dev, "gadget");
dev->gadget.dev.release = gadget_release;
dev->gadget.name = name; dev->gadget.name = name;
dev->gadget.max_speed = USB_SPEED_HIGH; dev->gadget.max_speed = USB_SPEED_HIGH;
...@@ -3297,17 +3291,11 @@ static int udc_probe(struct udc *dev) ...@@ -3297,17 +3291,11 @@ static int udc_probe(struct udc *dev)
"driver version: %s(for Geode5536 B1)\n", tmp); "driver version: %s(for Geode5536 B1)\n", tmp);
udc = dev; 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) if (retval)
goto finished; 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 */ /* timer init */
init_timer(&udc_timer); init_timer(&udc_timer);
udc_timer.function = udc_timer_function; udc_timer.function = udc_timer_function;
......
...@@ -472,7 +472,6 @@ struct udc_request { ...@@ -472,7 +472,6 @@ struct udc_request {
/* flags */ /* flags */
unsigned dma_going : 1, unsigned dma_going : 1,
dma_mapping : 1,
dma_done : 1; dma_done : 1;
/* phys. address */ /* phys. address */
dma_addr_t td_phys; dma_addr_t td_phys;
......
...@@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget, ...@@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget,
udc = container_of(gadget, struct at91_udc, gadget); udc = container_of(gadget, struct at91_udc, gadget);
udc->driver = driver; udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
udc->gadget.dev.of_node = udc->pdev->dev.of_node; udc->gadget.dev.of_node = udc->pdev->dev.of_node;
udc->enabled = 1; udc->enabled = 1;
udc->selfpowered = 1; udc->selfpowered = 1;
...@@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget, ...@@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget,
at91_udp_write(udc, AT91_UDP_IDR, ~0); at91_udp_write(udc, AT91_UDP_IDR, ~0);
spin_unlock_irqrestore(&udc->lock, flags); spin_unlock_irqrestore(&udc->lock, flags);
udc->gadget.dev.driver = NULL;
udc->driver = NULL; udc->driver = NULL;
DBG("unbound from %s\n", driver->driver.name); DBG("unbound from %s\n", driver->driver.name);
...@@ -1780,13 +1778,7 @@ static int at91udc_probe(struct platform_device *pdev) ...@@ -1780,13 +1778,7 @@ static int at91udc_probe(struct platform_device *pdev)
DBG("clocks missing\n"); DBG("clocks missing\n");
retval = -ENODEV; retval = -ENODEV;
/* NOTE: we "know" here that refcounts on these are NOPs */ /* NOTE: we "know" here that refcounts on these are NOPs */
goto fail0b; goto fail1;
}
retval = device_register(&udc->gadget.dev);
if (retval < 0) {
put_device(&udc->gadget.dev);
goto fail0b;
} }
/* don't do anything until we have both gadget driver and VBUS */ /* don't do anything until we have both gadget driver and VBUS */
...@@ -1857,8 +1849,6 @@ static int at91udc_probe(struct platform_device *pdev) ...@@ -1857,8 +1849,6 @@ static int at91udc_probe(struct platform_device *pdev)
fail2: fail2:
free_irq(udc->udp_irq, udc); free_irq(udc->udp_irq, udc);
fail1: fail1:
device_unregister(&udc->gadget.dev);
fail0b:
iounmap(udc->udp_baseaddr); iounmap(udc->udp_baseaddr);
fail0a: fail0a:
if (cpu_is_at91rm9200()) if (cpu_is_at91rm9200())
...@@ -1892,8 +1882,6 @@ static int __exit at91udc_remove(struct platform_device *pdev) ...@@ -1892,8 +1882,6 @@ static int __exit at91udc_remove(struct platform_device *pdev)
gpio_free(udc->board.vbus_pin); gpio_free(udc->board.vbus_pin);
} }
free_irq(udc->udp_irq, udc); free_irq(udc->udp_irq, udc);
device_unregister(&udc->gadget.dev);
iounmap(udc->udp_baseaddr); iounmap(udc->udp_baseaddr);
if (cpu_is_at91rm9200()) if (cpu_is_at91rm9200())
......
...@@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status) ...@@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status)
if (req->req.status == -EINPROGRESS) if (req->req.status == -EINPROGRESS)
req->req.status = status; req->req.status = status;
if (req->mapped) { if (req->using_dma)
dma_unmap_single( usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
&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;
}
DBG(DBG_GADGET | DBG_REQ, DBG(DBG_GADGET | DBG_REQ,
"%s: req %p complete: status %d, actual %u\n", "%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) ...@@ -684,7 +679,6 @@ usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
return NULL; return NULL;
INIT_LIST_HEAD(&req->queue); INIT_LIST_HEAD(&req->queue);
req->req.dma = DMA_ADDR_INVALID;
return &req->req; return &req->req;
} }
...@@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep, ...@@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
return -EINVAL; return -EINVAL;
} }
req->using_dma = 1; ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in);
if (ret)
if (req->req.dma == DMA_ADDR_INVALID) { return ret;
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->using_dma = 1;
req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length) req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
| USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE | USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
| USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE; | USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
...@@ -1799,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget, ...@@ -1799,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget,
udc->devstatus = 1 << USB_DEVICE_SELF_POWERED; udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
udc->driver = driver; udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
spin_unlock_irqrestore(&udc->lock, flags); spin_unlock_irqrestore(&udc->lock, flags);
clk_enable(udc->pclk); clk_enable(udc->pclk);
...@@ -1841,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget, ...@@ -1841,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
toggle_bias(0); toggle_bias(0);
usba_writel(udc, CTRL, USBA_DISABLE_MASK); usba_writel(udc, CTRL, USBA_DISABLE_MASK);
udc->gadget.dev.driver = NULL;
udc->driver = NULL; udc->driver = NULL;
clk_disable(udc->hclk); clk_disable(udc->hclk);
...@@ -1900,10 +1883,6 @@ static int __init usba_udc_probe(struct platform_device *pdev) ...@@ -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", dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
(unsigned long)fifo->start, udc->fifo); (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); platform_set_drvdata(pdev, udc);
/* Make sure we start from a clean slate */ /* Make sure we start from a clean slate */
...@@ -1962,12 +1941,6 @@ static int __init usba_udc_probe(struct platform_device *pdev) ...@@ -1962,12 +1941,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
} }
udc->irq = irq; 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_is_valid(pdata->vbus_pin)) {
if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) { if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
udc->vbus_pin = pdata->vbus_pin; udc->vbus_pin = pdata->vbus_pin;
...@@ -2007,9 +1980,6 @@ static int __init usba_udc_probe(struct platform_device *pdev) ...@@ -2007,9 +1980,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
gpio_free(udc->vbus_pin); gpio_free(udc->vbus_pin);
} }
device_unregister(&udc->gadget.dev);
err_device_add:
free_irq(irq, udc); free_irq(irq, udc);
err_request_irq: err_request_irq:
kfree(usba_ep); kfree(usba_ep);
...@@ -2053,8 +2023,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev) ...@@ -2053,8 +2023,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
clk_put(udc->hclk); clk_put(udc->hclk);
clk_put(udc->pclk); clk_put(udc->pclk);
device_unregister(&udc->gadget.dev);
return 0; return 0;
} }
......
...@@ -216,12 +216,6 @@ ...@@ -216,12 +216,6 @@
#define EP0_EPT_SIZE USBA_EPT_SIZE_64 #define EP0_EPT_SIZE USBA_EPT_SIZE_64
#define EP0_NR_BANKS 1 #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 FIFO_IOMEM_ID 0
#define CTRL_IOMEM_ID 1 #define CTRL_IOMEM_ID 1
......
...@@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget, ...@@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget,
udc->driver = driver; udc->driver = driver;
driver->driver.bus = NULL; driver->driver.bus = NULL;
udc->gadget.dev.driver = &driver->driver;
udc->gadget.dev.of_node = udc->dev->of_node; udc->gadget.dev.of_node = udc->dev->of_node;
spin_unlock_irqrestore(&udc->lock, flags); spin_unlock_irqrestore(&udc->lock, flags);
...@@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget, ...@@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget,
spin_lock_irqsave(&udc->lock, flags); spin_lock_irqsave(&udc->lock, flags);
udc->driver = NULL; udc->driver = NULL;
udc->gadget.dev.driver = NULL;
/* /*
* If we switch the PHY too abruptly after dropping D+, the host * 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) ...@@ -2305,17 +2303,6 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
* Driver init/exit * 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. * bcm63xx_udc_probe - Initialize a new instance of the UDC.
* @pdev: Platform device struct from the bcm63xx BSP code. * @pdev: Platform device struct from the bcm63xx BSP code.
...@@ -2368,13 +2355,9 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) ...@@ -2368,13 +2355,9 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
spin_lock_init(&udc->lock); spin_lock_init(&udc->lock);
INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process); INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
dev_set_name(&udc->gadget.dev, "gadget");
udc->gadget.ops = &bcm63xx_udc_ops; udc->gadget.ops = &bcm63xx_udc_ops;
udc->gadget.name = dev_name(dev); 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) if (!pd->use_fullspeed && !use_fullspeed)
udc->gadget.max_speed = USB_SPEED_HIGH; udc->gadget.max_speed = USB_SPEED_HIGH;
...@@ -2414,17 +2397,12 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) ...@@ -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); bcm63xx_udc_init_debugfs(udc);
rc = usb_add_gadget_udc(dev, &udc->gadget); rc = usb_add_gadget_udc(dev, &udc->gadget);
if (!rc) if (!rc)
return 0; return 0;
bcm63xx_udc_cleanup_debugfs(udc); bcm63xx_udc_cleanup_debugfs(udc);
device_unregister(&udc->gadget.dev);
out_uninit: out_uninit:
bcm63xx_uninit_udc_hw(udc); bcm63xx_uninit_udc_hw(udc);
return rc; return rc;
...@@ -2440,7 +2418,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev) ...@@ -2440,7 +2418,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)
bcm63xx_udc_cleanup_debugfs(udc); bcm63xx_udc_cleanup_debugfs(udc);
usb_del_gadget_udc(&udc->gadget); usb_del_gadget_udc(&udc->gadget);
device_unregister(&udc->gadget.dev);
BUG_ON(udc->driver); BUG_ON(udc->driver);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
......
...@@ -103,18 +103,16 @@ static struct usb_gadget_strings *dev_strings[] = { ...@@ -103,18 +103,16 @@ static struct usb_gadget_strings *dev_strings[] = {
}; };
static u8 hostaddr[ETH_ALEN]; static u8 hostaddr[ETH_ALEN];
static struct eth_dev *the_dev;
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static struct usb_function *f_acm; static struct usb_function *f_acm;
static struct usb_function_instance *fi_serial; static struct usb_function_instance *fi_serial;
static unsigned char tty_line;
/* /*
* We _always_ have both CDC ECM and CDC ACM functions. * We _always_ have both CDC ECM and CDC ACM functions.
*/ */
static int __init cdc_do_config(struct usb_configuration *c) static int __init cdc_do_config(struct usb_configuration *c)
{ {
struct f_serial_opts *opts;
int status; int status;
if (gadget_is_otg(c->cdev->gadget)) { if (gadget_is_otg(c->cdev->gadget)) {
...@@ -122,7 +120,7 @@ static int __init cdc_do_config(struct usb_configuration *c) ...@@ -122,7 +120,7 @@ static int __init cdc_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
} }
status = ecm_bind_config(c, hostaddr); status = ecm_bind_config(c, hostaddr, the_dev);
if (status < 0) if (status < 0)
return status; return status;
...@@ -130,9 +128,6 @@ static int __init cdc_do_config(struct usb_configuration *c) ...@@ -130,9 +128,6 @@ static int __init cdc_do_config(struct usb_configuration *c)
if (IS_ERR(fi_serial)) if (IS_ERR(fi_serial))
return PTR_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); f_acm = usb_get_function(fi_serial);
if (IS_ERR(f_acm)) if (IS_ERR(f_acm))
goto err_func_acm; goto err_func_acm;
...@@ -169,14 +164,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) ...@@ -169,14 +164,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
} }
/* set up network link layer */ /* set up network link layer */
status = gether_setup(cdev->gadget, hostaddr); the_dev = gether_setup(cdev->gadget, hostaddr);
if (status < 0) if (IS_ERR(the_dev))
return status; return PTR_ERR(the_dev);
/* set up serial link layer */
status = gserial_alloc_line(&tty_line);
if (status < 0)
goto fail0;
/* Allocate string descriptor numbers ... note that string /* Allocate string descriptor numbers ... note that string
* contents can be overridden by the composite_dev glue. * contents can be overridden by the composite_dev glue.
...@@ -200,9 +190,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) ...@@ -200,9 +190,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
return 0; return 0;
fail1: fail1:
gserial_free_line(tty_line); gether_cleanup(the_dev);
fail0:
gether_cleanup();
return status; return status;
} }
...@@ -210,8 +198,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev) ...@@ -210,8 +198,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)
{ {
usb_put_function(f_acm); usb_put_function(f_acm);
usb_put_function_instance(fi_serial); usb_put_function_instance(fi_serial);
gserial_free_line(tty_line); gether_cleanup(the_dev);
gether_cleanup();
return 0; return 0;
} }
......
...@@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev) ...@@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
kfree(cdev->req->buf); kfree(cdev->req->buf);
usb_ep_free_request(cdev->gadget->ep0, cdev->req); usb_ep_free_request(cdev->gadget->ep0, cdev->req);
} }
cdev->next_string_id = 0;
device_remove_file(&cdev->gadget->dev, &dev_attr_suspended); device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
} }
......
此差异已折叠。
...@@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g, ...@@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g,
dum->devstatus = 0; dum->devstatus = 0;
dum->driver = driver; dum->driver = driver;
dum->gadget.dev.driver = &driver->driver;
dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n", dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
driver->driver.name); driver->driver.name);
return 0; return 0;
...@@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g, ...@@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n", dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
driver->driver.name); driver->driver.name);
dum->gadget.dev.driver = NULL;
dum->driver = NULL; dum->driver = NULL;
return 0; return 0;
...@@ -937,11 +935,6 @@ static int dummy_udc_stop(struct usb_gadget *g, ...@@ -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 /* The gadget structure is stored inside the hcd structure and will be
* released along with it. */ * released along with it. */
static void dummy_gadget_release(struct device *dev)
{
return;
}
static void init_dummy_udc_hw(struct dummy *dum) static void init_dummy_udc_hw(struct dummy *dum)
{ {
int i; int i;
...@@ -984,15 +977,7 @@ static int dummy_udc_probe(struct platform_device *pdev) ...@@ -984,15 +977,7 @@ static int dummy_udc_probe(struct platform_device *pdev)
dum->gadget.ops = &dummy_ops; dum->gadget.ops = &dummy_ops;
dum->gadget.max_speed = USB_SPEED_SUPER; dum->gadget.max_speed = USB_SPEED_SUPER;
dev_set_name(&dum->gadget.dev, "gadget");
dum->gadget.dev.parent = &pdev->dev; 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); init_dummy_udc_hw(dum);
rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget); rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
...@@ -1008,7 +993,6 @@ static int dummy_udc_probe(struct platform_device *pdev) ...@@ -1008,7 +993,6 @@ static int dummy_udc_probe(struct platform_device *pdev)
err_dev: err_dev:
usb_del_gadget_udc(&dum->gadget); usb_del_gadget_udc(&dum->gadget);
err_udc: err_udc:
device_unregister(&dum->gadget.dev);
return rc; return rc;
} }
...@@ -1019,7 +1003,6 @@ static int dummy_udc_remove(struct platform_device *pdev) ...@@ -1019,7 +1003,6 @@ static int dummy_udc_remove(struct platform_device *pdev)
usb_del_gadget_udc(&dum->gadget); usb_del_gadget_udc(&dum->gadget);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
device_remove_file(&dum->gadget.dev, &dev_attr_function); device_remove_file(&dum->gadget.dev, &dev_attr_function);
device_unregister(&dum->gadget.dev);
return 0; return 0;
} }
...@@ -1923,7 +1906,7 @@ static int dummy_hub_status(struct usb_hcd *hcd, char *buf) ...@@ -1923,7 +1906,7 @@ static int dummy_hub_status(struct usb_hcd *hcd, char *buf)
} }
/* usb 3.0 root hub device descriptor */ /* usb 3.0 root hub device descriptor */
struct { static struct {
struct usb_bos_descriptor bos; struct usb_bos_descriptor bos;
struct usb_ss_cap_descriptor ss_cap; struct usb_ss_cap_descriptor ss_cap;
} __packed usb3_bos_desc = { } __packed usb3_bos_desc = {
......
...@@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = { ...@@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = {
}; };
static u8 hostaddr[ETH_ALEN]; 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) ...@@ -224,7 +224,7 @@ static int __init rndis_do_config(struct usb_configuration *c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; 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 = { static struct usb_configuration rndis_config_driver = {
...@@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c) ...@@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c)
} }
if (use_eem) if (use_eem)
return eem_bind_config(c); return eem_bind_config(c, the_dev);
else if (can_support_ecm(c->cdev->gadget)) else if (can_support_ecm(c->cdev->gadget))
return ecm_bind_config(c, hostaddr); return ecm_bind_config(c, hostaddr, the_dev);
else else
return geth_bind_config(c, hostaddr); return geth_bind_config(c, hostaddr, the_dev);
} }
static struct usb_configuration eth_config_driver = { static struct usb_configuration eth_config_driver = {
...@@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev) ...@@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
int status; int status;
/* set up network link layer */ /* set up network link layer */
status = gether_setup(cdev->gadget, hostaddr); the_dev = gether_setup(cdev->gadget, hostaddr);
if (status < 0) if (IS_ERR(the_dev))
return status; return PTR_ERR(the_dev);
/* set up main config label and device descriptor */ /* set up main config label and device descriptor */
if (use_eem) { if (use_eem) {
...@@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev) ...@@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
return 0; return 0;
fail: fail:
gether_cleanup(); gether_cleanup(the_dev);
return status; return status;
} }
static int __exit eth_unbind(struct usb_composite_dev *cdev) static int __exit eth_unbind(struct usb_composite_dev *cdev)
{ {
gether_cleanup(); gether_cleanup(the_dev);
return 0; return 0;
} }
......
...@@ -715,13 +715,31 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -715,13 +715,31 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
return status; return status;
} }
static struct f_acm *acm_alloc_basic_func(void) static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
acm_string_defs[0].id = 0;
usb_free_all_descriptors(f);
if (acm->notify_req)
gs_free_req(acm->notify, acm->notify_req);
}
static void acm_free_func(struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
kfree(acm);
}
static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
{ {
struct f_acm *acm; struct f_serial_opts *opts;
struct f_acm *acm;
acm = kzalloc(sizeof(*acm), GFP_KERNEL); acm = kzalloc(sizeof(*acm), GFP_KERNEL);
if (!acm) if (!acm)
return NULL; return ERR_PTR(-ENOMEM);
spin_lock_init(&acm->lock); spin_lock_init(&acm->lock);
...@@ -730,109 +748,100 @@ static struct f_acm *acm_alloc_basic_func(void) ...@@ -730,109 +748,100 @@ static struct f_acm *acm_alloc_basic_func(void)
acm->port.send_break = acm_send_break; acm->port.send_break = acm_send_break;
acm->port.func.name = "acm"; acm->port.func.name = "acm";
acm->port.func.strings = acm_strings;
/* descriptors are per-instance copies */ /* descriptors are per-instance copies */
acm->port.func.bind = acm_bind; acm->port.func.bind = acm_bind;
acm->port.func.set_alt = acm_set_alt; acm->port.func.set_alt = acm_set_alt;
acm->port.func.setup = acm_setup; acm->port.func.setup = acm_setup;
acm->port.func.disable = acm_disable; acm->port.func.disable = acm_disable;
return acm; opts = container_of(fi, struct f_serial_opts, func_inst);
acm->port_num = opts->port_num;
acm->port.func.unbind = acm_unbind;
acm->port.func.free_func = acm_free_func;
return &acm->port.func;
} }
#ifdef USB_FACM_INCLUDED static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
static void
acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
struct f_acm *acm = func_to_acm(f); return container_of(to_config_group(item), struct f_serial_opts,
func_inst.group);
usb_free_all_descriptors(f);
if (acm->notify_req)
gs_free_req(acm->notify, acm->notify_req);
kfree(acm);
} }
/** CONFIGFS_ATTR_STRUCT(f_serial_opts);
* acm_bind_config - add a CDC ACM function to a configuration static ssize_t f_acm_attr_show(struct config_item *item,
* @c: the configuration to support the CDC ACM instance struct configfs_attribute *attr,
* @port_num: /dev/ttyGS* port this interface will use char *page)
* 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; struct f_serial_opts *opts = to_f_serial_opts(item);
int status; struct f_serial_opts_attribute *f_serial_opts_attr =
container_of(attr, struct f_serial_opts_attribute, attr);
/* allocate and initialize one new instance */ ssize_t ret = 0;
acm = acm_alloc_basic_func();
if (!acm) if (f_serial_opts_attr->show)
return -ENOMEM; ret = f_serial_opts_attr->show(opts, page);
return ret;
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_attr_release(struct config_item *item)
static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
struct f_acm *acm = func_to_acm(f); struct f_serial_opts *opts = to_f_serial_opts(item);
acm_string_defs[0].id = 0; usb_put_function_instance(&opts->func_inst);
usb_free_all_descriptors(f);
if (acm->notify_req)
gs_free_req(acm->notify, acm->notify_req);
} }
static void acm_free_func(struct usb_function *f) static struct configfs_item_operations acm_item_ops = {
{ .release = acm_attr_release,
struct f_acm *acm = func_to_acm(f); .show_attribute = f_acm_attr_show,
};
kfree(acm); 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 usb_function *acm_alloc_func(struct usb_function_instance *fi) static struct f_serial_opts_attribute f_acm_port_num =
{ __CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
struct f_serial_opts *opts;
struct f_acm *acm;
acm = acm_alloc_basic_func();
if (!acm)
return ERR_PTR(-ENOMEM);
opts = container_of(fi, struct f_serial_opts, func_inst); static struct configfs_attribute *acm_attrs[] = {
acm->port_num = opts->port_num; &f_acm_port_num.attr,
acm->port.func.unbind = acm_unbind; NULL,
acm->port.func.free_func = acm_free_func; };
return &acm->port.func; 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) static void acm_free_instance(struct usb_function_instance *fi)
{ {
struct f_serial_opts *opts; struct f_serial_opts *opts;
opts = container_of(fi, struct f_serial_opts, func_inst); opts = container_of(fi, struct f_serial_opts, func_inst);
gserial_free_line(opts->port_num);
kfree(opts); kfree(opts);
} }
static struct usb_function_instance *acm_alloc_instance(void) static struct usb_function_instance *acm_alloc_instance(void)
{ {
struct f_serial_opts *opts; struct f_serial_opts *opts;
int ret;
opts = kzalloc(sizeof(*opts), GFP_KERNEL); opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts) if (!opts)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
opts->func_inst.free_func_inst = acm_free_instance; 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; return &opts->func_inst;
} }
DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func); DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#endif
...@@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
* for calling @gether_cleanup() before module unload. * for calling @gether_cleanup() before module unload.
*/ */
int 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; struct f_ecm *ecm;
int status; int status;
...@@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) ...@@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr); snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
ecm_string_defs[1].s = ecm->ethaddr; ecm_string_defs[1].s = ecm->ethaddr;
ecm->port.ioport = dev;
ecm->port.cdc_filter = DEFAULT_FILTER; ecm->port.cdc_filter = DEFAULT_FILTER;
ecm->port.func.name = "cdc_ethernet"; ecm->port.func.name = "cdc_ethernet";
......
...@@ -528,7 +528,7 @@ static int eem_unwrap(struct gether *port, ...@@ -528,7 +528,7 @@ static int eem_unwrap(struct gether *port,
* Caller must have called @gether_setup(). Caller is also responsible * Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload. * 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; struct f_eem *eem;
int status; int status;
...@@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c) ...@@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c)
if (!eem) if (!eem)
return -ENOMEM; return -ENOMEM;
eem->port.ioport = dev;
eem->port.cdc_filter = DEFAULT_FILTER; eem->port.cdc_filter = DEFAULT_FILTER;
eem->port.func.name = "cdc_eem"; eem->port.func.name = "cdc_eem";
......
...@@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
* Caller must have called @gether_setup(). Caller is also responsible * Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload. * 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; struct f_ncm *ncm;
int status; int status;
...@@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) ...@@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
spin_lock_init(&ncm->lock); spin_lock_init(&ncm->lock);
ncm_reset_values(ncm); ncm_reset_values(ncm);
ncm->port.ioport = dev;
ncm->port.is_fixed = true; ncm->port.is_fixed = true;
ncm->port.func.name = "cdc_network"; ncm->port.func.name = "cdc_network";
......
...@@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = { ...@@ -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), .bLength = sizeof(obex_control_intf),
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0, .bInterfaceNumber = 0,
...@@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = { ...@@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = {
.bInterfaceSubClass = USB_CDC_SUBCLASS_OBEX, .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), .bLength = sizeof(obex_data_nop_intf),
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 1, .bInterfaceNumber = 1,
...@@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = { ...@@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
.bInterfaceClass = USB_CLASS_CDC_DATA, .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), .bLength = sizeof(obex_data_intf),
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 2, .bInterfaceNumber = 2,
...@@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = { ...@@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = {
.bInterfaceClass = USB_CLASS_CDC_DATA, .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), .bLength = sizeof(obex_cdc_header_desc),
.bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE, .bDescriptorSubType = USB_CDC_HEADER_TYPE,
.bcdCDC = cpu_to_le16(0x0120), .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), .bLength = sizeof(obex_cdc_union_desc),
.bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_UNION_TYPE, .bDescriptorSubType = USB_CDC_UNION_TYPE,
...@@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { ...@@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
.bSlaveInterface0 = 2, .bSlaveInterface0 = 2,
}; };
static struct usb_cdc_obex_desc obex_desc __initdata = { static struct usb_cdc_obex_desc obex_desc = {
.bLength = sizeof(obex_desc), .bLength = sizeof(obex_desc),
.bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_OBEX_TYPE, .bDescriptorSubType = USB_CDC_OBEX_TYPE,
...@@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = { ...@@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = {
/* High-Speed Support */ /* 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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { ...@@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512), .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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { ...@@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512), .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_control_intf,
(struct usb_descriptor_header *) &obex_cdc_header_desc, (struct usb_descriptor_header *) &obex_cdc_header_desc,
(struct usb_descriptor_header *) &obex_desc, (struct usb_descriptor_header *) &obex_desc,
...@@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = { ...@@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = {
/* Full-Speed Support */ /* 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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = { ...@@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
...@@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = { ...@@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK, .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_control_intf,
(struct usb_descriptor_header *) &obex_cdc_header_desc, (struct usb_descriptor_header *) &obex_cdc_header_desc,
(struct usb_descriptor_header *) &obex_desc, (struct usb_descriptor_header *) &obex_desc,
...@@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g) ...@@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static int __init /* Some controllers can't support CDC OBEX ... */
obex_bind(struct usb_configuration *c, struct usb_function *f) 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 usb_composite_dev *cdev = c->cdev;
struct f_obex *obex = func_to_obex(f); struct f_obex *obex = func_to_obex(f);
int status; int status;
struct usb_ep *ep; 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 */ /* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f); status = usb_interface_id(c, f);
...@@ -376,29 +405,16 @@ obex_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -376,29 +405,16 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
return status; return status;
} }
#ifdef USBF_OBEX_INCLUDED
static void 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; obex_string_defs[OBEX_CTRL_IDX].id = 0;
usb_free_all_descriptors(f); usb_free_all_descriptors(f);
kfree(func_to_obex(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 * obex_bind_config - add a CDC OBEX function to a configuration
* @c: the configuration to support the CDC OBEX instance * @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) ...@@ -412,21 +428,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
struct f_obex *obex; struct f_obex *obex;
int status; 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 */ /* allocate and initialize one new instance */
obex = kzalloc(sizeof *obex, GFP_KERNEL); obex = kzalloc(sizeof *obex, GFP_KERNEL);
if (!obex) if (!obex)
...@@ -441,7 +442,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num) ...@@ -441,7 +442,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
obex->port.func.strings = obex_strings; obex->port.func.strings = obex_strings;
/* descriptors are per-instance copies */ /* descriptors are per-instance copies */
obex->port.func.bind = obex_bind; 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.set_alt = obex_set_alt;
obex->port.func.get_alt = obex_get_alt; obex->port.func.get_alt = obex_get_alt;
obex->port.func.disable = obex_disable; obex->port.func.disable = obex_disable;
...@@ -453,5 +454,138 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num) ...@@ -453,5 +454,138 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
return status; 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_AUTHOR("Felipe Balbi");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -813,7 +813,7 @@ static inline bool can_support_rndis(struct usb_configuration *c) ...@@ -813,7 +813,7 @@ static inline bool can_support_rndis(struct usb_configuration *c)
int int
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], 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; struct f_rndis *rndis;
int status; int status;
...@@ -846,6 +846,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], ...@@ -846,6 +846,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
rndis->vendorID = vendorID; rndis->vendorID = vendorID;
rndis->manufacturer = manufacturer; rndis->manufacturer = manufacturer;
rndis->port.ioport = dev;
/* RNDIS activates when the host changes this filter */ /* RNDIS activates when the host changes this filter */
rndis->port.cdc_filter = 0; rndis->port.cdc_filter = 0;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include "u_serial.h" #include "u_serial.h"
...@@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f) ...@@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f)
/* interface descriptor: */ /* interface descriptor: */
static struct usb_interface_descriptor gser_interface_desc __initdata = { static struct usb_interface_descriptor gser_interface_desc = {
.bLength = USB_DT_INTERFACE_SIZE, .bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
/* .bInterfaceNumber = DYNAMIC */ /* .bInterfaceNumber = DYNAMIC */
...@@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = { ...@@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = {
/* full speed support: */ /* 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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN, .bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK, .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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT, .bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK, .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_interface_desc,
(struct usb_descriptor_header *) &gser_fs_in_desc, (struct usb_descriptor_header *) &gser_fs_in_desc,
(struct usb_descriptor_header *) &gser_fs_out_desc, (struct usb_descriptor_header *) &gser_fs_out_desc,
...@@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = { ...@@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = {
/* high speed support: */ /* 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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512), .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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512), .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_interface_desc,
(struct usb_descriptor_header *) &gser_hs_in_desc, (struct usb_descriptor_header *) &gser_hs_in_desc,
(struct usb_descriptor_header *) &gser_hs_out_desc, (struct usb_descriptor_header *) &gser_hs_out_desc,
NULL, 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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024), .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, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_BULK, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024), .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, .bLength = sizeof gser_ss_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP, .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_interface_desc,
(struct usb_descriptor_header *) &gser_ss_in_desc, (struct usb_descriptor_header *) &gser_ss_in_desc,
(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc, (struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
...@@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f) ...@@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f)
/* serial function driver setup/binding */ /* serial function driver setup/binding */
static int __init static int gser_bind(struct usb_configuration *c, struct usb_function *f)
gser_bind(struct usb_configuration *c, struct usb_function *f)
{ {
struct usb_composite_dev *cdev = c->cdev; struct usb_composite_dev *cdev = c->cdev;
struct f_gser *gser = func_to_gser(f); struct f_gser *gser = func_to_gser(f);
int status; int status;
struct usb_ep *ep; 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 */ /* allocate instance-specific interface IDs */
status = usb_interface_id(c, f); status = usb_interface_id(c, f);
if (status < 0) if (status < 0)
...@@ -246,44 +258,115 @@ gser_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -246,44 +258,115 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
return status; return status;
} }
static void static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
gser_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
usb_free_all_descriptors(f); return container_of(to_config_group(item), struct f_serial_opts,
kfree(func_to_gser(f)); func_inst.group);
} }
/** CONFIGFS_ATTR_STRUCT(f_serial_opts);
* gser_bind_config - add a generic serial function to a configuration static ssize_t f_serial_attr_show(struct config_item *item,
* @c: the configuration to support the serial instance struct configfs_attribute *attr,
* @port_num: /dev/ttyGS* port this interface will use char *page)
* 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)
{ {
struct f_gser *gser; struct f_serial_opts *opts = to_f_serial_opts(item);
int status; struct f_serial_opts_attribute *f_serial_opts_attr =
container_of(attr, struct f_serial_opts_attribute, attr);
ssize_t ret = 0;
/* REVISIT might want instance-specific strings to help if (f_serial_opts_attr->show)
* distinguish instances ... ret = f_serial_opts_attr->show(opts, page);
*/
/* maybe allocate device-global string ID */ return ret;
if (gser_string_defs[0].id == 0) { }
status = usb_string_id(c->cdev);
if (status < 0) static void serial_attr_release(struct config_item *item)
return status; {
gser_string_defs[0].id = status; 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;
struct f_serial_opts *opts;
/* allocate and initialize one new instance */ /* allocate and initialize one new instance */
gser = kzalloc(sizeof *gser, GFP_KERNEL); gser = kzalloc(sizeof(*gser), GFP_KERNEL);
if (!gser) 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.name = "gser";
gser->port.func.strings = gser_strings; gser->port.func.strings = gser_strings;
...@@ -291,9 +374,12 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num) ...@@ -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.unbind = gser_unbind;
gser->port.func.set_alt = gser_set_alt; gser->port.func.set_alt = gser_set_alt;
gser->port.func.disable = gser_disable; gser->port.func.disable = gser_disable;
gser->port.func.free_func = gser_free;
status = usb_add_function(c, &gser->port.func); return &gser->port.func;
if (status)
kfree(gser);
return status;
} }
DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Al Borchers");
MODULE_AUTHOR("David Brownell");
...@@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)
* Caller must have called @gether_setup(). Caller is also responsible * Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload. * 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; struct f_gether *geth;
int status; int status;
...@@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) ...@@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr); snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
geth_string_defs[1].s = geth->ethaddr; geth_string_defs[1].s = geth->ethaddr;
geth->port.ioport = dev;
geth->port.cdc_filter = DEFAULT_FILTER; geth->port.cdc_filter = DEFAULT_FILTER;
geth->port.func.name = "cdc_subset"; geth->port.func.name = "cdc_subset";
......
此差异已折叠。
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
#include <linux/usb/composite.h> #include <linux/usb/composite.h>
#include <linux/usb/video.h> #include <linux/usb/video.h>
extern int uvc_bind_config(struct usb_configuration *c, int uvc_bind_config(struct usb_configuration *c,
const struct uvc_descriptor_header * const *fs_control, const struct uvc_descriptor_header * const *fs_control,
const struct uvc_descriptor_header * const *hs_control, const struct uvc_descriptor_header * const *hs_control,
const struct uvc_descriptor_header * const *fs_streaming, const struct uvc_descriptor_header * const *fs_streaming,
const struct uvc_descriptor_header * const *hs_streaming, const struct uvc_descriptor_header * const *hs_streaming,
const struct uvc_descriptor_header * const *ss_streaming); const struct uvc_descriptor_header * const *ss_streaming);
#endif /* _F_UVC_H_ */ #endif /* _F_UVC_H_ */
...@@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget, ...@@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget,
driver->driver.bus = NULL; driver->driver.bus = NULL;
/* hook up the driver */ /* hook up the driver */
udc->driver = driver; udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
udc->gadget.speed = driver->max_speed; udc->gadget.speed = driver->max_speed;
/* Enable IRQ reg and Set usbcmd reg EN bit */ /* Enable IRQ reg and Set usbcmd reg EN bit */
...@@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget, ...@@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
nuke(loop_ep, -ESHUTDOWN); nuke(loop_ep, -ESHUTDOWN);
spin_unlock_irqrestore(&udc->lock, flags); spin_unlock_irqrestore(&udc->lock, flags);
udc->gadget.dev.driver = NULL;
udc->driver = NULL; udc->driver = NULL;
dev_info(udc->dev, "unregistered gadget driver '%s'\r\n", dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
...@@ -2523,12 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev) ...@@ -2523,12 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev)
/* name: Identifies the controller hardware type. */ /* name: Identifies the controller hardware type. */
udc->gadget.name = driver_name; 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; udc->gadget.dev.parent = &ofdev->dev;
/* initialize qe_ep struct */ /* initialize qe_ep struct */
...@@ -2592,22 +2584,17 @@ static int qe_udc_probe(struct platform_device *ofdev) ...@@ -2592,22 +2584,17 @@ static int qe_udc_probe(struct platform_device *ofdev)
goto err5; goto err5;
} }
ret = device_add(&udc->gadget.dev); ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
qe_udc_release);
if (ret) if (ret)
goto err6; goto err6;
ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget);
if (ret)
goto err7;
dev_set_drvdata(&ofdev->dev, udc); dev_set_drvdata(&ofdev->dev, udc);
dev_info(udc->dev, dev_info(udc->dev,
"%s USB controller initialized as device\n", "%s USB controller initialized as device\n",
(udc->soc_type == PORT_QE) ? "QE" : "CPM"); (udc->soc_type == PORT_QE) ? "QE" : "CPM");
return 0; return 0;
err7:
device_unregister(&udc->gadget.dev);
err6: err6:
free_irq(udc->usb_irq, udc); free_irq(udc->usb_irq, udc);
err5: err5:
...@@ -2702,7 +2689,6 @@ static int qe_udc_remove(struct platform_device *ofdev) ...@@ -2702,7 +2689,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
iounmap(udc->usb_regs); iounmap(udc->usb_regs);
device_unregister(&udc->gadget.dev);
/* wait for release() of gadget.dev to free udc */ /* wait for release() of gadget.dev to free udc */
wait_for_completion(&done); wait_for_completion(&done);
......
此差异已折叠。
...@@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep) ...@@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
if (reg & FUSB300_EPSET0_STL) { if (reg & FUSB300_EPSET0_STL) {
printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep); 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)); iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
} }
} }
...@@ -930,33 +930,33 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep) ...@@ -930,33 +930,33 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0, fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
FUSB300_IGR0_EPn_PRD_INT(ep->epnum)); FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
return;
IDMA_RESET: IDMA_RESET:
fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0, reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0);
FUSB300_IGER0_EEPn_PRD_INT(ep->epnum)); 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) 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)) { ret = usb_gadget_map_request(&ep->fusb300->gadget,
printk(KERN_DEBUG "dma_mapping_error\n"); &req->req, DMA_TO_DEVICE);
if (ret)
return; return;
}
dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0, fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
FUSB300_IGER0_EEPn_PRD_INT(ep->epnum)); 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 */ /* check idma is done */
fusb300_wait_idma_finished(ep); 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) static void in_ep_fifo_handler(struct fusb300_ep *ep)
...@@ -1316,7 +1316,6 @@ static int fusb300_udc_start(struct usb_gadget *g, ...@@ -1316,7 +1316,6 @@ static int fusb300_udc_start(struct usb_gadget *g,
/* hook up the driver */ /* hook up the driver */
driver->driver.bus = NULL; driver->driver.bus = NULL;
fusb300->driver = driver; fusb300->driver = driver;
fusb300->gadget.dev.driver = &driver->driver;
return 0; return 0;
} }
...@@ -1327,7 +1326,6 @@ static int fusb300_udc_stop(struct usb_gadget *g, ...@@ -1327,7 +1326,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
struct fusb300 *fusb300 = to_fusb300(g); struct fusb300 *fusb300 = to_fusb300(g);
driver->unbind(&fusb300->gadget); driver->unbind(&fusb300->gadget);
fusb300->gadget.dev.driver = NULL;
init_controller(fusb300); init_controller(fusb300);
fusb300->driver = NULL; fusb300->driver = NULL;
...@@ -1422,14 +1420,7 @@ static int __init fusb300_probe(struct platform_device *pdev) ...@@ -1422,14 +1420,7 @@ static int __init fusb300_probe(struct platform_device *pdev)
fusb300->gadget.ops = &fusb300_gadget_ops; 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.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->gadget.name = udc_name;
fusb300->reg = reg; fusb300->reg = reg;
...@@ -1478,19 +1469,10 @@ static int __init fusb300_probe(struct platform_device *pdev) ...@@ -1478,19 +1469,10 @@ static int __init fusb300_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err_add_udc; 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); dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
return 0; return 0;
err_add_device:
usb_del_gadget_udc(&fusb300->gadget);
err_add_udc: err_add_udc:
fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req); fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
......
...@@ -111,8 +111,8 @@ ...@@ -111,8 +111,8 @@
/* /*
* * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 ) * * 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_CLRSEQNUM (1 << 2)
#define FUSB300_EPSET0_EPn_TX0BYTE (1 << 1)
#define FUSB300_EPSET0_STL (1 << 0) #define FUSB300_EPSET0_STL (1 << 0)
/* /*
......
此差异已折叠。
此差异已折叠。
...@@ -250,8 +250,7 @@ struct goku_udc { ...@@ -250,8 +250,7 @@ struct goku_udc {
got_region:1, got_region:1,
req_config:1, req_config:1,
configured:1, configured:1,
enabled:1, enabled:1;
registered:1;
/* pci state used to access those endpoints */ /* pci state used to access those endpoints */
struct pci_dev *pdev; struct pci_dev *pdev;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册