From 1f0972f5b05a674d73e4eb314fa1b6c78e37aef1 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 12 Mar 2013 13:24:19 +0200 Subject: [PATCH 001/303] usb: phy: nop: Add some parameters to platform data Add clk_rate parameter to platform data. If supplied, the NOP phy driver will program the clock to that rate during probe. Also add 2 flags, needs_vcc and needs_reset. If the flag is set and the regulator couldn't be found then the driver will bail out with -EPROBE_DEFER. Signed-off-by: Roger Quadros Acked-by: Felipe Balbi Signed-off-by: Felipe Balbi --- include/linux/usb/nop-usb-xceiv.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/usb/nop-usb-xceiv.h b/include/linux/usb/nop-usb-xceiv.h index 28884c717411..148d35171aac 100644 --- a/include/linux/usb/nop-usb-xceiv.h +++ b/include/linux/usb/nop-usb-xceiv.h @@ -5,6 +5,11 @@ struct nop_usb_xceiv_platform_data { enum usb_phy_type type; + unsigned long clk_rate; + + /* if set fails with -EPROBE_DEFER if can't get regulator */ + unsigned int needs_vcc:1; + unsigned int needs_reset:1; }; #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE)) From e4d7dc6674efd798792adbd689986cde5422aa62 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 12 Mar 2013 13:24:20 +0200 Subject: [PATCH 002/303] usb: phy: nop: use devm_kzalloc() Use resource managed kzalloc. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/otg/nop-usb-xceiv.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index a3ce24b94a73..af52870788ec 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -100,15 +100,14 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; - nop = kzalloc(sizeof *nop, GFP_KERNEL); + nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL); if (!nop) return -ENOMEM; - nop->phy.otg = kzalloc(sizeof *nop->phy.otg, GFP_KERNEL); - if (!nop->phy.otg) { - kfree(nop); + nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg), + GFP_KERNEL); + if (!nop->phy.otg) return -ENOMEM; - } if (pdata) type = pdata->type; @@ -127,7 +126,7 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "can't register transceiver, err: %d\n", err); - goto exit; + return err; } platform_set_drvdata(pdev, nop); @@ -135,10 +134,6 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier); return 0; -exit: - kfree(nop->phy.otg); - kfree(nop); - return err; } static int nop_usb_xceiv_remove(struct platform_device *pdev) @@ -148,8 +143,6 @@ static int nop_usb_xceiv_remove(struct platform_device *pdev) usb_remove_phy(&nop->phy); platform_set_drvdata(pdev, NULL); - kfree(nop->phy.otg); - kfree(nop); return 0; } From 2319fb88e16e56c64d4f3ab50af69ed6dadbc7b5 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 12 Mar 2013 13:24:21 +0200 Subject: [PATCH 003/303] usb: phy: nop: Manage PHY clock If the PHY has a clock associated to it then manage the clock. We just enable the clock in .init() and disable it in .shutdown(). Add clk_rate parameter in platform data and configure the clock rate during probe if supplied. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/otg/nop-usb-xceiv.c | 54 ++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index af52870788ec..17c174f18da7 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -32,10 +32,12 @@ #include #include #include +#include struct nop_usb_xceiv { struct usb_phy phy; struct device *dev; + struct clk *clk; }; static struct platform_device *pd; @@ -64,6 +66,24 @@ static int nop_set_suspend(struct usb_phy *x, int suspend) return 0; } +static int nop_init(struct usb_phy *phy) +{ + struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev); + + if (!IS_ERR(nop->clk)) + clk_enable(nop->clk); + + return 0; +} + +static void nop_shutdown(struct usb_phy *phy) +{ + struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev); + + if (!IS_ERR(nop->clk)) + clk_disable(nop->clk); +} + static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { if (!otg) @@ -112,10 +132,34 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) if (pdata) type = pdata->type; + nop->clk = devm_clk_get(&pdev->dev, "main_clk"); + if (IS_ERR(nop->clk)) { + dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n", + PTR_ERR(nop->clk)); + } + + if (!IS_ERR(nop->clk) && pdata && pdata->clk_rate) { + err = clk_set_rate(nop->clk, pdata->clk_rate); + if (err) { + dev_err(&pdev->dev, "Error setting clock rate\n"); + return err; + } + } + + if (!IS_ERR(nop->clk)) { + err = clk_prepare(nop->clk); + if (err) { + dev_err(&pdev->dev, "Error preparing clock\n"); + return err; + } + } + nop->dev = &pdev->dev; nop->phy.dev = nop->dev; nop->phy.label = "nop-xceiv"; nop->phy.set_suspend = nop_set_suspend; + nop->phy.init = nop_init; + nop->phy.shutdown = nop_shutdown; nop->phy.state = OTG_STATE_UNDEFINED; nop->phy.otg->phy = &nop->phy; @@ -126,7 +170,7 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "can't register transceiver, err: %d\n", err); - return err; + goto err_add; } platform_set_drvdata(pdev, nop); @@ -134,12 +178,20 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier); return 0; + +err_add: + if (!IS_ERR(nop->clk)) + clk_unprepare(nop->clk); + return err; } static int nop_usb_xceiv_remove(struct platform_device *pdev) { struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); + if (!IS_ERR(nop->clk)) + clk_unprepare(nop->clk); + usb_remove_phy(&nop->phy); platform_set_drvdata(pdev, NULL); From 58f735fe4778d34d9d1e37bcdd59325d66a8793e Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 12 Mar 2013 13:24:22 +0200 Subject: [PATCH 004/303] usb: phy: nop: Handle power supply regulator for the PHY We use "vcc" as the supply name for the PHY's power supply. The power supply will be enabled during .init() and disabled during .shutdown() Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/otg/nop-usb-xceiv.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index 17c174f18da7..fbdcfef7169b 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -33,11 +33,13 @@ #include #include #include +#include struct nop_usb_xceiv { struct usb_phy phy; struct device *dev; struct clk *clk; + struct regulator *vcc; }; static struct platform_device *pd; @@ -70,6 +72,11 @@ static int nop_init(struct usb_phy *phy) { struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev); + if (!IS_ERR(nop->vcc)) { + if (regulator_enable(nop->vcc)) + dev_err(phy->dev, "Failed to enable power\n"); + } + if (!IS_ERR(nop->clk)) clk_enable(nop->clk); @@ -82,6 +89,11 @@ static void nop_shutdown(struct usb_phy *phy) if (!IS_ERR(nop->clk)) clk_disable(nop->clk); + + if (!IS_ERR(nop->vcc)) { + if (regulator_disable(nop->vcc)) + dev_err(phy->dev, "Failed to disable power\n"); + } } static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) @@ -154,6 +166,12 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) } } + nop->vcc = devm_regulator_get(&pdev->dev, "vcc"); + if (IS_ERR(nop->vcc)) { + dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n", + PTR_ERR(nop->vcc)); + } + nop->dev = &pdev->dev; nop->phy.dev = nop->dev; nop->phy.label = "nop-xceiv"; From ad63ebfc3565bbdec87ee4e30e4d40d164c1d3b8 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 12 Mar 2013 13:24:23 +0200 Subject: [PATCH 005/303] usb: phy: nop: Handle RESET for the PHY We expect the RESET line to be modeled as a regulator with supply name "reset". The regulator should be modeled such that enabling the regulator brings the PHY device out of RESET and disabling the regulator holds the device in RESET. They PHY will be held in RESET in .shutdown() and brought out of RESET in .init(). Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/otg/nop-usb-xceiv.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index fbdcfef7169b..6efc9b793333 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -40,6 +40,7 @@ struct nop_usb_xceiv { struct device *dev; struct clk *clk; struct regulator *vcc; + struct regulator *reset; }; static struct platform_device *pd; @@ -80,6 +81,12 @@ static int nop_init(struct usb_phy *phy) if (!IS_ERR(nop->clk)) clk_enable(nop->clk); + if (!IS_ERR(nop->reset)) { + /* De-assert RESET */ + if (regulator_enable(nop->reset)) + dev_err(phy->dev, "Failed to de-assert reset\n"); + } + return 0; } @@ -87,6 +94,12 @@ static void nop_shutdown(struct usb_phy *phy) { struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev); + if (!IS_ERR(nop->reset)) { + /* Assert RESET */ + if (regulator_disable(nop->reset)) + dev_err(phy->dev, "Failed to assert reset\n"); + } + if (!IS_ERR(nop->clk)) clk_disable(nop->clk); @@ -172,6 +185,12 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) PTR_ERR(nop->vcc)); } + nop->reset = devm_regulator_get(&pdev->dev, "reset"); + if (IS_ERR(nop->reset)) { + dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n", + PTR_ERR(nop->reset)); + } + nop->dev = &pdev->dev; nop->phy.dev = nop->dev; nop->phy.label = "nop-xceiv"; From 90f4232f31f087f86667da03b1a4f3c90a32cb4a Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 12 Mar 2013 13:24:24 +0200 Subject: [PATCH 006/303] usb: phy: nop: use new PHY API to register PHY We would need to support multiple PHYs of the same type so use the new PHY API usb_add_phy_dev() to register the PHY. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/otg/nop-usb-xceiv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index 6efc9b793333..fe7a46001854 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -198,12 +198,13 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) nop->phy.init = nop_init; nop->phy.shutdown = nop_shutdown; nop->phy.state = OTG_STATE_UNDEFINED; + nop->phy.type = type; nop->phy.otg->phy = &nop->phy; nop->phy.otg->set_host = nop_set_host; nop->phy.otg->set_peripheral = nop_set_peripheral; - err = usb_add_phy(&nop->phy, type); + err = usb_add_phy_dev(&nop->phy); if (err) { dev_err(&pdev->dev, "can't register transceiver, err: %d\n", err); From 0eba387973f521e57f00584e5e840e5328a61dda Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 12 Mar 2013 13:24:25 +0200 Subject: [PATCH 007/303] usb: phy: nop: Add device tree support and binding information The PHY clock, clock rate, VCC regulator and RESET regulator can now be provided via device tree. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/usb-nop-xceiv.txt | 34 ++++++++++++++++++ drivers/usb/otg/nop-usb-xceiv.c | 35 ++++++++++++++----- 2 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt diff --git a/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt new file mode 100644 index 000000000000..d7e272671c7e --- /dev/null +++ b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt @@ -0,0 +1,34 @@ +USB NOP PHY + +Required properties: +- compatible: should be usb-nop-xceiv + +Optional properties: +- clocks: phandle to the PHY clock. Use as per Documentation/devicetree + /bindings/clock/clock-bindings.txt + This property is required if clock-frequency is specified. + +- clock-names: Should be "main_clk" + +- clock-frequency: the clock frequency (in Hz) that the PHY clock must + be configured to. + +- vcc-supply: phandle to the regulator that provides RESET to the PHY. + +- reset-supply: phandle to the regulator that provides power to the PHY. + +Example: + + hsusb1_phy { + compatible = "usb-nop-xceiv"; + clock-frequency = <19200000>; + clocks = <&osc 0>; + clock-names = "main_clk"; + vcc-supply = <&hsusb1_vcc_regulator>; + reset-supply = <&hsusb1_reset_regulator>; + }; + +hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator +and expects that clock to be configured to 19.2MHz by the NOP PHY driver. +hsusb1_vcc_regulator provides power to the PHY and hsusb1_reset_regulator +controls RESET. diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index fe7a46001854..b26b1c29194e 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -34,13 +34,14 @@ #include #include #include +#include struct nop_usb_xceiv { - struct usb_phy phy; - struct device *dev; - struct clk *clk; - struct regulator *vcc; - struct regulator *reset; + struct usb_phy phy; + struct device *dev; + struct clk *clk; + struct regulator *vcc; + struct regulator *reset; }; static struct platform_device *pd; @@ -140,10 +141,12 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) static int nop_usb_xceiv_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data; struct nop_usb_xceiv *nop; enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; + u32 clk_rate = 0; nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL); if (!nop) @@ -154,8 +157,16 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) if (!nop->phy.otg) return -ENOMEM; - if (pdata) + if (dev->of_node) { + struct device_node *node = dev->of_node; + + if (of_property_read_u32(node, "clock-frequency", &clk_rate)) + clk_rate = 0; + + } else if (pdata) { type = pdata->type; + clk_rate = pdata->clk_rate; + } nop->clk = devm_clk_get(&pdev->dev, "main_clk"); if (IS_ERR(nop->clk)) { @@ -163,8 +174,8 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) PTR_ERR(nop->clk)); } - if (!IS_ERR(nop->clk) && pdata && pdata->clk_rate) { - err = clk_set_rate(nop->clk, pdata->clk_rate); + if (!IS_ERR(nop->clk) && clk_rate) { + err = clk_set_rate(nop->clk, clk_rate); if (err) { dev_err(&pdev->dev, "Error setting clock rate\n"); return err; @@ -237,12 +248,20 @@ static int nop_usb_xceiv_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id nop_xceiv_dt_ids[] = { + { .compatible = "usb-nop-xceiv" }, + { } +}; + +MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids); + static struct platform_driver nop_usb_xceiv_driver = { .probe = nop_usb_xceiv_probe, .remove = nop_usb_xceiv_remove, .driver = { .name = "nop_usb_xceiv", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(nop_xceiv_dt_ids), }, }; From b54b5f56531d9fcbb30908373ba842af4de6a26b Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 12 Mar 2013 13:24:26 +0200 Subject: [PATCH 008/303] USB: phy: nop: Defer probe if device needs VCC/RESET Add 2 flags, needs_vcc and needs_reset to platform data. If the flag is set and the regulator couldn't be found then we bail out with -EPROBE_DEFER. For device tree boot we depend on presensce of vcc-supply/ reset-supply properties to decide if we should bail out with -EPROBE_DEFER or just continue in case the regulator can't be found. This is required for proper functionality in cases where the regulator is needed but is probed later than the PHY device. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/otg/nop-usb-xceiv.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index b26b1c29194e..2b10cc969bbb 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -147,6 +147,8 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; u32 clk_rate = 0; + bool needs_vcc = false; + bool needs_reset = false; nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL); if (!nop) @@ -163,9 +165,14 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) if (of_property_read_u32(node, "clock-frequency", &clk_rate)) clk_rate = 0; + needs_vcc = of_property_read_bool(node, "vcc-supply"); + needs_reset = of_property_read_bool(node, "reset-supply"); + } else if (pdata) { type = pdata->type; clk_rate = pdata->clk_rate; + needs_vcc = pdata->needs_vcc; + needs_reset = pdata->needs_reset; } nop->clk = devm_clk_get(&pdev->dev, "main_clk"); @@ -194,12 +201,16 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev) if (IS_ERR(nop->vcc)) { dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n", PTR_ERR(nop->vcc)); + if (needs_vcc) + return -EPROBE_DEFER; } nop->reset = devm_regulator_get(&pdev->dev, "reset"); if (IS_ERR(nop->reset)) { dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n", PTR_ERR(nop->reset)); + if (needs_reset) + return -EPROBE_DEFER; } nop->dev = &pdev->dev; From e36a0c870f7dbbfa7ed13cd83b79be00bcd00380 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 26 Feb 2013 20:03:27 +0530 Subject: [PATCH 009/303] usb: dwc3: omap: minor fixes to get dt working Includes few minor fixes in dwc3-omap like populating the compatible string in a correct way, extracting the utmi-mode property properly and changing the index of get_irq since irq of core is removed from hwmod entry. Also updated the documentation with dwc3-omap device tree binding information. Signed-off-by: Kishon Vijay Abraham I [ balbi@ti.com : fix a compile warning introduced by this commit ] Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/omap-usb.txt | 28 ++++++++++++ drivers/usb/dwc3/dwc3-omap.c | 45 +++++++++---------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt index 1ef0ce71f8fa..1b9f55fd96c0 100644 --- a/Documentation/devicetree/bindings/usb/omap-usb.txt +++ b/Documentation/devicetree/bindings/usb/omap-usb.txt @@ -41,6 +41,34 @@ Board specific device node entry power = <50>; }; +OMAP DWC3 GLUE + - compatible : Should be "ti,dwc3" + - ti,hwmods : Should be "usb_otg_ss" + - reg : Address and length of the register set for the device. + - interrupts : The irq number of this device that is used to interrupt the + MPU + - #address-cells, #size-cells : Must be present if the device has sub-nodes + - utmi-mode : controls the source of UTMI/PIPE status for VBUS and OTG ID. + It should be set to "1" for HW mode and "2" for SW mode. + - ranges: the child address space are mapped 1:1 onto the parent address space + +Sub-nodes: +The dwc3 core should be added as subnode to omap dwc3 glue. +- dwc3 : + The binding details of dwc3 can be found in: + Documentation/devicetree/bindings/usb/dwc3.txt + +omap_dwc3 { + compatible = "ti,dwc3"; + ti,hwmods = "usb_otg_ss"; + reg = <0x4a020000 0x1ff>; + interrupts = <0 93 4>; + #address-cells = <1>; + #size-cells = <1>; + utmi-mode = <2>; + ranges; +}; + OMAP CONTROL USB Required properties: diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index afa05e3c9cf4..e1206b419932 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -316,11 +316,11 @@ static int dwc3_omap_probe(struct platform_device *pdev) struct resource *res; struct device *dev = &pdev->dev; - int size; int ret = -ENOMEM; int irq; - const u32 *utmi_mode; + int utmi_mode = 0; + u32 reg; void __iomem *base; @@ -334,13 +334,13 @@ static int dwc3_omap_probe(struct platform_device *pdev) platform_set_drvdata(pdev, omap); - irq = platform_get_irq(pdev, 1); + irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "missing IRQ resource\n"); return -EINVAL; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory base resource\n"); return -EINVAL; @@ -387,25 +387,22 @@ static int dwc3_omap_probe(struct platform_device *pdev) reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); - utmi_mode = of_get_property(node, "utmi-mode", &size); - if (utmi_mode && size == sizeof(*utmi_mode)) { - reg |= *utmi_mode; - } else { - if (!pdata) { - dev_dbg(dev, "missing platform data\n"); - } else { - switch (pdata->utmi_mode) { - case DWC3_OMAP_UTMI_MODE_SW: - reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - case DWC3_OMAP_UTMI_MODE_HW: - reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; - break; - default: - dev_dbg(dev, "UNKNOWN utmi mode %d\n", - pdata->utmi_mode); - } - } + if (node) + of_property_read_u32(node, "utmi-mode", &utmi_mode); + else if (pdata) + utmi_mode = pdata->utmi_mode; + else + dev_dbg(dev, "missing platform data\n"); + + switch (utmi_mode) { + case DWC3_OMAP_UTMI_MODE_SW: + reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + case DWC3_OMAP_UTMI_MODE_HW: + reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + default: + dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode); } dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg); @@ -465,7 +462,7 @@ static int dwc3_omap_remove(struct platform_device *pdev) static const struct of_device_id of_dwc3_match[] = { { - "ti,dwc3", + .compatible = "ti,dwc3" }, { }, }; From 4495afcf713adb5bdb16504052952bdd0d11f90a Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 26 Feb 2013 20:03:28 +0530 Subject: [PATCH 010/303] usb: dwc3: omap: remove platform data associated with dwc3-omap omap5 is not going to have support for non-dt boot making the platform data associated with dwc3 useless. Removed it here. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 24 ++++++++++-------------- include/linux/platform_data/dwc3-omap.h | 4 ---- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index e1206b419932..43a248219aae 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -309,7 +309,6 @@ static int dwc3_omap_remove_core(struct device *dev, void *c) 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 dwc3_omap *omap; @@ -326,6 +325,11 @@ static int dwc3_omap_probe(struct platform_device *pdev) 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); if (!omap) { dev_err(dev, "not enough memory\n"); @@ -387,12 +391,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); - if (node) - of_property_read_u32(node, "utmi-mode", &utmi_mode); - else if (pdata) - utmi_mode = pdata->utmi_mode; - else - dev_dbg(dev, "missing platform data\n"); + of_property_read_u32(node, "utmi-mode", &utmi_mode); switch (utmi_mode) { case DWC3_OMAP_UTMI_MODE_SW: @@ -435,13 +434,10 @@ static int dwc3_omap_probe(struct platform_device *pdev) 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; - } + ret = of_platform_populate(node, NULL, NULL, dev); + if (ret) { + dev_err(&pdev->dev, "failed to create dwc3 core\n"); + return ret; } return 0; diff --git a/include/linux/platform_data/dwc3-omap.h b/include/linux/platform_data/dwc3-omap.h index ada401244e0b..1d36ca874cc8 100644 --- a/include/linux/platform_data/dwc3-omap.h +++ b/include/linux/platform_data/dwc3-omap.h @@ -41,7 +41,3 @@ enum dwc3_omap_utmi_mode { DWC3_OMAP_UTMI_MODE_HW, DWC3_OMAP_UTMI_MODE_SW, }; - -struct dwc3_omap_data { - enum dwc3_omap_utmi_mode utmi_mode; -}; From 7eaf8f2a7da6506df0e6edc4fdb22678f0eb3602 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 26 Feb 2013 20:03:29 +0530 Subject: [PATCH 011/303] usb: dwc3: omap: stop using nop-usb-xceiv Now that we have drivers for omap-usb2 phy and omap-usb3 phy, stop using nop-usb-xceiv. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 67 ------------------------------------ 1 file changed, 67 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 43a248219aae..3d343d92548a 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -52,7 +52,6 @@ #include #include -#include /* * All these registers belong to OMAP's Wrapper around the @@ -117,8 +116,6 @@ struct dwc3_omap { /* device lock */ spinlock_t lock; - struct platform_device *usb2_phy; - struct platform_device *usb3_phy; struct device *dev; int irq; @@ -193,60 +190,6 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) } EXPORT_SYMBOL_GPL(dwc3_omap_mailbox); -static int dwc3_omap_register_phys(struct dwc3_omap *omap) -{ - struct nop_usb_xceiv_platform_data pdata; - struct platform_device *pdev; - int ret; - - memset(&pdata, 0x00, sizeof(pdata)); - - pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO); - if (!pdev) - return -ENOMEM; - - omap->usb2_phy = pdev; - pdata.type = USB_PHY_TYPE_USB2; - - ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata)); - if (ret) - goto err1; - - pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO); - if (!pdev) { - ret = -ENOMEM; - goto err1; - } - - omap->usb3_phy = pdev; - pdata.type = USB_PHY_TYPE_USB3; - - ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata)); - if (ret) - goto err2; - - ret = platform_device_add(omap->usb2_phy); - if (ret) - goto err2; - - ret = platform_device_add(omap->usb3_phy); - if (ret) - goto err3; - - return 0; - -err3: - platform_device_del(omap->usb2_phy); - -err2: - platform_device_put(omap->usb3_phy); - -err1: - platform_device_put(omap->usb2_phy); - - return ret; -} - static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) { struct dwc3_omap *omap = _omap; @@ -356,12 +299,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) 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"); @@ -445,10 +382,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) static int dwc3_omap_remove(struct platform_device *pdev) { - struct dwc3_omap *omap = platform_get_drvdata(pdev); - - platform_device_unregister(omap->usb2_phy); - platform_device_unregister(omap->usb3_phy); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); From f07bd56bbdaa2340ebf46af9a37e7b2d1b4578e3 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 14:52:24 +0200 Subject: [PATCH 012/303] usb: gadget: udc-core: allow udc class register gadget device Currently all UDC drivers are calling device_register() before calling usb_add_gadget_udc(). In order to avoid code duplication, we can allow udc-core.c register that device. However that would become a really large patch, so to cope with the meanwhile and allow us to write bite-sized patches, we're adding a flag which will be set by UDC driver once it removes the code for registering the gadget device. Once all are converted, the new flag will be removed. Reviewed-by: Tomasz Figa Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 23 +++++++++++++++++++---- include/linux/usb/gadget.h | 4 ++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 2a9cd369f71c..919505426ec1 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -173,6 +173,14 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) if (!udc) goto err1; + if (gadget->register_my_device) { + dev_set_name(&gadget->dev, "gadget"); + + ret = device_register(&gadget->dev); + if (ret) + goto err2; + } + device_initialize(&udc->dev); udc->dev.release = usb_udc_release; udc->dev.class = udc_class; @@ -180,7 +188,7 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) udc->dev.parent = parent; ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj)); if (ret) - goto err2; + goto err3; udc->gadget = gadget; @@ -189,18 +197,22 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) ret = device_add(&udc->dev); if (ret) - goto err3; + goto err4; mutex_unlock(&udc_lock); return 0; -err3: + +err4: list_del(&udc->list); mutex_unlock(&udc_lock); -err2: +err3: put_device(&udc->dev); +err2: + if (gadget->register_my_device) + put_device(&gadget->dev); err1: return ret; } @@ -254,6 +266,9 @@ found: kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); device_unregister(&udc->dev); + + if (gadget->register_my_device) + device_unregister(&gadget->dev); } EXPORT_SYMBOL_GPL(usb_del_gadget_udc); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 2e297e80d59a..fcd9ef8d3f70 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -494,6 +494,9 @@ struct usb_gadget_ops { * only supports HNP on a different root port. * @b_hnp_enable: OTG device feature flag, indicating that the A-Host * enabled HNP support. + * @register_my_device: Flag telling udc-core that UDC driver didn't + * register the gadget device to the driver model. Temporary until + * all UDC drivers are fixed up properly. * @name: Identifies the controller hardware type. Used in diagnostics * and sometimes configuration. * @dev: Driver model state for this abstract device. @@ -531,6 +534,7 @@ struct usb_gadget { unsigned b_hnp_enable:1; unsigned a_hnp_support:1; unsigned a_alt_hnp_support:1; + unsigned register_my_device:1; const char *name; struct device dev; unsigned out_epnum; From 1e1930bd3d9c6174eba1e3ca4135fd25ea3ad59c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 14:56:26 +0200 Subject: [PATCH 013/303] usb: dwc3: gadget: let udc-core manage gadget->dev We don't need to register that device ourselves if we simply set gadget->register_my_device. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 82e160e96fca..10bb161eec88 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2488,8 +2488,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err3; } - dev_set_name(&dwc->gadget.dev, "gadget"); - dwc->gadget.ops = &dwc3_gadget_ops; dwc->gadget.max_speed = USB_SPEED_SUPER; dwc->gadget.speed = USB_SPEED_UNKNOWN; @@ -2501,6 +2499,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) 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.register_my_device = true; dwc->gadget.name = "dwc3-gadget"; /* @@ -2544,24 +2543,14 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc3_gadget_usb3_phy_suspend(dwc, false); } - ret = device_register(&dwc->gadget.dev); - if (ret) { - dev_err(dwc->dev, "failed to register gadget device\n"); - put_device(&dwc->gadget.dev); - goto err6; - } - ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { dev_err(dwc->dev, "failed to register udc\n"); - goto err7; + goto err6; } return 0; -err7: - device_unregister(&dwc->gadget.dev); - err6: dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); free_irq(irq, dwc); @@ -2610,6 +2599,4 @@ void dwc3_gadget_exit(struct dwc3 *dwc) dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), dwc->ctrl_req, dwc->ctrl_req_addr); - - device_unregister(&dwc->gadget.dev); } From 5ed01c6400270dccb8c3574061ff3d163f0fe3fe Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 15:03:59 +0200 Subject: [PATCH 014/303] usb: musb: gadget: let udc-core manage gadget-dev By simply setting a flag, we can delete a little boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index be18537c5f14..cadb750921e9 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1887,12 +1887,11 @@ int musb_gadget_setup(struct musb *musb) musb->g.speed = USB_SPEED_UNKNOWN; /* this "gadget" abstracts/virtualizes the controller */ - dev_set_name(&musb->g.dev, "gadget"); musb->g.dev.parent = musb->controller; musb->g.dev.dma_mask = musb->controller->dma_mask; musb->g.dev.release = musb_gadget_release; musb->g.name = musb_driver_name; - + musb->g.register_my_device = true; musb->g.is_otg = 1; musb_g_init_endpoints(musb); @@ -1900,11 +1899,6 @@ int musb_gadget_setup(struct musb *musb) musb->is_active = 0; musb_platform_try_idle(musb, 0); - status = device_register(&musb->g.dev); - if (status != 0) { - put_device(&musb->g.dev); - return status; - } status = usb_add_gadget_udc(musb->controller, &musb->g); if (status) goto err; @@ -1919,8 +1913,6 @@ err: void musb_gadget_cleanup(struct musb *musb) { usb_del_gadget_udc(&musb->g); - if (musb->g.dev.parent) - device_unregister(&musb->g.dev); } /* From 6dfc84fcb6eb32621c557e64f7520be27c0d636a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 15:07:29 +0200 Subject: [PATCH 015/303] usb: gadget: omap_udc: let udc-core manage gadget->dev By simply setting a flag, we drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index f8445653577f..c979272e7c86 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2632,10 +2632,9 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) udc->gadget.max_speed = USB_SPEED_FULL; udc->gadget.name = driver_name; - device_initialize(&udc->gadget.dev); - dev_set_name(&udc->gadget.dev, "gadget"); udc->gadget.dev.release = omap_udc_release; udc->gadget.dev.parent = &odev->dev; + udc->gadget.register_my_device = true; if (use_dma) udc->gadget.dev.dma_mask = odev->dev.dma_mask; @@ -2912,14 +2911,12 @@ bad_on_1710: } create_proc_file(); - status = device_add(&udc->gadget.dev); + status = usb_add_gadget_udc(&pdev->dev, &udc->gadget); if (status) goto cleanup4; - status = usb_add_gadget_udc(&pdev->dev, &udc->gadget); - if (!status) - return status; - /* If fail, fall through */ + return 0; + cleanup4: remove_proc_file(); @@ -2990,7 +2987,6 @@ static int omap_udc_remove(struct platform_device *pdev) release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); - device_unregister(&udc->gadget.dev); wait_for_completion(&done); return 0; From 12ad0fcaf2fbf3f48dd2b4dbaff372830aada8a2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 15:10:10 +0200 Subject: [PATCH 016/303] usb: gadget: amd5536udc: let udc-core manage gadget->dev By simply setting a flag, we drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 75973f33a4c8..eee01ea70f8c 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3080,7 +3080,6 @@ static void udc_pci_remove(struct pci_dev *pdev) if (dev->active) pci_disable_device(pdev); - device_unregister(&dev->gadget.dev); pci_set_drvdata(pdev, NULL); udc_remove(dev); @@ -3276,6 +3275,7 @@ static int udc_probe(struct udc *dev) dev->gadget.dev.release = gadget_release; dev->gadget.name = name; dev->gadget.max_speed = USB_SPEED_HIGH; + dev->gadget.register_my_device = true; /* init registers, interrupts, ... */ startup_registers(dev); @@ -3301,13 +3301,6 @@ static int udc_probe(struct udc *dev) if (retval) goto finished; - retval = device_register(&dev->gadget.dev); - if (retval) { - usb_del_gadget_udc(&dev->gadget); - put_device(&dev->gadget.dev); - goto finished; - } - /* timer init */ init_timer(&udc_timer); udc_timer.function = udc_timer_function; From 2533beea9025254215be65cd1fca8da65019fd04 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 15:15:30 +0200 Subject: [PATCH 017/303] usb: gadget: at91_udc: let udc-core manage gadget->dev By simply setting a flag, we can remove some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 45dd2929a671..47b7e58f8415 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1726,6 +1726,7 @@ static int at91udc_probe(struct platform_device *pdev) /* init software state */ udc = &controller; + udc->gadget.register_my_device = true; udc->gadget.dev.parent = dev; if (pdev->dev.of_node) at91udc_of_init(udc, pdev->dev.of_node); @@ -1780,13 +1781,7 @@ static int at91udc_probe(struct platform_device *pdev) DBG("clocks missing\n"); retval = -ENODEV; /* NOTE: we "know" here that refcounts on these are NOPs */ - goto fail0b; - } - - retval = device_register(&udc->gadget.dev); - if (retval < 0) { - put_device(&udc->gadget.dev); - goto fail0b; + goto fail1; } /* don't do anything until we have both gadget driver and VBUS */ @@ -1857,8 +1852,6 @@ fail3: fail2: free_irq(udc->udp_irq, udc); fail1: - device_unregister(&udc->gadget.dev); -fail0b: iounmap(udc->udp_baseaddr); fail0a: if (cpu_is_at91rm9200()) @@ -1892,8 +1885,6 @@ static int __exit at91udc_remove(struct platform_device *pdev) gpio_free(udc->board.vbus_pin); } free_irq(udc->udp_irq, udc); - device_unregister(&udc->gadget.dev); - iounmap(udc->udp_baseaddr); if (cpu_is_at91rm9200()) From 621c723eb71d2f02baafe20a3eaefc3a4dec7788 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 15:21:36 +0200 Subject: [PATCH 018/303] usb: gadget: atmel_usba_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/atmel_usba_udc.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index b66130c97269..2404d0c25668 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1900,9 +1900,9 @@ static int __init usba_udc_probe(struct platform_device *pdev) dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n", (unsigned long)fifo->start, udc->fifo); - device_initialize(&udc->gadget.dev); udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = pdev->dev.dma_mask; + udc->gadget.register_my_device = true; platform_set_drvdata(pdev, udc); @@ -1962,12 +1962,6 @@ static int __init usba_udc_probe(struct platform_device *pdev) } udc->irq = irq; - ret = device_add(&udc->gadget.dev); - if (ret) { - dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret); - goto err_device_add; - } - if (gpio_is_valid(pdata->vbus_pin)) { if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) { udc->vbus_pin = pdata->vbus_pin; @@ -2007,9 +2001,6 @@ err_add_udc: gpio_free(udc->vbus_pin); } - device_unregister(&udc->gadget.dev); - -err_device_add: free_irq(irq, udc); err_request_irq: kfree(usba_ep); @@ -2053,8 +2044,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev) clk_put(udc->hclk); clk_put(udc->pclk); - device_unregister(&udc->gadget.dev); - return 0; } From 9b4ead05e7a3abf350d4ca1f7e0b71dc44f07f57 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:09:06 +0200 Subject: [PATCH 019/303] usb: gadget: bcm63xx_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/bcm63xx_udc.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index 8cc8253f1100..c020b877219d 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -2368,13 +2368,13 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) spin_lock_init(&udc->lock); INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process); - dev_set_name(&udc->gadget.dev, "gadget"); udc->gadget.ops = &bcm63xx_udc_ops; udc->gadget.name = dev_name(dev); udc->gadget.dev.parent = dev; udc->gadget.dev.release = bcm63xx_udc_gadget_release; udc->gadget.dev.dma_mask = dev->dma_mask; + udc->gadget.register_my_device = true; if (!pd->use_fullspeed && !use_fullspeed) udc->gadget.max_speed = USB_SPEED_HIGH; @@ -2414,17 +2414,12 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) } } - rc = device_register(&udc->gadget.dev); - if (rc) - goto out_uninit; - bcm63xx_udc_init_debugfs(udc); rc = usb_add_gadget_udc(dev, &udc->gadget); if (!rc) return 0; bcm63xx_udc_cleanup_debugfs(udc); - device_unregister(&udc->gadget.dev); out_uninit: bcm63xx_uninit_udc_hw(udc); return rc; @@ -2440,7 +2435,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev) bcm63xx_udc_cleanup_debugfs(udc); usb_del_gadget_udc(&udc->gadget); - device_unregister(&udc->gadget.dev); BUG_ON(udc->driver); platform_set_drvdata(pdev, NULL); From 002cb13f4a6f3c28510575922a226a7a09ab6e91 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:10:16 +0200 Subject: [PATCH 020/303] usb: gadget: dummy_hcd: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 8cf0c0f6fa1f..a6950aa8f3be 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -983,16 +983,10 @@ static int dummy_udc_probe(struct platform_device *pdev) dum->gadget.name = gadget_name; dum->gadget.ops = &dummy_ops; dum->gadget.max_speed = USB_SPEED_SUPER; + dum->gadget.register_my_device = true; - dev_set_name(&dum->gadget.dev, "gadget"); dum->gadget.dev.parent = &pdev->dev; dum->gadget.dev.release = dummy_gadget_release; - rc = device_register(&dum->gadget.dev); - if (rc < 0) { - put_device(&dum->gadget.dev); - return rc; - } - init_dummy_udc_hw(dum); rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget); @@ -1008,7 +1002,6 @@ static int dummy_udc_probe(struct platform_device *pdev) err_dev: usb_del_gadget_udc(&dum->gadget); err_udc: - device_unregister(&dum->gadget.dev); return rc; } @@ -1019,7 +1012,6 @@ static int dummy_udc_remove(struct platform_device *pdev) usb_del_gadget_udc(&dum->gadget); platform_set_drvdata(pdev, NULL); device_remove_file(&dum->gadget.dev, &dev_attr_function); - device_unregister(&dum->gadget.dev); return 0; } From c07d1b63ac3c5f18f07739a8736633dd6998c944 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:11:38 +0200 Subject: [PATCH 021/303] usb: gadget: fsl_qe_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_qe_udc.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 034477ce77c6..0f78cd859d68 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2523,13 +2523,9 @@ static int qe_udc_probe(struct platform_device *ofdev) /* name: Identifies the controller hardware type. */ udc->gadget.name = driver_name; - - device_initialize(&udc->gadget.dev); - - dev_set_name(&udc->gadget.dev, "gadget"); - udc->gadget.dev.release = qe_udc_release; udc->gadget.dev.parent = &ofdev->dev; + udc->gadget.register_my_device = true; /* initialize qe_ep struct */ for (i = 0; i < USB_MAX_ENDPOINTS ; i++) { @@ -2592,13 +2588,9 @@ static int qe_udc_probe(struct platform_device *ofdev) goto err5; } - ret = device_add(&udc->gadget.dev); - if (ret) - goto err6; - ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget); if (ret) - goto err7; + goto err6; dev_set_drvdata(&ofdev->dev, udc); dev_info(udc->dev, @@ -2606,8 +2598,6 @@ static int qe_udc_probe(struct platform_device *ofdev) (udc->soc_type == PORT_QE) ? "QE" : "CPM"); return 0; -err7: - device_unregister(&udc->gadget.dev); err6: free_irq(udc->usb_irq, udc); err5: @@ -2702,7 +2692,6 @@ static int qe_udc_remove(struct platform_device *ofdev) iounmap(udc->usb_regs); - device_unregister(&udc->gadget.dev); /* wait for release() of gadget.dev to free udc */ wait_for_completion(&done); From eab35c4e6d952c91a413b408635ba6a9ec5fcf41 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:13:20 +0200 Subject: [PATCH 022/303] usb: gadget: fsl_udc_core: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_udc_core.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 04d5fef1440c..9140a2daad87 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2524,9 +2524,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) udc_controller->gadget.dev.release = fsl_udc_release; udc_controller->gadget.dev.parent = &pdev->dev; udc_controller->gadget.dev.of_node = pdev->dev.of_node; - ret = device_register(&udc_controller->gadget.dev); - if (ret < 0) - goto err_free_irq; + udc_controller->gadget.register_my_device = true; if (!IS_ERR_OR_NULL(udc_controller->transceiver)) udc_controller->gadget.is_otg = 1; @@ -2559,7 +2557,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) DTD_ALIGNMENT, UDC_DMA_BOUNDARY); if (udc_controller->td_pool == NULL) { ret = -ENOMEM; - goto err_unregister; + goto err_free_irq; } ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget); @@ -2571,8 +2569,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) err_del_udc: dma_pool_destroy(udc_controller->td_pool); -err_unregister: - device_unregister(&udc_controller->gadget.dev); err_free_irq: free_irq(udc_controller->irq, udc_controller); err_iounmap: @@ -2622,7 +2618,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev) if (pdata->operating_mode == FSL_USB2_DR_DEVICE) release_mem_region(res->start, resource_size(res)); - device_unregister(&udc_controller->gadget.dev); /* free udc --wait for the release() finished */ wait_for_completion(&done); From fc84d2fbe776f5352c3a981a5250a3ad83789f72 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:14:45 +0200 Subject: [PATCH 023/303] usb: gadget: fusb300_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fusb300_udc.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index 066cb89376de..d29017218b01 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -1422,15 +1422,12 @@ static int __init fusb300_probe(struct platform_device *pdev) fusb300->gadget.ops = &fusb300_gadget_ops; - device_initialize(&fusb300->gadget.dev); - - dev_set_name(&fusb300->gadget.dev, "gadget"); - fusb300->gadget.max_speed = USB_SPEED_HIGH; fusb300->gadget.dev.parent = &pdev->dev; fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask; fusb300->gadget.dev.release = pdev->dev.release; fusb300->gadget.name = udc_name; + fusb300->gadget.register_my_device = true; fusb300->reg = reg; ret = request_irq(ires->start, fusb300_irq, IRQF_SHARED, @@ -1478,19 +1475,10 @@ static int __init fusb300_probe(struct platform_device *pdev) if (ret) goto err_add_udc; - ret = device_add(&fusb300->gadget.dev); - if (ret) { - pr_err("device_add error (%d)\n", ret); - goto err_add_device; - } - dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION); return 0; -err_add_device: - usb_del_gadget_udc(&fusb300->gadget); - err_add_udc: fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req); From 5637bf5b7a91804fe0230dff70024df078786090 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:17:45 +0200 Subject: [PATCH 024/303] usb: gadget: goku_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/goku_udc.c | 10 +--------- drivers/usb/gadget/goku_udc.h | 3 +-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 85742d4c67df..b4ea2cf465a6 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1716,8 +1716,6 @@ static void goku_remove(struct pci_dev *pdev) pci_resource_len (pdev, 0)); if (dev->enabled) pci_disable_device(pdev); - if (dev->registered) - device_unregister(&dev->gadget.dev); pci_set_drvdata(pdev, NULL); dev->regs = NULL; @@ -1756,11 +1754,11 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.max_speed = USB_SPEED_FULL; /* the "gadget" abstracts/virtualizes the controller */ - dev_set_name(&dev->gadget.dev, "gadget"); dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; dev->gadget.name = driver_name; + dev->gadget.register_my_device = true; /* now all the pci goodies ... */ retval = pci_enable_device(pdev); @@ -1810,12 +1808,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev); #endif - retval = device_register(&dev->gadget.dev); - if (retval) { - put_device(&dev->gadget.dev); - goto err; - } - dev->registered = 1; retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget); if (retval) goto err; diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h index b4470d2b1d86..86d2adafe149 100644 --- a/drivers/usb/gadget/goku_udc.h +++ b/drivers/usb/gadget/goku_udc.h @@ -250,8 +250,7 @@ struct goku_udc { got_region:1, req_config:1, configured:1, - enabled:1, - registered:1; + enabled:1; /* pci state used to access those endpoints */ struct pci_dev *pdev; From 0b3702c62e41f3707cb8ba68bf46561597a6f0af Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:22:57 +0200 Subject: [PATCH 025/303] usb: gadget: imx_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/imx_udc.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 5bd930d779b9..435b20346ead 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1461,15 +1461,10 @@ static int __init imx_udc_probe(struct platform_device *pdev) imx_usb->clk = clk; imx_usb->dev = &pdev->dev; - device_initialize(&imx_usb->gadget.dev); - + imx_usb->gadget.register_my_device = true; imx_usb->gadget.dev.parent = &pdev->dev; imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask; - ret = device_add(&imx_usb->gadget.dev); - if (retval) - goto fail4; - platform_set_drvdata(pdev, imx_usb); usb_init_data(imx_usb); @@ -1481,11 +1476,9 @@ static int __init imx_udc_probe(struct platform_device *pdev) ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget); if (ret) - goto fail5; + goto fail4; return 0; -fail5: - device_unregister(&imx_usb->gadget.dev); fail4: for (i = 0; i < IMX_USB_NB_EP + 1; i++) free_irq(imx_usb->usbd_int[i], imx_usb); @@ -1509,7 +1502,6 @@ static int __exit imx_udc_remove(struct platform_device *pdev) int i; usb_del_gadget_udc(&imx_usb->gadget); - device_unregister(&imx_usb->gadget.dev); imx_udc_disable(imx_usb); del_timer(&imx_usb->timer); From e0c9e4739a6f9217f35f1a59807a2f19a4cd7cdd Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:26:46 +0200 Subject: [PATCH 026/303] usb: gadget: lpc32xx_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/lpc32xx_udc.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index aa04089d6899..329e1c5f0ef9 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -3090,6 +3090,7 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) /* init software state */ udc->gadget.dev.parent = dev; + udc->gadget.register_my_device = true; udc->pdev = pdev; udc->dev = &pdev->dev; udc->enabled = 0; @@ -3248,12 +3249,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) udc_disable(udc); udc_reinit(udc); - retval = device_register(&udc->gadget.dev); - if (retval < 0) { - dev_err(udc->dev, "Device registration failure\n"); - goto dev_register_fail; - } - /* Request IRQs - low and high priority USB device IRQs are routed to * the same handler, while the DMA interrupt is routed elsewhere */ retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq, @@ -3320,8 +3315,6 @@ irq_dev_fail: irq_hp_fail: free_irq(udc->udp_irq[IRQ_USB_LP], udc); irq_lp_fail: - device_unregister(&udc->gadget.dev); -dev_register_fail: dma_pool_destroy(udc->dd_cache); dma_alloc_fail: dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE, @@ -3376,8 +3369,6 @@ static int lpc32xx_udc_remove(struct platform_device *pdev) free_irq(udc->udp_irq[IRQ_USB_HP], udc); free_irq(udc->udp_irq[IRQ_USB_LP], udc); - device_unregister(&udc->gadget.dev); - clk_disable(udc->usb_otg_clk); clk_put(udc->usb_otg_clk); clk_disable(udc->usb_slv_clk); From 96d20c32f68b058b4430a6f711124511a2d9b361 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:35:12 +0200 Subject: [PATCH 027/303] usb: gadget: m66592-udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/m66592-udc.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index c1b8c2dd808d..43ad70dff74d 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1538,7 +1538,6 @@ static int __exit m66592_remove(struct platform_device *pdev) struct m66592 *m66592 = dev_get_drvdata(&pdev->dev); usb_del_gadget_udc(&m66592->gadget); - device_del(&m66592->gadget.dev); del_timer_sync(&m66592->timer); iounmap(m66592->reg); @@ -1608,13 +1607,12 @@ static int __init m66592_probe(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, m66592); m66592->gadget.ops = &m66592_gadget_ops; - device_initialize(&m66592->gadget.dev); - dev_set_name(&m66592->gadget.dev, "gadget"); m66592->gadget.max_speed = USB_SPEED_HIGH; m66592->gadget.dev.parent = &pdev->dev; m66592->gadget.dev.dma_mask = pdev->dev.dma_mask; m66592->gadget.dev.release = pdev->dev.release; m66592->gadget.name = udc_name; + m66592->gadget.register_my_device = true; init_timer(&m66592->timer); m66592->timer.function = m66592_timer; @@ -1674,12 +1672,6 @@ static int __init m66592_probe(struct platform_device *pdev) init_controller(m66592); - ret = device_add(&m66592->gadget.dev); - if (ret) { - pr_err("device_add error (%d)\n", ret); - goto err_device_add; - } - ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget); if (ret) goto err_add_udc; @@ -1688,9 +1680,6 @@ static int __init m66592_probe(struct platform_device *pdev) return 0; err_add_udc: - device_del(&m66592->gadget.dev); - -err_device_add: m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req); clean_up3: From 7a071890b467e3b820b6afb13f2a877a249ae8f9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:37:24 +0200 Subject: [PATCH 028/303] usb: gadget: mv_u3d_core: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index b5cea273c957..565addcd3956 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -1792,8 +1792,6 @@ static int mv_u3d_remove(struct platform_device *dev) clk_put(u3d->clk); - device_unregister(&u3d->gadget.dev); - platform_set_drvdata(dev, NULL); kfree(u3d); @@ -1957,15 +1955,11 @@ static int mv_u3d_probe(struct platform_device *dev) u3d->gadget.speed = USB_SPEED_UNKNOWN; /* speed */ /* the "gadget" abstracts/virtualizes the controller */ - dev_set_name(&u3d->gadget.dev, "gadget"); u3d->gadget.dev.parent = &dev->dev; u3d->gadget.dev.dma_mask = dev->dev.dma_mask; u3d->gadget.dev.release = mv_u3d_gadget_release; u3d->gadget.name = driver_name; /* gadget name */ - - retval = device_register(&u3d->gadget.dev); - if (retval) - goto err_register_gadget_device; + u3d->gadget.register_my_device = true; mv_u3d_eps_init(u3d); @@ -1991,8 +1985,6 @@ static int mv_u3d_probe(struct platform_device *dev) return 0; err_unregister: - device_unregister(&u3d->gadget.dev); -err_register_gadget_device: free_irq(u3d->irq, &dev->dev); err_request_irq: err_get_irq: From 2cd807e7a8ee18d13fd06e84ef9f485a5c28a521 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:38:19 +0200 Subject: [PATCH 029/303] usb: gadget: mv_u3d_core: fix a compile warning Fix the following compile warning: mv_u3d_core.c:1766:12: warning: 'mv_u3d_remove' \ defined but not used [-Wunused-function] Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index 565addcd3956..734ade11505f 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -2072,7 +2072,7 @@ static void mv_u3d_shutdown(struct platform_device *dev) static struct platform_driver mv_u3d_driver = { .probe = mv_u3d_probe, - .remove = __exit_p(mv_u3d_remove), + .remove = mv_u3d_remove, .shutdown = mv_u3d_shutdown, .driver = { .owner = THIS_MODULE, From 5dc7b773657d9e217eaacd51f74e9cea81260088 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:43:47 +0200 Subject: [PATCH 030/303] usb: gadget: mv_udc_core: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc_core.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index c8cf959057fe..a7afdfb413b3 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2138,8 +2138,6 @@ static int mv_udc_remove(struct platform_device *pdev) mv_udc_disable(udc); - device_unregister(&udc->gadget.dev); - /* free dev, wait for the release() finished */ wait_for_completion(udc->done); @@ -2311,15 +2309,11 @@ static int mv_udc_probe(struct platform_device *pdev) udc->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */ /* the "gadget" abstracts/virtualizes the controller */ - dev_set_name(&udc->gadget.dev, "gadget"); udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = pdev->dev.dma_mask; udc->gadget.dev.release = gadget_release; udc->gadget.name = driver_name; /* gadget name */ - - retval = device_register(&udc->gadget.dev); - if (retval) - goto err_destroy_dma; + udc->gadget.register_my_device = true; eps_init(udc); @@ -2342,7 +2336,7 @@ static int mv_udc_probe(struct platform_device *pdev) if (!udc->qwork) { dev_err(&pdev->dev, "cannot create workqueue\n"); retval = -ENOMEM; - goto err_unregister; + goto err_destroy_dma; } INIT_WORK(&udc->vbus_work, mv_udc_vbus_work); @@ -2370,8 +2364,6 @@ static int mv_udc_probe(struct platform_device *pdev) err_create_workqueue: destroy_workqueue(udc->qwork); -err_unregister: - device_unregister(&udc->gadget.dev); err_destroy_dma: dma_pool_destroy(udc->dtd_pool); err_free_dma: From c9f9c849ae873d592823d31c8e1dcade5c46fe14 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:48:12 +0200 Subject: [PATCH 031/303] usb: gadget: net2272: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2272.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index d226058e3b88..635248f42dcd 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2209,7 +2209,6 @@ net2272_remove(struct net2272 *dev) free_irq(dev->irq, dev); iounmap(dev->base_addr); - device_unregister(&dev->gadget.dev); device_remove_file(dev->dev, &dev_attr_registers); dev_info(dev->dev, "unbind\n"); @@ -2236,11 +2235,11 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq) ret->gadget.max_speed = USB_SPEED_HIGH; /* the "gadget" abstracts/virtualizes the controller */ - dev_set_name(&ret->gadget.dev, "gadget"); ret->gadget.dev.parent = dev; ret->gadget.dev.dma_mask = dev->dma_mask; ret->gadget.dev.release = net2272_gadget_release; ret->gadget.name = driver_name; + ret->gadget.register_my_device = true; return ret; } @@ -2275,12 +2274,9 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags) dma_mode_string()); dev_info(dev->dev, "version: %s\n", driver_vers); - ret = device_register(&dev->gadget.dev); - if (ret) - goto err_irq; ret = device_create_file(dev->dev, &dev_attr_registers); if (ret) - goto err_dev_reg; + goto err_irq; ret = usb_add_gadget_udc(dev->dev, &dev->gadget); if (ret) @@ -2290,8 +2286,6 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags) err_add_udc: device_remove_file(dev->dev, &dev_attr_registers); - err_dev_reg: - device_unregister(&dev->gadget.dev); err_irq: free_irq(dev->irq, dev); err: From 654dfe4d2ab0d00573dcb0d7d7c957165dc4d9f2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:52:14 +0200 Subject: [PATCH 032/303] usb: gadget: net2280: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2280.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index a1b650e11339..c55af4293509 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2679,7 +2679,6 @@ static void net2280_remove (struct pci_dev *pdev) pci_resource_len (pdev, 0)); if (dev->enabled) pci_disable_device (pdev); - device_unregister (&dev->gadget.dev); device_remove_file (&pdev->dev, &dev_attr_registers); pci_set_drvdata (pdev, NULL); @@ -2711,11 +2710,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.max_speed = USB_SPEED_HIGH; /* the "gadget" abstracts/virtualizes the controller */ - dev_set_name(&dev->gadget.dev, "gadget"); dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; dev->gadget.name = driver_name; + dev->gadget.register_my_device = true; /* now all the pci goodies ... */ if (pci_enable_device (pdev) < 0) { @@ -2823,8 +2822,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) use_dma ? (use_dma_chaining ? "chaining" : "enabled") : "disabled"); - retval = device_register (&dev->gadget.dev); - if (retval) goto done; retval = device_create_file (&pdev->dev, &dev_attr_registers); if (retval) goto done; From 5a8a375714d007f556c81b739aa69e3c745d8015 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 16:56:35 +0200 Subject: [PATCH 033/303] usb: gadget: pch_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index a787a8ef672b..703214543dd4 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -358,7 +358,6 @@ struct pch_udc_dev { prot_stall:1, irq_registered:1, mem_region:1, - registered:1, suspended:1, connected:1, vbus_session:1, @@ -3078,8 +3077,6 @@ static void pch_udc_remove(struct pci_dev *pdev) pci_resource_len(pdev, PCH_UDC_PCI_BAR)); if (dev->active) pci_disable_device(pdev); - if (dev->registered) - device_unregister(&dev->gadget.dev); kfree(dev); pci_set_drvdata(pdev, NULL); } @@ -3196,17 +3193,12 @@ static int pch_udc_probe(struct pci_dev *pdev, if (retval) goto finished; - dev_set_name(&dev->gadget.dev, "gadget"); dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; dev->gadget.name = KBUILD_MODNAME; dev->gadget.max_speed = USB_SPEED_HIGH; - - retval = device_register(&dev->gadget.dev); - if (retval) - goto finished; - dev->registered = 1; + dev->gadget.register_my_device = true; /* Put the device in disconnected state till a driver is bound */ pch_udc_set_disconnect(dev); From 80bf5343decf65d9e4141143d49e6ed381565cbf Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 17:01:28 +0200 Subject: [PATCH 034/303] usb: gadget: r8a66597-udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/r8a66597-udc.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index f46a1b77ce3e..ae94c0eaf633 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1837,7 +1837,6 @@ static int __exit r8a66597_remove(struct platform_device *pdev) clk_put(r8a66597->clk); } - device_unregister(&r8a66597->gadget.dev); kfree(r8a66597); return 0; } @@ -1915,17 +1914,12 @@ static int __init r8a66597_probe(struct platform_device *pdev) r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW; r8a66597->gadget.ops = &r8a66597_gadget_ops; - dev_set_name(&r8a66597->gadget.dev, "gadget"); r8a66597->gadget.max_speed = USB_SPEED_HIGH; r8a66597->gadget.dev.parent = &pdev->dev; r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask; r8a66597->gadget.dev.release = pdev->dev.release; r8a66597->gadget.name = udc_name; - ret = device_register(&r8a66597->gadget.dev); - if (ret < 0) { - dev_err(&pdev->dev, "device_register failed\n"); - goto clean_up; - } + r8a66597->gadget.register_my_device = true; init_timer(&r8a66597->timer); r8a66597->timer.function = r8a66597_timer; @@ -1939,7 +1933,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); ret = PTR_ERR(r8a66597->clk); - goto clean_up_dev; + goto clean_up; } clk_enable(r8a66597->clk); } @@ -2007,8 +2001,6 @@ clean_up2: clk_disable(r8a66597->clk); clk_put(r8a66597->clk); } -clean_up_dev: - device_unregister(&r8a66597->gadget.dev); clean_up: if (r8a66597) { if (r8a66597->sudmac_reg) From b8d833a327aaed6637398446ec8a3e555b3ddd11 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 17:03:10 +0200 Subject: [PATCH 035/303] usb: gadget: s3c-hsotg: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Reviewed-by: Tomasz Figa Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index c26564f29a2c..5fbd233eb6a0 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3567,17 +3567,13 @@ static int s3c_hsotg_probe(struct platform_device *pdev) dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq); - device_initialize(&hsotg->gadget.dev); - - dev_set_name(&hsotg->gadget.dev, "gadget"); - hsotg->gadget.max_speed = USB_SPEED_HIGH; hsotg->gadget.ops = &s3c_hsotg_gadget_ops; hsotg->gadget.name = dev_name(dev); - hsotg->gadget.dev.parent = dev; hsotg->gadget.dev.dma_mask = dev->dma_mask; hsotg->gadget.dev.release = s3c_hsotg_release; + hsotg->gadget.register_my_device = true; /* reset the system */ @@ -3658,12 +3654,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) s3c_hsotg_phy_disable(hsotg); - ret = device_add(&hsotg->gadget.dev); - if (ret) { - put_device(&hsotg->gadget.dev); - goto err_ep_mem; - } - ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget); if (ret) goto err_ep_mem; @@ -3702,10 +3692,8 @@ static int s3c_hsotg_remove(struct platform_device *pdev) } s3c_hsotg_phy_disable(hsotg); - clk_disable_unprepare(hsotg->clk); - device_unregister(&hsotg->gadget.dev); return 0; } From 40ed30cff5957d15dcd2638c6f48fae839a3100a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 17:04:56 +0200 Subject: [PATCH 036/303] usb: gadget: s3c-hsudc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsudc.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 458965a1b138..c4ff747f53fc 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1303,18 +1303,16 @@ static int s3c_hsudc_probe(struct platform_device *pdev) spin_lock_init(&hsudc->lock); - dev_set_name(&hsudc->gadget.dev, "gadget"); - hsudc->gadget.max_speed = USB_SPEED_HIGH; hsudc->gadget.ops = &s3c_hsudc_gadget_ops; hsudc->gadget.name = dev_name(dev); hsudc->gadget.dev.parent = dev; hsudc->gadget.dev.dma_mask = dev->dma_mask; hsudc->gadget.ep0 = &hsudc->ep[0].ep; - hsudc->gadget.is_otg = 0; hsudc->gadget.is_a_peripheral = 0; hsudc->gadget.speed = USB_SPEED_UNKNOWN; + hsudc->gadget.register_my_device = true; s3c_hsudc_setup_ep(hsudc); @@ -1345,12 +1343,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev) disable_irq(hsudc->irq); local_irq_enable(); - ret = device_register(&hsudc->gadget.dev); - if (ret) { - put_device(&hsudc->gadget.dev); - goto err_add_device; - } - ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget); if (ret) goto err_add_udc; @@ -1359,7 +1351,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev) return 0; err_add_udc: - device_unregister(&hsudc->gadget.dev); err_add_device: clk_disable(hsudc->uclk); err_res: From b1e1eaba2916427d25fbd411cd863052836560ff Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 17:06:42 +0200 Subject: [PATCH 037/303] usb: gadget: s3c2410_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c2410_udc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 08f89652533b..c4134948dd9e 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1824,16 +1824,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev) goto err_mem; } - device_initialize(&udc->gadget.dev); udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = pdev->dev.dma_mask; - - /* Bind the driver */ - retval = device_add(&udc->gadget.dev); - if (retval) { - dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval); - goto err_device_add; - } + udc->gadget.register_my_device = true; the_controller = udc; platform_set_drvdata(pdev, udc); @@ -1923,8 +1916,6 @@ err_gpio_claim: err_int: free_irq(IRQ_USBD, udc); err_map: - device_unregister(&udc->gadget.dev); -err_device_add: iounmap(base_addr); err_mem: release_mem_region(rsrc_start, rsrc_len); @@ -1946,7 +1937,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev) return -EBUSY; usb_del_gadget_udc(&udc->gadget); - device_unregister(&udc->gadget.dev); debugfs_remove(udc->regs_info); if (udc_info && !udc_info->udc_command && From 0972ef71b4841a59fab6f998d6e6c2c684443583 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 17:08:01 +0200 Subject: [PATCH 038/303] usb: renesas_usbhs: gadget: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 78fca978b2d0..5d5fab0ad0d1 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -976,15 +976,12 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) /* * init gadget */ - dev_set_name(&gpriv->gadget.dev, "gadget"); gpriv->gadget.dev.parent = dev; gpriv->gadget.dev.release = usbhs_mod_gadget_release; gpriv->gadget.name = "renesas_usbhs_udc"; gpriv->gadget.ops = &usbhsg_gadget_ops; gpriv->gadget.max_speed = USB_SPEED_HIGH; - ret = device_register(&gpriv->gadget.dev); - if (ret < 0) - goto err_add_udc; + gpriv->gadget.register_my_device = true; INIT_LIST_HEAD(&gpriv->gadget.ep_list); @@ -1014,15 +1011,13 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) ret = usb_add_gadget_udc(dev, &gpriv->gadget); if (ret) - goto err_register; + goto err_add_udc; dev_info(dev, "gadget probed\n"); return 0; -err_register: - device_unregister(&gpriv->gadget.dev); err_add_udc: kfree(gpriv->uep); @@ -1038,8 +1033,6 @@ void usbhs_mod_gadget_remove(struct usbhs_priv *priv) usb_del_gadget_udc(&gpriv->gadget); - device_unregister(&gpriv->gadget.dev); - kfree(gpriv->uep); kfree(gpriv); } From b73f5a2a0a2b2ff10d941e35c2ff08fcc04a9862 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 17:28:30 +0200 Subject: [PATCH 039/303] usb: gadget: pxa25x_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pxa25x_udc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index d0f37484b6b0..8996fcb053ef 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -2138,16 +2138,9 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) dev->timer.function = udc_watchdog; dev->timer.data = (unsigned long) dev; - device_initialize(&dev->gadget.dev); dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.dma_mask = pdev->dev.dma_mask; - - retval = device_add(&dev->gadget.dev); - if (retval) { - dev->driver = NULL; - dev->gadget.dev.driver = NULL; - goto err_device_add; - } + dev->gadget.register_my_device = true; the_controller = dev; platform_set_drvdata(pdev, dev); @@ -2199,8 +2192,6 @@ lubbock_fail0: free_irq(irq, dev); #endif err_irq1: - device_unregister(&dev->gadget.dev); - err_device_add: if (gpio_is_valid(dev->mach->gpio_pullup)) gpio_free(dev->mach->gpio_pullup); err_gpio_pullup: @@ -2226,7 +2217,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev) return -EBUSY; usb_del_gadget_udc(&dev->gadget); - device_unregister(&dev->gadget.dev); dev->pullup = 0; pullup(dev); From 45f596a6d776532f03135d48f10a1164006f9466 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 17:29:39 +0200 Subject: [PATCH 040/303] usb: gadget: pxa27x_udc: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Acked-by: Robert Jarzmik Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pxa27x_udc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 2fc867652ef5..1c5bfaafa6c8 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1871,7 +1871,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g, udc->driver = NULL; - if (!IS_ERR_OR_NULL(udc->transceiver)) return otg_set_peripheral(udc->transceiver->otg, NULL); return 0; @@ -2456,9 +2455,9 @@ static int __init pxa_udc_probe(struct platform_device *pdev) goto err_map; } - device_initialize(&udc->gadget.dev); udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = NULL; + udc->gadget.register_my_device = true; udc->vbus_sensed = 0; the_controller = udc; @@ -2475,12 +2474,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev) goto err_irq; } - retval = device_add(&udc->gadget.dev); - if (retval) { - dev_err(udc->dev, "device_add error %d\n", retval); - goto err_dev_add; - } - retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget); if (retval) goto err_add_udc; @@ -2490,8 +2483,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev) return 0; err_add_udc: - device_unregister(&udc->gadget.dev); -err_dev_add: free_irq(udc->irq, udc); err_irq: iounmap(udc->regs); @@ -2512,7 +2503,6 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) int gpio = udc->mach->gpio_pullup; usb_del_gadget_udc(&udc->gadget); - device_del(&udc->gadget.dev); usb_gadget_unregister_driver(udc->driver); free_irq(udc->irq, udc); pxa_cleanup_debugfs(udc); From dc9e2873b740331b186b8f315fd18bbc97108d2e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 17:36:39 +0200 Subject: [PATCH 041/303] usb: chipidea: let udc-core manage gadget->dev By simply setting a flag, we can drop some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/udc.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index f64fbea1cf20..e95e8bbde988 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1717,11 +1717,11 @@ static int udc_start(struct ci13xxx *ci) INIT_LIST_HEAD(&ci->gadget.ep_list); - dev_set_name(&ci->gadget.dev, "gadget"); ci->gadget.dev.dma_mask = dev->dma_mask; ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; ci->gadget.dev.parent = dev; ci->gadget.dev.release = udc_release; + ci->gadget.register_my_device = true; /* alloc resources */ ci->qh_pool = dma_pool_create("ci13xxx_qh", dev, @@ -1761,15 +1761,9 @@ static int udc_start(struct ci13xxx *ci) hw_enable_vbus_intr(ci); } - retval = device_register(&ci->gadget.dev); - if (retval) { - put_device(&ci->gadget.dev); - goto put_transceiver; - } - retval = dbg_create_files(ci->dev); if (retval) - goto unreg_device; + goto put_transceiver; if (!IS_ERR_OR_NULL(ci->transceiver)) { retval = otg_set_peripheral(ci->transceiver->otg, @@ -1797,8 +1791,6 @@ remove_trans: dev_err(dev, "error = %i\n", retval); remove_dbg: dbg_remove_files(ci->dev); -unreg_device: - device_unregister(&ci->gadget.dev); put_transceiver: if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy) usb_put_phy(ci->transceiver); @@ -1837,7 +1829,6 @@ static void udc_stop(struct ci13xxx *ci) usb_put_phy(ci->transceiver); } dbg_remove_files(ci->dev); - device_unregister(&ci->gadget.dev); /* my kobject is dynamic, I swear! */ memset(&ci->gadget, 0, sizeof(ci->gadget)); } From 7bce401cc6db5508ef2517e45bd8caf7ce0a15ee Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 17:41:00 +0200 Subject: [PATCH 042/303] usb: gadget: drop now unnecessary flag We don't need the ->register_my_device flag anymore because all UDC drivers have been properly converted. Let's remove every history of it. Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/udc.c | 1 - drivers/usb/dwc3/gadget.c | 1 - drivers/usb/gadget/amd5536udc.c | 1 - drivers/usb/gadget/at91_udc.c | 1 - drivers/usb/gadget/atmel_usba_udc.c | 1 - drivers/usb/gadget/bcm63xx_udc.c | 1 - drivers/usb/gadget/dummy_hcd.c | 1 - drivers/usb/gadget/fsl_qe_udc.c | 1 - drivers/usb/gadget/fsl_udc_core.c | 1 - drivers/usb/gadget/fusb300_udc.c | 1 - drivers/usb/gadget/goku_udc.c | 1 - drivers/usb/gadget/imx_udc.c | 1 - drivers/usb/gadget/lpc32xx_udc.c | 1 - drivers/usb/gadget/m66592-udc.c | 1 - drivers/usb/gadget/mv_u3d_core.c | 1 - drivers/usb/gadget/mv_udc_core.c | 1 - drivers/usb/gadget/net2272.c | 1 - drivers/usb/gadget/net2280.c | 1 - drivers/usb/gadget/omap_udc.c | 1 - drivers/usb/gadget/pch_udc.c | 1 - drivers/usb/gadget/pxa25x_udc.c | 1 - drivers/usb/gadget/pxa27x_udc.c | 1 - drivers/usb/gadget/r8a66597-udc.c | 1 - drivers/usb/gadget/s3c-hsotg.c | 1 - drivers/usb/gadget/s3c-hsudc.c | 1 - drivers/usb/gadget/s3c2410_udc.c | 1 - drivers/usb/gadget/udc-core.c | 18 +++++++----------- drivers/usb/musb/musb_gadget.c | 1 - drivers/usb/renesas_usbhs/mod_gadget.c | 1 - include/linux/usb/gadget.h | 4 ---- 30 files changed, 7 insertions(+), 43 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index e95e8bbde988..1b65ac8f3c9b 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1721,7 +1721,6 @@ static int udc_start(struct ci13xxx *ci) ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask; ci->gadget.dev.parent = dev; ci->gadget.dev.release = udc_release; - ci->gadget.register_my_device = true; /* alloc resources */ ci->qh_pool = dma_pool_create("ci13xxx_qh", dev, diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 10bb161eec88..65493b6cd5a6 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2499,7 +2499,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) 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.register_my_device = true; dwc->gadget.name = "dwc3-gadget"; /* diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index eee01ea70f8c..eec4461fb45f 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3275,7 +3275,6 @@ static int udc_probe(struct udc *dev) dev->gadget.dev.release = gadget_release; dev->gadget.name = name; dev->gadget.max_speed = USB_SPEED_HIGH; - dev->gadget.register_my_device = true; /* init registers, interrupts, ... */ startup_registers(dev); diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 47b7e58f8415..9936de9bbe50 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1726,7 +1726,6 @@ static int at91udc_probe(struct platform_device *pdev) /* init software state */ udc = &controller; - udc->gadget.register_my_device = true; udc->gadget.dev.parent = dev; if (pdev->dev.of_node) at91udc_of_init(udc, pdev->dev.of_node); diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 2404d0c25668..41518e612808 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1902,7 +1902,6 @@ static int __init usba_udc_probe(struct platform_device *pdev) udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = pdev->dev.dma_mask; - udc->gadget.register_my_device = true; platform_set_drvdata(pdev, udc); diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index c020b877219d..d4f73e1b37e6 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -2374,7 +2374,6 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) udc->gadget.dev.parent = dev; udc->gadget.dev.release = bcm63xx_udc_gadget_release; udc->gadget.dev.dma_mask = dev->dma_mask; - udc->gadget.register_my_device = true; if (!pd->use_fullspeed && !use_fullspeed) udc->gadget.max_speed = USB_SPEED_HIGH; diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index a6950aa8f3be..c4f27d5a2b9c 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -983,7 +983,6 @@ static int dummy_udc_probe(struct platform_device *pdev) dum->gadget.name = gadget_name; dum->gadget.ops = &dummy_ops; dum->gadget.max_speed = USB_SPEED_SUPER; - dum->gadget.register_my_device = true; dum->gadget.dev.parent = &pdev->dev; dum->gadget.dev.release = dummy_gadget_release; diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 0f78cd859d68..0e7531bd33f4 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2525,7 +2525,6 @@ static int qe_udc_probe(struct platform_device *ofdev) udc->gadget.name = driver_name; udc->gadget.dev.release = qe_udc_release; udc->gadget.dev.parent = &ofdev->dev; - udc->gadget.register_my_device = true; /* initialize qe_ep struct */ for (i = 0; i < USB_MAX_ENDPOINTS ; i++) { diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 9140a2daad87..f33b9005eeac 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2524,7 +2524,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) udc_controller->gadget.dev.release = fsl_udc_release; udc_controller->gadget.dev.parent = &pdev->dev; udc_controller->gadget.dev.of_node = pdev->dev.of_node; - udc_controller->gadget.register_my_device = true; if (!IS_ERR_OR_NULL(udc_controller->transceiver)) udc_controller->gadget.is_otg = 1; diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index d29017218b01..2d3c8b351f42 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -1427,7 +1427,6 @@ static int __init fusb300_probe(struct platform_device *pdev) fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask; fusb300->gadget.dev.release = pdev->dev.release; fusb300->gadget.name = udc_name; - fusb300->gadget.register_my_device = true; fusb300->reg = reg; ret = request_irq(ires->start, fusb300_irq, IRQF_SHARED, diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index b4ea2cf465a6..8a6c66618bd3 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1758,7 +1758,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; dev->gadget.name = driver_name; - dev->gadget.register_my_device = true; /* now all the pci goodies ... */ retval = pci_enable_device(pdev); diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 435b20346ead..9c5b7451a7d1 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1461,7 +1461,6 @@ static int __init imx_udc_probe(struct platform_device *pdev) imx_usb->clk = clk; imx_usb->dev = &pdev->dev; - imx_usb->gadget.register_my_device = true; imx_usb->gadget.dev.parent = &pdev->dev; imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask; diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index 329e1c5f0ef9..67c3ef9d9bed 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -3090,7 +3090,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) /* init software state */ udc->gadget.dev.parent = dev; - udc->gadget.register_my_device = true; udc->pdev = pdev; udc->dev = &pdev->dev; udc->enabled = 0; diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 43ad70dff74d..eb61d0b54f21 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1612,7 +1612,6 @@ static int __init m66592_probe(struct platform_device *pdev) m66592->gadget.dev.dma_mask = pdev->dev.dma_mask; m66592->gadget.dev.release = pdev->dev.release; m66592->gadget.name = udc_name; - m66592->gadget.register_my_device = true; init_timer(&m66592->timer); m66592->timer.function = m66592_timer; diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index 734ade11505f..e5735fc610de 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -1959,7 +1959,6 @@ static int mv_u3d_probe(struct platform_device *dev) u3d->gadget.dev.dma_mask = dev->dev.dma_mask; u3d->gadget.dev.release = mv_u3d_gadget_release; u3d->gadget.name = driver_name; /* gadget name */ - u3d->gadget.register_my_device = true; mv_u3d_eps_init(u3d); diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index a7afdfb413b3..be35573f8703 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2313,7 +2313,6 @@ static int mv_udc_probe(struct platform_device *pdev) udc->gadget.dev.dma_mask = pdev->dev.dma_mask; udc->gadget.dev.release = gadget_release; udc->gadget.name = driver_name; /* gadget name */ - udc->gadget.register_my_device = true; eps_init(udc); diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 635248f42dcd..78c8bb538332 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2239,7 +2239,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq) ret->gadget.dev.dma_mask = dev->dma_mask; ret->gadget.dev.release = net2272_gadget_release; ret->gadget.name = driver_name; - ret->gadget.register_my_device = true; return ret; } diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index c55af4293509..2089d9b0058c 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2714,7 +2714,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; dev->gadget.name = driver_name; - dev->gadget.register_my_device = true; /* now all the pci goodies ... */ if (pci_enable_device (pdev) < 0) { diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index c979272e7c86..b23c861e2a97 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2634,7 +2634,6 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) udc->gadget.dev.release = omap_udc_release; udc->gadget.dev.parent = &odev->dev; - udc->gadget.register_my_device = true; if (use_dma) udc->gadget.dev.dma_mask = odev->dev.dma_mask; diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 703214543dd4..e8c9afd8fbf0 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -3198,7 +3198,6 @@ static int pch_udc_probe(struct pci_dev *pdev, dev->gadget.dev.release = gadget_release; dev->gadget.name = KBUILD_MODNAME; dev->gadget.max_speed = USB_SPEED_HIGH; - dev->gadget.register_my_device = true; /* Put the device in disconnected state till a driver is bound */ pch_udc_set_disconnect(dev); diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 8996fcb053ef..e29bb878b2d7 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -2140,7 +2140,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) dev->gadget.dev.parent = &pdev->dev; dev->gadget.dev.dma_mask = pdev->dev.dma_mask; - dev->gadget.register_my_device = true; the_controller = dev; platform_set_drvdata(pdev, dev); diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 1c5bfaafa6c8..07ce1477f911 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -2457,7 +2457,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = NULL; - udc->gadget.register_my_device = true; udc->vbus_sensed = 0; the_controller = udc; diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index ae94c0eaf633..a67d47708b98 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1919,7 +1919,6 @@ static int __init r8a66597_probe(struct platform_device *pdev) r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask; r8a66597->gadget.dev.release = pdev->dev.release; r8a66597->gadget.name = udc_name; - r8a66597->gadget.register_my_device = true; init_timer(&r8a66597->timer); r8a66597->timer.function = r8a66597_timer; diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 5fbd233eb6a0..8ae0bd99ffde 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3573,7 +3573,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) hsotg->gadget.dev.parent = dev; hsotg->gadget.dev.dma_mask = dev->dma_mask; hsotg->gadget.dev.release = s3c_hsotg_release; - hsotg->gadget.register_my_device = true; /* reset the system */ diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index c4ff747f53fc..7fc3de537c9a 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1312,7 +1312,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev) hsudc->gadget.is_otg = 0; hsudc->gadget.is_a_peripheral = 0; hsudc->gadget.speed = USB_SPEED_UNKNOWN; - hsudc->gadget.register_my_device = true; s3c_hsudc_setup_ep(hsudc); diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index c4134948dd9e..a669081bbb88 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1826,7 +1826,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev) udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = pdev->dev.dma_mask; - udc->gadget.register_my_device = true; the_controller = udc; platform_set_drvdata(pdev, udc); diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 919505426ec1..40b1d888d5a1 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -173,13 +173,11 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) if (!udc) goto err1; - if (gadget->register_my_device) { - dev_set_name(&gadget->dev, "gadget"); + dev_set_name(&gadget->dev, "gadget"); - ret = device_register(&gadget->dev); - if (ret) - goto err2; - } + ret = device_register(&gadget->dev); + if (ret) + goto err2; device_initialize(&udc->dev); udc->dev.release = usb_udc_release; @@ -211,8 +209,8 @@ err3: put_device(&udc->dev); err2: - if (gadget->register_my_device) - put_device(&gadget->dev); + put_device(&gadget->dev); + err1: return ret; } @@ -266,9 +264,7 @@ found: kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); device_unregister(&udc->dev); - - if (gadget->register_my_device) - device_unregister(&gadget->dev); + device_unregister(&gadget->dev); } EXPORT_SYMBOL_GPL(usb_del_gadget_udc); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index cadb750921e9..e363033f6754 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1891,7 +1891,6 @@ int musb_gadget_setup(struct musb *musb) musb->g.dev.dma_mask = musb->controller->dma_mask; musb->g.dev.release = musb_gadget_release; musb->g.name = musb_driver_name; - musb->g.register_my_device = true; musb->g.is_otg = 1; musb_g_init_endpoints(musb); diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 5d5fab0ad0d1..6a3afa9b764c 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -981,7 +981,6 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) gpriv->gadget.name = "renesas_usbhs_udc"; gpriv->gadget.ops = &usbhsg_gadget_ops; gpriv->gadget.max_speed = USB_SPEED_HIGH; - gpriv->gadget.register_my_device = true; INIT_LIST_HEAD(&gpriv->gadget.ep_list); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index fcd9ef8d3f70..2e297e80d59a 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -494,9 +494,6 @@ struct usb_gadget_ops { * only supports HNP on a different root port. * @b_hnp_enable: OTG device feature flag, indicating that the A-Host * enabled HNP support. - * @register_my_device: Flag telling udc-core that UDC driver didn't - * register the gadget device to the driver model. Temporary until - * all UDC drivers are fixed up properly. * @name: Identifies the controller hardware type. Used in diagnostics * and sometimes configuration. * @dev: Driver model state for this abstract device. @@ -534,7 +531,6 @@ struct usb_gadget { unsigned b_hnp_enable:1; unsigned a_hnp_support:1; unsigned a_alt_hnp_support:1; - unsigned register_my_device:1; const char *name; struct device dev; unsigned out_epnum; From e58ebcd14210d3def22ba44d9d14daffbe2eb8e0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 28 Jan 2013 14:48:36 +0200 Subject: [PATCH 043/303] usb: gadget: s3c-hsotg: switch over to usb_gadget_map/unmap_request() we have generic implementations for a reason, let's use them. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 46 ++++------------------------------ 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 8ae0bd99ffde..2812fa51e296 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -39,8 +39,6 @@ #include "s3c-hsotg.h" -#define DMA_ADDR_INVALID (~((dma_addr_t)0)) - static const char * const s3c_hsotg_supply_names[] = { "vusb_d", /* digital USB supply, 1.2V */ "vusb_a", /* analog USB supply, 1.1V */ @@ -405,7 +403,6 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep, INIT_LIST_HEAD(&req->queue); - req->req.dma = DMA_ADDR_INVALID; return &req->req; } @@ -435,24 +432,12 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg, struct s3c_hsotg_req *hs_req) { struct usb_request *req = &hs_req->req; - enum dma_data_direction dir; - - dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE; /* ignore this if we're not moving any data */ if (hs_req->req.length == 0) return; - if (hs_req->mapped) { - /* we mapped this, so unmap and remove the dma */ - - dma_unmap_single(hsotg->dev, req->dma, req->length, dir); - - req->dma = DMA_ADDR_INVALID; - hs_req->mapped = 0; - } else { - dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir); - } + usb_gadget_unmap_request(&hsotg->gadget, hs_req, hs_ep->dir_in); } /** @@ -852,37 +837,16 @@ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg, struct s3c_hsotg_ep *hs_ep, struct usb_request *req) { - enum dma_data_direction dir; struct s3c_hsotg_req *hs_req = our_req(req); - - dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE; + int ret; /* if the length is zero, ignore the DMA data */ if (hs_req->req.length == 0) return 0; - if (req->dma == DMA_ADDR_INVALID) { - dma_addr_t dma; - - dma = dma_map_single(hsotg->dev, req->buf, req->length, dir); - - if (unlikely(dma_mapping_error(hsotg->dev, dma))) - goto dma_error; - - if (dma & 3) { - dev_err(hsotg->dev, "%s: unaligned dma buffer\n", - __func__); - - dma_unmap_single(hsotg->dev, dma, req->length, dir); - return -EINVAL; - } - - hs_req->mapped = 1; - req->dma = dma; - } else { - dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir); - hs_req->mapped = 0; - } + ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in); + if (ret) + goto dma_error; return 0; From 3be49f38d38a1a2c1cffc61579290c9ba6404446 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 28 Jan 2013 14:51:34 +0200 Subject: [PATCH 044/303] usb: gadget: amd5536udc: remove unused structure member that member isn't used anywhere in the driver and be removed with no mercy. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/amd5536udc.h b/drivers/usb/gadget/amd5536udc.h index f1bf32e6b8d8..6744d3b83109 100644 --- a/drivers/usb/gadget/amd5536udc.h +++ b/drivers/usb/gadget/amd5536udc.h @@ -472,7 +472,6 @@ struct udc_request { /* flags */ unsigned dma_going : 1, - dma_mapping : 1, dma_done : 1; /* phys. address */ dma_addr_t td_phys; From 1bda9df8dd6d39ac369020594c82d3f70f3a4721 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 28 Jan 2013 16:57:02 +0200 Subject: [PATCH 045/303] usb: gadget: atmel_usba_udc: switch over to usb_gadget_map/unmap_request() we have generic implementations for a reason, let's use them. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/atmel_usba_udc.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 41518e612808..94aeba84b21e 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status) if (req->req.status == -EINPROGRESS) req->req.status = status; - if (req->mapped) { - dma_unmap_single( - &udc->pdev->dev, req->req.dma, req->req.length, - ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } + if (req->using_dma) + usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in); DBG(DBG_GADGET | DBG_REQ, "%s: req %p complete: status %d, actual %u\n", @@ -684,7 +679,6 @@ usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) return NULL; INIT_LIST_HEAD(&req->queue); - req->req.dma = DMA_ADDR_INVALID; return &req->req; } @@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep, return -EINVAL; } + ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in); + if (ret) + return ret; + req->using_dma = 1; - - if (req->req.dma == DMA_ADDR_INVALID) { - req->req.dma = dma_map_single( - &udc->pdev->dev, req->req.buf, req->req.length, - ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->mapped = 1; - } else { - dma_sync_single_for_device( - &udc->pdev->dev, req->req.dma, req->req.length, - ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->mapped = 0; - } - req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length) | USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE | USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE; From 5f6da778578de6b7c43b943cf9cfba12289e9ff3 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 28 Jan 2013 17:03:21 +0200 Subject: [PATCH 046/303] usb: gadget: fsl_udc_core: switch over to usb_gadget_map/unmap_request() we have generic implementations for a reason, let's use them Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_udc_core.c | 51 ++++++++----------------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index f33b9005eeac..c948241c6507 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -185,20 +185,7 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status) dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma); } - if (req->mapped) { - dma_unmap_single(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - ep_is_in(ep) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } else - dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - ep_is_in(ep) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); + usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); if (status && (status != -ESHUTDOWN)) VDBG("complete %s req %p stat %d len %u/%u", @@ -888,6 +875,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) struct fsl_req *req = container_of(_req, struct fsl_req, req); struct fsl_udc *udc; unsigned long flags; + int ret; /* catch various bogus parameters */ if (!_req || !req->req.complete || !req->req.buf @@ -910,22 +898,9 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req->ep = ep; - /* map virtual address to hardware */ - if (req->req.dma == DMA_ADDR_INVALID) { - req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, - req->req.buf, - req->req.length, ep_is_in(ep) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - req->mapped = 1; - } else { - dma_sync_single_for_device(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - ep_is_in(ep) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - req->mapped = 0; - } + ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); + if (ret) + return ret; req->req.status = -EINPROGRESS; req->req.actual = 0; @@ -1290,6 +1265,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) { struct fsl_req *req = udc->status_req; struct fsl_ep *ep; + int ret; if (direction == EP_DIR_IN) udc->ep0_dir = USB_DIR_IN; @@ -1307,10 +1283,9 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) req->req.complete = NULL; req->dtd_count = 0; - req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, - req->req.buf, req->req.length, - ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->mapped = 1; + ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); + if (ret) + return ret; if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0) fsl_queue_td(ep, req); @@ -1353,6 +1328,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, u16 tmp = 0; /* Status, cpu endian */ struct fsl_req *req; struct fsl_ep *ep; + int ret; ep = &udc->eps[0]; @@ -1390,10 +1366,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, req->req.complete = NULL; req->dtd_count = 0; - req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, - req->req.buf, req->req.length, - ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - req->mapped = 1; + ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep)); + if (ret) + goto stall; /* prime the data phase */ if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0)) From 0324f25fc66cd94273d0aa67637ed260ff70f01e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 28 Jan 2013 17:08:28 +0200 Subject: [PATCH 047/303] usb: gadget: fusb300: switch over to usb_gadget_map/unmap_request() we have generic implementations for a reason, let's use them Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fusb300_udc.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index 2d3c8b351f42..5c9dd064767f 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -938,25 +938,22 @@ IDMA_RESET: static void fusb300_set_idma(struct fusb300_ep *ep, struct fusb300_request *req) { - dma_addr_t d; + int ret; - d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE); - - if (dma_mapping_error(NULL, d)) { - printk(KERN_DEBUG "dma_mapping_error\n"); + ret = usb_gadget_map_request(&ep->fusb300->gadget, + &req->req, DMA_TO_DEVICE); + if (ret) return; - } - - dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE); fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0, FUSB300_IGER0_EEPn_PRD_INT(ep->epnum)); - fusb300_fill_idma_prdtbl(ep, d, req->req.length); + fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length); /* check idma is done */ fusb300_wait_idma_finished(ep); - dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE); + usb_gadget_unmap_request(&ep->fusb300->gadget, + &req->req, DMA_TO_DEVICE); } static void in_ep_fifo_handler(struct fusb300_ep *ep) From 369ac9cb3e61ff9281dfec14e1e0ee4855c41352 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 28 Jan 2013 17:13:27 +0200 Subject: [PATCH 048/303] usb: gadget: lpc32xx_udc: switch over to usb_gadget_map/unmap_request() we have generic implementations for a reason, let's use them Signed-off-by: Felipe Balbi --- drivers/usb/gadget/lpc32xx_udc.c | 39 ++++---------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index 67c3ef9d9bed..147832783900 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -1469,23 +1469,7 @@ static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status) status = req->req.status; if (ep->lep) { - enum dma_data_direction direction; - - if (ep->is_in) - direction = DMA_TO_DEVICE; - else - direction = DMA_FROM_DEVICE; - - if (req->mapped) { - dma_unmap_single(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - direction); - req->req.dma = 0; - req->mapped = 0; - } else - dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - direction); + usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in); /* Free DDs */ udc_dd_free(udc, req->dd_desc_ptr); @@ -1841,26 +1825,11 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep, } if (ep->lep) { - enum dma_data_direction direction; struct lpc32xx_usbd_dd_gad *dd; - /* Map DMA pointer */ - if (ep->is_in) - direction = DMA_TO_DEVICE; - else - direction = DMA_FROM_DEVICE; - - if (req->req.dma == 0) { - req->req.dma = dma_map_single( - ep->udc->gadget.dev.parent, - req->req.buf, req->req.length, direction); - req->mapped = 1; - } else { - dma_sync_single_for_device( - ep->udc->gadget.dev.parent, req->req.dma, - req->req.length, direction); - req->mapped = 0; - } + status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in); + if (status) + return status; /* For the request, build a list of DDs */ dd = udc_dd_alloc(udc); From 4c0c6d0085337549e1b4fc97d9616eae732049d6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 28 Jan 2013 17:19:34 +0200 Subject: [PATCH 049/303] usb: gadget: mv_udc_core: switch over to usb_gadget_map/unmap_request() we have generic implementations for a reason, let's use them Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc_core.c | 53 ++++---------------------------- 1 file changed, 6 insertions(+), 47 deletions(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index be35573f8703..7f4d19d75578 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -237,18 +237,7 @@ static void done(struct mv_ep *ep, struct mv_req *req, int status) dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma); } - if (req->mapped) { - dma_unmap_single(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - ((ep_dir(ep) == EP_DIR_IN) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE)); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } else - dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - ((ep_dir(ep) == EP_DIR_IN) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE)); + usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep)); if (status && (status != -ESHUTDOWN)) dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u", @@ -732,21 +721,9 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req->ep = ep; /* map virtual address to hardware */ - if (req->req.dma == DMA_ADDR_INVALID) { - req->req.dma = dma_map_single(ep->udc->gadget.dev.parent, - req->req.buf, - req->req.length, ep_dir(ep) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - req->mapped = 1; - } else { - dma_sync_single_for_device(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - ep_dir(ep) - ? DMA_TO_DEVICE - : DMA_FROM_DEVICE); - req->mapped = 0; - } + retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep)); + if (retval) + return retval; req->req.status = -EINPROGRESS; req->req.actual = 0; @@ -780,18 +757,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) return 0; err_unmap_dma: - if (req->mapped) { - dma_unmap_single(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - ((ep_dir(ep) == EP_DIR_IN) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE)); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } else - dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - ((ep_dir(ep) == EP_DIR_IN) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE)); + usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep)); return retval; } @@ -1528,14 +1494,7 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) return 0; out: - if (req->mapped) { - dma_unmap_single(ep->udc->gadget.dev.parent, - req->req.dma, req->req.length, - ((ep_dir(ep) == EP_DIR_IN) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE)); - req->req.dma = DMA_ADDR_INVALID; - req->mapped = 0; - } + usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep)); return retval; } From f122d33e4b0045a42238b9a4c3943adf7e8313c1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 8 Feb 2013 15:15:11 +0200 Subject: [PATCH 050/303] usb: dwc3: core: explicitly setup and cleanup event buffers Make the call to dwc3_event_buffers_setup() and dwc3_event_buffers_cleanup() explicit, so it's easier to implement PM. Tested-by: Vivek Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ffa6b004a84b..47435086058b 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -337,12 +337,6 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GCTL, reg); - ret = dwc3_event_buffers_setup(dwc); - if (ret) { - dev_err(dwc->dev, "failed to setup event buffers\n"); - goto err0; - } - return 0; err0: @@ -351,8 +345,6 @@ err0: static void dwc3_core_exit(struct dwc3 *dwc) { - dwc3_event_buffers_cleanup(dwc); - usb_phy_shutdown(dwc->usb2_phy); usb_phy_shutdown(dwc->usb3_phy); } @@ -480,6 +472,12 @@ static int dwc3_probe(struct platform_device *pdev) goto err0; } + ret = dwc3_event_buffers_setup(dwc); + if (ret) { + dev_err(dwc->dev, "failed to setup event buffers\n"); + goto err1; + } + mode = DWC3_MODE(dwc->hwparams.hwparams0); switch (mode) { @@ -488,7 +486,7 @@ static int dwc3_probe(struct platform_device *pdev) ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize gadget\n"); - goto err1; + goto err2; } break; case DWC3_MODE_HOST: @@ -496,7 +494,7 @@ static int dwc3_probe(struct platform_device *pdev) ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); - goto err1; + goto err2; } break; case DWC3_MODE_DRD: @@ -504,32 +502,32 @@ static int dwc3_probe(struct platform_device *pdev) ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, "failed to initialize host\n"); - goto err1; + goto err2; } ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, "failed to initialize gadget\n"); - goto err1; + goto err2; } break; default: dev_err(dev, "Unsupported mode of operation %d\n", mode); - goto err1; + goto err2; } dwc->mode = mode; ret = dwc3_debugfs_init(dwc); if (ret) { dev_err(dev, "failed to initialize debugfs\n"); - goto err2; + goto err3; } pm_runtime_allow(dev); return 0; -err2: +err3: switch (mode) { case DWC3_MODE_DEVICE: dwc3_gadget_exit(dwc); @@ -546,6 +544,9 @@ err2: break; } +err2: + dwc3_event_buffers_cleanup(dwc); + err1: dwc3_core_exit(dwc); @@ -583,6 +584,7 @@ static int dwc3_remove(struct platform_device *pdev) break; } + dwc3_event_buffers_cleanup(dwc); dwc3_free_event_buffers(dwc); dwc3_core_exit(dwc); From 8698e2acf3a5e8d6f260ca7675f94e5087df5ae8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 8 Feb 2013 15:24:04 +0200 Subject: [PATCH 051/303] usb: dwc3: gadget: introduce and use enable/disable irq methods we don't need to enable IRQs until we have a gadget driver loaded and ready to work, so let's delay IRQ enable to ->udc_start() and IRQ disable to ->udc_stop(). While at that, also move the related use of request_irq() and free_irq(). Tested-by: Vivek Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 80 ++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 65493b6cd5a6..db2031725abc 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1469,6 +1469,32 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) return ret; } +static void dwc3_gadget_enable_irq(struct dwc3 *dwc) +{ + u32 reg; + + /* Enable all but Start and End of Frame IRQs */ + reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | + DWC3_DEVTEN_EVNTOVERFLOWEN | + DWC3_DEVTEN_CMDCMPLTEN | + DWC3_DEVTEN_ERRTICERREN | + DWC3_DEVTEN_WKUPEVTEN | + DWC3_DEVTEN_ULSTCNGEN | + DWC3_DEVTEN_CONNECTDONEEN | + DWC3_DEVTEN_USBRSTEN | + DWC3_DEVTEN_DISCONNEVTEN); + + dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); +} + +static void dwc3_gadget_disable_irq(struct dwc3 *dwc) +{ + /* mask all interrupts */ + dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); +} + +static irqreturn_t dwc3_interrupt(int irq, void *_dwc); + static int dwc3_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver) { @@ -1476,6 +1502,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, struct dwc3_ep *dep; unsigned long flags; int ret = 0; + int irq; u32 reg; spin_lock_irqsave(&dwc->lock, flags); @@ -1536,6 +1563,17 @@ static int dwc3_gadget_start(struct usb_gadget *g, dwc->ep0state = EP0_SETUP_PHASE; dwc3_ep0_out_start(dwc); + irq = platform_get_irq(to_platform_device(dwc->dev), 0); + ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, + "dwc3", dwc); + if (ret) { + dev_err(dwc->dev, "failed to request irq #%d --> %d\n", + irq, ret); + goto err1; + } + + dwc3_gadget_enable_irq(dwc); + spin_unlock_irqrestore(&dwc->lock, flags); return 0; @@ -1554,9 +1592,14 @@ static int dwc3_gadget_stop(struct usb_gadget *g, { struct dwc3 *dwc = gadget_to_dwc(g); unsigned long flags; + int irq; spin_lock_irqsave(&dwc->lock, flags); + dwc3_gadget_disable_irq(dwc); + irq = platform_get_irq(to_platform_device(dwc->dev), 0); + free_irq(irq, dwc); + __dwc3_gadget_ep_disable(dwc->eps[0]); __dwc3_gadget_ep_disable(dwc->eps[1]); @@ -2454,7 +2497,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) { u32 reg; int ret; - int irq; dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), &dwc->ctrl_req_addr, GFP_KERNEL); @@ -2510,33 +2552,11 @@ int dwc3_gadget_init(struct dwc3 *dwc) if (ret) goto err4; - irq = platform_get_irq(to_platform_device(dwc->dev), 0); - - ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, - "dwc3", dwc); - if (ret) { - dev_err(dwc->dev, "failed to request irq #%d --> %d\n", - irq, ret); - goto err5; - } - reg = dwc3_readl(dwc->regs, DWC3_DCFG); reg |= DWC3_DCFG_LPM_CAP; dwc3_writel(dwc->regs, DWC3_DCFG, reg); - /* Enable all but Start and End of Frame IRQs */ - reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | - DWC3_DEVTEN_EVNTOVERFLOWEN | - DWC3_DEVTEN_CMDCMPLTEN | - DWC3_DEVTEN_ERRTICERREN | - DWC3_DEVTEN_WKUPEVTEN | - DWC3_DEVTEN_ULSTCNGEN | - DWC3_DEVTEN_CONNECTDONEEN | - DWC3_DEVTEN_USBRSTEN | - DWC3_DEVTEN_DISCONNEVTEN); - dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); - - /* automatic phy suspend only on recent versions */ + /* Enable USB2 LPM and automatic phy suspend only on recent versions */ if (dwc->revision >= DWC3_REVISION_194A) { dwc3_gadget_usb2_phy_suspend(dwc, false); dwc3_gadget_usb3_phy_suspend(dwc, false); @@ -2545,15 +2565,11 @@ int dwc3_gadget_init(struct dwc3 *dwc) ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { dev_err(dwc->dev, "failed to register udc\n"); - goto err6; + goto err5; } return 0; -err6: - dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); - free_irq(irq, dwc); - err5: dwc3_gadget_free_endpoints(dwc); @@ -2578,13 +2594,7 @@ err0: void dwc3_gadget_exit(struct dwc3 *dwc) { - int irq; - usb_del_gadget_udc(&dwc->gadget); - irq = platform_get_irq(to_platform_device(dwc->dev), 0); - - dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); - free_irq(irq, dwc); dwc3_gadget_free_endpoints(dwc); From 9fcb3bd8d12db29c101d3722d37ddef9d1915317 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 8 Feb 2013 17:55:58 +0200 Subject: [PATCH 052/303] usb: dwc3: gadget: save state of pullups This will be used during resume to verify if we should reconnect our pullups or not. Tested-by: Vivek Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/gadget.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index b41750660235..35e4d3c01ed0 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -704,6 +704,7 @@ struct dwc3 { unsigned delayed_status:1; unsigned needs_fifo_resize:1; unsigned resize_fifos:1; + unsigned pullups_connected:1; enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index db2031725abc..04e4812fe2f9 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) if (dwc->revision >= DWC3_REVISION_194A) reg &= ~DWC3_DCTL_KEEP_CONNECT; reg |= DWC3_DCTL_RUN_STOP; + dwc->pullups_connected = true; } else { reg &= ~DWC3_DCTL_RUN_STOP; + dwc->pullups_connected = false; } dwc3_writel(dwc->regs, DWC3_DCTL, reg); From 7415f17c9560c923ba61cd330c8dfcd5c3630b80 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 30 Apr 2012 14:56:33 +0300 Subject: [PATCH 053/303] usb: dwc3: core: add power management support Add support for basic power management on the dwc3 driver. While there is still lots to improve for full PM support, this minimal patch will already make sure that we survive suspend-to-ram and suspend-to-disk without major issues. Cc: Vikas C Sajjan Tested-by: Vivek Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 118 ++++++++++++++++++++++++++++++++++++++ drivers/usb/dwc3/core.h | 33 +++++++++++ drivers/usb/dwc3/gadget.c | 61 ++++++++++++++++++++ 3 files changed, 212 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 47435086058b..75a9f88a5ad6 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -591,6 +591,123 @@ static int dwc3_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int dwc3_prepare(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&dwc->lock, flags); + + switch (dwc->mode) { + case DWC3_MODE_DEVICE: + case DWC3_MODE_DRD: + dwc3_gadget_prepare(dwc); + /* FALLTHROUGH */ + case DWC3_MODE_HOST: + default: + dwc3_event_buffers_cleanup(dwc); + break; + } + + spin_unlock_irqrestore(&dwc->lock, flags); + + return 0; +} + +static void dwc3_complete(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&dwc->lock, flags); + + switch (dwc->mode) { + case DWC3_MODE_DEVICE: + case DWC3_MODE_DRD: + dwc3_gadget_complete(dwc); + /* FALLTHROUGH */ + case DWC3_MODE_HOST: + default: + dwc3_event_buffers_setup(dwc); + break; + } + + spin_unlock_irqrestore(&dwc->lock, flags); +} + +static int dwc3_suspend(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + unsigned long flags; + + spin_lock_irqsave(&dwc->lock, flags); + + switch (dwc->mode) { + case DWC3_MODE_DEVICE: + case DWC3_MODE_DRD: + dwc3_gadget_suspend(dwc); + /* FALLTHROUGH */ + case DWC3_MODE_HOST: + default: + /* do nothing */ + break; + } + + dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); + spin_unlock_irqrestore(&dwc->lock, flags); + + usb_phy_shutdown(dwc->usb3_phy); + usb_phy_shutdown(dwc->usb2_phy); + + return 0; +} + +static int dwc3_resume(struct device *dev) +{ + struct dwc3 *dwc = dev_get_drvdata(dev); + unsigned long flags; + + usb_phy_init(dwc->usb3_phy); + usb_phy_init(dwc->usb2_phy); + msleep(100); + + spin_lock_irqsave(&dwc->lock, flags); + + dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); + + switch (dwc->mode) { + case DWC3_MODE_DEVICE: + case DWC3_MODE_DRD: + dwc3_gadget_resume(dwc); + /* FALLTHROUGH */ + case DWC3_MODE_HOST: + default: + /* do nothing */ + break; + } + + spin_unlock_irqrestore(&dwc->lock, flags); + + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return 0; +} + +static const struct dev_pm_ops dwc3_dev_pm_ops = { + .prepare = dwc3_prepare, + .complete = dwc3_complete, + + SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) +}; + +#define DWC3_PM_OPS &(dwc3_dev_pm_ops) +#else +#define DWC3_PM_OPS NULL +#endif + #ifdef CONFIG_OF static const struct of_device_id of_dwc3_match[] = { { @@ -607,6 +724,7 @@ static struct platform_driver dwc3_driver = { .driver = { .name = "dwc3", .of_match_table = of_match_ptr(of_dwc3_match), + .pm = DWC3_PM_OPS, }, }; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 35e4d3c01ed0..52e48e21c82f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -626,6 +626,8 @@ struct dwc3_scratchpad_array { * @mode: mode of operation * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY + * @dcfg: saved contents of DCFG register + * @gctl: saved contents of GCTL register * @is_selfpowered: true when we are selfpowered * @three_stage_setup: set if we perform a three phase setup * @ep0_bounced: true when we used bounce buffer @@ -675,6 +677,10 @@ struct dwc3 { void __iomem *regs; size_t regs_size; + /* used for suspend/resume */ + u32 dcfg; + u32 gctl; + u32 num_event_buffers; u32 u1u2; u32 maximum_speed; @@ -885,4 +891,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc) { } #endif +/* power management interface */ +#if !IS_ENABLED(CONFIG_USB_DWC3_HOST) +int dwc3_gadget_prepare(struct dwc3 *dwc); +void dwc3_gadget_complete(struct dwc3 *dwc); +int dwc3_gadget_suspend(struct dwc3 *dwc); +int dwc3_gadget_resume(struct dwc3 *dwc); +#else +static inline int dwc3_gadget_prepare(struct dwc3 *dwc) +{ + return 0; +} + +static inline void dwc3_gadget_complete(struct dwc3 *dwc) +{ +} + +static inline int dwc3_gadget_suspend(struct dwc3 *dwc) +{ + return 0; +} + +static inline int dwc3_gadget_resume(struct dwc3 *dwc) +{ + return 0; +} +#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */ + #endif /* __DRIVERS_USB_DWC3_CORE_H */ diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 04e4812fe2f9..73b0b7fc77f1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2594,6 +2594,8 @@ err0: return ret; } +/* -------------------------------------------------------------------------- */ + void dwc3_gadget_exit(struct dwc3 *dwc) { usb_del_gadget_udc(&dwc->gadget); @@ -2611,3 +2613,62 @@ void dwc3_gadget_exit(struct dwc3 *dwc) dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req), dwc->ctrl_req, dwc->ctrl_req_addr); } + +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; +} From 9a4b5dab91a8bfae46bfa572660cf43e9ebdc6c3 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 11 Feb 2013 11:03:59 +0200 Subject: [PATCH 054/303] usb: dwc3: omap: introduce enable/disable IRQ methods they will be re-used on suspend/resume implementation. Tested-by: Vivek Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 47 ++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 3d343d92548a..43d62053e158 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -250,6 +250,34 @@ static int dwc3_omap_remove_core(struct device *dev, void *c) 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 int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -355,21 +383,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) return ret; } - /* 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); + dwc3_omap_enable_irqs(omap); ret = of_platform_populate(node, NULL, NULL, dev); if (ret) { @@ -382,6 +396,9 @@ static int dwc3_omap_probe(struct platform_device *pdev) static int dwc3_omap_remove(struct platform_device *pdev) { + struct dwc3_omap *omap = platform_get_drvdata(pdev); + + dwc3_omap_disable_irqs(omap); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core); From 1d9a00eeca1deeebf001047aa5e5e9d00e5588cf Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 11 Feb 2013 11:07:34 +0200 Subject: [PATCH 055/303] usb: dwc3: omap: remove unused fields from private structure we're not using those fields of the structure, might as well remove them. Tested-by: Vivek Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 43d62053e158..ed178c0fc426 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -121,9 +121,6 @@ struct dwc3_omap { int irq; void __iomem *base; - void *context; - u32 resource_size; - u32 dma_status:1; }; @@ -294,7 +291,6 @@ static int dwc3_omap_probe(struct platform_device *pdev) u32 reg; void __iomem *base; - void *context; if (!node) { dev_err(dev, "device node not found\n"); @@ -327,16 +323,8 @@ static int dwc3_omap_probe(struct platform_device *pdev) return -ENOMEM; } - context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL); - if (!context) { - dev_err(dev, "couldn't allocate dwc3 context memory\n"); - return -ENOMEM; - } - spin_lock_init(&omap->lock); - omap->resource_size = resource_size(res); - omap->context = context; omap->dev = dev; omap->irq = irq; omap->base = base; From f3e117f4437af5a2d1b72ae0fa1890dbf9bca72f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 11 Feb 2013 11:12:02 +0200 Subject: [PATCH 056/303] usb: dwc3: omap: add basic suspend/resume support this patch implements basic suspend/resume functionality for the OMAP glue layer. Tested-by: Vivek Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 56 ++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index ed178c0fc426..35b9673b84df 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -121,6 +121,8 @@ struct dwc3_omap { int irq; void __iomem *base; + u32 utmi_otg_status; + u32 dma_status:1; }; @@ -402,12 +404,66 @@ static const struct of_device_id of_dwc3_match[] = { }; MODULE_DEVICE_TABLE(of, of_dwc3_match); +#ifdef CONFIG_PM +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 */ + static struct platform_driver dwc3_omap_driver = { .probe = dwc3_omap_probe, .remove = dwc3_omap_remove, .driver = { .name = "omap-dwc3", .of_match_table = of_dwc3_match, + .pm = DEV_PM_OPS, }, }; From 0646caf754aa3ce55ef978d7f4a3e3d0aab7a187 Mon Sep 17 00:00:00 2001 From: Vikas Sajjan Date: Tue, 16 Oct 2012 15:15:38 +0530 Subject: [PATCH 057/303] usb: dwc3: exynos: add basic suspend/resume support Adds suspend and resume callbacks to exynos dwc3 driver as part of power management support. This change does gating of dwc3 clock during suspend/resume cycles. Signed-off-by: Abhilash Kesavan Signed-off-by: Vikas C Sajjan CC: Doug Anderson Tested-by: Vivek Gautam [ balbi@ti.com : refreshed to current linus/master ] Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-exynos.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index b082bec7343e..e12e45248862 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -187,12 +187,46 @@ static const struct of_device_id exynos_dwc3_match[] = { MODULE_DEVICE_TABLE(of, exynos_dwc3_match); #endif +#ifdef CONFIG_PM +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 */ + static struct platform_driver dwc3_exynos_driver = { .probe = dwc3_exynos_probe, .remove = dwc3_exynos_remove, .driver = { .name = "exynos-dwc3", .of_match_table = of_match_ptr(exynos_dwc3_match), + .pm = DEV_PM_OPS, }, }; From 68907a77431f405c0e8e7031aa77aae03383c69d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 11 Feb 2013 11:36:22 +0200 Subject: [PATCH 058/303] usb: dwc3: pci: add basic suspend/resume support this patch adds basic PM support for the PCI glue layer. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-pci.c | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index e8d77689a322..227d4a7acad7 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -212,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { }; MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); +#ifdef CONFIG_PM +static int dwc3_pci_suspend(struct device *dev) +{ + struct pci_dev *pci = to_pci_dev(dev); + + pci_disable_device(pci); + + return 0; +} + +static int dwc3_pci_resume(struct device *dev) +{ + struct pci_dev *pci = to_pci_dev(dev); + int ret; + + ret = pci_enable_device(pci); + if (ret) { + dev_err(dev, "can't re-enable device --> %d\n", ret); + return ret; + } + + pci_set_master(pci); + + return 0; +} + +static const struct dev_pm_ops dwc3_pci_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume) +}; + +#define DEV_PM_OPS (&dwc3_pci_dev_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM */ + static struct pci_driver dwc3_pci_driver = { .name = "dwc3-pci", .id_table = dwc3_pci_id_table, .probe = dwc3_pci_probe, .remove = dwc3_pci_remove, + .driver = { + .pm = DEV_PM_OPS, + }, }; MODULE_AUTHOR("Felipe Balbi "); From 6110a7ebda18d103f28bec0eab65f7be01871233 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 1 Feb 2013 23:33:50 +0200 Subject: [PATCH 059/303] usb: musb: core: remove unnecessary pr_info() there's really no need for that message. It's been a while since it printed something useful. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index daec6e0f7e38..36b7a1e16e48 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2293,8 +2293,6 @@ static int __init musb_init(void) if (usb_disabled()) return 0; - pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", - musb_driver_name); return platform_driver_register(&musb_driver); } module_init(musb_init); From b42f7f3091de06f25abf59a26a3446f7b2fd0a50 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Feb 2013 19:04:45 +0200 Subject: [PATCH 060/303] usb: musb: switch over to devm_ioremap_resource() this will make sure that request_memory_region() will be called and that we don't need to manually call iounmap() on ->remove(). Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 36b7a1e16e48..fad8571ed433 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2008,7 +2008,6 @@ static int musb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int irq = platform_get_irq_byname(pdev, "mc"); - int status; struct resource *iomem; void __iomem *base; @@ -2016,24 +2015,17 @@ static int musb_probe(struct platform_device *pdev) if (!iomem || irq <= 0) return -ENODEV; - base = ioremap(iomem->start, resource_size(iomem)); - if (!base) { - dev_err(dev, "ioremap failed\n"); - return -ENOMEM; - } + base = devm_ioremap_resource(dev, iomem); + if (IS_ERR(base)) + return PTR_ERR(base); - status = musb_init_controller(dev, irq, base); - if (status < 0) - iounmap(base); - - return status; + return musb_init_controller(dev, irq, base); } static int musb_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct musb *musb = dev_to_musb(dev); - void __iomem *ctrl_base = musb->ctrl_base; /* this gets called on rmmod. * - Host mode: host may still be active @@ -2044,7 +2036,6 @@ static int musb_remove(struct platform_device *pdev) musb_shutdown(pdev); musb_free(musb); - iounmap(ctrl_base); device_init_wakeup(dev, 0); #ifndef CONFIG_MUSB_PIO_ONLY dma_set_mask(dev, *dev->parent->dma_mask); From 38c5df225692cde4d695e4c74eaa7d83546ebe53 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Feb 2013 19:57:23 +0200 Subject: [PATCH 061/303] usb: musb: gadget: delete wrong comment Those comments haven't been updated for a long time, so much that they don't make sense anymore. Best to remove them. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 108 --------------------------------- 1 file changed, 108 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index e363033f6754..b47f66d32b40 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -46,48 +46,6 @@ #include "musb_core.h" -/* MUSB PERIPHERAL status 3-mar-2006: - * - * - EP0 seems solid. It passes both USBCV and usbtest control cases. - * Minor glitches: - * - * + remote wakeup to Linux hosts work, but saw USBCV failures; - * in one test run (operator error?) - * + endpoint halt tests -- in both usbtest and usbcv -- seem - * to break when dma is enabled ... is something wrongly - * clearing SENDSTALL? - * - * - Mass storage behaved ok when last tested. Network traffic patterns - * (with lots of short transfers etc) need retesting; they turn up the - * worst cases of the DMA, since short packets are typical but are not - * required. - * - * - TX/IN - * + both pio and dma behave in with network and g_zero tests - * + no cppi throughput issues other than no-hw-queueing - * + failed with FLAT_REG (DaVinci) - * + seems to behave with double buffering, PIO -and- CPPI - * + with gadgetfs + AIO, requests got lost? - * - * - RX/OUT - * + both pio and dma behave in with network and g_zero tests - * + dma is slow in typical case (short_not_ok is clear) - * + double buffering ok with PIO - * + double buffering *FAILS* with CPPI, wrong data bytes sometimes - * + request lossage observed with gadgetfs - * - * - ISO not tested ... might work, but only weakly isochronous - * - * - Gadget driver disabling of softconnect during bind() is ignored; so - * drivers can't hold off host requests until userspace is ready. - * (Workaround: they can turn it off later.) - * - * - PORTABILITY (assumes PIO works): - * + DaVinci, basically works with cppi dma - * + OMAP 2430, ditto with mentor dma - * + TUSB 6010, platform-specific dma in the works - */ - /* ----------------------------------------------------------------------- */ #define is_buffer_mapped(req) (is_dma_capable() && \ @@ -275,41 +233,6 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep) return ep->packet_sz; } - -#ifdef CONFIG_USB_INVENTRA_DMA - -/* Peripheral tx (IN) using Mentor DMA works as follows: - Only mode 0 is used for transfers <= wPktSize, - mode 1 is used for larger transfers, - - One of the following happens: - - Host sends IN token which causes an endpoint interrupt - -> TxAvail - -> if DMA is currently busy, exit. - -> if queue is non-empty, txstate(). - - - Request is queued by the gadget driver. - -> if queue was previously empty, txstate() - - txstate() - -> start - /\ -> setup DMA - | (data is transferred to the FIFO, then sent out when - | IN token(s) are recd from Host. - | -> DMA interrupt on completion - | calls TxAvail. - | -> stop DMA, ~DMAENAB, - | -> set TxPktRdy for last short pkt or zlp - | -> Complete Request - | -> Continue next request (call txstate) - |___________________________________| - - * Non-Mentor DMA engines can of course work differently, such as by - * upleveling from irq-per-packet to irq-per-buffer. - */ - -#endif - /* * An endpoint is transmitting data. This can be called either from * the IRQ routine or from ep.queue() to kickstart a request on an @@ -616,37 +539,6 @@ void musb_g_tx(struct musb *musb, u8 epnum) /* ------------------------------------------------------------ */ -#ifdef CONFIG_USB_INVENTRA_DMA - -/* Peripheral rx (OUT) using Mentor DMA works as follows: - - Only mode 0 is used. - - - Request is queued by the gadget class driver. - -> if queue was previously empty, rxstate() - - - Host sends OUT token which causes an endpoint interrupt - /\ -> RxReady - | -> if request queued, call rxstate - | /\ -> setup DMA - | | -> DMA interrupt on completion - | | -> RxReady - | | -> stop DMA - | | -> ack the read - | | -> if data recd = max expected - | | by the request, or host - | | sent a short packet, - | | complete the request, - | | and start the next one. - | |_____________________________________| - | else just wait for the host - | to send the next OUT token. - |__________________________________________________| - - * Non-Mentor DMA engines can of course work differently. - */ - -#endif - /* * Context: controller locked, IRQs blocked, endpoint selected */ From 99b7856f3cec5db7ec71a8b4675a63e4bcadd63e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Feb 2013 09:22:47 +0200 Subject: [PATCH 062/303] usb: musb: force PIO-only if we're building multiplatform kernels MUSB still needs lots of work on the DMA part if we want to enable multiple DMA engines on a multiplatform kernel. Meanwhile, we're forcing PIO-only so that we, at least, have a working driver. Signed-off-by: Felipe Balbi --- drivers/usb/musb/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 05e51432dd2f..39864e3184a6 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -67,6 +67,7 @@ endchoice choice prompt 'MUSB DMA mode' + default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM default USB_UX500_DMA if USB_MUSB_UX500 default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI From 787f5627bec80094db487bfcb401e9744f181aed Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Feb 2013 09:24:55 +0200 Subject: [PATCH 063/303] usb: musb: make davinci and da8xx glues depend on BROKEN those two glues are still including headers and no active developement has been going on those glues for quite some time. Apparently, for da8xx glue, only initial commit 3ee076de (usb: musb: introduce DA8xx/OMAP-L1x glue layer) has been tested. All other patches seem to have been compile-tested only. For davinci glue layer, last real commit dates back from 2010, with commit f405387 (USB: MUSB: fix kernel WARNING/oops when unloading module in OTG mode). Signed-off-by: Felipe Balbi --- drivers/usb/musb/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 39864e3184a6..de0fc884b6da 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -34,10 +34,12 @@ choice config USB_MUSB_DAVINCI tristate "DaVinci" depends on ARCH_DAVINCI_DMx + depends on BROKEN config USB_MUSB_DA8XX tristate "DA8xx/OMAP-L1x" depends on ARCH_DAVINCI_DA8XX + depends on BROKEN config USB_MUSB_TUSB6010 tristate "TUSB6010" From 0f53e48132cd95b359fc79e0aa44db1c406b4eff Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Feb 2013 09:47:58 +0200 Subject: [PATCH 064/303] usb: musb: dsps: add missing include is the header defining SZ_4 and SZ_16M, we shouldn't depend on indirect inclusion so let's explicitly include it. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 1 + drivers/usb/musb/ux500_dma.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 6bb89715b637..dfaa0241c223 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index 039e567dd3b6..12dd6ed7033c 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "musb_core.h" From 6a3b003620f0bd31390422619092fcb87cf1069e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Feb 2013 09:53:01 +0200 Subject: [PATCH 065/303] usb: musb: ux500_dma: kill compile warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following compile warnings: drivers/usb/musb/ux500_dma.c: In function ‘ux500_configure_channel’: drivers/usb/musb/ux500_dma.c:96:2: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 6 has type ‘dma_addr_t’ [-Wformat] drivers/usb/musb/ux500_dma.c: In function ‘ux500_dma_is_compatible’: drivers/usb/musb/ux500_dma.c:195:4: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] Signed-off-by: Felipe Balbi --- drivers/usb/musb/ux500_dma.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index 12dd6ed7033c..c3a584cf01bb 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -94,8 +94,9 @@ static bool ux500_configure_channel(struct dma_channel *channel, struct musb *musb = ux500_channel->controller->private_data; dev_dbg(musb->controller, - "packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n", - packet_sz, mode, dma_addr, len, ux500_channel->is_tx); + "packet_sz=%d, mode=%d, dma_addr=0x%llu, len=%d is_tx=%d\n", + packet_sz, mode, (unsigned long long) dma_addr, + len, ux500_channel->is_tx); ux500_channel->cur_len = len; @@ -192,7 +193,7 @@ static int ux500_dma_is_compatible(struct dma_channel *channel, u16 maxpacket, void *buf, u32 length) { if ((maxpacket & 0x3) || - ((int)buf & 0x3) || + ((unsigned long int) buf & 0x3) || (length < 512) || (length & 0x3)) return false; From cc5060366b3c8cc20f0f4020a15fa5d39f4dc936 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Feb 2013 09:57:18 +0200 Subject: [PATCH 066/303] usb: musb: dsps: fix possible compile warning if CONFIG_OF is disabled, np will be unused and that will give us a compile warning. This patch just avoids it. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index dfaa0241c223..4b4987461adb 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -597,14 +597,13 @@ err0: static int dsps_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; const struct dsps_musb_wrapper *wrp; struct dsps_glue *glue; struct resource *iomem; int ret, i; - match = of_match_node(musb_dsps_of_match, np); + match = of_match_node(musb_dsps_of_match, pdev->dev.of_node); if (!match) { dev_err(&pdev->dev, "fail to get matching of_match struct\n"); ret = -EINVAL; From 37730eccf214ec343b7b0e6cce31400f56ca09ff Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Feb 2013 10:19:15 +0200 Subject: [PATCH 067/303] usb: musb: gadget: fix compile warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following compile warning: drivers/usb/musb/musb_gadget.c: In function ‘rxstate’: drivers/usb/musb/musb_gadget.c:714:22: warning: comparison of distinct pointer types lacks a cast [enabled by default] Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index b47f66d32b40..d35a375c6070 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -627,7 +627,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) struct dma_controller *c; struct dma_channel *channel; int use_dma = 0; - int transfer_size; + unsigned int transfer_size; c = musb->dma_controller; channel = musb_ep->dma; @@ -669,10 +669,11 @@ static void rxstate(struct musb *musb, struct musb_request *req) csr | MUSB_RXCSR_DMAMODE); musb_writew(epio, MUSB_RXCSR, csr); - transfer_size = min(request->length - request->actual, + transfer_size = min_t(unsigned int, + request->length - + request->actual, channel->max_len); musb_ep->dma->desired_mode = 1; - } else { if (!musb_ep->hb_mult && musb_ep->hw_ep->rx_double_buffered) @@ -702,7 +703,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) struct dma_controller *c; struct dma_channel *channel; - int transfer_size = 0; + unsigned int transfer_size = 0; c = musb->dma_controller; channel = musb_ep->dma; @@ -711,11 +712,13 @@ static void rxstate(struct musb *musb, struct musb_request *req) if (fifo_count < musb_ep->packet_sz) transfer_size = fifo_count; else if (request->short_not_ok) - transfer_size = min(request->length - + transfer_size = min_t(unsigned int, + request->length - request->actual, channel->max_len); else - transfer_size = min(request->length - + transfer_size = min_t(unsigned int, + request->length - request->actual, (unsigned)fifo_count); From a033f7ae607eb1d281448cda694c83f0c3f95e0d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 6 Feb 2013 10:23:37 +0200 Subject: [PATCH 068/303] usb: musb: Kconfig: drop unnecessary dependencies those glues can build cleanly anywhere. Signed-off-by: Felipe Balbi --- drivers/usb/musb/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index de0fc884b6da..d38cf9859abb 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -55,7 +55,6 @@ config USB_MUSB_AM35X config USB_MUSB_DSPS tristate "TI DSPS platforms" - depends on SOC_TI81XX || SOC_AM33XX config USB_MUSB_BLACKFIN tristate "Blackfin" @@ -63,7 +62,6 @@ config USB_MUSB_BLACKFIN config USB_MUSB_UX500 tristate "U8500 and U5500" - depends on (ARCH_U8500 && AB8500_USB) endchoice From 9e86e71bcec99256fa29466d207b414919beb977 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Feb 2013 12:47:07 +0200 Subject: [PATCH 069/303] usb: dwc3: core: remove bogus comment to our structure that irq field has been removed already. This patch just removes its documentation. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 52e48e21c82f..80f763f92e04 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -618,7 +618,6 @@ struct dwc3_scratchpad_array { * @gadget_driver: pointer to the gadget driver * @regs: base address for our registers * @regs_size: address space size - * @irq: IRQ number * @num_event_buffers: calculated number of event buffers * @u1u2: only used on revisions <1.83a for workaround * @maximum_speed: maximum speed requested (mainly for testing purposes) From abed411869770a0f6c31e66388d7566bae672c2c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Jul 2011 20:20:04 +0300 Subject: [PATCH 070/303] usb: dwc3: add a flags field to event buffer that way we know if a particular event buffer has pending events, or not. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 80f763f92e04..e7b06798fb69 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -369,6 +369,8 @@ struct dwc3_trb; * @list: a list of event buffers * @buf: _THE_ buffer * @length: size of this buffer + * @lpos: event offset + * @flags: flags related to this event buffer * @dma: dma_addr_t * @dwc: pointer to DWC controller */ @@ -376,6 +378,9 @@ struct dwc3_event_buffer { void *buf; unsigned length; unsigned int lpos; + unsigned int flags; + +#define DWC3_EVENT_PENDING BIT(0) dma_addr_t dma; From 60d04bbee0b729dc1e95d4dc669f68dea2a32570 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 4 Jul 2011 20:23:14 +0300 Subject: [PATCH 071/303] usb: dwc3: add count field to event buffer we can cache the last read value of the event buffer count register on this field, for later handling. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index e7b06798fb69..cdd70cb78aa4 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -370,6 +370,7 @@ struct dwc3_trb; * @buf: _THE_ buffer * @length: size of this buffer * @lpos: event offset + * @count: cache of last read event count register * @flags: flags related to this event buffer * @dma: dma_addr_t * @dwc: pointer to DWC controller @@ -378,6 +379,7 @@ struct dwc3_event_buffer { void *buf; unsigned length; unsigned int lpos; + unsigned int count; unsigned int flags; #define DWC3_EVENT_PENDING BIT(0) From b15a762f02acb4f1e695a17435f719350f9d5bc1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 30 Jun 2011 16:57:15 +0300 Subject: [PATCH 072/303] usb: dwc3: gadget: move to threaded IRQ by moving to threaded IRQs, we allow our IRQ priorities to be configurable when running with realtime patch. Also, since we're running in thread context, we can call functions which might sleep, such as sysfs_notify() without problems. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 86 +++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 26 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 73b0b7fc77f1..742eb8268e9a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1496,6 +1496,7 @@ static void dwc3_gadget_disable_irq(struct dwc3 *dwc) } static irqreturn_t dwc3_interrupt(int irq, void *_dwc); +static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc); static int dwc3_gadget_start(struct usb_gadget *g, struct usb_gadget_driver *driver) @@ -1566,8 +1567,8 @@ static int dwc3_gadget_start(struct usb_gadget *g, dwc3_ep0_out_start(dwc); irq = platform_get_irq(to_platform_device(dwc->dev), 0); - ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, - "dwc3", dwc); + 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); @@ -2432,40 +2433,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc, } } +static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) +{ + struct dwc3 *dwc = _dwc; + unsigned long flags; + irqreturn_t ret = IRQ_NONE; + int i; + + spin_lock_irqsave(&dwc->lock, flags); + + for (i = 0; i < dwc->num_event_buffers; i++) { + struct dwc3_event_buffer *evt; + int left; + + evt = dwc->ev_buffs[i]; + left = evt->count; + + if (!(evt->flags & DWC3_EVENT_PENDING)) + continue; + + while (left > 0) { + union dwc3_event event; + + event.raw = *(u32 *) (evt->buf + evt->lpos); + + dwc3_process_event_entry(dwc, &event); + + /* + * FIXME we wrap around correctly to the next entry as + * almost all entries are 4 bytes in size. There is one + * entry which has 12 bytes which is a regular entry + * followed by 8 bytes data. ATM I don't know how + * things are organized if we get next to the a + * boundary so I worry about that once we try to handle + * that. + */ + evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; + left -= 4; + + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4); + } + + evt->count = 0; + evt->flags &= ~DWC3_EVENT_PENDING; + ret = IRQ_HANDLED; + } + + spin_unlock_irqrestore(&dwc->lock, flags); + + return ret; +} + static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) { struct dwc3_event_buffer *evt; - int left; u32 count; + evt = dwc->ev_buffs[buf]; + count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf)); count &= DWC3_GEVNTCOUNT_MASK; if (!count) return IRQ_NONE; - evt = dwc->ev_buffs[buf]; - left = count; + evt->count = count; + evt->flags |= DWC3_EVENT_PENDING; - while (left > 0) { - union dwc3_event event; - - event.raw = *(u32 *) (evt->buf + evt->lpos); - - dwc3_process_event_entry(dwc, &event); - /* - * XXX we wrap around correctly to the next entry as almost all - * entries are 4 bytes in size. There is one entry which has 12 - * bytes which is a regular entry followed by 8 bytes data. ATM - * I don't know how things are organized if were get next to the - * a boundary so I worry about that once we try to handle that. - */ - evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; - left -= 4; - - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4); - } - - return IRQ_HANDLED; + return IRQ_WAKE_THREAD; } static irqreturn_t dwc3_interrupt(int irq, void *_dwc) @@ -2480,7 +2514,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) irqreturn_t status; status = dwc3_process_event_buf(dwc, i); - if (status == IRQ_HANDLED) + if (status == IRQ_WAKE_THREAD) ret = status; } From d1e3d757f7aa91f15db347fc05ffd7ef7f413091 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Jan 2013 22:29:48 +0200 Subject: [PATCH 073/303] usb: common: introduce usb_state_string() this function will receive enum usb_device_state and return a human-readable string from it or, case an unknown value is passed as argument, the string "UNKNOWN". Signed-off-by: Felipe Balbi --- drivers/usb/usb-common.c | 21 +++++++++++++++++++++ include/linux/usb/ch9.h | 9 +++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c index d29503e954ab..070b681e5d17 100644 --- a/drivers/usb/usb-common.c +++ b/drivers/usb/usb-common.c @@ -32,4 +32,25 @@ const char *usb_speed_string(enum usb_device_speed speed) } EXPORT_SYMBOL_GPL(usb_speed_string); +const char *usb_state_string(enum usb_device_state state) +{ + static const char *const names[] = { + [USB_STATE_NOTATTACHED] = "not attached", + [USB_STATE_ATTACHED] = "attached", + [USB_STATE_POWERED] = "powered", + [USB_STATE_RECONNECTING] = "reconnecting", + [USB_STATE_UNAUTHENTICATED] = "unauthenticated", + [USB_STATE_DEFAULT] = "default", + [USB_STATE_ADDRESS] = "addresssed", + [USB_STATE_CONFIGURED] = "configured", + [USB_STATE_SUSPENDED] = "suspended", + }; + + if (state < 0 || state >= ARRAY_SIZE(names)) + return "UNKNOWN"; + + return names[state]; +} +EXPORT_SYMBOL_GPL(usb_state_string); + MODULE_LICENSE("GPL"); diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 9c210f2283df..27603bcbb9b9 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -43,4 +43,13 @@ */ extern const char *usb_speed_string(enum usb_device_speed speed); + +/** + * usb_state_string - Returns human readable name for the state. + * @state: The state to return a human-readable name for. If it's not + * any of the states devices in usb_device_state_string enum, + * the string UNKNOWN will be returned. + */ +extern const char *usb_state_string(enum usb_device_state state); + #endif /* __LINUX_USB_CH9_H */ From 49401f4169c0e5a1b38f1a676d6f12eecaf77485 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 12:57:04 +0200 Subject: [PATCH 074/303] usb: gadget: introduce gadget state tracking that's useful information to expose to userland. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 23 +++++++++++++++++++++++ include/linux/usb/gadget.h | 9 +++++++++ 2 files changed, 32 insertions(+) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 40b1d888d5a1..8a1eeb24ae6a 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -101,6 +101,16 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); /* ------------------------------------------------------------------------- */ +void usb_gadget_set_state(struct usb_gadget *gadget, + enum usb_device_state state) +{ + gadget->state = state; + sysfs_notify(&gadget->dev.kobj, NULL, "status"); +} +EXPORT_SYMBOL_GPL(usb_gadget_set_state); + +/* ------------------------------------------------------------------------- */ + /** * usb_gadget_udc_start - tells usb device controller to start up * @gadget: The gadget we want to get started @@ -197,6 +207,8 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) if (ret) goto err4; + usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED); + mutex_unlock(&udc_lock); return 0; @@ -406,6 +418,16 @@ static ssize_t usb_udc_softconn_store(struct device *dev, } static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store); +static ssize_t usb_gadget_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_udc *udc = container_of(dev, struct usb_udc, dev); + struct usb_gadget *gadget = udc->gadget; + + return sprintf(buf, "%s\n", usb_state_string(gadget->state)); +} +static DEVICE_ATTR(state, S_IRUGO, usb_gadget_state_show, NULL); + #define USB_UDC_SPEED_ATTR(name, param) \ ssize_t usb_udc_##param##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ @@ -439,6 +461,7 @@ static USB_UDC_ATTR(a_alt_hnp_support); static struct attribute *usb_udc_attrs[] = { &dev_attr_srp.attr, &dev_attr_soft_connect.attr, + &dev_attr_state.attr, &dev_attr_current_speed.attr, &dev_attr_maximum_speed.attr, diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 2e297e80d59a..32b734d88d6b 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -482,6 +482,7 @@ struct usb_gadget_ops { * @speed: Speed of current connection to USB host. * @max_speed: Maximal speed the UDC can handle. UDC must support this * and all slower speeds. + * @state: the state we are now (attached, suspended, configured, etc) * @sg_supported: true if we can handle scatter-gather * @is_otg: True if the USB device port uses a Mini-AB jack, so that the * gadget driver must provide a USB OTG descriptor. @@ -525,6 +526,7 @@ struct usb_gadget { struct list_head ep_list; /* of usb_ep */ enum usb_device_speed speed; enum usb_device_speed max_speed; + enum usb_device_state state; unsigned sg_supported:1; unsigned is_otg:1; unsigned is_a_peripheral:1; @@ -959,6 +961,13 @@ extern void usb_gadget_unmap_request(struct usb_gadget *gadget, /*-------------------------------------------------------------------------*/ +/* utility to set gadget state properly */ + +extern void usb_gadget_set_state(struct usb_gadget *gadget, + enum usb_device_state state); + +/*-------------------------------------------------------------------------*/ + /* utility wrapping a simple endpoint selection policy */ extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *, From 14cd592f72ea1ce1a25d7a576a5ed6aa761456bc Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 19 Dec 2011 13:01:52 +0200 Subject: [PATCH 075/303] usb: dwc3: gadget: implement gadget state tracking make use of the previously introduced gadget->state field. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 15 ++++++++++++--- drivers/usb/dwc3/gadget.c | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 1d139ca05ef1..2a82b7145052 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -512,10 +512,13 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) reg |= DWC3_DCFG_DEVADDR(addr); dwc3_writel(dwc->regs, DWC3_DCFG, reg); - if (addr) + if (addr) { dwc->dev_state = DWC3_ADDRESS_STATE; - else + usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); + } else { dwc->dev_state = DWC3_DEFAULT_STATE; + usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); + } return 0; } @@ -549,6 +552,9 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) /* if the cfg matches and the cfg is non zero */ if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { dwc->dev_state = DWC3_CONFIGURED_STATE; + usb_gadget_set_state(&dwc->gadget, + USB_STATE_CONFIGURED); + /* * Enable transition to U1/U2 state when * nothing is pending from application. @@ -564,8 +570,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) case DWC3_CONFIGURED_STATE: 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; default: ret = -EINVAL; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 742eb8268e9a..2686bf26ccaf 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2137,7 +2137,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) } /* after reset -> Default State */ - dwc->dev_state = DWC3_DEFAULT_STATE; + usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); /* Recent versions support automatic phy suspend and don't need this */ if (dwc->revision < DWC3_REVISION_194A) { From fdba5aa54cfca795b73e50d45f617a0498a29af7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 25 Jan 2013 11:28:19 +0200 Subject: [PATCH 076/303] usb: dwc3: remove our homebrew state mechanism We can reuse the generic implementation via our struct usb_gadget. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 7 ------- drivers/usb/dwc3/ep0.c | 34 +++++++++++++++++----------------- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index cdd70cb78aa4..d8c36fccce96 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -494,12 +494,6 @@ enum dwc3_link_state { DWC3_LINK_STATE_MASK = 0x0f, }; -enum dwc3_device_state { - DWC3_DEFAULT_STATE, - DWC3_ADDRESS_STATE, - DWC3_CONFIGURED_STATE, -}; - /* TRB Length, PCM and Status */ #define DWC3_TRB_SIZE_MASK (0x00ffffff) #define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK) @@ -721,7 +715,6 @@ struct dwc3 { enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; enum dwc3_link_state link_state; - enum dwc3_device_state dev_state; u16 isoch_delay; u16 u2sel; diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 2a82b7145052..5acbb948b704 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, u32 wIndex; u32 reg; int ret; + enum usb_device_state state; wValue = le16_to_cpu(ctrl->wValue); wIndex = le16_to_cpu(ctrl->wIndex); recip = ctrl->bRequestType & USB_RECIP_MASK; + state = dwc->gadget.state; + switch (recip) { case USB_RECIP_DEVICE: @@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, * default control pipe */ case USB_DEVICE_U1_ENABLE: - if (dwc->dev_state != DWC3_CONFIGURED_STATE) + if (state != USB_STATE_CONFIGURED) return -EINVAL; if (dwc->speed != DWC3_DSTS_SUPERSPEED) return -EINVAL; @@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, break; case USB_DEVICE_U2_ENABLE: - if (dwc->dev_state != DWC3_CONFIGURED_STATE) + if (state != USB_STATE_CONFIGURED) return -EINVAL; if (dwc->speed != DWC3_DSTS_SUPERSPEED) return -EINVAL; @@ -493,6 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { + enum usb_device_state state = dwc->gadget.state; u32 addr; u32 reg; @@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) return -EINVAL; } - if (dwc->dev_state == DWC3_CONFIGURED_STATE) { + if (state == USB_STATE_CONFIGURED) { dev_dbg(dwc->dev, "trying to set address when configured\n"); return -EINVAL; } @@ -512,13 +516,10 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) reg |= DWC3_DCFG_DEVADDR(addr); dwc3_writel(dwc->regs, DWC3_DCFG, reg); - if (addr) { - dwc->dev_state = DWC3_ADDRESS_STATE; + if (addr) usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); - } else { - dwc->dev_state = DWC3_DEFAULT_STATE; + else usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); - } return 0; } @@ -535,6 +536,7 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { + enum usb_device_state state = dwc->gadget.state; u32 cfg; int ret; u32 reg; @@ -542,16 +544,15 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) dwc->start_config_issued = false; cfg = le16_to_cpu(ctrl->wValue); - switch (dwc->dev_state) { - case DWC3_DEFAULT_STATE: + switch (state) { + case USB_STATE_DEFAULT: return -EINVAL; break; - case DWC3_ADDRESS_STATE: + case USB_STATE_ADDRESS: ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { - dwc->dev_state = DWC3_CONFIGURED_STATE; usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); @@ -568,13 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) } break; - case DWC3_CONFIGURED_STATE: + case USB_STATE_CONFIGURED: ret = dwc3_ep0_delegate_req(dwc, ctrl); - if (!cfg) { - dwc->dev_state = DWC3_ADDRESS_STATE; + if (!cfg) usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); - } break; default: ret = -EINVAL; @@ -629,10 +628,11 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req) static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) { struct dwc3_ep *dep; + enum usb_device_state state = dwc->gadget.state; u16 wLength; u16 wValue; - if (dwc->dev_state == DWC3_DEFAULT_STATE) + if (state == USB_STATE_DEFAULT) return -EINVAL; wValue = le16_to_cpu(ctrl->wValue); From 6b2a0eb854602b627a21b0256ae556506e91261e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Feb 2013 14:28:54 +0200 Subject: [PATCH 077/303] usb: dwc3: debugfs: add two missing Link States for Reset and Resume we were going to print "UNKNOWN" when we actually knew what those were. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 4a752e730c5f..c740c7643f43 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -577,6 +577,12 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) case DWC3_LINK_STATE_LPBK: seq_printf(s, "Loopback\n"); break; + case DWC3_LINK_STATE_RESET: + seq_printf(s, "Reset\n"); + break; + case DWC3_LINK_STATE_RESUME: + seq_printf(s, "Resume\n"); + break; default: seq_printf(s, "UNKNOWN %d\n", reg); } From 5b9ec339e45916ee682b8402597d7f2c6a04da17 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Feb 2013 14:29:39 +0200 Subject: [PATCH 078/303] usb: dwc3: debugfs: when unknown, print only the state value whenever we grab an unknown link_state we were printing the entire register value as a integer but that's hardly useful; instead, let's print only the bogus state value. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index c740c7643f43..5512560e972b 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -584,7 +584,7 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) seq_printf(s, "Resume\n"); break; default: - seq_printf(s, "UNKNOWN %d\n", reg); + seq_printf(s, "UNKNOWN %d\n", state); } return 0; From 4ec0ddb1b4fe3f7d93fdc862d2a7338cd354fe94 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Feb 2013 16:17:31 +0200 Subject: [PATCH 079/303] usb: dwc3: debugfs: mark our regset structure const nobody should be modifying that structure and debugfs has already being fixed to take const arguments, so we won't cause any new compile warnings. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 5512560e972b..a1bac9a07837 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -59,7 +59,7 @@ .offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \ } -static struct debugfs_reg32 dwc3_regs[] = { +static const struct debugfs_reg32 dwc3_regs[] = { dump_register(GSBUSCFG0), dump_register(GSBUSCFG1), dump_register(GTXTHRCFG), From dbfff05d7c9b982e364c90a699961fb7000c6181 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Feb 2013 16:24:49 +0200 Subject: [PATCH 080/303] usb: dwc3: debugfs: improve debugfs file creation when commit 388e5c5 (usb: dwc3: remove dwc3 dependency on host AND gadget.) changed the way debugfs files are created, it failed to note that 'mode' is necessary in Dual Role mode only while 'testmode' and 'link_state' are valid in Dual Role and Peripheral-only builds. Fix this while also converting pre- processor conditional to C conditionals. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/debugfs.c | 39 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index a1bac9a07837..8b23d0455b1c 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -667,28 +667,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc) goto err1; } -#if IS_ENABLED(CONFIG_USB_DWC3_GADGET) - file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, - dwc, &dwc3_mode_fops); - if (!file) { - ret = -ENOMEM; - goto err1; + if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { + file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, + dwc, &dwc3_mode_fops); + if (!file) { + ret = -ENOMEM; + goto err1; + } } - file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, - dwc, &dwc3_testmode_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } + if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) || + IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { + file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, + dwc, &dwc3_testmode_fops); + if (!file) { + ret = -ENOMEM; + goto err1; + } - file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, - dwc, &dwc3_link_state_fops); - if (!file) { - ret = -ENOMEM; - goto err1; + file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, + dwc, &dwc3_link_state_fops); + if (!file) { + ret = -ENOMEM; + goto err1; + } } -#endif return 0; From 67d0b500ebbe78e2ca50036721fef530dfd3d9c8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Feb 2013 16:31:07 +0200 Subject: [PATCH 081/303] usb: dwc3: core: avoid checkpatch.pl warning trivial patch to avoid "over 80-chars" rule break. No functional changes. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 75a9f88a5ad6..b81b3357f007 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -140,7 +140,8 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc, * Returns a pointer to the allocated event buffer structure on success * otherwise ERR_PTR(errno). */ -static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length) +static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, + unsigned length) { struct dwc3_event_buffer *evt; From 756380e04276c9099f41716d279d24e5847b1030 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 25 Feb 2013 09:46:18 +0200 Subject: [PATCH 082/303] usb: gadget: pxa27x_udc: drop ARCH_PXA dependency This driver can compile in any arch quite easily by just removing a few headers and dropping cpu_is_* check from module_init. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 - drivers/usb/gadget/pxa27x_udc.c | 11 ++--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 5a0c541daf89..50586fffa9fb 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -258,7 +258,6 @@ config USB_RENESAS_USBHS_UDC config USB_PXA27X tristate "PXA 27x" - depends on ARCH_PXA && (PXA27x || PXA3xx) select USB_OTG_UTILS help Intel's PXA 27x series XScale ARM v5TE processors include diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 07ce1477f911..def73f2aa18b 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -24,14 +24,12 @@ #include #include #include - -#include -#include +#include +#include #include #include #include -#include #include "pxa27x_udc.h" @@ -2624,15 +2622,10 @@ static struct platform_driver udc_driver = { static int __init udc_init(void) { - if (!cpu_is_pxa27x() && !cpu_is_pxa3xx()) - return -ENODEV; - - printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION); return platform_driver_probe(&udc_driver, pxa_udc_probe); } module_init(udc_init); - static void __exit udc_exit(void) { platform_driver_unregister(&udc_driver); From ef222cb5b575df57d8cd511965800519b90a6c31 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 25 Feb 2013 09:47:50 +0200 Subject: [PATCH 083/303] usb: gadget: pxa27x_udc: switch over to module_platform_driver just removing some boilerplate code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pxa27x_udc.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index def73f2aa18b..3276a6d278fd 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -2410,7 +2410,7 @@ static struct pxa_udc memory = { * Perform basic init : allocates udc clock, creates sysfs files, requests * irq. */ -static int __init pxa_udc_probe(struct platform_device *pdev) +static int pxa_udc_probe(struct platform_device *pdev) { struct resource *regs; struct pxa_udc *udc = &memory; @@ -2612,6 +2612,7 @@ static struct platform_driver udc_driver = { .name = "pxa27x-udc", .owner = THIS_MODULE, }, + .probe = pxa_udc_probe, .remove = __exit_p(pxa_udc_remove), .shutdown = pxa_udc_shutdown, #ifdef CONFIG_PM @@ -2620,17 +2621,7 @@ static struct platform_driver udc_driver = { #endif }; -static int __init udc_init(void) -{ - return platform_driver_probe(&udc_driver, pxa_udc_probe); -} -module_init(udc_init); - -static void __exit udc_exit(void) -{ - platform_driver_unregister(&udc_driver); -} -module_exit(udc_exit); +module_platform_driver(udc_driver); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR("Robert Jarzmik"); From 658c8cf14dce1093e9f810f7e04a711ed79da6bd Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 10:50:42 +0200 Subject: [PATCH 084/303] usb: gadget: udc-core: copy dma-related parameters from parent gadget's device pointer now is guaranteed to have valid dma_mask, dma_parms and coherent_dma_mask fields since we're always copying from our parent device. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 8a1eeb24ae6a..3e19a016c197 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -185,6 +185,10 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) dev_set_name(&gadget->dev, "gadget"); + dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask); + gadget->dev.dma_parms = parent->dma_parms; + gadget->dev.dma_mask = parent->dma_mask; + ret = device_register(&gadget->dev); if (ret) goto err2; From 2ed14320f3fed9e5b774ef68bdf73a4f3e28844e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 10:59:41 +0200 Subject: [PATCH 085/303] usb: gadget: udc-core: initialize parent if udc-core always does it, we can delete some extra lines from all UDC drivers. Besides, it avoids mistakes from happening and propagating. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 3e19a016c197..447a1614736e 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -184,6 +184,7 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) goto err1; dev_set_name(&gadget->dev, "gadget"); + gadget->dev.parent = parent; dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask); gadget->dev.dma_parms = parent->dma_parms; From 036804a4b7089bdff9e5c70805c09ce4133b4440 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 10:52:43 +0200 Subject: [PATCH 086/303] usb: gadget: chipidea: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/udc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 1b65ac8f3c9b..e303fd4b1b93 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1717,9 +1717,6 @@ static int udc_start(struct ci13xxx *ci) INIT_LIST_HEAD(&ci->gadget.ep_list); - 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 */ From 6c39d90393a2feff052f9cb5e460a5c2b25d8214 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 10:53:40 +0200 Subject: [PATCH 087/303] usb: gadget: amd5536udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index eec4461fb45f..c9941222e4a7 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3244,8 +3244,6 @@ static int udc_pci_probe( dev->phys_addr = resource; dev->irq = pdev->irq; dev->pdev = pdev; - dev->gadget.dev.parent = &pdev->dev; - dev->gadget.dev.dma_mask = pdev->dev.dma_mask; /* general probing */ if (udc_probe(dev) == 0) From 442803d844315a96ec5f3ed981a427ed56d41835 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 10:54:46 +0200 Subject: [PATCH 088/303] usb: gadget: atmel_usba_udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/atmel_usba_udc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 94aeba84b21e..e85d50b75de3 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1885,9 +1885,6 @@ static int __init usba_udc_probe(struct platform_device *pdev) dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n", (unsigned long)fifo->start, udc->fifo); - udc->gadget.dev.parent = &pdev->dev; - udc->gadget.dev.dma_mask = pdev->dev.dma_mask; - platform_set_drvdata(pdev, udc); /* Make sure we start from a clean slate */ From 9d2d93d86de32b82939a32d6abe6c8c5d3cb97f2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 10:57:06 +0200 Subject: [PATCH 089/303] usb: gadget: bcm63xx_udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/bcm63xx_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index d4f73e1b37e6..e7d2cd0b8f94 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -2371,9 +2371,7 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) udc->gadget.ops = &bcm63xx_udc_ops; udc->gadget.name = dev_name(dev); - udc->gadget.dev.parent = dev; udc->gadget.dev.release = bcm63xx_udc_gadget_release; - udc->gadget.dev.dma_mask = dev->dma_mask; if (!pd->use_fullspeed && !use_fullspeed) udc->gadget.max_speed = USB_SPEED_HIGH; From 9502d03c429860f83370615922bcb45050417ad8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:03:46 +0200 Subject: [PATCH 090/303] usb: gadget: fusb300_udc: remove unnecessary initializations udc-core nos sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fusb300_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index 5c9dd064767f..7f48aa6a5d3f 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -1420,8 +1420,6 @@ static int __init fusb300_probe(struct platform_device *pdev) fusb300->gadget.ops = &fusb300_gadget_ops; fusb300->gadget.max_speed = USB_SPEED_HIGH; - fusb300->gadget.dev.parent = &pdev->dev; - fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask; fusb300->gadget.dev.release = pdev->dev.release; fusb300->gadget.name = udc_name; fusb300->reg = reg; From 1a36315c976bb1e0f8aa6e18c149a951d685cc20 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:04:34 +0200 Subject: [PATCH 091/303] usb: gadget: goku_udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/goku_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 8a6c66618bd3..c02cbdd182c5 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1754,8 +1754,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.max_speed = USB_SPEED_FULL; /* the "gadget" abstracts/virtualizes the controller */ - dev->gadget.dev.parent = &pdev->dev; - dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; dev->gadget.name = driver_name; From 975cbd49391822bc98f693e3a43d26754849948a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:05:19 +0200 Subject: [PATCH 092/303] usb: gadget: goku_udc: remove unused macro DMA_ADDR_INVALID isn't used anymore on goku_udc, we can just delete it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/goku_udc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index c02cbdd182c5..1c070f4209f0 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -51,8 +51,6 @@ #define DRIVER_DESC "TC86C001 USB Device Controller" #define DRIVER_VERSION "30-Oct 2003" -#define DMA_ADDR_INVALID (~(dma_addr_t)0) - static const char driver_name [] = "goku_udc"; static const char driver_desc [] = DRIVER_DESC; @@ -275,7 +273,6 @@ goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) if (!req) return NULL; - req->req.dma = DMA_ADDR_INVALID; INIT_LIST_HEAD(&req->queue); return &req->req; } From 53fae098be09eeced37cf06419ae4e9c872cf0d0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:06:17 +0200 Subject: [PATCH 093/303] usb: gadget: imx_udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/imx_udc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 9c5b7451a7d1..c29d9e81dae4 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1461,9 +1461,6 @@ static int __init imx_udc_probe(struct platform_device *pdev) imx_usb->clk = clk; imx_usb->dev = &pdev->dev; - imx_usb->gadget.dev.parent = &pdev->dev; - imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask; - platform_set_drvdata(pdev, imx_usb); usb_init_data(imx_usb); From 859d02c2d84da10536d1e0f1cebfa9105023f8e6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:07:39 +0200 Subject: [PATCH 094/303] usb: gadget: m66592-udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/m66592-udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index eb61d0b54f21..ae33e535c283 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1608,8 +1608,6 @@ static int __init m66592_probe(struct platform_device *pdev) m66592->gadget.ops = &m66592_gadget_ops; m66592->gadget.max_speed = USB_SPEED_HIGH; - m66592->gadget.dev.parent = &pdev->dev; - m66592->gadget.dev.dma_mask = pdev->dev.dma_mask; m66592->gadget.dev.release = pdev->dev.release; m66592->gadget.name = udc_name; From 1048d83d5bfcbf1c71391fc1aae57326e940149c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:10:03 +0200 Subject: [PATCH 095/303] usb: dwc3: gadget: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2686bf26ccaf..322fb0bf6fce 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2569,13 +2569,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.ops = &dwc3_gadget_ops; dwc->gadget.max_speed = USB_SPEED_SUPER; dwc->gadget.speed = USB_SPEED_UNKNOWN; - dwc->gadget.dev.parent = dwc->dev; dwc->gadget.sg_supported = true; - - dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); - - dwc->gadget.dev.dma_parms = dwc->dev->dma_parms; - dwc->gadget.dev.dma_mask = dwc->dev->dma_mask; dwc->gadget.dev.release = dwc3_gadget_release; dwc->gadget.name = "dwc3-gadget"; From 2b5ced1a0cf2407e2bbe66e49687f6eb59d5df94 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:13:28 +0200 Subject: [PATCH 096/303] usb: gadget: mv_u3d_core: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index e5735fc610de..e6521b195449 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -1955,8 +1955,6 @@ static int mv_u3d_probe(struct platform_device *dev) u3d->gadget.speed = USB_SPEED_UNKNOWN; /* speed */ /* the "gadget" abstracts/virtualizes the controller */ - u3d->gadget.dev.parent = &dev->dev; - u3d->gadget.dev.dma_mask = dev->dev.dma_mask; u3d->gadget.dev.release = mv_u3d_gadget_release; u3d->gadget.name = driver_name; /* gadget name */ From d606b356cd07ffa3daea6dfcbf50fc2cbf4ba9a3 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:14:14 +0200 Subject: [PATCH 097/303] usb: gadget: mv_udc_core: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 7f4d19d75578..b3061112d13a 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2268,8 +2268,6 @@ static int mv_udc_probe(struct platform_device *pdev) udc->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */ /* the "gadget" abstracts/virtualizes the controller */ - udc->gadget.dev.parent = &pdev->dev; - udc->gadget.dev.dma_mask = pdev->dev.dma_mask; udc->gadget.dev.release = gadget_release; udc->gadget.name = driver_name; /* gadget name */ From 162303f6d39c94d984d291fa4f13510093356404 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:14:54 +0200 Subject: [PATCH 098/303] usb: gadget: net2272: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2272.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 78c8bb538332..bfb55d382cf9 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2235,8 +2235,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq) ret->gadget.max_speed = USB_SPEED_HIGH; /* the "gadget" abstracts/virtualizes the controller */ - ret->gadget.dev.parent = dev; - ret->gadget.dev.dma_mask = dev->dma_mask; ret->gadget.dev.release = net2272_gadget_release; ret->gadget.name = driver_name; From 2127ce0f2f11b2817e8ed8e3bd728731e06baac0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:15:29 +0200 Subject: [PATCH 099/303] usb: gadget: net2280: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2280.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 2089d9b0058c..6ce25133c14c 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2710,8 +2710,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.max_speed = USB_SPEED_HIGH; /* the "gadget" abstracts/virtualizes the controller */ - dev->gadget.dev.parent = &pdev->dev; - dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; dev->gadget.name = driver_name; From 981e070fdde4316d5a8d0c9681db505ba6a833eb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:16:36 +0200 Subject: [PATCH 100/303] usb: gadget: omap_udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index b23c861e2a97..bda1abdd75d8 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2631,12 +2631,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) udc->gadget.speed = USB_SPEED_UNKNOWN; udc->gadget.max_speed = USB_SPEED_FULL; udc->gadget.name = driver_name; - udc->gadget.dev.release = omap_udc_release; - udc->gadget.dev.parent = &odev->dev; - if (use_dma) - udc->gadget.dev.dma_mask = odev->dev.dma_mask; - udc->transceiver = xceiv; /* ep0 is special; put it right after the SETUP buffer */ From 91497600e27abf38ca00ead504fe2fdffab7e5c4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:17:25 +0200 Subject: [PATCH 101/303] usb: gadget: pch_udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index e8c9afd8fbf0..c1db902ebb7f 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -3193,8 +3193,6 @@ static int pch_udc_probe(struct pci_dev *pdev, if (retval) goto finished; - dev->gadget.dev.parent = &pdev->dev; - dev->gadget.dev.dma_mask = pdev->dev.dma_mask; dev->gadget.dev.release = gadget_release; dev->gadget.name = KBUILD_MODNAME; dev->gadget.max_speed = USB_SPEED_HIGH; From 6966fe8add4d47a2d55cab197925165e772f1197 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:19:56 +0200 Subject: [PATCH 102/303] usb: gadget: pxa25x_udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pxa25x_udc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index e29bb878b2d7..9fea05340689 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -2138,9 +2138,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) dev->timer.function = udc_watchdog; dev->timer.data = (unsigned long) dev; - dev->gadget.dev.parent = &pdev->dev; - dev->gadget.dev.dma_mask = pdev->dev.dma_mask; - the_controller = dev; platform_set_drvdata(pdev, dev); From b372c9572c4513500f0811371f3bd09616a64eba Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:20:39 +0200 Subject: [PATCH 103/303] usb: gadget: pxa27x_udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pxa27x_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 3276a6d278fd..5fda425f263f 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -2453,8 +2453,6 @@ static int pxa_udc_probe(struct platform_device *pdev) goto err_map; } - udc->gadget.dev.parent = &pdev->dev; - udc->gadget.dev.dma_mask = NULL; udc->vbus_sensed = 0; the_controller = udc; From 71b0dd272d9c5d985c4174632a28d6b8c990093c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:21:35 +0200 Subject: [PATCH 104/303] usb: gadget: r8a66597-udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/r8a66597-udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index a67d47708b98..2de775dbd92c 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1915,8 +1915,6 @@ static int __init r8a66597_probe(struct platform_device *pdev) r8a66597->gadget.ops = &r8a66597_gadget_ops; r8a66597->gadget.max_speed = USB_SPEED_HIGH; - r8a66597->gadget.dev.parent = &pdev->dev; - r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask; r8a66597->gadget.dev.release = pdev->dev.release; r8a66597->gadget.name = udc_name; From 2015760c2e626cc71ecd471648941b29789972bf Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:23:05 +0200 Subject: [PATCH 105/303] usb: gadget: s3c-hsotg: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 2812fa51e296..9d2330de5fcf 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2927,7 +2927,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, hsotg->driver = driver; hsotg->gadget.dev.driver = &driver->driver; hsotg->gadget.dev.of_node = hsotg->dev->of_node; - hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask; hsotg->gadget.speed = USB_SPEED_UNKNOWN; ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies), @@ -3534,8 +3533,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) hsotg->gadget.max_speed = USB_SPEED_HIGH; hsotg->gadget.ops = &s3c_hsotg_gadget_ops; hsotg->gadget.name = dev_name(dev); - hsotg->gadget.dev.parent = dev; - hsotg->gadget.dev.dma_mask = dev->dma_mask; hsotg->gadget.dev.release = s3c_hsotg_release; /* reset the system */ From 4c422049bd0f373b79b3dfbb7f984958c80bc7aa Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:23:52 +0200 Subject: [PATCH 106/303] usb: gadget: s3c-hsudc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsudc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 7fc3de537c9a..8db7b10f3d07 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1306,8 +1306,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev) hsudc->gadget.max_speed = USB_SPEED_HIGH; hsudc->gadget.ops = &s3c_hsudc_gadget_ops; hsudc->gadget.name = dev_name(dev); - hsudc->gadget.dev.parent = dev; - hsudc->gadget.dev.dma_mask = dev->dma_mask; hsudc->gadget.ep0 = &hsudc->ep[0].ep; hsudc->gadget.is_otg = 0; hsudc->gadget.is_a_peripheral = 0; From 31bff47aa2147ceab5d88a12f115afa44cdf4449 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:24:30 +0200 Subject: [PATCH 107/303] usb: gadget: s3c2410_udc: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c2410_udc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index a669081bbb88..e15d1bbc2ad9 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1824,9 +1824,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev) goto err_mem; } - udc->gadget.dev.parent = &pdev->dev; - udc->gadget.dev.dma_mask = pdev->dev.dma_mask; - the_controller = udc; platform_set_drvdata(pdev, udc); From 5e6e3d3814004a509c9023abfc86ddea6803f8e1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 11:25:21 +0200 Subject: [PATCH 108/303] usb: musb: gadget: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d35a375c6070..2dd952c330fd 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1782,8 +1782,6 @@ int musb_gadget_setup(struct musb *musb) musb->g.speed = USB_SPEED_UNKNOWN; /* this "gadget" abstracts/virtualizes the controller */ - musb->g.dev.parent = musb->controller; - musb->g.dev.dma_mask = musb->controller->dma_mask; musb->g.dev.release = musb_gadget_release; musb->g.name = musb_driver_name; musb->g.is_otg = 1; From 8a1c33075e5e42074397aa8478fc16481e306b31 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:59:40 +0200 Subject: [PATCH 109/303] usb: gadget: fsl_udc_core: remove unnecessary initializations udc-core now sets dma-related and parent fields for us, we don't need to do it ourselves. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_udc_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index c948241c6507..acb176d54067 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2497,7 +2497,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) /* Setup gadget.dev and register with kernel */ dev_set_name(&udc_controller->gadget.dev, "gadget"); udc_controller->gadget.dev.release = fsl_udc_release; - udc_controller->gadget.dev.parent = &pdev->dev; udc_controller->gadget.dev.of_node = pdev->dev.of_node; if (!IS_ERR_OR_NULL(udc_controller->transceiver)) From 70d3a49878cb3fc0e5ec0bd1e607c7ac63743f67 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 13:51:24 +0200 Subject: [PATCH 110/303] usb: gadget: udc-core: initialize gadget->dev.driver if we initialize gadget->dev.driver ourselves, UDC drivers won't have to do the same, so we can remove some duplicated code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 447a1614736e..2423d024654f 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -247,6 +247,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) udc->driver = NULL; udc->dev.driver = NULL; + udc->gadget->dev.driver = NULL; } /** @@ -296,6 +297,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri udc->driver = driver; udc->dev.driver = &driver->driver; + udc->gadget->dev.driver = &driver->driver; ret = driver->bind(udc->gadget, driver); if (ret) @@ -314,6 +316,7 @@ err1: udc->driver->function, ret); udc->driver = NULL; udc->dev.driver = NULL; + udc->gadget->dev.driver = NULL; return ret; } From 180cc68ed82ced0c19f5a478f8d1cdd2024c1875 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:15:15 +0200 Subject: [PATCH 111/303] usb: dwc3: gadget: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 322fb0bf6fce..9339eb10508f 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1519,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g, } dwc->gadget_driver = driver; - dwc->gadget.dev.driver = &driver->driver; reg = dwc3_readl(dwc->regs, DWC3_DCFG); reg &= ~(DWC3_DCFG_SPEED_MASK); @@ -1607,7 +1606,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g, __dwc3_gadget_ep_disable(dwc->eps[1]); dwc->gadget_driver = NULL; - dwc->gadget.dev.driver = NULL; spin_unlock_irqrestore(&dwc->lock, flags); From fd3682d9fd49210447c37085fe4e96e74061ae7f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:15:51 +0200 Subject: [PATCH 112/303] usb: gadget: amd5536udc: don't touch gadget.dev.driver udc-core handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index c9941222e4a7..a8ff93cf344d 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g, driver->driver.bus = NULL; dev->driver = driver; - dev->gadget.dev.driver = &driver->driver; /* Some gadget drivers use both ep0 directions. * NOTE: to gadget driver, ep0 is just one endpoint... @@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g, shutdown(dev, driver); spin_unlock_irqrestore(&dev->lock, flags); - dev->gadget.dev.driver = NULL; dev->driver = NULL; /* set SD */ From 8f3d7c86944ad03b2b45f1f4442577f087bb8591 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:16:21 +0200 Subject: [PATCH 113/303] usb: gadget: at91_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 9936de9bbe50..a690d64217f4 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget, udc = container_of(gadget, struct at91_udc, gadget); udc->driver = driver; - udc->gadget.dev.driver = &driver->driver; udc->gadget.dev.of_node = udc->pdev->dev.of_node; udc->enabled = 1; udc->selfpowered = 1; @@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget, at91_udp_write(udc, AT91_UDP_IDR, ~0); spin_unlock_irqrestore(&udc->lock, flags); - udc->gadget.dev.driver = NULL; udc->driver = NULL; DBG("unbound from %s\n", driver->driver.name); From 1503a33932732dfbd880b905993e4122a7b53f53 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:34:17 +0200 Subject: [PATCH 114/303] usb: gadget: atmel_usba_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/atmel_usba_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index e85d50b75de3..f2a970f75bfa 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1784,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget, udc->devstatus = 1 << USB_DEVICE_SELF_POWERED; udc->driver = driver; - udc->gadget.dev.driver = &driver->driver; spin_unlock_irqrestore(&udc->lock, flags); clk_enable(udc->pclk); @@ -1826,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget, toggle_bias(0); usba_writel(udc, CTRL, USBA_DISABLE_MASK); - udc->gadget.dev.driver = NULL; udc->driver = NULL; clk_disable(udc->hclk); From 155149e6724435eff47e0c6427b271b23815b40e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:34:33 +0200 Subject: [PATCH 115/303] usb: gadget: bcm63xx_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/bcm63xx_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index e7d2cd0b8f94..904d4746922d 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget, udc->driver = driver; driver->driver.bus = NULL; - udc->gadget.dev.driver = &driver->driver; udc->gadget.dev.of_node = udc->dev->of_node; spin_unlock_irqrestore(&udc->lock, flags); @@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget, spin_lock_irqsave(&udc->lock, flags); udc->driver = NULL; - udc->gadget.dev.driver = NULL; /* * If we switch the PHY too abruptly after dropping D+, the host From 42c82fb4d1658bb9630f6248178f79d8854c5bfd Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:34:49 +0200 Subject: [PATCH 116/303] usb: gadget: dummy_hcd: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index c4f27d5a2b9c..9d54c01cbf56 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g, dum->devstatus = 0; dum->driver = driver; - dum->gadget.dev.driver = &driver->driver; dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n", driver->driver.name); return 0; @@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g, dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n", driver->driver.name); - dum->gadget.dev.driver = NULL; dum->driver = NULL; return 0; From fc2dba950b27e6ec412efb932458cd6abfe77940 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:35:06 +0200 Subject: [PATCH 117/303] usb: gadget: fsl_qe_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_qe_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 0e7531bd33f4..37feb62fa930 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget, driver->driver.bus = NULL; /* hook up the driver */ udc->driver = driver; - udc->gadget.dev.driver = &driver->driver; udc->gadget.speed = driver->max_speed; /* Enable IRQ reg and Set usbcmd reg EN bit */ @@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget, nuke(loop_ep, -ESHUTDOWN); spin_unlock_irqrestore(&udc->lock, flags); - udc->gadget.dev.driver = NULL; udc->driver = NULL; dev_info(udc->dev, "unregistered gadget driver '%s'\r\n", From a1827ef6ac81072e9f2894d0db8cfa956d1b2a8d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:35:15 +0200 Subject: [PATCH 118/303] usb: gadget: fsl_udc_core: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_udc_core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index acb176d54067..4d5ff236bed4 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1939,7 +1939,6 @@ static int fsl_udc_start(struct usb_gadget *g, driver->driver.bus = NULL; /* hook up the driver */ udc_controller->driver = driver; - udc_controller->gadget.dev.driver = &driver->driver; spin_unlock_irqrestore(&udc_controller->lock, flags); if (!IS_ERR_OR_NULL(udc_controller->transceiver)) { @@ -1955,7 +1954,6 @@ static int fsl_udc_start(struct usb_gadget *g, if (retval < 0) { ERR("can't bind to transceiver\n"); driver->unbind(&udc_controller->gadget); - udc_controller->gadget.dev.driver = 0; udc_controller->driver = 0; return retval; } @@ -1998,7 +1996,6 @@ static int fsl_udc_stop(struct usb_gadget *g, nuke(loop_ep, -ESHUTDOWN); spin_unlock_irqrestore(&udc_controller->lock, flags); - udc_controller->gadget.dev.driver = NULL; udc_controller->driver = NULL; return 0; From 6a609129c2e4da76bc3607671d33d660faf52590 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:35:24 +0200 Subject: [PATCH 119/303] usb: gadget: fusb300_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fusb300_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index 7f48aa6a5d3f..d69e840b101b 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -1313,7 +1313,6 @@ static int fusb300_udc_start(struct usb_gadget *g, /* hook up the driver */ driver->driver.bus = NULL; fusb300->driver = driver; - fusb300->gadget.dev.driver = &driver->driver; return 0; } @@ -1324,7 +1323,6 @@ static int fusb300_udc_stop(struct usb_gadget *g, struct fusb300 *fusb300 = to_fusb300(g); driver->unbind(&fusb300->gadget); - fusb300->gadget.dev.driver = NULL; init_controller(fusb300); fusb300->driver = NULL; From 88060d60b618cd71a5e109ac9d3d629556dcea25 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:35:31 +0200 Subject: [PATCH 120/303] usb: gadget: goku_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/goku_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 1c070f4209f0..aa1976ee34e0 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1351,7 +1351,6 @@ static int goku_udc_start(struct usb_gadget *g, /* hook up the driver */ driver->driver.bus = NULL; dev->driver = driver; - dev->gadget.dev.driver = &driver->driver; /* * then enable host detection and ep0; and we're ready @@ -1391,7 +1390,6 @@ static int goku_udc_stop(struct usb_gadget *g, dev->driver = NULL; stop_activity(dev, driver); spin_unlock_irqrestore(&dev->lock, flags); - dev->gadget.dev.driver = NULL; return 0; } From 9fa4c960aa5ed69cde90283d8a0a750a2f36504c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:35:40 +0200 Subject: [PATCH 121/303] usb: gadget: imx_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/imx_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index c29d9e81dae4..b5cebd6b0d7a 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1338,7 +1338,6 @@ static int imx_udc_start(struct usb_gadget *gadget, imx_usb = container_of(gadget, struct imx_udc_struct, gadget); /* first hook up the driver ... */ imx_usb->driver = driver; - imx_usb->gadget.dev.driver = &driver->driver; D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n", __func__, driver->driver.name); @@ -1358,7 +1357,6 @@ static int imx_udc_stop(struct usb_gadget *gadget, imx_udc_disable(imx_usb); del_timer(&imx_usb->timer); - imx_usb->gadget.dev.driver = NULL; imx_usb->driver = NULL; D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n", From ee4b47cf6b026d35528ecc78e7c82d2c5eae28be Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:35:48 +0200 Subject: [PATCH 122/303] usb: gadget: lpc32xx_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/lpc32xx_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index 147832783900..b943d8cdfbf7 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -2946,7 +2946,6 @@ static int lpc32xx_start(struct usb_gadget *gadget, } udc->driver = driver; - udc->gadget.dev.driver = &driver->driver; udc->gadget.dev.of_node = udc->dev->of_node; udc->enabled = 1; udc->selfpowered = 1; @@ -2995,7 +2994,6 @@ static int lpc32xx_stop(struct usb_gadget *gadget, } udc->enabled = 0; - udc->gadget.dev.driver = NULL; udc->driver = NULL; return 0; From e3ee46f291875a18afe9debeeb676483953e22e7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:35:53 +0200 Subject: [PATCH 123/303] usb: gadget: m66592-udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/m66592-udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index ae33e535c283..21a20a6ffb66 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1471,7 +1471,6 @@ static int m66592_udc_start(struct usb_gadget *g, /* hook up the driver */ driver->driver.bus = NULL; m66592->driver = driver; - m66592->gadget.dev.driver = &driver->driver; m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0); if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) { @@ -1494,7 +1493,6 @@ static int m66592_udc_stop(struct usb_gadget *g, m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0); driver->unbind(&m66592->gadget); - m66592->gadget.dev.driver = NULL; init_controller(m66592); disable_controller(m66592); From 900b5817d874dd894ca05b2cd8df8acd63dfd64e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:35:59 +0200 Subject: [PATCH 124/303] usb: gadget: mv_u3d_core: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index e6521b195449..dc6445046da7 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -1264,7 +1264,6 @@ static int mv_u3d_start(struct usb_gadget *g, /* hook up the driver ... */ driver->driver.bus = NULL; u3d->driver = driver; - u3d->gadget.dev.driver = &driver->driver; u3d->ep0_dir = USB_DIR_OUT; @@ -1302,7 +1301,6 @@ static int mv_u3d_stop(struct usb_gadget *g, spin_unlock_irqrestore(&u3d->lock, flags); - u3d->gadget.dev.driver = NULL; u3d->driver = NULL; return 0; From 9ab7f79923f7ff2af798c42da104a03a936f704d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:36:05 +0200 Subject: [PATCH 125/303] usb: gadget: mv_udc_core: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc_core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index b3061112d13a..d1b243d76669 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -1352,7 +1352,6 @@ static int mv_udc_start(struct usb_gadget *gadget, /* hook up the driver ... */ driver->driver.bus = NULL; udc->driver = driver; - udc->gadget.dev.driver = &driver->driver; udc->usb_state = USB_STATE_ATTACHED; udc->ep0_state = WAIT_FOR_SETUP; @@ -1367,7 +1366,6 @@ static int mv_udc_start(struct usb_gadget *gadget, dev_err(&udc->dev->dev, "unable to register peripheral to otg\n"); udc->driver = NULL; - udc->gadget.dev.driver = NULL; return retval; } } @@ -1403,7 +1401,6 @@ static int mv_udc_stop(struct usb_gadget *gadget, spin_unlock_irqrestore(&udc->lock, flags); /* unbind gadget driver */ - udc->gadget.dev.driver = NULL; udc->driver = NULL; return 0; From 812abae5d66ce1a7a102afe1b3564df597687e79 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:36:14 +0200 Subject: [PATCH 126/303] usb: gadget: net2272: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2272.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index bfb55d382cf9..af99223e0126 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -1467,7 +1467,6 @@ static int net2272_start(struct usb_gadget *_gadget, dev->softconnect = 1; driver->driver.bus = NULL; dev->driver = driver; - dev->gadget.dev.driver = &driver->driver; /* ... then enable host detection and ep0; and we're ready * for set_configuration as well as eventual disconnect. @@ -1510,7 +1509,6 @@ static int net2272_stop(struct usb_gadget *_gadget, stop_activity(dev, driver); spin_unlock_irqrestore(&dev->lock, flags); - dev->gadget.dev.driver = NULL; dev->driver = NULL; dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name); From 68abc94f8de89ef885332a101654a0aef2db6d97 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:36:21 +0200 Subject: [PATCH 127/303] usb: gadget: net2280: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2280.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 6ce25133c14c..9e4f0a26108e 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -1896,7 +1896,6 @@ static int net2280_start(struct usb_gadget *_gadget, dev->softconnect = 1; driver->driver.bus = NULL; dev->driver = driver; - dev->gadget.dev.driver = &driver->driver; retval = device_create_file (&dev->pdev->dev, &dev_attr_function); if (retval) goto err_unbind; @@ -1925,7 +1924,6 @@ err_func: device_remove_file (&dev->pdev->dev, &dev_attr_function); err_unbind: driver->unbind (&dev->gadget); - dev->gadget.dev.driver = NULL; dev->driver = NULL; return retval; } @@ -1961,7 +1959,6 @@ static int net2280_stop(struct usb_gadget *_gadget, stop_activity (dev, driver); spin_unlock_irqrestore (&dev->lock, flags); - dev->gadget.dev.driver = NULL; dev->driver = NULL; net2280_led_active (dev, 0); From f6511d153eff9cd16e44ab54faa63149e2ddef75 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:36:26 +0200 Subject: [PATCH 128/303] usb: gadget: omap_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index bda1abdd75d8..19420ad128ce 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2067,7 +2067,6 @@ static int omap_udc_start(struct usb_gadget *g, /* hook up the driver */ driver->driver.bus = NULL; udc->driver = driver; - udc->gadget.dev.driver = &driver->driver; spin_unlock_irqrestore(&udc->lock, flags); if (udc->dc_clk != NULL) @@ -2083,7 +2082,6 @@ static int omap_udc_start(struct usb_gadget *g, ERR("can't bind to transceiver\n"); if (driver->unbind) { driver->unbind(&udc->gadget); - udc->gadget.dev.driver = NULL; udc->driver = NULL; } goto done; @@ -2129,7 +2127,6 @@ static int omap_udc_stop(struct usb_gadget *g, udc_quiesce(udc); spin_unlock_irqrestore(&udc->lock, flags); - udc->gadget.dev.driver = NULL; udc->driver = NULL; if (udc->dc_clk != NULL) From 37e337e1d3e20b101d6f3a6b55e7c7118a6d99a0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:36:40 +0200 Subject: [PATCH 129/303] usb: gadget: pch_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index c1db902ebb7f..79cf2966f634 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -2988,7 +2988,6 @@ static int pch_udc_start(struct usb_gadget *g, driver->driver.bus = NULL; dev->driver = driver; - dev->gadget.dev.driver = &driver->driver; /* get ready for ep0 traffic */ pch_udc_setup_ep0(dev); @@ -3009,7 +3008,6 @@ static int pch_udc_stop(struct usb_gadget *g, pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK); /* Assures that there are no pending requests with this driver */ - dev->gadget.dev.driver = NULL; dev->driver = NULL; dev->connected = 0; From 83a9adc9d815d12797df45a30c0f391c07c762bd Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:36:47 +0200 Subject: [PATCH 130/303] usb: gadget: pxa25x_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pxa25x_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 9fea05340689..ef47495dec8f 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -1263,7 +1263,6 @@ static int pxa25x_udc_start(struct usb_gadget *g, /* first hook up the driver ... */ dev->driver = driver; - dev->gadget.dev.driver = &driver->driver; dev->pullup = 1; /* ... then enable host detection and ep0; and we're ready @@ -1325,7 +1324,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g, if (!IS_ERR_OR_NULL(dev->transceiver)) (void) otg_set_peripheral(dev->transceiver->otg, NULL); - dev->gadget.dev.driver = NULL; dev->driver = NULL; dump_state(dev); From 0280f4d99a1e9ff2883a3df20ad2c995110ed011 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:36:52 +0200 Subject: [PATCH 131/303] usb: gadget: pxa27x_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pxa27x_udc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 5fda425f263f..ad954c49d061 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1809,7 +1809,6 @@ static int pxa27x_udc_start(struct usb_gadget *g, /* first hook up the driver ... */ udc->driver = driver; - udc->gadget.dev.driver = &driver->driver; dplus_pullup(udc, 1); if (!IS_ERR_OR_NULL(udc->transceiver)) { @@ -1827,7 +1826,6 @@ static int pxa27x_udc_start(struct usb_gadget *g, fail: udc->driver = NULL; - udc->gadget.dev.driver = NULL; return retval; } From 430e958e1d732b1d27d9ba31cdf79e5656b1a41b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:36:58 +0200 Subject: [PATCH 132/303] usb: gadget: s3c-hsotg: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 9d2330de5fcf..dfe72889c5b2 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2925,7 +2925,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, driver->driver.bus = NULL; hsotg->driver = driver; - hsotg->gadget.dev.driver = &driver->driver; hsotg->gadget.dev.of_node = hsotg->dev->of_node; hsotg->gadget.speed = USB_SPEED_UNKNOWN; @@ -2942,7 +2941,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget, err: hsotg->driver = NULL; - hsotg->gadget.dev.driver = NULL; return ret; } @@ -2977,7 +2975,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, hsotg->driver = NULL; hsotg->gadget.speed = USB_SPEED_UNKNOWN; - hsotg->gadget.dev.driver = NULL; spin_unlock_irqrestore(&hsotg->lock, flags); From 492a39022ad5825d8edbbdca993e18bf3f37f5fc Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:37:04 +0200 Subject: [PATCH 133/303] usb: gadget: s3c-hsudc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsudc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 8db7b10f3d07..bfe79103abab 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1154,7 +1154,6 @@ static int s3c_hsudc_start(struct usb_gadget *gadget, return -EBUSY; hsudc->driver = driver; - hsudc->gadget.dev.driver = &driver->driver; ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); @@ -1190,7 +1189,6 @@ err_otg: regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); err_supplies: hsudc->driver = NULL; - hsudc->gadget.dev.driver = NULL; return ret; } @@ -1208,7 +1206,6 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget, spin_lock_irqsave(&hsudc->lock, flags); hsudc->driver = NULL; - hsudc->gadget.dev.driver = NULL; hsudc->gadget.speed = USB_SPEED_UNKNOWN; s3c_hsudc_uninit_phy(); From bbdb72702e9268cad8136b6bd0d8862eed90535d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:37:12 +0200 Subject: [PATCH 134/303] usb: gadget: s3c2410_udc: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c2410_udc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index e15d1bbc2ad9..d0e75e1b3ccb 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1674,7 +1674,6 @@ static int s3c2410_udc_start(struct usb_gadget *g, /* Hook the driver */ udc->driver = driver; - udc->gadget.dev.driver = &driver->driver; /* Enable udc */ s3c2410_udc_enable(udc); From 8707d5abbd96f7a124647357005511bee8d3ccdd Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:37:17 +0200 Subject: [PATCH 135/303] usb: renesas: gadget: don't touch gadget.dev.driver udc-core now handles that for us, which means we can remove it from our driver. Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 6a3afa9b764c..883b0120b454 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -845,7 +845,6 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget, /* first hook up the driver ... */ gpriv->driver = driver; - gpriv->gadget.dev.driver = &driver->driver; return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); } @@ -861,7 +860,6 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget, return -EINVAL; usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); - gpriv->gadget.dev.driver = NULL; gpriv->driver = NULL; return 0; From 792bfcf7a1cd7913fa5d55f2b3a40e3275e98f6f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 14:47:44 +0200 Subject: [PATCH 136/303] usb: gadget: udc-core: introduce usb_add_gadget_udc_release() not all UDC drivers need a proper release function, for those which don't need it, we udc-core will provide a no-op release method so we can remove "redefinition" of such methods in almost every UDC driver. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 39 ++++++++++++++++++++++++++++++----- include/linux/usb/gadget.h | 2 ++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 2423d024654f..a50811e35bdb 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -166,15 +166,23 @@ static void usb_udc_release(struct device *dev) } static const struct attribute_group *usb_udc_attr_groups[]; + +static void usb_udc_nop_release(struct device *dev) +{ + dev_vdbg(dev, "%s\n", __func__); +} + /** - * usb_add_gadget_udc - adds a new gadget to the udc class driver list - * @parent: the parent device to this udc. Usually the controller - * driver's device. - * @gadget: the gadget to be added to the list + * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list + * @parent: the parent device to this udc. Usually the controller driver's + * device. + * @gadget: the gadget to be added to the list. + * @release: a gadget release function. * * Returns zero on success, negative errno otherwise. */ -int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) +int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, + void (*release)(struct device *dev)) { struct usb_udc *udc; int ret = -ENOMEM; @@ -190,6 +198,13 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) gadget->dev.dma_parms = parent->dma_parms; gadget->dev.dma_mask = parent->dma_mask; + if (release) { + gadget->dev.release = release; + } else { + if (!gadget->dev.release) + gadget->dev.release = usb_udc_nop_release; + } + ret = device_register(&gadget->dev); if (ret) goto err2; @@ -231,6 +246,20 @@ err2: err1: return ret; } +EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release); + +/** + * usb_add_gadget_udc - adds a new gadget to the udc class driver list + * @parent: the parent device to this udc. Usually the controller + * driver's device. + * @gadget: the gadget to be added to the list + * + * Returns zero on success, negative errno otherwise. + */ +int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget) +{ + return usb_add_gadget_udc_release(parent, gadget, NULL); +} EXPORT_SYMBOL_GPL(usb_add_gadget_udc); static void usb_gadget_remove_driver(struct usb_udc *udc) diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 32b734d88d6b..c454a88abf2e 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -874,6 +874,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver); */ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver); +extern int usb_add_gadget_udc_release(struct device *parent, + struct usb_gadget *gadget, void (*release)(struct device *dev)); extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget); extern void usb_del_gadget_udc(struct usb_gadget *gadget); extern int udc_attach_driver(const char *name, From 79c7d849777bc24d995371a066ded2ab2b359a18 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:10:51 +0200 Subject: [PATCH 137/303] usb: chipidea: udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/chipidea/udc.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index e303fd4b1b93..9bddf3f633f1 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1688,16 +1688,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci) return retval; } -/** - * udc_release: driver release function - * @dev: device - * - * Currently does nothing - */ -static void udc_release(struct device *dev) -{ -} - /** * udc_start: initialize gadget role * @ci: chipidea controller @@ -1717,8 +1707,6 @@ static int udc_start(struct ci13xxx *ci) INIT_LIST_HEAD(&ci->gadget.ep_list); - ci->gadget.dev.release = udc_release; - /* alloc resources */ ci->qh_pool = dma_pool_create("ci13xxx_qh", dev, sizeof(struct ci13xxx_qh), From e5caff6831d00d96b4618de939312570527ad54a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:11:05 +0200 Subject: [PATCH 138/303] usb: dwc3: gadget: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 9339eb10508f..4ffec1aa2e25 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1690,12 +1690,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) } } -static void dwc3_gadget_release(struct device *dev) -{ - dev_dbg(dev, "%s\n", __func__); -} - /* -------------------------------------------------------------------------- */ + static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, struct dwc3_request *req, struct dwc3_trb *trb, const struct dwc3_event_depevt *event, int status) @@ -2568,7 +2564,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.max_speed = USB_SPEED_SUPER; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.sg_supported = true; - dwc->gadget.dev.release = dwc3_gadget_release; dwc->gadget.name = "dwc3-gadget"; /* From e1f07ced2a27a7068786beaf23e0ac9fda6d8ca6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:25 +0200 Subject: [PATCH 139/303] usb: gadget: amd5536udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/amd5536udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index a8ff93cf344d..f52dcfe8f545 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3268,7 +3268,6 @@ static int udc_probe(struct udc *dev) dev->gadget.ops = &udc_ops; dev_set_name(&dev->gadget.dev, "gadget"); - dev->gadget.dev.release = gadget_release; dev->gadget.name = name; dev->gadget.max_speed = USB_SPEED_HIGH; @@ -3292,7 +3291,8 @@ static int udc_probe(struct udc *dev) "driver version: %s(for Geode5536 B1)\n", tmp); udc = dev; - retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget); + retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget, + gadget_release); if (retval) goto finished; From a995d9e2a50b30907814f178eeaa1f632a66c0cb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:26 +0200 Subject: [PATCH 140/303] usb: gadget: bcm63xx_udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/bcm63xx_udc.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index 904d4746922d..6e6518264c42 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -2303,17 +2303,6 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc) * Driver init/exit ***********************************************************************/ -/** - * bcm63xx_udc_gadget_release - Called from device_release(). - * @dev: Unused. - * - * We get a warning if this function doesn't exist, but it's empty because - * we don't have to free any of the memory allocated with the devm_* APIs. - */ -static void bcm63xx_udc_gadget_release(struct device *dev) -{ -} - /** * bcm63xx_udc_probe - Initialize a new instance of the UDC. * @pdev: Platform device struct from the bcm63xx BSP code. @@ -2369,7 +2358,6 @@ static int bcm63xx_udc_probe(struct platform_device *pdev) udc->gadget.ops = &bcm63xx_udc_ops; udc->gadget.name = dev_name(dev); - udc->gadget.dev.release = bcm63xx_udc_gadget_release; if (!pd->use_fullspeed && !use_fullspeed) udc->gadget.max_speed = USB_SPEED_HIGH; From f7162e9e1cead8510e371f8273902539102670ac Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:26 +0200 Subject: [PATCH 141/303] usb: gadget: dummy_hcd: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 9d54c01cbf56..ce751555f6ba 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -935,11 +935,6 @@ static int dummy_udc_stop(struct usb_gadget *g, /* The gadget structure is stored inside the hcd structure and will be * released along with it. */ -static void dummy_gadget_release(struct device *dev) -{ - return; -} - static void init_dummy_udc_hw(struct dummy *dum) { int i; @@ -983,7 +978,6 @@ static int dummy_udc_probe(struct platform_device *pdev) dum->gadget.max_speed = USB_SPEED_SUPER; dum->gadget.dev.parent = &pdev->dev; - dum->gadget.dev.release = dummy_gadget_release; init_dummy_udc_hw(dum); rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget); From 29e7dbf32967361fa67e99cf97ff9935b7292ac4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:26 +0200 Subject: [PATCH 142/303] usb: gadget: fsl_qe_udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_qe_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 37feb62fa930..9a7ee3347e4d 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2521,7 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev) /* name: Identifies the controller hardware type. */ udc->gadget.name = driver_name; - udc->gadget.dev.release = qe_udc_release; udc->gadget.dev.parent = &ofdev->dev; /* initialize qe_ep struct */ @@ -2585,7 +2584,8 @@ static int qe_udc_probe(struct platform_device *ofdev) goto err5; } - ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget); + ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget, + qe_udc_release); if (ret) goto err6; From 0e4d65e5292ed76578ff1571a1132e2f5f188261 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:26 +0200 Subject: [PATCH 143/303] usb: gadget: fsl_udc_core: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_udc_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 4d5ff236bed4..f22416986486 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2493,7 +2493,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) /* Setup gadget.dev and register with kernel */ dev_set_name(&udc_controller->gadget.dev, "gadget"); - udc_controller->gadget.dev.release = fsl_udc_release; udc_controller->gadget.dev.of_node = pdev->dev.of_node; if (!IS_ERR_OR_NULL(udc_controller->transceiver)) @@ -2530,7 +2529,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev) goto err_free_irq; } - ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget); + ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget, + fsl_udc_release); if (ret) goto err_del_udc; From 509d986a37edd7d89cb706142b540c74c6fbab0e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:26 +0200 Subject: [PATCH 144/303] usb: gadget: fusb300_udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fusb300_udc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index d69e840b101b..d05355389dd6 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -1418,7 +1418,6 @@ static int __init fusb300_probe(struct platform_device *pdev) fusb300->gadget.ops = &fusb300_gadget_ops; fusb300->gadget.max_speed = USB_SPEED_HIGH; - fusb300->gadget.dev.release = pdev->dev.release; fusb300->gadget.name = udc_name; fusb300->reg = reg; From 2ae837e4d83c5d1046f83b1bf3e3737126a6776a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:26 +0200 Subject: [PATCH 145/303] usb: gadget: goku_udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/goku_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index aa1976ee34e0..991aba390d9d 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1749,7 +1749,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.max_speed = USB_SPEED_FULL; /* the "gadget" abstracts/virtualizes the controller */ - dev->gadget.dev.release = gadget_release; dev->gadget.name = driver_name; /* now all the pci goodies ... */ @@ -1800,7 +1799,8 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev); #endif - retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget); + retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget, + gadget_release); if (retval) goto err; From 4b282fbe97412cc06fd9f173b4318e69a90b3442 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:26 +0200 Subject: [PATCH 146/303] usb: gadget: m66592-udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/m66592-udc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 21a20a6ffb66..866ef0999247 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1606,7 +1606,6 @@ static int __init m66592_probe(struct platform_device *pdev) m66592->gadget.ops = &m66592_gadget_ops; m66592->gadget.max_speed = USB_SPEED_HIGH; - m66592->gadget.dev.release = pdev->dev.release; m66592->gadget.name = udc_name; init_timer(&m66592->timer); From 7c9c3c7e1855e28d35c8d70607e68690def85fed Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:27 +0200 Subject: [PATCH 147/303] usb: gadget: mv_u3d_core: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index dc6445046da7..e91281d2aa21 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -1756,11 +1756,6 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev) return IRQ_HANDLED; } -static void mv_u3d_gadget_release(struct device *dev) -{ - dev_dbg(dev, "%s\n", __func__); -} - static int mv_u3d_remove(struct platform_device *dev) { struct mv_u3d *u3d = platform_get_drvdata(dev); @@ -1953,7 +1948,6 @@ static int mv_u3d_probe(struct platform_device *dev) u3d->gadget.speed = USB_SPEED_UNKNOWN; /* speed */ /* the "gadget" abstracts/virtualizes the controller */ - u3d->gadget.dev.release = mv_u3d_gadget_release; u3d->gadget.name = driver_name; /* gadget name */ mv_u3d_eps_init(u3d); From e861c768e57fd74ff947eadcf8ff86c01ba170d6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:27 +0200 Subject: [PATCH 148/303] usb: gadget: mv_udc_core: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index d1b243d76669..d278e8f512c0 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2265,7 +2265,6 @@ static int mv_udc_probe(struct platform_device *pdev) udc->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */ /* the "gadget" abstracts/virtualizes the controller */ - udc->gadget.dev.release = gadget_release; udc->gadget.name = driver_name; /* gadget name */ eps_init(udc); @@ -2305,7 +2304,8 @@ static int mv_udc_probe(struct platform_device *pdev) else udc->vbus_active = 1; - retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget); + retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, + gadget_release); if (retval) goto err_create_workqueue; From 8efeeef61d4f253aaa1a566a8e0d01b635c216d9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:27 +0200 Subject: [PATCH 149/303] usb: gadget: net2272: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2272.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index af99223e0126..8dcbe770e2d4 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -2233,7 +2233,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq) ret->gadget.max_speed = USB_SPEED_HIGH; /* the "gadget" abstracts/virtualizes the controller */ - ret->gadget.dev.release = net2272_gadget_release; ret->gadget.name = driver_name; return ret; @@ -2273,7 +2272,8 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags) if (ret) goto err_irq; - ret = usb_add_gadget_udc(dev->dev, &dev->gadget); + ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget, + net2272_gadget_release); if (ret) goto err_add_udc; From 2901df68499d75cb43d37495797f7ca73fb548a4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:27 +0200 Subject: [PATCH 150/303] usb: gadget: net2280: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2280.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 9e4f0a26108e..e5f2ef184367 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2707,7 +2707,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) dev->gadget.max_speed = USB_SPEED_HIGH; /* the "gadget" abstracts/virtualizes the controller */ - dev->gadget.dev.release = gadget_release; dev->gadget.name = driver_name; /* now all the pci goodies ... */ @@ -2819,7 +2818,8 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) retval = device_create_file (&pdev->dev, &dev_attr_registers); if (retval) goto done; - retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget); + retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget, + gadget_release); if (retval) goto done; return 0; From 2fb29f215cc8f23eedabcc289cd4b5280a054aad Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:27 +0200 Subject: [PATCH 151/303] usb: gadget: omap_udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/omap_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 19420ad128ce..b8ed74a823cb 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2628,7 +2628,6 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) udc->gadget.speed = USB_SPEED_UNKNOWN; udc->gadget.max_speed = USB_SPEED_FULL; udc->gadget.name = driver_name; - udc->gadget.dev.release = omap_udc_release; udc->transceiver = xceiv; /* ep0 is special; put it right after the SETUP buffer */ @@ -2902,7 +2901,8 @@ bad_on_1710: } create_proc_file(); - status = usb_add_gadget_udc(&pdev->dev, &udc->gadget); + status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, + omap_udc_release); if (status) goto cleanup4; From ef98f7465fe28a39800b07e14b1e4a43906bd77b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:27 +0200 Subject: [PATCH 152/303] usb: gadget: pch_udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 79cf2966f634..44aacf7192ab 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -3191,13 +3191,13 @@ static int pch_udc_probe(struct pci_dev *pdev, if (retval) goto finished; - dev->gadget.dev.release = gadget_release; dev->gadget.name = KBUILD_MODNAME; dev->gadget.max_speed = USB_SPEED_HIGH; /* Put the device in disconnected state till a driver is bound */ pch_udc_set_disconnect(dev); - retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget); + retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget, + gadget_release); if (retval) goto finished; return 0; From 59139706a0bc6950759c588ca3a28a732fa18d5f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:27 +0200 Subject: [PATCH 153/303] usb: gadget: r8a66597-udc: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/r8a66597-udc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 2de775dbd92c..0b742d171843 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1915,7 +1915,6 @@ static int __init r8a66597_probe(struct platform_device *pdev) r8a66597->gadget.ops = &r8a66597_gadget_ops; r8a66597->gadget.max_speed = USB_SPEED_HIGH; - r8a66597->gadget.dev.release = pdev->dev.release; r8a66597->gadget.name = udc_name; init_timer(&r8a66597->timer); From ad8033fcd08ed9d0e2c262015baf7e22e1544db2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:28 +0200 Subject: [PATCH 154/303] usb: gadget: s3c-hsotg: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index dfe72889c5b2..f1ceabff7cce 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3443,16 +3443,6 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) debugfs_remove(hsotg->debug_root); } -/** - * s3c_hsotg_release - release callback for hsotg device - * @dev: Device to for which release is called - * - * Nothing to do as the resource is allocated using devm_ API. - */ -static void s3c_hsotg_release(struct device *dev) -{ -} - /** * s3c_hsotg_probe - probe function for hsotg driver * @pdev: The platform information for the driver @@ -3530,7 +3520,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) hsotg->gadget.max_speed = USB_SPEED_HIGH; hsotg->gadget.ops = &s3c_hsotg_gadget_ops; hsotg->gadget.name = dev_name(dev); - hsotg->gadget.dev.release = s3c_hsotg_release; /* reset the system */ From 07d83168278a73647e3a30fc33e274708418c52b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:28 +0200 Subject: [PATCH 155/303] usb: musb: gadget: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 2dd952c330fd..6101ebf803fd 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1691,13 +1691,6 @@ static const struct usb_gadget_ops musb_gadget_operations = { * all peripheral ports are external... */ -static void musb_gadget_release(struct device *dev) -{ - /* kref_put(WHAT) */ - dev_dbg(dev, "%s\n", __func__); -} - - static void init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in) { @@ -1782,7 +1775,6 @@ int musb_gadget_setup(struct musb *musb) musb->g.speed = USB_SPEED_UNKNOWN; /* this "gadget" abstracts/virtualizes the controller */ - musb->g.dev.release = musb_gadget_release; musb->g.name = musb_driver_name; musb->g.is_otg = 1; From 3920193d8e71d1f7e0d077aa71624b64fa3499ac Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:15:51 +0200 Subject: [PATCH 156/303] usb: renesas: gadget: don't assign gadget.dev.release directly udc-core provides a better way to handle release methods, let's use it. Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 883b0120b454..c2781bc9dabe 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -923,11 +923,6 @@ static int usbhsg_stop(struct usbhs_priv *priv) return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); } -static void usbhs_mod_gadget_release(struct device *pdev) -{ - /* do nothing */ -} - int usbhs_mod_gadget_probe(struct usbhs_priv *priv) { struct usbhsg_gpriv *gpriv; @@ -975,7 +970,6 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) * init gadget */ gpriv->gadget.dev.parent = dev; - gpriv->gadget.dev.release = usbhs_mod_gadget_release; gpriv->gadget.name = "renesas_usbhs_udc"; gpriv->gadget.ops = &usbhsg_gadget_ops; gpriv->gadget.max_speed = USB_SPEED_HIGH; From ddf47ccbfebc12add813cf729ecfc2d5ab59ca19 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 15:25:41 +0200 Subject: [PATCH 157/303] usb: gadget: udc-core: remove protection when setting gadget.dev.release now that no UDC driver touches gadget.dev.release we can assign our release function to it without being afraid of breaking anything. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index a50811e35bdb..26e116bd6f59 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -198,12 +198,10 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, gadget->dev.dma_parms = parent->dma_parms; gadget->dev.dma_mask = parent->dma_mask; - if (release) { + if (release) gadget->dev.release = release; - } else { - if (!gadget->dev.release) - gadget->dev.release = usb_udc_nop_release; - } + else + gadget->dev.release = usb_udc_nop_release; ret = device_register(&gadget->dev); if (ret) From a5fcb066d284d8e525e1e1a4799722e8616cfe76 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 26 Feb 2013 19:15:14 +0200 Subject: [PATCH 158/303] usb: gadget: udc-core: anywone can read 'speed' attributes current code only allows the file owner (usually root) to read current_speed and maximum_speed sysfs files. Let anyone read those. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 26e116bd6f59..7999cc656979 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -471,7 +471,7 @@ ssize_t usb_udc_##param##_show(struct device *dev, \ return snprintf(buf, PAGE_SIZE, "%s\n", \ usb_speed_string(udc->gadget->param)); \ } \ -static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL) +static DEVICE_ATTR(name, S_IRUGO, usb_udc_##param##_show, NULL) static USB_UDC_SPEED_ATTR(current_speed, speed); static USB_UDC_SPEED_ATTR(maximum_speed, max_speed); From 7ac6a593d512de38e710591afea4c839626b3bd0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 18 Sep 2012 21:22:32 +0300 Subject: [PATCH 159/303] usb: dwc3: core: define more revisions Some new revisions of the DWC3 core have been released, let's add our defines to help implementing known erratas. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index d8c36fccce96..ad2ffac71500 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -700,6 +700,9 @@ struct dwc3 { #define DWC3_REVISION_202A 0x5533202a #define DWC3_REVISION_210A 0x5533210a #define DWC3_REVISION_220A 0x5533220a +#define DWC3_REVISION_230A 0x5533230a +#define DWC3_REVISION_240A 0x5533240a +#define DWC3_REVISION_250A 0x5533250a unsigned is_selfpowered:1; unsigned three_stage_setup:1; From 0b0cc1cd31bed3e3147398e54530f1f819b27692 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 18 Sep 2012 21:39:24 +0300 Subject: [PATCH 160/303] usb: dwc3: workaround: unexpected transtion U3 -> RESUME In DWC3 versions < 2.50a configured without Hibernation mode enabled, there will be an extra link status change interrupt if device detects host-initiated U3 exit. In that case, core will generate an unnecessary U3 -> RESUME transition which should be ignored by the driver. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4ffec1aa2e25..8e53acc0e43e 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2317,6 +2317,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, unsigned int evtinfo) { enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; + unsigned int pwropt; + + /* + * WORKAROUND: DWC3 < 2.50a have an issue when configured without + * Hibernation mode enabled which would show up when device detects + * host-initiated U3 exit. + * + * In that case, device will generate a Link State Change Interrupt + * from U3 to RESUME which is only necessary if Hibernation is + * configured in. + * + * There are no functional changes due to such spurious event and we + * just need to ignore it. + * + * Refers to: + * + * STAR#9000570034 RTL: SS Resume event generated in non-Hibernation + * operational mode + */ + pwropt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1); + if ((dwc->revision < DWC3_REVISION_250A) && + (pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) { + if ((dwc->link_state == DWC3_LINK_STATE_U3) && + (next == DWC3_LINK_STATE_RESUME)) { + dev_vdbg(dwc->dev, "ignoring transition U3 -> Resume\n"); + return; + } + } /* * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending From cedf8602373a3a5d02e49af7bebc401ffe3b38f3 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 27 Feb 2013 15:16:28 +0100 Subject: [PATCH 161/303] usb: phy: move bulk of otg/otg.c to phy/phy.c Most of otg/otg.c is not otg specific, but phy specific, so move it to the phy directory. Tested-by: Steffen Trumtrar Reported-by: Kishon Vijay Abraham I Signed-off-by: Sascha Hauer Signed-off-by: Marc Kleine-Budde Signed-off-by: Felipe Balbi --- drivers/usb/otg/otg.c | 427 -------------------------------------- drivers/usb/phy/Makefile | 1 + drivers/usb/phy/phy.c | 438 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 439 insertions(+), 427 deletions(-) create mode 100644 drivers/usb/phy/phy.c diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index 2bd03d261a50..358cfd9bce89 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c @@ -8,436 +8,9 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ - -#include #include -#include -#include -#include -#include -#include - #include -static LIST_HEAD(phy_list); -static LIST_HEAD(phy_bind_list); -static DEFINE_SPINLOCK(phy_lock); - -static struct usb_phy *__usb_find_phy(struct list_head *list, - enum usb_phy_type type) -{ - struct usb_phy *phy = NULL; - - list_for_each_entry(phy, list, head) { - if (phy->type != type) - continue; - - return phy; - } - - return ERR_PTR(-ENODEV); -} - -static struct usb_phy *__usb_find_phy_dev(struct device *dev, - struct list_head *list, u8 index) -{ - struct usb_phy_bind *phy_bind = NULL; - - list_for_each_entry(phy_bind, list, list) { - if (!(strcmp(phy_bind->dev_name, dev_name(dev))) && - phy_bind->index == index) { - if (phy_bind->phy) - return phy_bind->phy; - else - return ERR_PTR(-EPROBE_DEFER); - } - } - - return ERR_PTR(-ENODEV); -} - -static struct usb_phy *__of_usb_find_phy(struct device_node *node) -{ - struct usb_phy *phy; - - list_for_each_entry(phy, &phy_list, head) { - if (node != phy->dev->of_node) - continue; - - return phy; - } - - return ERR_PTR(-ENODEV); -} - -static void devm_usb_phy_release(struct device *dev, void *res) -{ - struct usb_phy *phy = *(struct usb_phy **)res; - - usb_put_phy(phy); -} - -static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) -{ - return res == match_data; -} - -/** - * devm_usb_get_phy - find the USB PHY - * @dev - device that requests this phy - * @type - the type of the phy the controller requires - * - * Gets the phy using usb_get_phy(), and associates a device with it using - * devres. On driver detach, release function is invoked on the devres data, - * then, devres data is freed. - * - * For use by USB host and peripheral drivers. - */ -struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type) -{ - struct usb_phy **ptr, *phy; - - ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return NULL; - - phy = usb_get_phy(type); - if (!IS_ERR(phy)) { - *ptr = phy; - devres_add(dev, ptr); - } else - devres_free(ptr); - - return phy; -} -EXPORT_SYMBOL(devm_usb_get_phy); - -/** - * usb_get_phy - find the USB PHY - * @type - the type of the phy the controller requires - * - * Returns the phy driver, after getting a refcount to it; or - * -ENODEV if there is no such phy. The caller is responsible for - * calling usb_put_phy() to release that count. - * - * For use by USB host and peripheral drivers. - */ -struct usb_phy *usb_get_phy(enum usb_phy_type type) -{ - struct usb_phy *phy = NULL; - unsigned long flags; - - spin_lock_irqsave(&phy_lock, flags); - - phy = __usb_find_phy(&phy_list, type); - if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { - pr_err("unable to find transceiver of type %s\n", - usb_phy_type_string(type)); - goto err0; - } - - get_device(phy->dev); - -err0: - spin_unlock_irqrestore(&phy_lock, flags); - - return phy; -} -EXPORT_SYMBOL(usb_get_phy); - - /** - * devm_usb_get_phy_by_phandle - find the USB PHY by phandle - * @dev - device that requests this phy - * @phandle - name of the property holding the phy phandle value - * @index - the index of the phy - * - * Returns the phy driver associated with the given phandle value, - * after getting a refcount to it, -ENODEV if there is no such phy or - * -EPROBE_DEFER if there is a phandle to the phy, but the device is - * not yet loaded. While at that, it also associates the device with - * the phy using devres. On driver detach, release function is invoked - * on the devres data, then, devres data is freed. - * - * For use by USB host and peripheral drivers. - */ -struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, - const char *phandle, u8 index) -{ - struct usb_phy *phy = ERR_PTR(-ENOMEM), **ptr; - unsigned long flags; - struct device_node *node; - - if (!dev->of_node) { - dev_dbg(dev, "device does not have a device node entry\n"); - return ERR_PTR(-EINVAL); - } - - node = of_parse_phandle(dev->of_node, phandle, index); - if (!node) { - dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle, - dev->of_node->full_name); - return ERR_PTR(-ENODEV); - } - - ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) { - dev_dbg(dev, "failed to allocate memory for devres\n"); - goto err0; - } - - spin_lock_irqsave(&phy_lock, flags); - - phy = __of_usb_find_phy(node); - if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { - phy = ERR_PTR(-EPROBE_DEFER); - devres_free(ptr); - goto err1; - } - - *ptr = phy; - devres_add(dev, ptr); - - get_device(phy->dev); - -err1: - spin_unlock_irqrestore(&phy_lock, flags); - -err0: - of_node_put(node); - - return phy; -} -EXPORT_SYMBOL(devm_usb_get_phy_by_phandle); - -/** - * usb_get_phy_dev - find the USB PHY - * @dev - device that requests this phy - * @index - the index of the phy - * - * Returns the phy driver, after getting a refcount to it; or - * -ENODEV if there is no such phy. The caller is responsible for - * calling usb_put_phy() to release that count. - * - * For use by USB host and peripheral drivers. - */ -struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) -{ - struct usb_phy *phy = NULL; - unsigned long flags; - - spin_lock_irqsave(&phy_lock, flags); - - phy = __usb_find_phy_dev(dev, &phy_bind_list, index); - if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { - pr_err("unable to find transceiver\n"); - goto err0; - } - - get_device(phy->dev); - -err0: - spin_unlock_irqrestore(&phy_lock, flags); - - return phy; -} -EXPORT_SYMBOL(usb_get_phy_dev); - -/** - * devm_usb_get_phy_dev - find the USB PHY using device ptr and index - * @dev - device that requests this phy - * @index - the index of the phy - * - * Gets the phy using usb_get_phy_dev(), and associates a device with it using - * devres. On driver detach, release function is invoked on the devres data, - * then, devres data is freed. - * - * For use by USB host and peripheral drivers. - */ -struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index) -{ - struct usb_phy **ptr, *phy; - - ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) - return NULL; - - phy = usb_get_phy_dev(dev, index); - if (!IS_ERR(phy)) { - *ptr = phy; - devres_add(dev, ptr); - } else - devres_free(ptr); - - return phy; -} -EXPORT_SYMBOL(devm_usb_get_phy_dev); - -/** - * devm_usb_put_phy - release the USB PHY - * @dev - device that wants to release this phy - * @phy - the phy returned by devm_usb_get_phy() - * - * destroys the devres associated with this phy and invokes usb_put_phy - * to release the phy. - * - * For use by USB host and peripheral drivers. - */ -void devm_usb_put_phy(struct device *dev, struct usb_phy *phy) -{ - int r; - - r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy); - dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); -} -EXPORT_SYMBOL(devm_usb_put_phy); - -/** - * usb_put_phy - release the USB PHY - * @x: the phy returned by usb_get_phy() - * - * Releases a refcount the caller received from usb_get_phy(). - * - * For use by USB host and peripheral drivers. - */ -void usb_put_phy(struct usb_phy *x) -{ - if (x) { - struct module *owner = x->dev->driver->owner; - - put_device(x->dev); - module_put(owner); - } -} -EXPORT_SYMBOL(usb_put_phy); - -/** - * usb_add_phy - declare the USB PHY - * @x: the USB phy to be used; or NULL - * @type - the type of this PHY - * - * This call is exclusively for use by phy drivers, which - * coordinate the activities of drivers for host and peripheral - * controllers, and in some cases for VBUS current regulation. - */ -int usb_add_phy(struct usb_phy *x, enum usb_phy_type type) -{ - int ret = 0; - unsigned long flags; - struct usb_phy *phy; - - if (x->type != USB_PHY_TYPE_UNDEFINED) { - dev_err(x->dev, "not accepting initialized PHY %s\n", x->label); - return -EINVAL; - } - - spin_lock_irqsave(&phy_lock, flags); - - list_for_each_entry(phy, &phy_list, head) { - if (phy->type == type) { - ret = -EBUSY; - dev_err(x->dev, "transceiver type %s already exists\n", - usb_phy_type_string(type)); - goto out; - } - } - - x->type = type; - list_add_tail(&x->head, &phy_list); - -out: - spin_unlock_irqrestore(&phy_lock, flags); - return ret; -} -EXPORT_SYMBOL(usb_add_phy); - -/** - * usb_add_phy_dev - declare the USB PHY - * @x: the USB phy to be used; or NULL - * - * This call is exclusively for use by phy drivers, which - * coordinate the activities of drivers for host and peripheral - * controllers, and in some cases for VBUS current regulation. - */ -int usb_add_phy_dev(struct usb_phy *x) -{ - struct usb_phy_bind *phy_bind; - unsigned long flags; - - if (!x->dev) { - dev_err(x->dev, "no device provided for PHY\n"); - return -EINVAL; - } - - spin_lock_irqsave(&phy_lock, flags); - list_for_each_entry(phy_bind, &phy_bind_list, list) - if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev)))) - phy_bind->phy = x; - - list_add_tail(&x->head, &phy_list); - - spin_unlock_irqrestore(&phy_lock, flags); - return 0; -} -EXPORT_SYMBOL(usb_add_phy_dev); - -/** - * usb_remove_phy - remove the OTG PHY - * @x: the USB OTG PHY to be removed; - * - * This reverts the effects of usb_add_phy - */ -void usb_remove_phy(struct usb_phy *x) -{ - unsigned long flags; - struct usb_phy_bind *phy_bind; - - spin_lock_irqsave(&phy_lock, flags); - if (x) { - list_for_each_entry(phy_bind, &phy_bind_list, list) - if (phy_bind->phy == x) - phy_bind->phy = NULL; - list_del(&x->head); - } - spin_unlock_irqrestore(&phy_lock, flags); -} -EXPORT_SYMBOL(usb_remove_phy); - -/** - * usb_bind_phy - bind the phy and the controller that uses the phy - * @dev_name: the device name of the device that will bind to the phy - * @index: index to specify the port number - * @phy_dev_name: the device name of the phy - * - * Fills the phy_bind structure with the dev_name and phy_dev_name. This will - * be used when the phy driver registers the phy and when the controller - * requests this phy. - * - * To be used by platform specific initialization code. - */ -int __init usb_bind_phy(const char *dev_name, u8 index, - const char *phy_dev_name) -{ - struct usb_phy_bind *phy_bind; - unsigned long flags; - - phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL); - if (!phy_bind) { - pr_err("phy_bind(): No memory for phy_bind"); - return -ENOMEM; - } - - phy_bind->dev_name = dev_name; - phy_bind->phy_dev_name = phy_dev_name; - phy_bind->index = index; - - spin_lock_irqsave(&phy_lock, flags); - list_add_tail(&phy_bind->list, &phy_bind_list); - spin_unlock_irqrestore(&phy_lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(usb_bind_phy); - const char *otg_state_string(enum usb_otg_state state) { switch (state) { diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index b13faa193e0c..9fa6327d4c52 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -4,6 +4,7 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG +obj-$(CONFIG_USB_OTG_UTILS) += phy.o obj-$(CONFIG_OMAP_USB2) += omap-usb2.o obj-$(CONFIG_OMAP_USB3) += omap-usb3.o obj-$(CONFIG_OMAP_CONTROL_USB) += omap-control-usb.o diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c new file mode 100644 index 000000000000..bc1970c55df0 --- /dev/null +++ b/drivers/usb/phy/phy.c @@ -0,0 +1,438 @@ +/* + * phy.c -- USB phy handling + * + * Copyright (C) 2004-2013 Texas Instruments + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +static LIST_HEAD(phy_list); +static LIST_HEAD(phy_bind_list); +static DEFINE_SPINLOCK(phy_lock); + +static struct usb_phy *__usb_find_phy(struct list_head *list, + enum usb_phy_type type) +{ + struct usb_phy *phy = NULL; + + list_for_each_entry(phy, list, head) { + if (phy->type != type) + continue; + + return phy; + } + + return ERR_PTR(-ENODEV); +} + +static struct usb_phy *__usb_find_phy_dev(struct device *dev, + struct list_head *list, u8 index) +{ + struct usb_phy_bind *phy_bind = NULL; + + list_for_each_entry(phy_bind, list, list) { + if (!(strcmp(phy_bind->dev_name, dev_name(dev))) && + phy_bind->index == index) { + if (phy_bind->phy) + return phy_bind->phy; + else + return ERR_PTR(-EPROBE_DEFER); + } + } + + return ERR_PTR(-ENODEV); +} + +static struct usb_phy *__of_usb_find_phy(struct device_node *node) +{ + struct usb_phy *phy; + + list_for_each_entry(phy, &phy_list, head) { + if (node != phy->dev->of_node) + continue; + + return phy; + } + + return ERR_PTR(-ENODEV); +} + +static void devm_usb_phy_release(struct device *dev, void *res) +{ + struct usb_phy *phy = *(struct usb_phy **)res; + + usb_put_phy(phy); +} + +static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) +{ + return res == match_data; +} + +/** + * devm_usb_get_phy - find the USB PHY + * @dev - device that requests this phy + * @type - the type of the phy the controller requires + * + * Gets the phy using usb_get_phy(), and associates a device with it using + * devres. On driver detach, release function is invoked on the devres data, + * then, devres data is freed. + * + * For use by USB host and peripheral drivers. + */ +struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type) +{ + struct usb_phy **ptr, *phy; + + ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + phy = usb_get_phy(type); + if (!IS_ERR(phy)) { + *ptr = phy; + devres_add(dev, ptr); + } else + devres_free(ptr); + + return phy; +} +EXPORT_SYMBOL(devm_usb_get_phy); + +/** + * usb_get_phy - find the USB PHY + * @type - the type of the phy the controller requires + * + * Returns the phy driver, after getting a refcount to it; or + * -ENODEV if there is no such phy. The caller is responsible for + * calling usb_put_phy() to release that count. + * + * For use by USB host and peripheral drivers. + */ +struct usb_phy *usb_get_phy(enum usb_phy_type type) +{ + struct usb_phy *phy = NULL; + unsigned long flags; + + spin_lock_irqsave(&phy_lock, flags); + + phy = __usb_find_phy(&phy_list, type); + if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { + pr_err("unable to find transceiver of type %s\n", + usb_phy_type_string(type)); + goto err0; + } + + get_device(phy->dev); + +err0: + spin_unlock_irqrestore(&phy_lock, flags); + + return phy; +} +EXPORT_SYMBOL(usb_get_phy); + + /** + * devm_usb_get_phy_by_phandle - find the USB PHY by phandle + * @dev - device that requests this phy + * @phandle - name of the property holding the phy phandle value + * @index - the index of the phy + * + * Returns the phy driver associated with the given phandle value, + * after getting a refcount to it, -ENODEV if there is no such phy or + * -EPROBE_DEFER if there is a phandle to the phy, but the device is + * not yet loaded. While at that, it also associates the device with + * the phy using devres. On driver detach, release function is invoked + * on the devres data, then, devres data is freed. + * + * For use by USB host and peripheral drivers. + */ +struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, + const char *phandle, u8 index) +{ + struct usb_phy *phy = ERR_PTR(-ENOMEM), **ptr; + unsigned long flags; + struct device_node *node; + + if (!dev->of_node) { + dev_dbg(dev, "device does not have a device node entry\n"); + return ERR_PTR(-EINVAL); + } + + node = of_parse_phandle(dev->of_node, phandle, index); + if (!node) { + dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle, + dev->of_node->full_name); + return ERR_PTR(-ENODEV); + } + + ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) { + dev_dbg(dev, "failed to allocate memory for devres\n"); + goto err0; + } + + spin_lock_irqsave(&phy_lock, flags); + + phy = __of_usb_find_phy(node); + if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { + phy = ERR_PTR(-EPROBE_DEFER); + devres_free(ptr); + goto err1; + } + + *ptr = phy; + devres_add(dev, ptr); + + get_device(phy->dev); + +err1: + spin_unlock_irqrestore(&phy_lock, flags); + +err0: + of_node_put(node); + + return phy; +} +EXPORT_SYMBOL(devm_usb_get_phy_by_phandle); + +/** + * usb_get_phy_dev - find the USB PHY + * @dev - device that requests this phy + * @index - the index of the phy + * + * Returns the phy driver, after getting a refcount to it; or + * -ENODEV if there is no such phy. The caller is responsible for + * calling usb_put_phy() to release that count. + * + * For use by USB host and peripheral drivers. + */ +struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) +{ + struct usb_phy *phy = NULL; + unsigned long flags; + + spin_lock_irqsave(&phy_lock, flags); + + phy = __usb_find_phy_dev(dev, &phy_bind_list, index); + if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { + pr_err("unable to find transceiver\n"); + goto err0; + } + + get_device(phy->dev); + +err0: + spin_unlock_irqrestore(&phy_lock, flags); + + return phy; +} +EXPORT_SYMBOL(usb_get_phy_dev); + +/** + * devm_usb_get_phy_dev - find the USB PHY using device ptr and index + * @dev - device that requests this phy + * @index - the index of the phy + * + * Gets the phy using usb_get_phy_dev(), and associates a device with it using + * devres. On driver detach, release function is invoked on the devres data, + * then, devres data is freed. + * + * For use by USB host and peripheral drivers. + */ +struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index) +{ + struct usb_phy **ptr, *phy; + + ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return NULL; + + phy = usb_get_phy_dev(dev, index); + if (!IS_ERR(phy)) { + *ptr = phy; + devres_add(dev, ptr); + } else + devres_free(ptr); + + return phy; +} +EXPORT_SYMBOL(devm_usb_get_phy_dev); + +/** + * devm_usb_put_phy - release the USB PHY + * @dev - device that wants to release this phy + * @phy - the phy returned by devm_usb_get_phy() + * + * destroys the devres associated with this phy and invokes usb_put_phy + * to release the phy. + * + * For use by USB host and peripheral drivers. + */ +void devm_usb_put_phy(struct device *dev, struct usb_phy *phy) +{ + int r; + + r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy); + dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); +} +EXPORT_SYMBOL(devm_usb_put_phy); + +/** + * usb_put_phy - release the USB PHY + * @x: the phy returned by usb_get_phy() + * + * Releases a refcount the caller received from usb_get_phy(). + * + * For use by USB host and peripheral drivers. + */ +void usb_put_phy(struct usb_phy *x) +{ + if (x) { + struct module *owner = x->dev->driver->owner; + + put_device(x->dev); + module_put(owner); + } +} +EXPORT_SYMBOL(usb_put_phy); + +/** + * usb_add_phy - declare the USB PHY + * @x: the USB phy to be used; or NULL + * @type - the type of this PHY + * + * This call is exclusively for use by phy drivers, which + * coordinate the activities of drivers for host and peripheral + * controllers, and in some cases for VBUS current regulation. + */ +int usb_add_phy(struct usb_phy *x, enum usb_phy_type type) +{ + int ret = 0; + unsigned long flags; + struct usb_phy *phy; + + if (x->type != USB_PHY_TYPE_UNDEFINED) { + dev_err(x->dev, "not accepting initialized PHY %s\n", x->label); + return -EINVAL; + } + + spin_lock_irqsave(&phy_lock, flags); + + list_for_each_entry(phy, &phy_list, head) { + if (phy->type == type) { + ret = -EBUSY; + dev_err(x->dev, "transceiver type %s already exists\n", + usb_phy_type_string(type)); + goto out; + } + } + + x->type = type; + list_add_tail(&x->head, &phy_list); + +out: + spin_unlock_irqrestore(&phy_lock, flags); + return ret; +} +EXPORT_SYMBOL(usb_add_phy); + +/** + * usb_add_phy_dev - declare the USB PHY + * @x: the USB phy to be used; or NULL + * + * This call is exclusively for use by phy drivers, which + * coordinate the activities of drivers for host and peripheral + * controllers, and in some cases for VBUS current regulation. + */ +int usb_add_phy_dev(struct usb_phy *x) +{ + struct usb_phy_bind *phy_bind; + unsigned long flags; + + if (!x->dev) { + dev_err(x->dev, "no device provided for PHY\n"); + return -EINVAL; + } + + spin_lock_irqsave(&phy_lock, flags); + list_for_each_entry(phy_bind, &phy_bind_list, list) + if (!(strcmp(phy_bind->phy_dev_name, dev_name(x->dev)))) + phy_bind->phy = x; + + list_add_tail(&x->head, &phy_list); + + spin_unlock_irqrestore(&phy_lock, flags); + return 0; +} +EXPORT_SYMBOL(usb_add_phy_dev); + +/** + * usb_remove_phy - remove the OTG PHY + * @x: the USB OTG PHY to be removed; + * + * This reverts the effects of usb_add_phy + */ +void usb_remove_phy(struct usb_phy *x) +{ + unsigned long flags; + struct usb_phy_bind *phy_bind; + + spin_lock_irqsave(&phy_lock, flags); + if (x) { + list_for_each_entry(phy_bind, &phy_bind_list, list) + if (phy_bind->phy == x) + phy_bind->phy = NULL; + list_del(&x->head); + } + spin_unlock_irqrestore(&phy_lock, flags); +} +EXPORT_SYMBOL(usb_remove_phy); + +/** + * usb_bind_phy - bind the phy and the controller that uses the phy + * @dev_name: the device name of the device that will bind to the phy + * @index: index to specify the port number + * @phy_dev_name: the device name of the phy + * + * Fills the phy_bind structure with the dev_name and phy_dev_name. This will + * be used when the phy driver registers the phy and when the controller + * requests this phy. + * + * To be used by platform specific initialization code. + */ +int __init usb_bind_phy(const char *dev_name, u8 index, + const char *phy_dev_name) +{ + struct usb_phy_bind *phy_bind; + unsigned long flags; + + phy_bind = kzalloc(sizeof(*phy_bind), GFP_KERNEL); + if (!phy_bind) { + pr_err("phy_bind(): No memory for phy_bind"); + return -ENOMEM; + } + + phy_bind->dev_name = dev_name; + phy_bind->phy_dev_name = phy_dev_name; + phy_bind->index = index; + + spin_lock_irqsave(&phy_lock, flags); + list_add_tail(&phy_bind->list, &phy_bind_list); + spin_unlock_irqrestore(&phy_lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(usb_bind_phy); From 25df6397a6c063811154868b868e8bd10e5ae9b1 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 27 Feb 2013 15:16:30 +0100 Subject: [PATCH 162/303] usb: phy: mxs-phy: register phy with framework We now have usb_add_phy_dev(), so use it to register with the framework to be able to find the phy from the USB driver. Tested-by: Steffen Trumtrar Reviewed-by: Kishon Vijay Abraham I Reviewed-by: Peter Chen Signed-off-by: Sascha Hauer Signed-off-by: Marc Kleine-Budde Signed-off-by: Felipe Balbi --- drivers/usb/otg/mxs-phy.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c index b0d9f119c749..aa403256d4b6 100644 --- a/drivers/usb/otg/mxs-phy.c +++ b/drivers/usb/otg/mxs-phy.c @@ -127,6 +127,7 @@ static int mxs_phy_probe(struct platform_device *pdev) void __iomem *base; struct clk *clk; struct mxs_phy *mxs_phy; + int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -166,11 +167,19 @@ static int mxs_phy_probe(struct platform_device *pdev) platform_set_drvdata(pdev, &mxs_phy->phy); + ret = usb_add_phy_dev(&mxs_phy->phy); + if (ret) + return ret; + return 0; } static int mxs_phy_remove(struct platform_device *pdev) { + struct mxs_phy *mxs_phy = platform_get_drvdata(pdev); + + usb_remove_phy(&mxs_phy->phy); + platform_set_drvdata(pdev, NULL); return 0; From b5a726b30436ab332aea4133bbfa0484d1c658b3 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 28 Feb 2013 11:52:30 +0100 Subject: [PATCH 163/303] usb: phy: mxs: use readl(), writel() instead of the _relaxed() versions This patch converts the mxs-phy driver from readl_relaxed(), writel_relaxed() to the plain readl(), writel() functions, which are available on all platforms. This is done to enable compile time testing on non ARM platforms. Reported-by: Alexander Shishkin Signed-off-by: Marc Kleine-Budde Signed-off-by: Felipe Balbi --- drivers/usb/otg/mxs-phy.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c index aa403256d4b6..9d4381e64d51 100644 --- a/drivers/usb/otg/mxs-phy.c +++ b/drivers/usb/otg/mxs-phy.c @@ -48,12 +48,12 @@ static void mxs_phy_hw_init(struct mxs_phy *mxs_phy) stmp_reset_block(base + HW_USBPHY_CTRL); /* Power up the PHY */ - writel_relaxed(0, base + HW_USBPHY_PWD); + writel(0, base + HW_USBPHY_PWD); /* enable FS/LS device */ - writel_relaxed(BM_USBPHY_CTRL_ENUTMILEVEL2 | - BM_USBPHY_CTRL_ENUTMILEVEL3, - base + HW_USBPHY_CTRL_SET); + writel(BM_USBPHY_CTRL_ENUTMILEVEL2 | + BM_USBPHY_CTRL_ENUTMILEVEL3, + base + HW_USBPHY_CTRL_SET); } static int mxs_phy_init(struct usb_phy *phy) @@ -70,8 +70,8 @@ static void mxs_phy_shutdown(struct usb_phy *phy) { struct mxs_phy *mxs_phy = to_mxs_phy(phy); - writel_relaxed(BM_USBPHY_CTRL_CLKGATE, - phy->io_priv + HW_USBPHY_CTRL_SET); + writel(BM_USBPHY_CTRL_CLKGATE, + phy->io_priv + HW_USBPHY_CTRL_SET); clk_disable_unprepare(mxs_phy->clk); } @@ -81,15 +81,15 @@ static int mxs_phy_suspend(struct usb_phy *x, int suspend) struct mxs_phy *mxs_phy = to_mxs_phy(x); if (suspend) { - writel_relaxed(0xffffffff, x->io_priv + HW_USBPHY_PWD); - writel_relaxed(BM_USBPHY_CTRL_CLKGATE, - x->io_priv + HW_USBPHY_CTRL_SET); + writel(0xffffffff, x->io_priv + HW_USBPHY_PWD); + writel(BM_USBPHY_CTRL_CLKGATE, + x->io_priv + HW_USBPHY_CTRL_SET); clk_disable_unprepare(mxs_phy->clk); } else { clk_prepare_enable(mxs_phy->clk); - writel_relaxed(BM_USBPHY_CTRL_CLKGATE, - x->io_priv + HW_USBPHY_CTRL_CLR); - writel_relaxed(0, x->io_priv + HW_USBPHY_PWD); + writel(BM_USBPHY_CTRL_CLKGATE, + x->io_priv + HW_USBPHY_CTRL_CLR); + writel(0, x->io_priv + HW_USBPHY_PWD); } return 0; @@ -102,8 +102,8 @@ static int mxs_phy_on_connect(struct usb_phy *phy, (speed == USB_SPEED_HIGH) ? "high" : "non-high"); if (speed == USB_SPEED_HIGH) - writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, - phy->io_priv + HW_USBPHY_CTRL_SET); + writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + phy->io_priv + HW_USBPHY_CTRL_SET); return 0; } @@ -115,8 +115,8 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy, (speed == USB_SPEED_HIGH) ? "high" : "non-high"); if (speed == USB_SPEED_HIGH) - writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, - phy->io_priv + HW_USBPHY_CTRL_CLR); + writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + phy->io_priv + HW_USBPHY_CTRL_CLR); return 0; } From cd051da2c81c8a86f331b4caa0c135c33d3ea3f6 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Sat, 2 Mar 2013 18:55:24 +0530 Subject: [PATCH 164/303] usb: dwc3: set 'mode' based on selected Kconfig choices Now that machines may select dwc3's working mode (HOST only, GADGET only or DUAL_ROLE) via Kconfig, let's set dwc3's mode based on that, rather than fixing it to whatever hardware says. This way we can skip initializing Gadget/Host in case we are using Host-only/Gadget-only mode respectively. Signed-off-by: Vivek Gautam Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index b81b3357f007..c6a46e0efe4f 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -479,7 +479,12 @@ static int dwc3_probe(struct platform_device *pdev) goto err1; } - mode = DWC3_MODE(dwc->hwparams.hwparams0); + if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) + mode = DWC3_MODE_HOST; + else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) + mode = DWC3_MODE_DEVICE; + else + mode = DWC3_MODE_DRD; switch (mode) { case DWC3_MODE_DEVICE: From d25ab3ece05c7cb740af155ecac87b6b36f16566 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 5 Mar 2013 09:42:15 +0530 Subject: [PATCH 165/303] usb: gadget: fsl_udc_core: Use module_platform_driver_probe macro module_platform_driver_probe() eliminates the boilerplate and simplifies the code. Signed-off-by: Sachin Kamat Acked-by: Li Yang Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fsl_udc_core.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index f22416986486..7c2a101d19ac 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2712,21 +2712,7 @@ static struct platform_driver udc_driver = { }, }; -static int __init udc_init(void) -{ - printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION); - return platform_driver_probe(&udc_driver, fsl_udc_probe); -} - -module_init(udc_init); - -static void __exit udc_exit(void) -{ - platform_driver_unregister(&udc_driver); - printk(KERN_WARNING "%s unregistered\n", driver_desc); -} - -module_exit(udc_exit); +module_platform_driver_probe(udc_driver, fsl_udc_probe); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR(DRIVER_AUTHOR); From 2daf5966d140d23d1b5ba347b53d102eeb029d2c Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 20 Feb 2013 09:53:39 +0100 Subject: [PATCH 166/303] usb: musb: drop dangling CONFIG_USB_MUSB_DEBUG CONFIG_USB_MUSB_DEBUG option was removed in 5c8a86e usb: musb: drop unneeded musb_debug trickery to cleanup the code from driver specific debug facilities. This patch drops the last references to the musb debug config option, unconditionally enabling all debug code paths, thus letting that code being dropped at compile time if not needed. Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/musb/cppi_dma.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index f522000e8f06..9db211ee15b5 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -435,7 +435,6 @@ cppi_rndis_update(struct cppi_channel *c, int is_rx, } } -#ifdef CONFIG_USB_MUSB_DEBUG static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd) { pr_debug("RXBD/%s %08x: " @@ -444,21 +443,16 @@ static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd) bd->hw_next, bd->hw_bufp, bd->hw_off_len, bd->hw_options); } -#endif static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx) { -#ifdef CONFIG_USB_MUSB_DEBUG struct cppi_descriptor *bd; - if (!_dbg_level(level)) - return; cppi_dump_rx(level, rx, tag); if (rx->last_processed) cppi_dump_rxbd("last", rx->last_processed); for (bd = rx->head; bd; bd = bd->next) cppi_dump_rxbd("active", bd); -#endif } @@ -784,6 +778,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket) void __iomem *tibase = musb->ctrl_base; int is_rndis = 0; struct cppi_rx_stateram __iomem *rx_ram = rx->state_ram; + struct cppi_descriptor *d; if (onepacket) { /* almost every USB driver, host or peripheral side */ @@ -897,14 +892,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket) bd->hw_options |= CPPI_SOP_SET; tail->hw_options |= CPPI_EOP_SET; -#ifdef CONFIG_USB_MUSB_DEBUG - if (_dbg_level(5)) { - struct cppi_descriptor *d; - - for (d = rx->head; d; d = d->next) - cppi_dump_rxbd("S", d); - } -#endif + for (d = rx->head; d; d = d->next) + cppi_dump_rxbd("S", d); /* in case the preceding transfer left some state... */ tail = rx->last_processed; From 5f71791947fcb1942df7d0df45520d420c2aee2b Mon Sep 17 00:00:00 2001 From: Syam Sidhardhan Date: Wed, 6 Mar 2013 01:04:50 +0530 Subject: [PATCH 167/303] usb: otg: fsl_otg: remove redundant NULL check before kfree kfree on NULL pointer is a no-op. Signed-off-by: Syam Sidhardhan Signed-off-by: Felipe Balbi --- drivers/usb/otg/fsl_otg.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index d16adb41eb21..37e8e1578316 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -361,28 +361,18 @@ int fsl_otg_init_timers(struct otg_fsm *fsm) void fsl_otg_uninit_timers(void) { /* FSM used timers */ - if (a_wait_vrise_tmr != NULL) - kfree(a_wait_vrise_tmr); - if (a_wait_bcon_tmr != NULL) - kfree(a_wait_bcon_tmr); - if (a_aidl_bdis_tmr != NULL) - kfree(a_aidl_bdis_tmr); - if (b_ase0_brst_tmr != NULL) - kfree(b_ase0_brst_tmr); - if (b_se0_srp_tmr != NULL) - kfree(b_se0_srp_tmr); - if (b_srp_fail_tmr != NULL) - kfree(b_srp_fail_tmr); - if (a_wait_enum_tmr != NULL) - kfree(a_wait_enum_tmr); + kfree(a_wait_vrise_tmr); + kfree(a_wait_bcon_tmr); + kfree(a_aidl_bdis_tmr); + kfree(b_ase0_brst_tmr); + kfree(b_se0_srp_tmr); + kfree(b_srp_fail_tmr); + kfree(a_wait_enum_tmr); /* device driver used timers */ - if (b_srp_wait_tmr != NULL) - kfree(b_srp_wait_tmr); - if (b_data_pulse_tmr != NULL) - kfree(b_data_pulse_tmr); - if (b_vbus_pulse_tmr != NULL) - kfree(b_vbus_pulse_tmr); + kfree(b_srp_wait_tmr); + kfree(b_data_pulse_tmr); + kfree(b_vbus_pulse_tmr); } /* Add timer to timer list */ From 789451f6c698282d0745f265bde47173c9372867 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 5 May 2011 15:53:10 +0300 Subject: [PATCH 168/303] usb: dwc3: calculate the number of endpoints hwparams2 holds the number of endpoints which were selected during RTL generation, we can use that on our driver. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 13 +++++++++++++ drivers/usb/dwc3/core.h | 15 +++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c6a46e0efe4f..66c05725daf3 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -260,6 +260,17 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) } } +static void dwc3_core_num_eps(struct dwc3 *dwc) +{ + struct dwc3_hwparams *parms = &dwc->hwparams; + + dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); + dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; + + dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n", + dwc->num_in_eps, dwc->num_out_eps); +} + static void dwc3_cache_hwparams(struct dwc3 *dwc) { struct dwc3_hwparams *parms = &dwc->hwparams; @@ -336,6 +347,8 @@ static int dwc3_core_init(struct dwc3 *dwc) if (dwc->revision < DWC3_REVISION_190A) reg |= DWC3_GCTL_U2RSTECN; + dwc3_core_num_eps(dwc); + dwc3_writel(dwc->regs, DWC3_GCTL, reg); return 0; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index ad2ffac71500..b42f71cb87dd 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -575,6 +575,14 @@ struct dwc3_hwparams { /* HWPARAMS1 */ #define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15) +/* HWPARAMS3 */ +#define DWC3_NUM_IN_EPS_MASK (0x1f << 18) +#define DWC3_NUM_EPS_MASK (0x3f << 12) +#define DWC3_NUM_EPS(p) (((p)->hwparams3 & \ + (DWC3_NUM_EPS_MASK)) >> 12) +#define DWC3_NUM_IN_EPS(p) (((p)->hwparams3 & \ + (DWC3_NUM_IN_EPS_MASK)) >> 18) + /* HWPARAMS7 */ #define DWC3_RAM1_DEPTH(n) ((n) & 0xffff) @@ -641,6 +649,8 @@ struct dwc3_scratchpad_array { * @u2pel: parameter from Set SEL request. * @u1sel: parameter from Set SEL request. * @u1pel: parameter from Set SEL request. + * @num_out_eps: number of out endpoints + * @num_in_eps: number of in endpoints * @ep0_next_event: hold the next expected event * @ep0state: state of endpoint zero * @link_state: link state @@ -658,8 +668,10 @@ struct dwc3 { dma_addr_t ep0_trb_addr; dma_addr_t ep0_bounce_addr; struct dwc3_request ep0_usb_req; + /* device lock */ spinlock_t lock; + struct device *dev; struct platform_device *xhci; @@ -727,6 +739,9 @@ struct dwc3 { u8 speed; + u8 num_out_eps; + u8 num_in_eps; + void *mem; struct dwc3_hwparams hwparams; From 6a1e3ef45fb0c4d79cbb5190c8fc59263c630b0e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 5 May 2011 16:21:59 +0300 Subject: [PATCH 169/303] usb: dwc3: gadget: use num_(in|out)_eps from HW params that way we will only tell gadget framework about the endpoints we actually have. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8e53acc0e43e..2b6e7e001207 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1623,14 +1623,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { /* -------------------------------------------------------------------------- */ -static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) +static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, + u8 num, u32 direction) { struct dwc3_ep *dep; - u8 epnum; + u8 i; - INIT_LIST_HEAD(&dwc->gadget.ep_list); + for (i = 0; i < num; i++) { + u8 epnum = (i << 1) | (!!direction); - for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) { dep = kzalloc(sizeof(*dep), GFP_KERNEL); if (!dep) { dev_err(dwc->dev, "can't allocate endpoint %d\n", @@ -1644,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1, (epnum & 1) ? "in" : "out"); + dep->endpoint.name = dep->name; dep->direction = (epnum & 1); @@ -1674,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) return 0; } +static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) +{ + int ret; + + INIT_LIST_HEAD(&dwc->gadget.ep_list); + + ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0); + if (ret < 0) { + dev_vdbg(dwc->dev, "failed to allocate OUT endpoints\n"); + return ret; + } + + ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1); + if (ret < 0) { + dev_vdbg(dwc->dev, "failed to allocate IN endpoints\n"); + return ret; + } + + return 0; +} + static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) { struct dwc3_ep *dep; @@ -1681,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) { dep = dwc->eps[epnum]; + if (!dep) + continue; + dwc3_free_trb_pool(dep); if (epnum != 0 && epnum != 1) @@ -2015,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc) struct dwc3_ep *dep; dep = dwc->eps[epnum]; + if (!dep) + continue; + if (!(dep->flags & DWC3_EP_ENABLED)) continue; @@ -2032,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) int ret; dep = dwc->eps[epnum]; + if (!dep) + continue; if (!(dep->flags & DWC3_EP_STALL)) continue; From 42c0bf1ce7c067bbc3e77d5626f102a16bc4fb6b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 10:39:57 +0200 Subject: [PATCH 170/303] usb: otg: prefix otg_state_string with usb_ all other functions under drivers/usb/ start with usb_, let's do the same thing. This patch is in preparation for moving otg_state_string to usb-common.c and deleting otg.c completely. Signed-off-by: Felipe Balbi --- drivers/usb/musb/am35x.c | 8 +++---- drivers/usb/musb/blackfin.c | 6 ++--- drivers/usb/musb/da8xx.c | 8 +++---- drivers/usb/musb/davinci.c | 4 ++-- drivers/usb/musb/musb_core.c | 39 +++++++++++++++++---------------- drivers/usb/musb/musb_dsps.c | 8 +++---- drivers/usb/musb/musb_gadget.c | 8 +++---- drivers/usb/musb/musb_host.c | 2 +- drivers/usb/musb/musb_virthub.c | 4 ++-- drivers/usb/musb/omap2430.c | 6 ++--- drivers/usb/musb/tusb6010.c | 14 ++++++------ drivers/usb/otg/fsl_otg.c | 2 +- drivers/usb/otg/isp1301_omap.c | 6 ++--- drivers/usb/otg/otg.c | 4 ++-- drivers/usb/otg/otg_fsm.c | 2 +- include/linux/usb/otg.h | 4 ++-- 16 files changed, 63 insertions(+), 62 deletions(-) diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 59eea219034a..2231850c0625 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -149,7 +149,7 @@ static void otg_timer(unsigned long _musb) */ devctl = musb_readb(mregs, MUSB_DEVCTL); dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); spin_lock_irqsave(&musb->lock, flags); switch (musb->xceiv->state) { @@ -195,7 +195,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout) if (musb->is_active || (musb->a_wait_bcon == 0 && musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); del_timer(&otg_workaround); last_timer = jiffies; return; @@ -208,7 +208,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout) last_timer = timeout; dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), jiffies_to_msecs(timeout - jiffies)); mod_timer(&otg_workaround, timeout); } @@ -298,7 +298,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) /* NOTE: this must complete power-on within 100 ms. */ dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", drvvbus ? "on" : "off", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), err ? " ERROR" : "", devctl); ret = IRQ_HANDLED; diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index dbb31b30c7fa..5e63b160db0c 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -280,13 +280,13 @@ static void musb_conn_timer_handler(unsigned long _musb) break; default: dev_dbg(musb->controller, "%s state not handled\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); break; } spin_unlock_irqrestore(&musb->lock, flags); dev_dbg(musb->controller, "state is %s\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } static void bfin_musb_enable(struct musb *musb) @@ -307,7 +307,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on) dev_dbg(musb->controller, "VBUS %s, devctl %02x " /* otg %3x conf %08x prcm %08x */ "\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), musb_readb(musb->mregs, MUSB_DEVCTL)); } diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 7c71769d71ff..ea7e591093ee 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -198,7 +198,7 @@ static void otg_timer(unsigned long _musb) */ devctl = musb_readb(mregs, MUSB_DEVCTL); dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); spin_lock_irqsave(&musb->lock, flags); switch (musb->xceiv->state) { @@ -267,7 +267,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) if (musb->is_active || (musb->a_wait_bcon == 0 && musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); del_timer(&otg_workaround); last_timer = jiffies; return; @@ -280,7 +280,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) last_timer = timeout; dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), jiffies_to_msecs(timeout - jiffies)); mod_timer(&otg_workaround, timeout); } @@ -360,7 +360,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", drvvbus ? "on" : "off", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), err ? " ERROR" : "", devctl); ret = IRQ_HANDLED; diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index e040d9103735..bea6cc35471c 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb) */ devctl = musb_readb(mregs, MUSB_DEVCTL); dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl, - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); spin_lock_irqsave(&musb->lock, flags); switch (musb->xceiv->state) { @@ -349,7 +349,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) davinci_musb_source_power(musb, drvvbus, 0); dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", drvvbus ? "on" : "off", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), err ? " ERROR" : "", devctl); retval = IRQ_HANDLED; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fad8571ed433..6bd879257e4c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -372,13 +372,13 @@ static void musb_otg_timer_func(unsigned long data) case OTG_STATE_A_SUSPEND: case OTG_STATE_A_WAIT_BCON: dev_dbg(musb->controller, "HNP: %s timeout\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); musb_platform_set_vbus(musb, 0); musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; break; default: dev_dbg(musb->controller, "HNP: Unhandled mode %s\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } musb->ignore_disconnect = 0; spin_unlock_irqrestore(&musb->lock, flags); @@ -393,13 +393,14 @@ void musb_hnp_stop(struct musb *musb) void __iomem *mbase = musb->mregs; u8 reg; - dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state)); + dev_dbg(musb->controller, "HNP: stop from %s\n", + usb_otg_state_string(musb->xceiv->state)); switch (musb->xceiv->state) { case OTG_STATE_A_PERIPHERAL: musb_g_disconnect(musb); dev_dbg(musb->controller, "HNP: back to %s\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); break; case OTG_STATE_B_HOST: dev_dbg(musb->controller, "HNP: Disabling HR\n"); @@ -413,7 +414,7 @@ void musb_hnp_stop(struct musb *musb) break; default: dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } /* @@ -451,7 +452,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, */ if (int_usb & MUSB_INTR_RESUME) { handled = IRQ_HANDLED; - dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state)); + dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->state)); if (devctl & MUSB_DEVCTL_HM) { void __iomem *mbase = musb->mregs; @@ -493,7 +494,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, default: WARNING("bogus %s RESUME (%s)\n", "host", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } } else { switch (musb->xceiv->state) { @@ -522,7 +523,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, default: WARNING("bogus %s RESUME (%s)\n", "peripheral", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } } } @@ -538,7 +539,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, } dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); /* IRQ arrives from ID pin sense or (later, if VBUS power * is removed) SRP. responses are time critical: @@ -603,7 +604,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, } dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), devctl, ({ char *s; switch (devctl & MUSB_DEVCTL_VBUS) { @@ -628,7 +629,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, if (int_usb & MUSB_INTR_SUSPEND) { dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n", - otg_state_string(musb->xceiv->state), devctl); + usb_otg_state_string(musb->xceiv->state), devctl); handled = IRQ_HANDLED; switch (musb->xceiv->state) { @@ -745,12 +746,12 @@ b_host: usb_hcd_resume_root_hub(hcd); dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n", - otg_state_string(musb->xceiv->state), devctl); + usb_otg_state_string(musb->xceiv->state), devctl); } if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) { dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), MUSB_MODE(musb), devctl); handled = IRQ_HANDLED; @@ -787,7 +788,7 @@ b_host: break; default: WARNING("unhandled DISCONNECT transition (%s)\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); break; } } @@ -813,7 +814,7 @@ b_host: } } else { dev_dbg(musb->controller, "BUS RESET as %s\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); switch (musb->xceiv->state) { case OTG_STATE_A_SUSPEND: /* We need to ignore disconnect on suspend @@ -826,7 +827,7 @@ b_host: case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ /* never use invalid T(a_wait_bcon) */ dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), TA_WAIT_BCON(musb)); mod_timer(&musb->otg_timer, jiffies + msecs_to_jiffies(TA_WAIT_BCON(musb))); @@ -838,7 +839,7 @@ b_host: break; case OTG_STATE_B_WAIT_ACON: dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); musb->xceiv->state = OTG_STATE_B_PERIPHERAL; musb_g_reset(musb); break; @@ -850,7 +851,7 @@ b_host: break; default: dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } } } @@ -1632,7 +1633,7 @@ musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf) int ret = -EINVAL; spin_lock_irqsave(&musb->lock, flags); - ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state)); + ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->state)); spin_unlock_irqrestore(&musb->lock, flags); return ret; diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 4b4987461adb..1ea553d2b77f 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -225,7 +225,7 @@ static void otg_timer(unsigned long _musb) */ devctl = dsps_readb(mregs, MUSB_DEVCTL); dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); spin_lock_irqsave(&musb->lock, flags); switch (musb->xceiv->state) { @@ -274,7 +274,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) if (musb->is_active || (musb->a_wait_bcon == 0 && musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); del_timer(&glue->timer[pdev->id]); glue->last_timer[pdev->id] = jiffies; return; @@ -289,7 +289,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) glue->last_timer[pdev->id] = timeout; dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), jiffies_to_msecs(timeout - jiffies)); mod_timer(&glue->timer[pdev->id], timeout); } @@ -378,7 +378,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) /* NOTE: this must complete power-on within 100 ms. */ dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", drvvbus ? "on" : "off", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), err ? " ERROR" : "", devctl); ret = IRQ_HANDLED; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 6101ebf803fd..e8408883ab0d 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1571,7 +1571,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget) goto done; default: dev_dbg(musb->controller, "Unhandled wake: %s\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); goto done; } @@ -1970,7 +1970,7 @@ void musb_g_resume(struct musb *musb) break; default: WARNING("unhandled RESUME transition (%s)\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } } @@ -2000,7 +2000,7 @@ void musb_g_suspend(struct musb *musb) * A_PERIPHERAL may need care too */ WARNING("unhandled SUSPEND transition (%s)\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } } @@ -2034,7 +2034,7 @@ void musb_g_disconnect(struct musb *musb) switch (musb->xceiv->state) { default: dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); musb->xceiv->state = OTG_STATE_A_IDLE; MUSB_HST_MODE(musb); break; diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 1ce1fcf3f3e7..51e9e8a38444 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2453,7 +2453,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd) if (musb->is_active) { WARNING("trying to suspend as %s while active\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); return -EBUSY; } else return 0; diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index f70579154ded..ef7d11045f56 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -95,7 +95,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) break; default: dev_dbg(musb->controller, "bogus rh suspend? %s\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } } else if (power & MUSB_POWER_SUSPENDM) { power &= ~MUSB_POWER_SUSPENDM; @@ -203,7 +203,7 @@ void musb_root_disconnect(struct musb *musb) break; default: dev_dbg(musb->controller, "host disconnect (%s)\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } } diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 1a42a458f2c4..8ba9bb2a91a7 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -117,7 +117,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) if (musb->is_active || ((musb->a_wait_bcon == 0) && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); del_timer(&musb_idle_timer); last_timer = jiffies; return; @@ -134,7 +134,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout) last_timer = timeout; dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), (unsigned long)jiffies_to_msecs(timeout - jiffies)); mod_timer(&musb_idle_timer, timeout); } @@ -200,7 +200,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) dev_dbg(musb->controller, "VBUS %s, devctl %02x " /* otg %3x conf %08x prcm %08x */ "\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), musb_readb(musb->mregs, MUSB_DEVCTL)); } diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 464bd23cccda..7369ba33c94f 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -423,7 +423,7 @@ static void musb_do_idle(unsigned long _musb) && (musb->idle_timeout == 0 || time_after(jiffies, musb->idle_timeout))) { dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); } /* FALLTHROUGH */ case OTG_STATE_A_IDLE: @@ -478,7 +478,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout) if (musb->is_active || ((musb->a_wait_bcon == 0) && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { dev_dbg(musb->controller, "%s active, deleting timer\n", - otg_state_string(musb->xceiv->state)); + usb_otg_state_string(musb->xceiv->state)); del_timer(&musb_idle_timer); last_timer = jiffies; return; @@ -495,7 +495,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout) last_timer = timeout; dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), (unsigned long)jiffies_to_msecs(timeout - jiffies)); mod_timer(&musb_idle_timer, timeout); } @@ -571,7 +571,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); dev_dbg(musb->controller, "VBUS %s, devctl %02x otg %3x conf %08x prcm %08x\n", - otg_state_string(musb->xceiv->state), + usb_otg_state_string(musb->xceiv->state), musb_readb(musb->mregs, MUSB_DEVCTL), musb_readl(tbase, TUSB_DEV_OTG_STAT), conf, prcm); @@ -678,13 +678,13 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) musb->is_active = 0; } dev_dbg(musb->controller, "vbus change, %s, otg %03x\n", - otg_state_string(musb->xceiv->state), otg_stat); + usb_otg_state_string(musb->xceiv->state), otg_stat); idle_timeout = jiffies + (1 * HZ); schedule_work(&musb->irq_work); } else /* A-dev state machine */ { dev_dbg(musb->controller, "vbus change, %s, otg %03x\n", - otg_state_string(musb->xceiv->state), otg_stat); + usb_otg_state_string(musb->xceiv->state), otg_stat); switch (musb->xceiv->state) { case OTG_STATE_A_IDLE: @@ -733,7 +733,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) u8 devctl; dev_dbg(musb->controller, "%s timer, %03x\n", - otg_state_string(musb->xceiv->state), otg_stat); + usb_otg_state_string(musb->xceiv->state), otg_stat); switch (musb->xceiv->state) { case OTG_STATE_A_WAIT_VRISE: diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index 37e8e1578316..72a2a00c2487 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -992,7 +992,7 @@ static int show_fsl_usb2_otg_state(struct device *dev, /* State */ t = scnprintf(next, size, "OTG state: %s\n\n", - otg_state_string(fsl_otg_dev->phy.state)); + usb_otg_state_string(fsl_otg_dev->phy.state)); size -= t; next += t; diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index af9cb11626b2..8fe0c3b95261 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -236,7 +236,7 @@ isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits) static inline const char *state_name(struct isp1301 *isp) { - return otg_state_string(isp->phy.state); + return usb_otg_state_string(isp->phy.state); } /*-------------------------------------------------------------------------*/ @@ -481,7 +481,7 @@ static void check_state(struct isp1301 *isp, const char *tag) if (isp->phy.state == state && !extra) return; pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag, - otg_state_string(state), fsm, state_name(isp), + usb_otg_state_string(state), fsm, state_name(isp), omap_readl(OTG_CTRL)); } @@ -1077,7 +1077,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat) if (state != isp->phy.state) pr_debug(" isp, %s -> %s\n", - otg_state_string(state), state_name(isp)); + usb_otg_state_string(state), state_name(isp)); #ifdef CONFIG_USB_OTG /* update the OTG controller state to match the isp1301; may diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index 358cfd9bce89..fd9a4b7bebe7 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c @@ -11,7 +11,7 @@ #include #include -const char *otg_state_string(enum usb_otg_state state) +const char *usb_otg_state_string(enum usb_otg_state state) { switch (state) { case OTG_STATE_A_IDLE: @@ -44,4 +44,4 @@ const char *otg_state_string(enum usb_otg_state state) return "UNDEFINED"; } } -EXPORT_SYMBOL(otg_state_string); +EXPORT_SYMBOL(usb_otg_state_string); diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/otg/otg_fsm.c index ade131a8ae5e..1f729a15decb 100644 --- a/drivers/usb/otg/otg_fsm.c +++ b/drivers/usb/otg/otg_fsm.c @@ -119,7 +119,7 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state) state_changed = 1; if (fsm->otg->phy->state == new_state) return 0; - VDBG("Set state: %s\n", otg_state_string(new_state)); + VDBG("Set state: %s\n", usb_otg_state_string(new_state)); otg_leave_state(fsm, fsm->otg->phy->state); switch (new_state) { case OTG_STATE_B_IDLE: diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index e8a5fe87c6bd..9f9fb3927b0a 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -37,9 +37,9 @@ struct usb_otg { }; #ifdef CONFIG_USB_OTG_UTILS -extern const char *otg_state_string(enum usb_otg_state state); +extern const char *usb_otg_state_string(enum usb_otg_state state); #else -static inline const char *otg_state_string(enum usb_otg_state state) +static inline const char *usb_otg_state_string(enum usb_otg_state state) { return NULL; } From 7009bdd7f31ed6e769af0f76e2368bb6033be572 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 10:45:56 +0200 Subject: [PATCH 171/303] usb: otg: move usb_otg_state_string to usb-common.c otg.c only had a single function definition which might make more sense to be placed in usb-common.c. While doing that, we also delete otg.c since it's now empty. Signed-off-by: Felipe Balbi --- drivers/usb/otg/Makefile | 3 --- drivers/usb/otg/otg.c | 47 ---------------------------------------- drivers/usb/usb-common.c | 26 ++++++++++++++++++++++ include/linux/usb/otg.h | 7 ------ 4 files changed, 26 insertions(+), 57 deletions(-) delete mode 100644 drivers/usb/otg/otg.c diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index a844b8d35d14..6abc45388e24 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -5,9 +5,6 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG -# infrastructure -obj-$(CONFIG_USB_OTG_UTILS) += otg.o - # transceiver drivers obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c deleted file mode 100644 index fd9a4b7bebe7..000000000000 --- a/drivers/usb/otg/otg.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * otg.c -- USB OTG utility code - * - * Copyright (C) 2004 Texas Instruments - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#include -#include - -const char *usb_otg_state_string(enum usb_otg_state state) -{ - switch (state) { - case OTG_STATE_A_IDLE: - return "a_idle"; - case OTG_STATE_A_WAIT_VRISE: - return "a_wait_vrise"; - case OTG_STATE_A_WAIT_BCON: - return "a_wait_bcon"; - case OTG_STATE_A_HOST: - return "a_host"; - case OTG_STATE_A_SUSPEND: - return "a_suspend"; - case OTG_STATE_A_PERIPHERAL: - return "a_peripheral"; - case OTG_STATE_A_WAIT_VFALL: - return "a_wait_vfall"; - case OTG_STATE_A_VBUS_ERR: - return "a_vbus_err"; - case OTG_STATE_B_IDLE: - return "b_idle"; - case OTG_STATE_B_SRP_INIT: - return "b_srp_init"; - case OTG_STATE_B_PERIPHERAL: - return "b_peripheral"; - case OTG_STATE_B_WAIT_ACON: - return "b_wait_acon"; - case OTG_STATE_B_HOST: - return "b_host"; - default: - return "UNDEFINED"; - } -} -EXPORT_SYMBOL(usb_otg_state_string); diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c index 070b681e5d17..0db0a919d72b 100644 --- a/drivers/usb/usb-common.c +++ b/drivers/usb/usb-common.c @@ -14,6 +14,32 @@ #include #include #include +#include + +const char *usb_otg_state_string(enum usb_otg_state state) +{ + static const char *const names[] = { + [OTG_STATE_A_IDLE] = "a_idle", + [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise", + [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon", + [OTG_STATE_A_HOST] = "a_host", + [OTG_STATE_A_SUSPEND] = "a_suspend", + [OTG_STATE_A_PERIPHERAL] = "a_peripheral", + [OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall", + [OTG_STATE_A_VBUS_ERR] = "a_vbus_err", + [OTG_STATE_B_IDLE] = "b_idle", + [OTG_STATE_B_SRP_INIT] = "b_srp_init", + [OTG_STATE_B_PERIPHERAL] = "b_peripheral", + [OTG_STATE_B_WAIT_ACON] = "b_wait_acon", + [OTG_STATE_B_HOST] = "b_host", + }; + + if (state < 0 || state >= ARRAY_SIZE(names)) + return "UNDEFINED"; + + return names[state]; +} +EXPORT_SYMBOL_GPL(usb_otg_state_string); const char *usb_speed_string(enum usb_device_speed speed) { diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 9f9fb3927b0a..291e01ba32e5 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -36,14 +36,7 @@ struct usb_otg { }; -#ifdef CONFIG_USB_OTG_UTILS extern const char *usb_otg_state_string(enum usb_otg_state state); -#else -static inline const char *usb_otg_state_string(enum usb_otg_state state) -{ - return NULL; -} -#endif /* Context: can sleep */ static inline int From 110ff6d04162a8a3b288019eaf84dee0800270e0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 10:49:27 +0200 Subject: [PATCH 172/303] usb: phy: convert EXPORT_SYMBOL to EXPORT_SYMBOL_GPL we only want GPL users for our generic functions, so let's switch over to EXPORT_SYMBOL_GPL. Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index bc1970c55df0..f52c006417ff 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -109,7 +109,7 @@ struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type) return phy; } -EXPORT_SYMBOL(devm_usb_get_phy); +EXPORT_SYMBOL_GPL(devm_usb_get_phy); /** * usb_get_phy - find the USB PHY @@ -142,7 +142,7 @@ err0: return phy; } -EXPORT_SYMBOL(usb_get_phy); +EXPORT_SYMBOL_GPL(usb_get_phy); /** * devm_usb_get_phy_by_phandle - find the USB PHY by phandle @@ -206,7 +206,7 @@ err0: return phy; } -EXPORT_SYMBOL(devm_usb_get_phy_by_phandle); +EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle); /** * usb_get_phy_dev - find the USB PHY @@ -239,7 +239,7 @@ err0: return phy; } -EXPORT_SYMBOL(usb_get_phy_dev); +EXPORT_SYMBOL_GPL(usb_get_phy_dev); /** * devm_usb_get_phy_dev - find the USB PHY using device ptr and index @@ -269,7 +269,7 @@ struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index) return phy; } -EXPORT_SYMBOL(devm_usb_get_phy_dev); +EXPORT_SYMBOL_GPL(devm_usb_get_phy_dev); /** * devm_usb_put_phy - release the USB PHY @@ -288,7 +288,7 @@ void devm_usb_put_phy(struct device *dev, struct usb_phy *phy) r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy); dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); } -EXPORT_SYMBOL(devm_usb_put_phy); +EXPORT_SYMBOL_GPL(devm_usb_put_phy); /** * usb_put_phy - release the USB PHY @@ -307,7 +307,7 @@ void usb_put_phy(struct usb_phy *x) module_put(owner); } } -EXPORT_SYMBOL(usb_put_phy); +EXPORT_SYMBOL_GPL(usb_put_phy); /** * usb_add_phy - declare the USB PHY @@ -347,7 +347,7 @@ out: spin_unlock_irqrestore(&phy_lock, flags); return ret; } -EXPORT_SYMBOL(usb_add_phy); +EXPORT_SYMBOL_GPL(usb_add_phy); /** * usb_add_phy_dev - declare the USB PHY @@ -377,7 +377,7 @@ int usb_add_phy_dev(struct usb_phy *x) spin_unlock_irqrestore(&phy_lock, flags); return 0; } -EXPORT_SYMBOL(usb_add_phy_dev); +EXPORT_SYMBOL_GPL(usb_add_phy_dev); /** * usb_remove_phy - remove the OTG PHY @@ -399,7 +399,7 @@ void usb_remove_phy(struct usb_phy *x) } spin_unlock_irqrestore(&phy_lock, flags); } -EXPORT_SYMBOL(usb_remove_phy); +EXPORT_SYMBOL_GPL(usb_remove_phy); /** * usb_bind_phy - bind the phy and the controller that uses the phy From a0e631235a04f8a815a1ecec93ef418f7d1e6086 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 11:01:15 +0200 Subject: [PATCH 173/303] usb: phy: move all PHY drivers to drivers/usb/phy/ that's a much more reasonable location for those drivers. It helps us saving drivers/usb/otg/ for when we actually start adding generic OTG code. Also completely delete drivers/usb/otg/ as there's nothing left there. Signed-off-by: Felipe Balbi --- drivers/usb/Kconfig | 2 - drivers/usb/Makefile | 2 - drivers/usb/otg/Kconfig | 141 ------------------- drivers/usb/otg/Makefile | 21 --- drivers/usb/phy/Kconfig | 168 ++++++++++++++++++++--- drivers/usb/phy/Makefile | 26 +++- drivers/usb/{otg => phy}/ab8500-usb.c | 0 drivers/usb/{otg => phy}/fsl_otg.c | 0 drivers/usb/{otg => phy}/fsl_otg.h | 0 drivers/usb/{otg => phy}/gpio_vbus.c | 0 drivers/usb/{otg => phy}/isp1301_omap.c | 0 drivers/usb/{otg => phy}/msm_otg.c | 0 drivers/usb/{otg => phy}/mv_otg.c | 0 drivers/usb/{otg => phy}/mv_otg.h | 0 drivers/usb/{otg => phy}/mxs-phy.c | 0 drivers/usb/{otg => phy}/nop-usb-xceiv.c | 0 drivers/usb/{otg => phy}/otg_fsm.c | 0 drivers/usb/{otg => phy}/otg_fsm.h | 0 drivers/usb/{otg => phy}/twl4030-usb.c | 0 drivers/usb/{otg => phy}/twl6030-usb.c | 0 drivers/usb/{otg => phy}/ulpi.c | 0 drivers/usb/{otg => phy}/ulpi_viewport.c | 0 22 files changed, 172 insertions(+), 188 deletions(-) delete mode 100644 drivers/usb/otg/Kconfig delete mode 100644 drivers/usb/otg/Makefile rename drivers/usb/{otg => phy}/ab8500-usb.c (100%) rename drivers/usb/{otg => phy}/fsl_otg.c (100%) rename drivers/usb/{otg => phy}/fsl_otg.h (100%) rename drivers/usb/{otg => phy}/gpio_vbus.c (100%) rename drivers/usb/{otg => phy}/isp1301_omap.c (100%) rename drivers/usb/{otg => phy}/msm_otg.c (100%) rename drivers/usb/{otg => phy}/mv_otg.c (100%) rename drivers/usb/{otg => phy}/mv_otg.h (100%) rename drivers/usb/{otg => phy}/mxs-phy.c (100%) rename drivers/usb/{otg => phy}/nop-usb-xceiv.c (100%) rename drivers/usb/{otg => phy}/otg_fsm.c (100%) rename drivers/usb/{otg => phy}/otg_fsm.h (100%) rename drivers/usb/{otg => phy}/twl4030-usb.c (100%) rename drivers/usb/{otg => phy}/twl6030-usb.c (100%) rename drivers/usb/{otg => phy}/ulpi.c (100%) rename drivers/usb/{otg => phy}/ulpi_viewport.c (100%) diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 640ae6c6d2d2..2c481b808276 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -186,6 +186,4 @@ source "drivers/usb/atm/Kconfig" source "drivers/usb/gadget/Kconfig" -source "drivers/usb/otg/Kconfig" - endif # USB_SUPPORT diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 8f5ebced5df0..860306b14392 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -6,8 +6,6 @@ obj-$(CONFIG_USB) += core/ -obj-$(CONFIG_USB_OTG_UTILS) += otg/ - obj-$(CONFIG_USB_DWC3) += dwc3/ obj-$(CONFIG_USB_MON) += mon/ diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig deleted file mode 100644 index 37962c99ff1e..000000000000 --- a/drivers/usb/otg/Kconfig +++ /dev/null @@ -1,141 +0,0 @@ -# -# USB OTG infrastructure may be needed for peripheral-only, host-only, -# or OTG-capable configurations when OTG transceivers or controllers -# are used. -# - -comment "OTG and related infrastructure" - -config USB_OTG_UTILS - bool - help - Select this to make sure the build includes objects from - the OTG infrastructure directory. - -if USB || USB_GADGET - -# -# USB Transceiver Drivers -# -config USB_GPIO_VBUS - tristate "GPIO based peripheral-only VBUS sensing 'transceiver'" - depends on GENERIC_GPIO - select USB_OTG_UTILS - help - Provides simple GPIO VBUS sensing for controllers with an - internal transceiver via the usb_phy interface, and - optionally control of a D+ pullup GPIO as well as a VBUS - current limit regulator. - -config ISP1301_OMAP - tristate "Philips ISP1301 with OMAP OTG" - depends on I2C && ARCH_OMAP_OTG - select USB_OTG_UTILS - help - If you say yes here you get support for the Philips ISP1301 - USB-On-The-Go transceiver working with the OMAP OTG controller. - The ISP1301 is a full speed USB transceiver which is used in - products including H2, H3, and H4 development boards for Texas - Instruments OMAP processors. - - This driver can also be built as a module. If so, the module - will be called isp1301_omap. - -config USB_ULPI - bool "Generic ULPI Transceiver Driver" - depends on ARM - select USB_OTG_UTILS - help - Enable this to support ULPI connected USB OTG transceivers which - are likely found on embedded boards. - -config USB_ULPI_VIEWPORT - bool - depends on USB_ULPI - help - Provides read/write operations to the ULPI phy register set for - controllers with a viewport register (e.g. Chipidea/ARC controllers). - -config TWL4030_USB - tristate "TWL4030 USB Transceiver Driver" - depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS - select USB_OTG_UTILS - help - Enable this to support the USB OTG transceiver on TWL4030 - family chips (including the TWL5030 and TPS659x0 devices). - This transceiver supports high and full speed devices plus, - in host mode, low speed. - -config TWL6030_USB - tristate "TWL6030 USB Transceiver Driver" - depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS - select USB_OTG_UTILS - help - Enable this to support the USB OTG transceiver on TWL6030 - family chips. This TWL6030 transceiver has the VBUS and ID GND - and OTG SRP events capabilities. For all other transceiver functionality - UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs - are hooked to this driver through platform_data structure. - The definition of internal PHY APIs are in the mach-omap2 layer. - -config NOP_USB_XCEIV - tristate "NOP USB Transceiver Driver" - select USB_OTG_UTILS - help - This driver is to be used by all the usb transceiver which are either - built-in with usb ip or which are autonomous and doesn't require any - phy programming such as ISP1x04 etc. - -config USB_MSM_OTG - tristate "OTG support for Qualcomm on-chip USB controller" - depends on (USB || USB_GADGET) && ARCH_MSM - select USB_OTG_UTILS - help - Enable this to support the USB OTG transceiver on MSM chips. It - handles PHY initialization, clock management, and workarounds - required after resetting the hardware and power management. - This driver is required even for peripheral only or host only - mode configurations. - This driver is not supported on boards like trout which - has an external PHY. - -config AB8500_USB - tristate "AB8500 USB Transceiver Driver" - depends on AB8500_CORE - select USB_OTG_UTILS - help - Enable this to support the USB OTG transceiver in AB8500 chip. - This transceiver supports high and full speed devices plus, - in host mode, low speed. - -config FSL_USB2_OTG - bool "Freescale USB OTG Transceiver Driver" - depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND - select USB_OTG - select USB_OTG_UTILS - help - Enable this to support Freescale USB OTG transceiver. - -config USB_MXS_PHY - tristate "Freescale MXS USB PHY support" - depends on ARCH_MXC || ARCH_MXS - select STMP_DEVICE - select USB_OTG_UTILS - help - Enable this to support the Freescale MXS USB PHY. - - MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. - -config USB_MV_OTG - tristate "Marvell USB OTG support" - depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND - select USB_OTG - select USB_OTG_UTILS - help - Say Y here if you want to build Marvell USB OTG transciever - driver in kernel (including PXA and MMP series). This driver - implements role switch between EHCI host driver and gadget driver. - - To compile this driver as a module, choose M here. - -endif # USB || OTG diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile deleted file mode 100644 index 6abc45388e24..000000000000 --- a/drivers/usb/otg/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# OTG infrastructure and transceiver drivers -# - -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG -ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG - -# transceiver drivers -obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o -obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o -obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o -obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o -obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o -obj-$(CONFIG_USB_ULPI) += ulpi.o -obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o -obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o -obj-$(CONFIG_AB8500_USB) += ab8500-usb.o -fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o -obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o -obj-$(CONFIG_USB_MXS_PHY) += mxs-phy.o -obj-$(CONFIG_USB_MV_OTG) += mv_otg.o diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 65217a590068..32ce740a9dd5 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -4,6 +4,73 @@ comment "USB Physical Layer drivers" depends on USB || USB_GADGET +config USB_OTG_UTILS + bool + help + Select this to make sure the build includes objects from + the OTG infrastructure directory. + +if USB || USB_GADGET + +# +# USB Transceiver Drivers +# +config AB8500_USB + tristate "AB8500 USB Transceiver Driver" + depends on AB8500_CORE + select USB_OTG_UTILS + help + Enable this to support the USB OTG transceiver in AB8500 chip. + This transceiver supports high and full speed devices plus, + in host mode, low speed. + +config FSL_USB2_OTG + bool "Freescale USB OTG Transceiver Driver" + depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND + select USB_OTG + select USB_OTG_UTILS + help + Enable this to support Freescale USB OTG transceiver. + +config ISP1301_OMAP + tristate "Philips ISP1301 with OMAP OTG" + depends on I2C && ARCH_OMAP_OTG + select USB_OTG_UTILS + help + If you say yes here you get support for the Philips ISP1301 + USB-On-The-Go transceiver working with the OMAP OTG controller. + The ISP1301 is a full speed USB transceiver which is used in + products including H2, H3, and H4 development boards for Texas + Instruments OMAP processors. + + This driver can also be built as a module. If so, the module + will be called isp1301_omap. + +config MV_U3D_PHY + bool "Marvell USB 3.0 PHY controller Driver" + depends on USB_MV_U3D + select USB_OTG_UTILS + help + Enable this to support Marvell USB 3.0 phy controller for Marvell + SoC. + +config NOP_USB_XCEIV + tristate "NOP USB Transceiver Driver" + select USB_OTG_UTILS + help + This driver is to be used by all the usb transceiver which are either + built-in with usb ip or which are autonomous and doesn't require any + phy programming such as ISP1x04 etc. + +config OMAP_CONTROL_USB + tristate "OMAP CONTROL USB Driver" + help + Enable this to add support for the USB part present in the control + module. This driver has API to power on the USB2 PHY and to write to + the mailbox. The mailbox is present only in omap4 and the register to + power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an + additional register to power on USB3 PHY. + config OMAP_USB2 tristate "OMAP USB2 PHY Driver" depends on ARCH_OMAP2PLUS @@ -25,14 +92,45 @@ config OMAP_USB3 This driver interacts with the "OMAP Control USB Driver" to power on/off the PHY. -config OMAP_CONTROL_USB - tristate "OMAP CONTROL USB Driver" +config SAMSUNG_USBPHY + bool "Samsung USB PHY controller Driver" + depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS + select USB_OTG_UTILS help - Enable this to add support for the USB part present in the control - module. This driver has API to power on the USB2 PHY and to write to - the mailbox. The mailbox is present only in omap4 and the register to - power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an - additional register to power on USB3 PHY. + Enable this to support Samsung USB phy controller for samsung + SoCs. + +config TWL4030_USB + tristate "TWL4030 USB Transceiver Driver" + depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS + select USB_OTG_UTILS + help + Enable this to support the USB OTG transceiver on TWL4030 + family chips (including the TWL5030 and TPS659x0 devices). + This transceiver supports high and full speed devices plus, + in host mode, low speed. + +config TWL6030_USB + tristate "TWL6030 USB Transceiver Driver" + depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS + select USB_OTG_UTILS + help + Enable this to support the USB OTG transceiver on TWL6030 + family chips. This TWL6030 transceiver has the VBUS and ID GND + and OTG SRP events capabilities. For all other transceiver functionality + UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs + are hooked to this driver through platform_data structure. + The definition of internal PHY APIs are in the mach-omap2 layer. + +config USB_GPIO_VBUS + tristate "GPIO based peripheral-only VBUS sensing 'transceiver'" + depends on GENERIC_GPIO + select USB_OTG_UTILS + help + Provides simple GPIO VBUS sensing for controllers with an + internal transceiver via the usb_phy interface, and + optionally control of a D+ pullup GPIO as well as a VBUS + current limit regulator. config USB_ISP1301 tristate "NXP ISP1301 USB transceiver support" @@ -46,13 +144,40 @@ config USB_ISP1301 To compile this driver as a module, choose M here: the module will be called isp1301. -config MV_U3D_PHY - bool "Marvell USB 3.0 PHY controller Driver" - depends on USB_MV_U3D +config USB_MSM_OTG + tristate "OTG support for Qualcomm on-chip USB controller" + depends on (USB || USB_GADGET) && ARCH_MSM select USB_OTG_UTILS help - Enable this to support Marvell USB 3.0 phy controller for Marvell - SoC. + Enable this to support the USB OTG transceiver on MSM chips. It + handles PHY initialization, clock management, and workarounds + required after resetting the hardware and power management. + This driver is required even for peripheral only or host only + mode configurations. + This driver is not supported on boards like trout which + has an external PHY. + +config USB_MV_OTG + tristate "Marvell USB OTG support" + depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND + select USB_OTG + select USB_OTG_UTILS + help + Say Y here if you want to build Marvell USB OTG transciever + driver in kernel (including PXA and MMP series). This driver + implements role switch between EHCI host driver and gadget driver. + + To compile this driver as a module, choose M here. + +config USB_MXS_PHY + tristate "Freescale MXS USB PHY support" + depends on ARCH_MXC || ARCH_MXS + select STMP_DEVICE + select USB_OTG_UTILS + help + Enable this to support the Freescale MXS USB PHY. + + MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. config USB_RCAR_PHY tristate "Renesas R-Car USB phy support" @@ -66,10 +191,19 @@ config USB_RCAR_PHY To compile this driver as a module, choose M here: the module will be called rcar-phy. -config SAMSUNG_USBPHY - bool "Samsung USB PHY controller Driver" - depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS +config USB_ULPI + bool "Generic ULPI Transceiver Driver" + depends on ARM select USB_OTG_UTILS help - Enable this to support Samsung USB phy controller for samsung - SoCs. + Enable this to support ULPI connected USB OTG transceivers which + are likely found on embedded boards. + +config USB_ULPI_VIEWPORT + bool + depends on USB_ULPI + help + Provides read/write operations to the ULPI phy register set for + controllers with a viewport register (e.g. Chipidea/ARC controllers). + +endif # USB || OTG diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 9fa6327d4c52..34488ceef491 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -5,11 +5,27 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG obj-$(CONFIG_USB_OTG_UTILS) += phy.o + +# transceiver drivers, keep the list sorted + +obj-$(CONFIG_AB8500_USB) += ab8500-usb.o +fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o +obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o +obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o +obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o +obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o +obj-$(CONFIG_OMAP_CONTROL_USB) += omap-control-usb.o obj-$(CONFIG_OMAP_USB2) += omap-usb2.o obj-$(CONFIG_OMAP_USB3) += omap-usb3.o -obj-$(CONFIG_OMAP_CONTROL_USB) += omap-control-usb.o -obj-$(CONFIG_USB_ISP1301) += isp1301.o -obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o -obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o -obj-$(CONFIG_USB_RCAR_PHY) += rcar-phy.o obj-$(CONFIG_SAMSUNG_USBPHY) += samsung-usbphy.o +obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o +obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o +obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o +obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o +obj-$(CONFIG_USB_ISP1301) += isp1301.o +obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o +obj-$(CONFIG_USB_MV_OTG) += mv_otg.o +obj-$(CONFIG_USB_MXS_PHY) += mxs-phy.o +obj-$(CONFIG_USB_RCAR_PHY) += rcar-phy.o +obj-$(CONFIG_USB_ULPI) += ulpi.o +obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/phy/ab8500-usb.c similarity index 100% rename from drivers/usb/otg/ab8500-usb.c rename to drivers/usb/phy/ab8500-usb.c diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/phy/fsl_otg.c similarity index 100% rename from drivers/usb/otg/fsl_otg.c rename to drivers/usb/phy/fsl_otg.c diff --git a/drivers/usb/otg/fsl_otg.h b/drivers/usb/phy/fsl_otg.h similarity index 100% rename from drivers/usb/otg/fsl_otg.h rename to drivers/usb/phy/fsl_otg.h diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/phy/gpio_vbus.c similarity index 100% rename from drivers/usb/otg/gpio_vbus.c rename to drivers/usb/phy/gpio_vbus.c diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/phy/isp1301_omap.c similarity index 100% rename from drivers/usb/otg/isp1301_omap.c rename to drivers/usb/phy/isp1301_omap.c diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/phy/msm_otg.c similarity index 100% rename from drivers/usb/otg/msm_otg.c rename to drivers/usb/phy/msm_otg.c diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/phy/mv_otg.c similarity index 100% rename from drivers/usb/otg/mv_otg.c rename to drivers/usb/phy/mv_otg.c diff --git a/drivers/usb/otg/mv_otg.h b/drivers/usb/phy/mv_otg.h similarity index 100% rename from drivers/usb/otg/mv_otg.h rename to drivers/usb/phy/mv_otg.h diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/phy/mxs-phy.c similarity index 100% rename from drivers/usb/otg/mxs-phy.c rename to drivers/usb/phy/mxs-phy.c diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/phy/nop-usb-xceiv.c similarity index 100% rename from drivers/usb/otg/nop-usb-xceiv.c rename to drivers/usb/phy/nop-usb-xceiv.c diff --git a/drivers/usb/otg/otg_fsm.c b/drivers/usb/phy/otg_fsm.c similarity index 100% rename from drivers/usb/otg/otg_fsm.c rename to drivers/usb/phy/otg_fsm.c diff --git a/drivers/usb/otg/otg_fsm.h b/drivers/usb/phy/otg_fsm.h similarity index 100% rename from drivers/usb/otg/otg_fsm.h rename to drivers/usb/phy/otg_fsm.h diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/phy/twl4030-usb.c similarity index 100% rename from drivers/usb/otg/twl4030-usb.c rename to drivers/usb/phy/twl4030-usb.c diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/phy/twl6030-usb.c similarity index 100% rename from drivers/usb/otg/twl6030-usb.c rename to drivers/usb/phy/twl6030-usb.c diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/phy/ulpi.c similarity index 100% rename from drivers/usb/otg/ulpi.c rename to drivers/usb/phy/ulpi.c diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/phy/ulpi_viewport.c similarity index 100% rename from drivers/usb/otg/ulpi_viewport.c rename to drivers/usb/phy/ulpi_viewport.c From edc7cb2e955f222fe51cd44c1cf9c94d58017344 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 11:13:43 +0200 Subject: [PATCH 174/303] usb: phy: make it a menuconfig We already have a considerable amount of USB PHY drivers, making it a menuconfig just prevents us from adding too much churn to USB's menuconfig. While at that, also select USB_OTG_UTILS from this new menuconfig just to keep backwards compatibility until we manage to remove that symbol. Signed-off-by: Felipe Balbi --- drivers/Makefile | 2 +- drivers/usb/phy/Kconfig | 17 ++++++++++++----- drivers/usb/phy/Makefile | 2 +- include/linux/usb/phy.h | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/Makefile b/drivers/Makefile index dce39a95fa71..3c200a243af0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -79,7 +79,7 @@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ obj-$(CONFIG_PARIDE) += block/paride/ obj-$(CONFIG_TC) += tc/ obj-$(CONFIG_UWB) += uwb/ -obj-$(CONFIG_USB_OTG_UTILS) += usb/ +obj-$(CONFIG_USB_PHY) += usb/ obj-$(CONFIG_USB) += usb/ obj-$(CONFIG_PCI) += usb/ obj-$(CONFIG_USB_GADGET) += usb/ diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 32ce740a9dd5..832cd694fb8b 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -1,8 +1,17 @@ # # Physical Layer USB driver configuration # -comment "USB Physical Layer drivers" - depends on USB || USB_GADGET +menuconfig USB_PHY + tristate "USB Physical Layer drivers" + select USB_OTG_UTILS + help + USB controllers (those which are host, device or DRD) need a + device to handle the physical layer signalling, commonly called + a PHY. + + The following drivers add support for such PHY devices. + +if USB_PHY config USB_OTG_UTILS bool @@ -10,8 +19,6 @@ config USB_OTG_UTILS Select this to make sure the build includes objects from the OTG infrastructure directory. -if USB || USB_GADGET - # # USB Transceiver Drivers # @@ -206,4 +213,4 @@ config USB_ULPI_VIEWPORT Provides read/write operations to the ULPI phy register set for controllers with a viewport register (e.g. Chipidea/ARC controllers). -endif # USB || OTG +endif # USB_PHY diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 34488ceef491..d10a8b387ffe 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -4,7 +4,7 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG -obj-$(CONFIG_USB_OTG_UTILS) += phy.o +obj-$(CONFIG_USB_PHY) += phy.o # transceiver drivers, keep the list sorted diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index 15847cbdb512..b001dc3d6354 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -161,7 +161,7 @@ usb_phy_shutdown(struct usb_phy *x) } /* for usb host and peripheral controller drivers */ -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) extern struct usb_phy *usb_get_phy(enum usb_phy_type type); extern struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type); From 820d08835d2688963607dbd08e50d89a20cb0442 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 11:23:50 +0200 Subject: [PATCH 175/303] usb: power: pda_power: check against CONFIG_USB_PHY CONFIG_USB_OTG_UTILS will be removed very soon, so we should check CONFIG_USB_PHY instead. Signed-off-by: Felipe Balbi --- drivers/power/pda_power.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index 7df7c5facc10..0c52e2a0d90c 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c @@ -35,7 +35,7 @@ static struct timer_list supply_timer; static struct timer_list polling_timer; static int polling; -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) static struct usb_phy *transceiver; static struct notifier_block otg_nb; #endif @@ -218,7 +218,7 @@ static void polling_timer_func(unsigned long unused) jiffies + msecs_to_jiffies(pdata->polling_interval)); } -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) static int otg_is_usb_online(void) { return (transceiver->last_event == USB_EVENT_VBUS || @@ -315,7 +315,7 @@ static int pda_power_probe(struct platform_device *pdev) pda_psy_usb.num_supplicants = pdata->num_supplicants; } -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) transceiver = usb_get_phy(USB_PHY_TYPE_USB2); if (!IS_ERR_OR_NULL(transceiver)) { if (!pdata->is_usb_online) @@ -367,7 +367,7 @@ static int pda_power_probe(struct platform_device *pdev) } } -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) { otg_nb.notifier_call = otg_handle_notification; ret = usb_register_notifier(transceiver, &otg_nb); @@ -391,7 +391,7 @@ static int pda_power_probe(struct platform_device *pdev) return 0; -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) otg_reg_notifier_failed: if (pdata->is_usb_online && usb_irq) free_irq(usb_irq->start, &pda_psy_usb); @@ -402,7 +402,7 @@ usb_irq_failed: usb_supply_failed: if (pdata->is_ac_online && ac_irq) free_irq(ac_irq->start, &pda_psy_ac); -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) if (!IS_ERR_OR_NULL(transceiver)) usb_put_phy(transceiver); #endif @@ -437,7 +437,7 @@ static int pda_power_remove(struct platform_device *pdev) power_supply_unregister(&pda_psy_usb); if (pdata->is_ac_online) power_supply_unregister(&pda_psy_ac); -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) if (!IS_ERR_OR_NULL(transceiver)) usb_put_phy(transceiver); #endif From 1d3dbfc3a74f70750c8385dff36d4d46b6bd3a1a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 11:24:08 +0200 Subject: [PATCH 176/303] usb: gadget: mv_udc_core: check against CONFIG_USB_PHY CONFIG_USB_OTG_UTILS will be removed very soon, so we should check CONFIG_USB_PHY instead. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index d278e8f512c0..d550b2129133 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2127,7 +2127,7 @@ static int mv_udc_probe(struct platform_device *pdev) udc->dev = pdev; -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) if (pdata->mode == MV_USB_MODE_OTG) { udc->transceiver = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); From fcd12b9711816e7cb0a3eb1b47790979e4c14c58 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 11:24:32 +0200 Subject: [PATCH 177/303] usb: ehci: marvel: check against CONFIG_USB_PHY CONFIG_USB_OTG_UTILS will be removed very soon, so we should check CONFIG_USB_PHY instead. Acked-by: Alan Stern Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-mv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 3065809546b1..9751823395e1 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -240,7 +240,7 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->mode = pdata->mode; if (ehci_mv->mode == MV_USB_MODE_OTG) { -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(ehci_mv->otg)) { dev_err(&pdev->dev, @@ -260,7 +260,7 @@ static int mv_ehci_probe(struct platform_device *pdev) mv_ehci_disable(ehci_mv); #else dev_info(&pdev->dev, "MV_USB_MODE_OTG " - "must have CONFIG_USB_OTG_UTILS enabled\n"); + "must have CONFIG_USB_PHY enabled\n"); goto err_disable_clk; #endif } else { From a948712d2a064be5f928f37d137e9d14b48cc94f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 11:24:58 +0200 Subject: [PATCH 178/303] usb: ehci: tegra: check against CONFIG_USB_PHY CONFIG_USB_OTG_UTILS will be removed very soon, so we should check CONFIG_USB_PHY instead. Acked-by: Alan Stern Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-tegra.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 568aecc7075b..fafbc819ab18 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -768,7 +768,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) goto fail; } -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) if (pdata->operating_mode == TEGRA_USB_OTG) { tegra->transceiver = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); @@ -794,7 +794,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) return err; fail: -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); #endif @@ -815,7 +815,7 @@ static int tegra_ehci_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); -#ifdef CONFIG_USB_OTG_UTILS +#if IS_ENABLED(CONFIG_USB_PHY) if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); #endif From fd891498751f53dda3733d9e9ff8a1f6ea16c5e5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 11:31:18 +0200 Subject: [PATCH 179/303] usb: phy: remove CONFIG_USB_OTG_UTILS there are no more users of CONFIG_USB_OTG_UTILS left in tree, we can remove it just fine. [ kishon@ti.com : fixed a linking error due to original patch forgetting to change drivers/usb/Makefile ] Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/power/Kconfig | 2 +- drivers/usb/Makefile | 2 +- drivers/usb/dwc3/Kconfig | 1 - drivers/usb/gadget/Kconfig | 3 --- drivers/usb/host/Kconfig | 1 - drivers/usb/musb/Kconfig | 1 - drivers/usb/phy/Kconfig | 23 ----------------------- 7 files changed, 2 insertions(+), 31 deletions(-) diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 9e00c389e777..ffe02fb7cbc7 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -254,7 +254,7 @@ config BATTERY_RX51 config CHARGER_ISP1704 tristate "ISP1704 USB Charger Detection" - depends on USB_OTG_UTILS + depends on USB_PHY help Say Y to enable support for USB Charger Detection with ISP1707/ISP1704 USB transceivers. diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 860306b14392..c41feba8d5c0 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -44,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB) += misc/ -obj-$(CONFIG_USB_OTG_UTILS) += phy/ +obj-$(CONFIG_USB_PHY) += phy/ obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ obj-$(CONFIG_USB_ATM) += atm/ diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 68e9a2c5a01a..ea5ee9c21c35 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -1,7 +1,6 @@ config USB_DWC3 tristate "DesignWare USB3 DRD Core Support" depends on (USB || USB_GADGET) && GENERIC_HARDIRQS - select USB_OTG_UTILS select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD help Say Y or M here if your system has a Dual Role SuperSpeed diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 50586fffa9fb..7ad108a3555d 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -195,7 +195,6 @@ config USB_OMAP tristate "OMAP USB Device Controller" depends on ARCH_OMAP1 select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG - select USB_OTG_UTILS if ARCH_OMAP help Many Texas Instruments OMAP processors have flexible full speed USB device controllers, with support for up to 30 @@ -210,7 +209,6 @@ config USB_OMAP config USB_PXA25X tristate "PXA 25x or IXP 4xx" depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX - select USB_OTG_UTILS help Intel's PXA 25x series XScale ARM-5TE processors include an integrated full speed USB 1.1 device controller. The @@ -258,7 +256,6 @@ config USB_RENESAS_USBHS_UDC config USB_PXA27X tristate "PXA 27x" - select USB_OTG_UTILS help Intel's PXA 27x series XScale ARM v5TE processors include an integrated full speed USB 1.1 device controller. diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c59a1126926f..ba1347ccb9dd 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -300,7 +300,6 @@ config USB_OHCI_HCD tristate "OHCI HCD support" depends on USB && USB_ARCH_HAS_OHCI select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 - select USB_OTG_UTILS if ARCH_OMAP depends on USB_ISP1301 || !ARCH_LPC32XX ---help--- The Open Host Controller Interface (OHCI) is a standard for accessing diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index d38cf9859abb..47442d35b6fc 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -7,7 +7,6 @@ config USB_MUSB_HDRC tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' depends on USB && USB_GADGET - select USB_OTG_UTILS help Say Y here if your system has a dual role high speed USB controller based on the Mentor Graphics silicon IP. Then diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 832cd694fb8b..97de6de9b4b9 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -3,7 +3,6 @@ # menuconfig USB_PHY tristate "USB Physical Layer drivers" - select USB_OTG_UTILS help USB controllers (those which are host, device or DRD) need a device to handle the physical layer signalling, commonly called @@ -13,19 +12,12 @@ menuconfig USB_PHY if USB_PHY -config USB_OTG_UTILS - bool - help - Select this to make sure the build includes objects from - the OTG infrastructure directory. - # # USB Transceiver Drivers # config AB8500_USB tristate "AB8500 USB Transceiver Driver" depends on AB8500_CORE - select USB_OTG_UTILS help Enable this to support the USB OTG transceiver in AB8500 chip. This transceiver supports high and full speed devices plus, @@ -35,14 +27,12 @@ config FSL_USB2_OTG bool "Freescale USB OTG Transceiver Driver" depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND select USB_OTG - select USB_OTG_UTILS help Enable this to support Freescale USB OTG transceiver. config ISP1301_OMAP tristate "Philips ISP1301 with OMAP OTG" depends on I2C && ARCH_OMAP_OTG - select USB_OTG_UTILS help If you say yes here you get support for the Philips ISP1301 USB-On-The-Go transceiver working with the OMAP OTG controller. @@ -56,14 +46,12 @@ config ISP1301_OMAP config MV_U3D_PHY bool "Marvell USB 3.0 PHY controller Driver" depends on USB_MV_U3D - select USB_OTG_UTILS help Enable this to support Marvell USB 3.0 phy controller for Marvell SoC. config NOP_USB_XCEIV tristate "NOP USB Transceiver Driver" - select USB_OTG_UTILS help This driver is to be used by all the usb transceiver which are either built-in with usb ip or which are autonomous and doesn't require any @@ -81,7 +69,6 @@ config OMAP_CONTROL_USB config OMAP_USB2 tristate "OMAP USB2 PHY Driver" depends on ARCH_OMAP2PLUS - select USB_OTG_UTILS select OMAP_CONTROL_USB help Enable this to support the transceiver that is part of SOC. This @@ -91,7 +78,6 @@ config OMAP_USB2 config OMAP_USB3 tristate "OMAP USB3 PHY Driver" - select USB_OTG_UTILS select OMAP_CONTROL_USB help Enable this to support the USB3 PHY that is part of SOC. This @@ -102,7 +88,6 @@ config OMAP_USB3 config SAMSUNG_USBPHY bool "Samsung USB PHY controller Driver" depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS - select USB_OTG_UTILS help Enable this to support Samsung USB phy controller for samsung SoCs. @@ -110,7 +95,6 @@ config SAMSUNG_USBPHY config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS - select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL4030 family chips (including the TWL5030 and TPS659x0 devices). @@ -120,7 +104,6 @@ config TWL4030_USB config TWL6030_USB tristate "TWL6030 USB Transceiver Driver" depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS - select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL6030 family chips. This TWL6030 transceiver has the VBUS and ID GND @@ -132,7 +115,6 @@ config TWL6030_USB config USB_GPIO_VBUS tristate "GPIO based peripheral-only VBUS sensing 'transceiver'" depends on GENERIC_GPIO - select USB_OTG_UTILS help Provides simple GPIO VBUS sensing for controllers with an internal transceiver via the usb_phy interface, and @@ -154,7 +136,6 @@ config USB_ISP1301 config USB_MSM_OTG tristate "OTG support for Qualcomm on-chip USB controller" depends on (USB || USB_GADGET) && ARCH_MSM - select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on MSM chips. It handles PHY initialization, clock management, and workarounds @@ -168,7 +149,6 @@ config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND select USB_OTG - select USB_OTG_UTILS help Say Y here if you want to build Marvell USB OTG transciever driver in kernel (including PXA and MMP series). This driver @@ -180,7 +160,6 @@ config USB_MXS_PHY tristate "Freescale MXS USB PHY support" depends on ARCH_MXC || ARCH_MXS select STMP_DEVICE - select USB_OTG_UTILS help Enable this to support the Freescale MXS USB PHY. @@ -189,7 +168,6 @@ config USB_MXS_PHY config USB_RCAR_PHY tristate "Renesas R-Car USB phy support" depends on USB || USB_GADGET - select USB_OTG_UTILS help Say Y here to add support for the Renesas R-Car USB phy driver. This chip is typically used as USB phy for USB host, gadget. @@ -201,7 +179,6 @@ config USB_RCAR_PHY config USB_ULPI bool "Generic ULPI Transceiver Driver" depends on ARM - select USB_OTG_UTILS help Enable this to support ULPI connected USB OTG transceivers which are likely found on embedded boards. From 94ae98433a397dd4695652fc62ca7bc784b08216 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 7 Mar 2013 17:37:59 +0200 Subject: [PATCH 180/303] usb: phy: rename all phy drivers to phy-$name-usb.c this will make sure that we have sensible names for all phy drivers. Current situation was already quite bad with too generic names being used. Signed-off-by: Felipe Balbi --- drivers/usb/phy/Makefile | 42 +++++++++---------- .../phy/{ab8500-usb.c => phy-ab8500-usb.c} | 0 drivers/usb/phy/{fsl_otg.c => phy-fsl-usb.c} | 2 +- drivers/usb/phy/{fsl_otg.h => phy-fsl-usb.h} | 0 drivers/usb/phy/{otg_fsm.c => phy-fsm-usb.c} | 2 +- drivers/usb/phy/{otg_fsm.h => phy-fsm-usb.h} | 0 .../phy/{gpio_vbus.c => phy-gpio-vbus-usb.c} | 0 .../{isp1301_omap.c => phy-isp1301-omap.c} | 0 drivers/usb/phy/{isp1301.c => phy-isp1301.c} | 0 drivers/usb/phy/{msm_otg.c => phy-msm-usb.c} | 0 .../phy/{mv_u3d_phy.c => phy-mv-u3d-usb.c} | 2 +- .../phy/{mv_u3d_phy.h => phy-mv-u3d-usb.h} | 0 drivers/usb/phy/{mv_otg.c => phy-mv-usb.c} | 2 +- drivers/usb/phy/{mv_otg.h => phy-mv-usb.h} | 0 drivers/usb/phy/{mxs-phy.c => phy-mxs-usb.c} | 0 .../usb/phy/{nop-usb-xceiv.c => phy-nop.c} | 0 ...{omap-control-usb.c => phy-omap-control.c} | 0 .../usb/phy/{omap-usb2.c => phy-omap-usb2.c} | 0 .../usb/phy/{omap-usb3.c => phy-omap-usb3.c} | 0 .../usb/phy/{rcar-phy.c => phy-rcar-usb.c} | 0 .../{samsung-usbphy.c => phy-samsung-usb.c} | 0 .../phy/{tegra_usb_phy.c => phy-tegra-usb.c} | 0 .../phy/{twl4030-usb.c => phy-twl4030-usb.c} | 0 .../phy/{twl6030-usb.c => phy-twl6030-usb.c} | 0 .../{ulpi_viewport.c => phy-ulpi-viewport.c} | 0 drivers/usb/phy/{ulpi.c => phy-ulpi.c} | 0 26 files changed, 25 insertions(+), 25 deletions(-) rename drivers/usb/phy/{ab8500-usb.c => phy-ab8500-usb.c} (100%) rename drivers/usb/phy/{fsl_otg.c => phy-fsl-usb.c} (99%) rename drivers/usb/phy/{fsl_otg.h => phy-fsl-usb.h} (100%) rename drivers/usb/phy/{otg_fsm.c => phy-fsm-usb.c} (99%) rename drivers/usb/phy/{otg_fsm.h => phy-fsm-usb.h} (100%) rename drivers/usb/phy/{gpio_vbus.c => phy-gpio-vbus-usb.c} (100%) rename drivers/usb/phy/{isp1301_omap.c => phy-isp1301-omap.c} (100%) rename drivers/usb/phy/{isp1301.c => phy-isp1301.c} (100%) rename drivers/usb/phy/{msm_otg.c => phy-msm-usb.c} (100%) rename drivers/usb/phy/{mv_u3d_phy.c => phy-mv-u3d-usb.c} (99%) rename drivers/usb/phy/{mv_u3d_phy.h => phy-mv-u3d-usb.h} (100%) rename drivers/usb/phy/{mv_otg.c => phy-mv-usb.c} (99%) rename drivers/usb/phy/{mv_otg.h => phy-mv-usb.h} (100%) rename drivers/usb/phy/{mxs-phy.c => phy-mxs-usb.c} (100%) rename drivers/usb/phy/{nop-usb-xceiv.c => phy-nop.c} (100%) rename drivers/usb/phy/{omap-control-usb.c => phy-omap-control.c} (100%) rename drivers/usb/phy/{omap-usb2.c => phy-omap-usb2.c} (100%) rename drivers/usb/phy/{omap-usb3.c => phy-omap-usb3.c} (100%) rename drivers/usb/phy/{rcar-phy.c => phy-rcar-usb.c} (100%) rename drivers/usb/phy/{samsung-usbphy.c => phy-samsung-usb.c} (100%) rename drivers/usb/phy/{tegra_usb_phy.c => phy-tegra-usb.c} (100%) rename drivers/usb/phy/{twl4030-usb.c => phy-twl4030-usb.c} (100%) rename drivers/usb/phy/{twl6030-usb.c => phy-twl6030-usb.c} (100%) rename drivers/usb/phy/{ulpi_viewport.c => phy-ulpi-viewport.c} (100%) rename drivers/usb/phy/{ulpi.c => phy-ulpi.c} (100%) diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index d10a8b387ffe..5fb4a5d55945 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -8,24 +8,24 @@ obj-$(CONFIG_USB_PHY) += phy.o # transceiver drivers, keep the list sorted -obj-$(CONFIG_AB8500_USB) += ab8500-usb.o -fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o -obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o -obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o -obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o -obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o -obj-$(CONFIG_OMAP_CONTROL_USB) += omap-control-usb.o -obj-$(CONFIG_OMAP_USB2) += omap-usb2.o -obj-$(CONFIG_OMAP_USB3) += omap-usb3.o -obj-$(CONFIG_SAMSUNG_USBPHY) += samsung-usbphy.o -obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o -obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o -obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o -obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o -obj-$(CONFIG_USB_ISP1301) += isp1301.o -obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o -obj-$(CONFIG_USB_MV_OTG) += mv_otg.o -obj-$(CONFIG_USB_MXS_PHY) += mxs-phy.o -obj-$(CONFIG_USB_RCAR_PHY) += rcar-phy.o -obj-$(CONFIG_USB_ULPI) += ulpi.o -obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o +obj-$(CONFIG_AB8500_USB) += phy-ab8500-usb.o +phy-fsl-usb2-objs := phy-fsl-usb.o phy-fsm-usb.o +obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-usb2.o +obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301.omap.o +obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o +obj-$(CONFIG_NOP_USB_XCEIV) += phy-nop.o +obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o +obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o +obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o +obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o +obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o +obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o +obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o +obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o +obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o +obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o +obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o +obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o +obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o +obj-$(CONFIG_USB_ULPI) += phy-ulpi.o +obj-$(CONFIG_USB_ULPI_VIEWPORT) += phy-ulpi-viewport.o diff --git a/drivers/usb/phy/ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c similarity index 100% rename from drivers/usb/phy/ab8500-usb.c rename to drivers/usb/phy/phy-ab8500-usb.c diff --git a/drivers/usb/phy/fsl_otg.c b/drivers/usb/phy/phy-fsl-usb.c similarity index 99% rename from drivers/usb/phy/fsl_otg.c rename to drivers/usb/phy/phy-fsl-usb.c index 72a2a00c2487..97b9308507c3 100644 --- a/drivers/usb/phy/fsl_otg.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -43,7 +43,7 @@ #include -#include "fsl_otg.h" +#include "phy-fsl-usb.h" #define DRIVER_VERSION "Rev. 1.55" #define DRIVER_AUTHOR "Jerry Huang/Li Yang" diff --git a/drivers/usb/phy/fsl_otg.h b/drivers/usb/phy/phy-fsl-usb.h similarity index 100% rename from drivers/usb/phy/fsl_otg.h rename to drivers/usb/phy/phy-fsl-usb.h diff --git a/drivers/usb/phy/otg_fsm.c b/drivers/usb/phy/phy-fsm-usb.c similarity index 99% rename from drivers/usb/phy/otg_fsm.c rename to drivers/usb/phy/phy-fsm-usb.c index 1f729a15decb..c520b3548e7c 100644 --- a/drivers/usb/phy/otg_fsm.c +++ b/drivers/usb/phy/phy-fsm-usb.c @@ -29,7 +29,7 @@ #include #include -#include "otg_fsm.h" +#include "phy-otg-fsm.h" /* Change USB protocol when there is a protocol change */ static int otg_set_protocol(struct otg_fsm *fsm, int protocol) diff --git a/drivers/usb/phy/otg_fsm.h b/drivers/usb/phy/phy-fsm-usb.h similarity index 100% rename from drivers/usb/phy/otg_fsm.h rename to drivers/usb/phy/phy-fsm-usb.h diff --git a/drivers/usb/phy/gpio_vbus.c b/drivers/usb/phy/phy-gpio-vbus-usb.c similarity index 100% rename from drivers/usb/phy/gpio_vbus.c rename to drivers/usb/phy/phy-gpio-vbus-usb.c diff --git a/drivers/usb/phy/isp1301_omap.c b/drivers/usb/phy/phy-isp1301-omap.c similarity index 100% rename from drivers/usb/phy/isp1301_omap.c rename to drivers/usb/phy/phy-isp1301-omap.c diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/phy-isp1301.c similarity index 100% rename from drivers/usb/phy/isp1301.c rename to drivers/usb/phy/phy-isp1301.c diff --git a/drivers/usb/phy/msm_otg.c b/drivers/usb/phy/phy-msm-usb.c similarity index 100% rename from drivers/usb/phy/msm_otg.c rename to drivers/usb/phy/phy-msm-usb.c diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/phy-mv-u3d-usb.c similarity index 99% rename from drivers/usb/phy/mv_u3d_phy.c rename to drivers/usb/phy/phy-mv-u3d-usb.c index 9d8599122aa9..cb7e70f17709 100644 --- a/drivers/usb/phy/mv_u3d_phy.c +++ b/drivers/usb/phy/phy-mv-u3d-usb.c @@ -15,7 +15,7 @@ #include #include -#include "mv_u3d_phy.h" +#include "phy-mv-u3d-usb.h" /* * struct mv_u3d_phy - transceiver driver state diff --git a/drivers/usb/phy/mv_u3d_phy.h b/drivers/usb/phy/phy-mv-u3d-usb.h similarity index 100% rename from drivers/usb/phy/mv_u3d_phy.h rename to drivers/usb/phy/phy-mv-u3d-usb.h diff --git a/drivers/usb/phy/mv_otg.c b/drivers/usb/phy/phy-mv-usb.c similarity index 99% rename from drivers/usb/phy/mv_otg.c rename to drivers/usb/phy/phy-mv-usb.c index b6a9be31133b..6872bf0a3681 100644 --- a/drivers/usb/phy/mv_otg.c +++ b/drivers/usb/phy/phy-mv-usb.c @@ -27,7 +27,7 @@ #include #include -#include "mv_otg.h" +#include "phy-mv-usb.h" #define DRIVER_DESC "Marvell USB OTG transceiver driver" #define DRIVER_VERSION "Jan 20, 2010" diff --git a/drivers/usb/phy/mv_otg.h b/drivers/usb/phy/phy-mv-usb.h similarity index 100% rename from drivers/usb/phy/mv_otg.h rename to drivers/usb/phy/phy-mv-usb.h diff --git a/drivers/usb/phy/mxs-phy.c b/drivers/usb/phy/phy-mxs-usb.c similarity index 100% rename from drivers/usb/phy/mxs-phy.c rename to drivers/usb/phy/phy-mxs-usb.c diff --git a/drivers/usb/phy/nop-usb-xceiv.c b/drivers/usb/phy/phy-nop.c similarity index 100% rename from drivers/usb/phy/nop-usb-xceiv.c rename to drivers/usb/phy/phy-nop.c diff --git a/drivers/usb/phy/omap-control-usb.c b/drivers/usb/phy/phy-omap-control.c similarity index 100% rename from drivers/usb/phy/omap-control-usb.c rename to drivers/usb/phy/phy-omap-control.c diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/phy-omap-usb2.c similarity index 100% rename from drivers/usb/phy/omap-usb2.c rename to drivers/usb/phy/phy-omap-usb2.c diff --git a/drivers/usb/phy/omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c similarity index 100% rename from drivers/usb/phy/omap-usb3.c rename to drivers/usb/phy/phy-omap-usb3.c diff --git a/drivers/usb/phy/rcar-phy.c b/drivers/usb/phy/phy-rcar-usb.c similarity index 100% rename from drivers/usb/phy/rcar-phy.c rename to drivers/usb/phy/phy-rcar-usb.c diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/phy-samsung-usb.c similarity index 100% rename from drivers/usb/phy/samsung-usbphy.c rename to drivers/usb/phy/phy-samsung-usb.c diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/phy-tegra-usb.c similarity index 100% rename from drivers/usb/phy/tegra_usb_phy.c rename to drivers/usb/phy/phy-tegra-usb.c diff --git a/drivers/usb/phy/twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c similarity index 100% rename from drivers/usb/phy/twl4030-usb.c rename to drivers/usb/phy/phy-twl4030-usb.c diff --git a/drivers/usb/phy/twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c similarity index 100% rename from drivers/usb/phy/twl6030-usb.c rename to drivers/usb/phy/phy-twl6030-usb.c diff --git a/drivers/usb/phy/ulpi_viewport.c b/drivers/usb/phy/phy-ulpi-viewport.c similarity index 100% rename from drivers/usb/phy/ulpi_viewport.c rename to drivers/usb/phy/phy-ulpi-viewport.c diff --git a/drivers/usb/phy/ulpi.c b/drivers/usb/phy/phy-ulpi.c similarity index 100% rename from drivers/usb/phy/ulpi.c rename to drivers/usb/phy/phy-ulpi.c From 790d3a5ab6e36fb06e99339afe35ecdec4d3b2cb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 8 Mar 2013 13:01:40 +0200 Subject: [PATCH 181/303] usb: phy: isp1301: give it a context structure this patch is a small preparation to fix isp1301 driver so that other platforms can use it. We're defining our private data structure to represent this device and adding the PHY to the PHY list. Later patches will come implementing proper PHY API and removing bogus code from ohci_nxp and lpc32xx_udc drivers. Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-isp1301.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c index 18dbf7e37607..5e0f14369145 100644 --- a/drivers/usb/phy/phy-isp1301.c +++ b/drivers/usb/phy/phy-isp1301.c @@ -11,10 +11,19 @@ */ #include +#include #include +#include #define DRV_NAME "isp1301" +struct isp1301 { + struct usb_phy phy; + struct mutex mutex; + + struct i2c_client *client; +}; + static const struct i2c_device_id isp1301_id[] = { { "isp1301", 0 }, { } @@ -25,12 +34,35 @@ static struct i2c_client *isp1301_i2c_client; static int isp1301_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { + struct isp1301 *isp; + struct usb_phy *phy; + + isp = devm_kzalloc(&client->dev, sizeof(*isp), GFP_KERNEL); + if (!isp) + return -ENOMEM; + + isp->client = client; + mutex_init(&isp->mutex); + + phy = &isp->phy; + phy->label = DRV_NAME; + phy->type = USB_PHY_TYPE_USB2; + + i2c_set_clientdata(client, isp); + usb_add_phy_dev(phy); + isp1301_i2c_client = client; + return 0; } static int isp1301_remove(struct i2c_client *client) { + struct isp1301 *isp = i2c_get_clientdata(client); + + usb_remove_phy(&isp->phy); + isp1301_i2c_client = NULL; + return 0; } From b774212ea5f13911a5e0211a7088e42dad46b4c8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 8 Mar 2013 13:22:58 +0200 Subject: [PATCH 182/303] usb: phy: introduce ->set_vbus() method this method will be used to enable or disable the charge pump. Whenever we have DRD devices, we need to be able to turn VBUS on or off whenever we want. Note that in the ideal case, this would be controlled by the ID-pin Interrupt, but not all devices have ID-pin properly routed since manufacturers can choose to save that trace if they're building a host-only product out of a DRD IP. This is also useful during debugging where we might not have the proper cable hanging around. Signed-off-by: Felipe Balbi --- include/linux/usb/phy.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index b001dc3d6354..b7c2217c585f 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -91,6 +91,9 @@ struct usb_phy { int (*init)(struct usb_phy *x); void (*shutdown)(struct usb_phy *x); + /* enable/disable VBUS */ + int (*set_vbus)(struct usb_phy *x, int on); + /* effective for B devices, ignored for A-peripheral */ int (*set_power)(struct usb_phy *x, unsigned mA); @@ -160,6 +163,24 @@ usb_phy_shutdown(struct usb_phy *x) x->shutdown(x); } +static inline int +usb_phy_vbus_on(struct usb_phy *x) +{ + if (!x->set_vbus) + return 0; + + return x->set_vbus(x, true); +} + +static inline int +usb_phy_vbus_off(struct usb_phy *x) +{ + if (!x->set_vbus) + return 0; + + return x->set_vbus(x, false); +} + /* for usb host and peripheral controller drivers */ #if IS_ENABLED(CONFIG_USB_PHY) extern struct usb_phy *usb_get_phy(enum usb_phy_type type); From c38a4f3f508d47e51c3f28e8946b1482ebf47fee Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 8 Mar 2013 13:25:18 +0200 Subject: [PATCH 183/303] usb: phy: isp1301: implement PHY API this patch implements ->init() and ->set_vbus() methods for isp1301 transceiver driver. Later patches can now come in order to remove the hackery from ohci-nxp and lpc32xx udc drivers. Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-isp1301.c | 59 +++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c index 5e0f14369145..225ae6c97eeb 100644 --- a/drivers/usb/phy/phy-isp1301.c +++ b/drivers/usb/phy/phy-isp1301.c @@ -14,6 +14,7 @@ #include #include #include +#include #define DRV_NAME "isp1301" @@ -24,6 +25,8 @@ struct isp1301 { struct i2c_client *client; }; +#define phy_to_isp(p) (container_of((p), struct isp1301, phy)) + static const struct i2c_device_id isp1301_id[] = { { "isp1301", 0 }, { } @@ -31,6 +34,60 @@ static const struct i2c_device_id isp1301_id[] = { static struct i2c_client *isp1301_i2c_client; +static int __isp1301_write(struct isp1301 *isp, u8 reg, u8 value, u8 clear) +{ + return i2c_smbus_write_byte_data(isp->client, reg | clear, value); +} + +static int isp1301_write(struct isp1301 *isp, u8 reg, u8 value) +{ + return __isp1301_write(isp, reg, value, 0); +} + +static int isp1301_clear(struct isp1301 *isp, u8 reg, u8 value) +{ + return __isp1301_write(isp, reg, value, ISP1301_I2C_REG_CLEAR_ADDR); +} + +static int isp1301_phy_init(struct usb_phy *phy) +{ + struct isp1301 *isp = phy_to_isp(phy); + + /* Disable transparent UART mode first */ + isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_UART_EN); + isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, ~MC1_SPEED_REG); + isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_SPEED_REG); + isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_2, ~0); + isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_PSW_EN + | MC2_SPD_SUSP_CTRL)); + + isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, ~0); + isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0); + isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLDOWN + | OTG1_DP_PULLDOWN)); + isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLUP + | OTG1_DP_PULLUP)); + + /* mask all interrupts */ + isp1301_clear(isp, ISP1301_I2C_INTERRUPT_LATCH, ~0); + isp1301_clear(isp, ISP1301_I2C_INTERRUPT_FALLING, ~0); + isp1301_clear(isp, ISP1301_I2C_INTERRUPT_RISING, ~0); + + return 0; +} + +static int isp1301_phy_set_vbus(struct usb_phy *phy, int on) +{ + struct isp1301 *isp = phy_to_isp(phy); + + if (on) + isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV); + else + isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV); + + return 0; +} + static int isp1301_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { @@ -46,6 +103,8 @@ static int isp1301_probe(struct i2c_client *client, phy = &isp->phy; phy->label = DRV_NAME; + phy->init = isp1301_phy_init; + phy->set_vbus = isp1301_phy_set_vbus; phy->type = USB_PHY_TYPE_USB2; i2c_set_clientdata(client, isp); From 38678f25689c6ee90b443407dba04fb8c0297db3 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Mon, 11 Mar 2013 18:28:02 +0800 Subject: [PATCH 184/303] usb: gadget: s3c-hsudc: delete outdated comment since commit d93e260 (usb: gadget: s3c-hsudc: use udc_start and udc_stop functions) the 'driver' parameter has been deleted from s3c_hsudc_stop_activity() but its documentation was left outdated. This patch deletes the comment since it makes no sense anymore. Signed-off-by: Chen Gang Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsudc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index bfe79103abab..b1f0771fbd3d 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -283,7 +283,6 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status) /** * s3c_hsudc_stop_activity - Stop activity on all endpoints. * @hsudc: Device controller for which EP activity is to be stopped. - * @driver: Reference to the gadget driver which is currently active. * * All the endpoints are stopped and any pending transfer requests if any on * the endpoint are terminated. From 662e9469cbd736e9e0cd72468f3d62e75b159464 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Mar 2013 10:45:02 +0200 Subject: [PATCH 185/303] usb: gadget: atmel: remove unused DMA_ADDR_INVALID DMA_ADDR_INVALID isn't (and shouldn't) be used anymore, let's remove it. Acked-by: Nicolas Ferre Signed-off-by: Felipe Balbi --- drivers/usb/gadget/atmel_usba_udc.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/gadget/atmel_usba_udc.h b/drivers/usb/gadget/atmel_usba_udc.h index 9791259cbda7..d65a61851d3d 100644 --- a/drivers/usb/gadget/atmel_usba_udc.h +++ b/drivers/usb/gadget/atmel_usba_udc.h @@ -216,12 +216,6 @@ #define EP0_EPT_SIZE USBA_EPT_SIZE_64 #define EP0_NR_BANKS 1 -/* - * REVISIT: Try to eliminate this value. Can we rely on req->mapped to - * provide this information? - */ -#define DMA_ADDR_INVALID (~(dma_addr_t)0) - #define FIFO_IOMEM_ID 0 #define CTRL_IOMEM_ID 1 From c36cbfc045bf6e812fa3b9e898603ff45316f369 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Mar 2013 10:45:42 +0200 Subject: [PATCH 186/303] usb: gadget: net2272: remove unused DMA_ADDR_INVALID DMA_ADDR_INVALID isn't used anymore, it's safe to remove it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2272.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 8dcbe770e2d4..03e41049ed30 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -58,7 +58,6 @@ static const char * const ep_name[] = { "ep-a", "ep-b", "ep-c", }; -#define DMA_ADDR_INVALID (~(dma_addr_t)0) #ifdef CONFIG_USB_GADGET_NET2272_DMA /* * use_dma: the NET2272 can use an external DMA controller. @@ -341,7 +340,6 @@ net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) if (!req) return NULL; - req->req.dma = DMA_ADDR_INVALID; INIT_LIST_HEAD(&req->queue); return &req->req; From 853f97b5f3886012d293257db74d65b14f958940 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Mar 2013 10:46:19 +0200 Subject: [PATCH 187/303] usb: gadget: net2280: remove unused DMA_ADDR_INVALID DMA_ADDR_INVALID isn't used anymore, it's safe to remove it. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2280.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index e5f2ef184367..691cc658ddf9 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -65,7 +65,6 @@ #define DRIVER_DESC "PLX NET228x USB Peripheral Controller" #define DRIVER_VERSION "2005 Sept 27" -#define DMA_ADDR_INVALID (~(dma_addr_t)0) #define EP_DONTUSE 13 /* nonzero */ #define USE_RDK_LEDS /* GPIO pins control three LEDs */ @@ -406,7 +405,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) if (!req) return NULL; - req->req.dma = DMA_ADDR_INVALID; INIT_LIST_HEAD (&req->queue); /* this dma descriptor may be swapped with the previous dummy */ @@ -420,7 +418,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) return NULL; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); td->dmadesc = td->dmaaddr; req->td = td; } @@ -2788,7 +2785,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) goto done; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); td->dmadesc = td->dmaaddr; dev->ep [i].dummy = td; } From 482ef1d2fec5e5d44d97f7e20b4ccf3d3604aaae Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Mar 2013 10:48:02 +0200 Subject: [PATCH 188/303] usb: gadget: uvc: remove references to DMA_ADDR_INVALID gadget drivers shouldn't touch req->dma at all, since UDC drivers are the ones required to handle mapping and unmapping of the request buffer. Remove references to DMA_ADDR_INVALID so we don't creat false expectations to gadget driver writers. Acked-by: Laurent Pinchart Signed-off-by: Felipe Balbi --- drivers/usb/gadget/uvc.h | 2 -- drivers/usb/gadget/uvc_v4l2.c | 1 - drivers/usb/gadget/uvc_video.c | 1 - 3 files changed, 4 deletions(-) diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index 93b0c1191115..7e90b1d12d09 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -98,8 +98,6 @@ extern unsigned int uvc_gadget_trace_param; #define DRIVER_VERSION "0.1.0" #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0) -#define DMA_ADDR_INVALID (~(dma_addr_t)0) - #define UVC_NUM_REQUESTS 4 #define UVC_MAX_REQUEST_SIZE 64 #define UVC_MAX_EVENTS 4 diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index 2ca9386d655b..0080d073bd5e 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -41,7 +41,6 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) req->length = min_t(unsigned int, uvc->event_length, data->length); req->zero = data->length < uvc->event_length; - req->dma = DMA_ADDR_INVALID; memcpy(req->buf, data->data, data->length); diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c index b0e53a8ea4f7..885c393ee470 100644 --- a/drivers/usb/gadget/uvc_video.c +++ b/drivers/usb/gadget/uvc_video.c @@ -245,7 +245,6 @@ uvc_video_alloc_requests(struct uvc_video *video) video->req[i]->buf = video->req_buffer[i]; video->req[i]->length = 0; - video->req[i]->dma = DMA_ADDR_INVALID; video->req[i]->complete = uvc_video_complete; video->req[i]->context = video; From 40b8156f9426db48d5d648cdc95bd0789981e9f4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Mar 2013 10:49:13 +0200 Subject: [PATCH 189/303] usb: renesas: remove unused DMA_ADDR_INVALID DMA_ADDR_INVALID isn't used anymore, it's safe to remove it. Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/fifo.c | 1 - drivers/usb/renesas_usbhs/fifo.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 9538f0feafe2..45b94019aec8 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -32,7 +32,6 @@ */ void usbhs_pkt_init(struct usbhs_pkt *pkt) { - pkt->dma = DMA_ADDR_INVALID; INIT_LIST_HEAD(&pkt->node); } diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index c31731a843d1..a168a1760fce 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -23,8 +23,6 @@ #include #include "pipe.h" -#define DMA_ADDR_INVALID (~(dma_addr_t)0) - struct usbhs_fifo { char *name; u32 port; /* xFIFO */ From d4436c3a6e4ea3000b794eb61e0fc1db46d14175 Mon Sep 17 00:00:00 2001 From: George Cherian Date: Thu, 14 Mar 2013 16:05:24 +0530 Subject: [PATCH 190/303] usb: dwc3: core: fix wrong OTG event regitser offset This patch fixes the wrong OTG_EVT,OTG_EVTEN and OTG_STS register offsets. While at that, also add a missing register to debugfs regdump utility. Signed-off-by: George Cherian Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 5 +++-- drivers/usb/dwc3/debugfs.c | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index b42f71cb87dd..b69d322e3cab 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -154,8 +154,9 @@ /* OTG Registers */ #define DWC3_OCFG 0xcc00 #define DWC3_OCTL 0xcc04 -#define DWC3_OEVTEN 0xcc08 -#define DWC3_OSTS 0xcc0C +#define DWC3_OEVT 0xcc08 +#define DWC3_OEVTEN 0xcc0C +#define DWC3_OSTS 0xcc10 /* Bit fields */ diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 8b23d0455b1c..9e9f122162f2 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -372,6 +372,7 @@ static const struct debugfs_reg32 dwc3_regs[] = { dump_register(OCFG), dump_register(OCTL), + dump_register(OEVT), dump_register(OEVTEN), dump_register(OSTS), }; From ddff14f1ab9b55b73ba59126ef4a10966725fc9d Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 7 Mar 2013 18:51:43 +0530 Subject: [PATCH 191/303] usb: dwc3: set dma_mask for dwc3_omap device *dma_mask* is not set for devices created from dt data. So filled dma_mask for dwc3_omap device here. And dwc3 core will copy the dma_mask from its parent. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 4 ++++ drivers/usb/dwc3/dwc3-omap.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 66c05725daf3..c845e7087069 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -454,6 +454,10 @@ static int dwc3_probe(struct platform_device *pdev) dwc->regs_size = resource_size(res); dwc->dev = dev; + dev->dma_mask = dev->parent->dma_mask; + dev->dma_parms = dev->parent->dma_parms; + dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); + if (!strncmp("super", maximum_speed, 5)) dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; else if (!strncmp("high", maximum_speed, 4)) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 35b9673b84df..546f1fd84920 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -277,6 +277,8 @@ static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x00); } +static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); + static int dwc3_omap_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -330,6 +332,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) omap->dev = dev; omap->irq = irq; omap->base = base; + dev->dma_mask = &dwc3_omap_dma_mask; /* * REVISIT if we ever have two instances of the wrapper, we will be From 2ba7943af0f0cca5a069cd3aff807815bc76fff1 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 7 Mar 2013 18:51:44 +0530 Subject: [PATCH 192/303] usb: dwc3: dwc3-omap: return -EPROBE_DEFER if probe has not yet executed return -EPROBE_DEFER from dwc3_omap_mailbox in dwc3-omap.c, if the probe of dwc3-omap has not yet been executed or failed. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 7 +++++-- include/linux/usb/dwc3-omap.h | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 546f1fd84920..2fe9723ff1df 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -138,11 +138,14 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value) writel(value, base + offset); } -void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) +int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) { u32 val; struct dwc3_omap *omap = _omap; + if (!omap) + return -EPROBE_DEFER; + switch (status) { case OMAP_DWC3_ID_GROUND: dev_dbg(omap->dev, "ID GND\n"); @@ -185,7 +188,7 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) dev_dbg(omap->dev, "ID float\n"); } - return; + return 0; } EXPORT_SYMBOL_GPL(dwc3_omap_mailbox); diff --git a/include/linux/usb/dwc3-omap.h b/include/linux/usb/dwc3-omap.h index 51eae14477f7..5615f4d82724 100644 --- a/include/linux/usb/dwc3-omap.h +++ b/include/linux/usb/dwc3-omap.h @@ -19,11 +19,11 @@ enum omap_dwc3_vbus_id_status { }; #if (defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_DWC3_MODULE)) -extern void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status); +extern int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status); #else -static inline void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) +static inline int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) { - return; + return -ENODEV; } #endif From dc2377d0b0a298ec9d7d232c0d757f462dedcca2 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Thu, 14 Mar 2013 15:59:10 +0530 Subject: [PATCH 193/303] usb: phy: samsung: Common out the generic stuff Moving register and structure definitions to header file, and keeping the generic functions to be used across multiple PHYs in common phy helper driver under SAMSUNG_USBPHY, and moving USB 2.0 PHY driver under SAMSUNG_USB2PHY. Also allowing samsung PHY drivers be built as modules. Signed-off-by: Vivek Gautam Acked-by: Kukjin Kim Signed-off-by: Felipe Balbi --- .../bindings/usb/samsung-usbphy.txt | 22 +- drivers/usb/phy/Kconfig | 15 +- drivers/usb/phy/Makefile | 1 + drivers/usb/phy/phy-samsung-usb.c | 726 +----------------- drivers/usb/phy/phy-samsung-usb.h | 247 ++++++ drivers/usb/phy/phy-samsung-usb2.c | 509 ++++++++++++ 6 files changed, 800 insertions(+), 720 deletions(-) create mode 100644 drivers/usb/phy/phy-samsung-usb.h create mode 100644 drivers/usb/phy/phy-samsung-usb2.c diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt index 033194934f64..96940abe9a57 100644 --- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt +++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt @@ -1,20 +1,25 @@ -* Samsung's usb phy transceiver +SAMSUNG USB-PHY controllers -The Samsung's phy transceiver is used for controlling usb phy for -s3c-hsotg as well as ehci-s5p and ohci-exynos usb controllers -across Samsung SOCs. +** Samsung's usb 2.0 phy transceiver + +The Samsung's usb 2.0 phy transceiver is used for controlling +usb 2.0 phy for s3c-hsotg as well as ehci-s5p and ohci-exynos +usb controllers across Samsung SOCs. TODO: Adding the PHY binding with controller(s) according to the under developement generic PHY driver. Required properties: Exynos4210: -- compatible : should be "samsung,exynos4210-usbphy" +- compatible : should be "samsung,exynos4210-usb2phy" - reg : base physical address of the phy registers and length of memory mapped region. +- clocks: Clock IDs array as required by the controller. +- clock-names: names of clock correseponding IDs clock property as requested + by the controller driver. Exynos5250: -- compatible : should be "samsung,exynos5250-usbphy" +- compatible : should be "samsung,exynos5250-usb2phy" - reg : base physical address of the phy registers and length of memory mapped region. @@ -44,10 +49,13 @@ Example: usbphy@125B0000 { #address-cells = <1>; #size-cells = <1>; - compatible = "samsung,exynos4210-usbphy"; + compatible = "samsung,exynos4210-usb2phy"; reg = <0x125B0000 0x100>; ranges; + clocks = <&clock 2>, <&clock 305>; + clock-names = "xusbxti", "otg"; + usbphy-sys { /* USB device and host PHY_CONTROL registers */ reg = <0x10020704 0x8>; diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 97de6de9b4b9..e8cd52ac5c05 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -86,11 +86,18 @@ config OMAP_USB3 on/off the PHY. config SAMSUNG_USBPHY - bool "Samsung USB PHY controller Driver" - depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS + tristate "Samsung USB PHY Driver" help - Enable this to support Samsung USB phy controller for samsung - SoCs. + Enable this to support Samsung USB phy helper driver for Samsung SoCs. + This driver provides common interface to interact, for Samsung USB 2.0 PHY + driver and later for Samsung USB 3.0 PHY driver. + +config SAMSUNG_USB2PHY + tristate "Samsung USB 2.0 PHY controller Driver" + select SAMSUNG_USBPHY + help + Enable this to support Samsung USB 2.0 (High Speed) PHY controller + driver for Samsung SoCs. config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 5fb4a5d55945..8cd355f051f6 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o +obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c index 967101ec15fd..7b118ee5f5e4 100644 --- a/drivers/usb/phy/phy-samsung-usb.c +++ b/drivers/usb/phy/phy-samsung-usb.c @@ -1,12 +1,13 @@ -/* linux/drivers/usb/phy/samsung-usbphy.c +/* linux/drivers/usb/phy/phy-samsung-usb.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com * * Author: Praveen Paneri * - * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and - * OHCI-EXYNOS controllers. + * Samsung USB-PHY helper driver with common function calls; + * interacts with Samsung USB 2.0 PHY controller driver and later + * with Samsung USB 3.0 PHY driver. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -21,233 +22,16 @@ #include #include #include -#include #include #include #include #include #include -#include #include -#include -/* Register definitions */ +#include "phy-samsung-usb.h" -#define SAMSUNG_PHYPWR (0x00) - -#define PHYPWR_NORMAL_MASK (0x19 << 0) -#define PHYPWR_OTG_DISABLE (0x1 << 4) -#define PHYPWR_ANALOG_POWERDOWN (0x1 << 3) -#define PHYPWR_FORCE_SUSPEND (0x1 << 1) -/* For Exynos4 */ -#define PHYPWR_NORMAL_MASK_PHY0 (0x39 << 0) -#define PHYPWR_SLEEP_PHY0 (0x1 << 5) - -#define SAMSUNG_PHYCLK (0x04) - -#define PHYCLK_MODE_USB11 (0x1 << 6) -#define PHYCLK_EXT_OSC (0x1 << 5) -#define PHYCLK_COMMON_ON_N (0x1 << 4) -#define PHYCLK_ID_PULL (0x1 << 2) -#define PHYCLK_CLKSEL_MASK (0x3 << 0) -#define PHYCLK_CLKSEL_48M (0x0 << 0) -#define PHYCLK_CLKSEL_12M (0x2 << 0) -#define PHYCLK_CLKSEL_24M (0x3 << 0) - -#define SAMSUNG_RSTCON (0x08) - -#define RSTCON_PHYLINK_SWRST (0x1 << 2) -#define RSTCON_HLINK_SWRST (0x1 << 1) -#define RSTCON_SWRST (0x1 << 0) - -/* EXYNOS5 */ -#define EXYNOS5_PHY_HOST_CTRL0 (0x00) - -#define HOST_CTRL0_PHYSWRSTALL (0x1 << 31) - -#define HOST_CTRL0_REFCLKSEL_MASK (0x3 << 19) -#define HOST_CTRL0_REFCLKSEL_XTAL (0x0 << 19) -#define HOST_CTRL0_REFCLKSEL_EXTL (0x1 << 19) -#define HOST_CTRL0_REFCLKSEL_CLKCORE (0x2 << 19) - -#define HOST_CTRL0_FSEL_MASK (0x7 << 16) -#define HOST_CTRL0_FSEL(_x) ((_x) << 16) - -#define FSEL_CLKSEL_50M (0x7) -#define FSEL_CLKSEL_24M (0x5) -#define FSEL_CLKSEL_20M (0x4) -#define FSEL_CLKSEL_19200K (0x3) -#define FSEL_CLKSEL_12M (0x2) -#define FSEL_CLKSEL_10M (0x1) -#define FSEL_CLKSEL_9600K (0x0) - -#define HOST_CTRL0_TESTBURNIN (0x1 << 11) -#define HOST_CTRL0_RETENABLE (0x1 << 10) -#define HOST_CTRL0_COMMONON_N (0x1 << 9) -#define HOST_CTRL0_SIDDQ (0x1 << 6) -#define HOST_CTRL0_FORCESLEEP (0x1 << 5) -#define HOST_CTRL0_FORCESUSPEND (0x1 << 4) -#define HOST_CTRL0_WORDINTERFACE (0x1 << 3) -#define HOST_CTRL0_UTMISWRST (0x1 << 2) -#define HOST_CTRL0_LINKSWRST (0x1 << 1) -#define HOST_CTRL0_PHYSWRST (0x1 << 0) - -#define EXYNOS5_PHY_HOST_TUNE0 (0x04) - -#define EXYNOS5_PHY_HSIC_CTRL1 (0x10) - -#define EXYNOS5_PHY_HSIC_TUNE1 (0x14) - -#define EXYNOS5_PHY_HSIC_CTRL2 (0x20) - -#define EXYNOS5_PHY_HSIC_TUNE2 (0x24) - -#define HSIC_CTRL_REFCLKSEL_MASK (0x3 << 23) -#define HSIC_CTRL_REFCLKSEL (0x2 << 23) - -#define HSIC_CTRL_REFCLKDIV_MASK (0x7f << 16) -#define HSIC_CTRL_REFCLKDIV(_x) ((_x) << 16) -#define HSIC_CTRL_REFCLKDIV_12 (0x24 << 16) -#define HSIC_CTRL_REFCLKDIV_15 (0x1c << 16) -#define HSIC_CTRL_REFCLKDIV_16 (0x1a << 16) -#define HSIC_CTRL_REFCLKDIV_19_2 (0x15 << 16) -#define HSIC_CTRL_REFCLKDIV_20 (0x14 << 16) - -#define HSIC_CTRL_SIDDQ (0x1 << 6) -#define HSIC_CTRL_FORCESLEEP (0x1 << 5) -#define HSIC_CTRL_FORCESUSPEND (0x1 << 4) -#define HSIC_CTRL_WORDINTERFACE (0x1 << 3) -#define HSIC_CTRL_UTMISWRST (0x1 << 2) -#define HSIC_CTRL_PHYSWRST (0x1 << 0) - -#define EXYNOS5_PHY_HOST_EHCICTRL (0x30) - -#define HOST_EHCICTRL_ENAINCRXALIGN (0x1 << 29) -#define HOST_EHCICTRL_ENAINCR4 (0x1 << 28) -#define HOST_EHCICTRL_ENAINCR8 (0x1 << 27) -#define HOST_EHCICTRL_ENAINCR16 (0x1 << 26) - -#define EXYNOS5_PHY_HOST_OHCICTRL (0x34) - -#define HOST_OHCICTRL_SUSPLGCY (0x1 << 3) -#define HOST_OHCICTRL_APPSTARTCLK (0x1 << 2) -#define HOST_OHCICTRL_CNTSEL (0x1 << 1) -#define HOST_OHCICTRL_CLKCKTRST (0x1 << 0) - -#define EXYNOS5_PHY_OTG_SYS (0x38) - -#define OTG_SYS_PHYLINK_SWRESET (0x1 << 14) -#define OTG_SYS_LINKSWRST_UOTG (0x1 << 13) -#define OTG_SYS_PHY0_SWRST (0x1 << 12) - -#define OTG_SYS_REFCLKSEL_MASK (0x3 << 9) -#define OTG_SYS_REFCLKSEL_XTAL (0x0 << 9) -#define OTG_SYS_REFCLKSEL_EXTL (0x1 << 9) -#define OTG_SYS_REFCLKSEL_CLKCORE (0x2 << 9) - -#define OTG_SYS_IDPULLUP_UOTG (0x1 << 8) -#define OTG_SYS_COMMON_ON (0x1 << 7) - -#define OTG_SYS_FSEL_MASK (0x7 << 4) -#define OTG_SYS_FSEL(_x) ((_x) << 4) - -#define OTG_SYS_FORCESLEEP (0x1 << 3) -#define OTG_SYS_OTGDISABLE (0x1 << 2) -#define OTG_SYS_SIDDQ_UOTG (0x1 << 1) -#define OTG_SYS_FORCESUSPEND (0x1 << 0) - -#define EXYNOS5_PHY_OTG_TUNE (0x40) - -#ifndef MHZ -#define MHZ (1000*1000) -#endif - -#ifndef KHZ -#define KHZ (1000) -#endif - -#define EXYNOS_USBHOST_PHY_CTRL_OFFSET (0x4) -#define S3C64XX_USBPHY_ENABLE (0x1 << 16) -#define EXYNOS_USBPHY_ENABLE (0x1 << 0) -#define EXYNOS_USB20PHY_CFG_HOST_LINK (0x1 << 0) - -enum samsung_cpu_type { - TYPE_S3C64XX, - TYPE_EXYNOS4210, - TYPE_EXYNOS5250, -}; - -/* - * struct samsung_usbphy_drvdata - driver data for various SoC variants - * @cpu_type: machine identifier - * @devphy_en_mask: device phy enable mask for PHY CONTROL register - * @hostphy_en_mask: host phy enable mask for PHY CONTROL register - * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from - * mapped address of system controller. - * @hostphy_reg_offset: offset to HOST PHY CONTROL register from - * mapped address of system controller. - * - * Here we have a separate mask for device type phy. - * Having different masks for host and device type phy helps - * in setting independent masks in case of SoCs like S5PV210, - * in which PHY0 and PHY1 enable bits belong to same register - * placed at position 0 and 1 respectively. - * Although for newer SoCs like exynos these bits belong to - * different registers altogether placed at position 0. - */ -struct samsung_usbphy_drvdata { - int cpu_type; - int devphy_en_mask; - int hostphy_en_mask; - u32 devphy_reg_offset; - u32 hostphy_reg_offset; -}; - -/* - * struct samsung_usbphy - transceiver driver state - * @phy: transceiver structure - * @plat: platform data - * @dev: The parent device supplied to the probe function - * @clk: usb phy clock - * @regs: usb phy controller registers memory base - * @pmuregs: USB device PHY_CONTROL register memory base - * @sysreg: USB2.0 PHY_CFG register memory base - * @ref_clk_freq: reference clock frequency selection - * @drv_data: driver data available for different SoCs - * @phy_type: Samsung SoCs specific phy types: #HOST - * #DEVICE - * @phy_usage: usage count for phy - * @lock: lock for phy operations - */ -struct samsung_usbphy { - struct usb_phy phy; - struct samsung_usbphy_data *plat; - struct device *dev; - struct clk *clk; - void __iomem *regs; - void __iomem *pmuregs; - void __iomem *sysreg; - int ref_clk_freq; - const struct samsung_usbphy_drvdata *drv_data; - enum samsung_usb_phy_type phy_type; - atomic_t phy_usage; - spinlock_t lock; -}; - -#define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy) - -int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host) -{ - if (!otg) - return -ENODEV; - - if (!otg->host) - otg->host = host; - - return 0; -} - -static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy) +int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy) { struct device_node *usbphy_sys; @@ -282,13 +66,14 @@ err0: of_node_put(usbphy_sys); return -ENXIO; } +EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt); /* * Set isolation here for phy. * Here 'on = true' would mean USB PHY block is isolated, hence * de-activated and vice-versa. */ -static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) +void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) { void __iomem *reg = NULL; u32 reg_val; @@ -336,11 +121,12 @@ static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) writel(reg_val, reg); } +EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation); /* * Configure the mode of working of usb-phy here: HOST/DEVICE. */ -static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy) +void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy) { u32 reg; @@ -358,13 +144,14 @@ static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy) writel(reg, sphy->sysreg); } +EXPORT_SYMBOL_GPL(samsung_usbphy_cfg_sel); /* * PHYs are different for USB Device and USB Host. * This make sure that correct PHY type is selected before * any operation on PHY. */ -static int samsung_usbphy_set_type(struct usb_phy *phy, +int samsung_usbphy_set_type(struct usb_phy *phy, enum samsung_usb_phy_type phy_type) { struct samsung_usbphy *sphy = phy_to_sphy(phy); @@ -373,11 +160,12 @@ static int samsung_usbphy_set_type(struct usb_phy *phy, return 0; } +EXPORT_SYMBOL_GPL(samsung_usbphy_set_type); /* * Returns reference clock frequency selection value */ -static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) +int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) { struct clk *ref_clk; int refclk_freq = 0; @@ -387,9 +175,9 @@ static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) * external crystal clock XXTI */ if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) - ref_clk = clk_get(sphy->dev, "ext_xtal"); + ref_clk = devm_clk_get(sphy->dev, "ext_xtal"); else - ref_clk = clk_get(sphy->dev, "xusbxti"); + ref_clk = devm_clk_get(sphy->dev, "xusbxti"); if (IS_ERR(ref_clk)) { dev_err(sphy->dev, "Failed to get reference clock\n"); return PTR_ERR(ref_clk); @@ -445,484 +233,4 @@ static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) return refclk_freq; } - -static bool exynos5_phyhost_is_on(void *regs) -{ - u32 reg; - - reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0); - - return !(reg & HOST_CTRL0_SIDDQ); -} - -static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy) -{ - void __iomem *regs = sphy->regs; - u32 phyclk = sphy->ref_clk_freq; - u32 phyhost; - u32 phyotg; - u32 phyhsic; - u32 ehcictrl; - u32 ohcictrl; - - /* - * phy_usage helps in keeping usage count for phy - * so that the first consumer enabling the phy is also - * the last consumer to disable it. - */ - - atomic_inc(&sphy->phy_usage); - - if (exynos5_phyhost_is_on(regs)) { - dev_info(sphy->dev, "Already power on PHY\n"); - return; - } - - /* Host configuration */ - phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); - - /* phy reference clock configuration */ - phyhost &= ~HOST_CTRL0_FSEL_MASK; - phyhost |= HOST_CTRL0_FSEL(phyclk); - - /* host phy reset */ - phyhost &= ~(HOST_CTRL0_PHYSWRST | - HOST_CTRL0_PHYSWRSTALL | - HOST_CTRL0_SIDDQ | - /* Enable normal mode of operation */ - HOST_CTRL0_FORCESUSPEND | - HOST_CTRL0_FORCESLEEP); - - /* Link reset */ - phyhost |= (HOST_CTRL0_LINKSWRST | - HOST_CTRL0_UTMISWRST | - /* COMMON Block configuration during suspend */ - HOST_CTRL0_COMMONON_N); - writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); - udelay(10); - phyhost &= ~(HOST_CTRL0_LINKSWRST | - HOST_CTRL0_UTMISWRST); - writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); - - /* OTG configuration */ - phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); - - /* phy reference clock configuration */ - phyotg &= ~OTG_SYS_FSEL_MASK; - phyotg |= OTG_SYS_FSEL(phyclk); - - /* Enable normal mode of operation */ - phyotg &= ~(OTG_SYS_FORCESUSPEND | - OTG_SYS_SIDDQ_UOTG | - OTG_SYS_FORCESLEEP | - OTG_SYS_REFCLKSEL_MASK | - /* COMMON Block configuration during suspend */ - OTG_SYS_COMMON_ON); - - /* OTG phy & link reset */ - phyotg |= (OTG_SYS_PHY0_SWRST | - OTG_SYS_LINKSWRST_UOTG | - OTG_SYS_PHYLINK_SWRESET | - OTG_SYS_OTGDISABLE | - /* Set phy refclk */ - OTG_SYS_REFCLKSEL_CLKCORE); - - writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); - udelay(10); - phyotg &= ~(OTG_SYS_PHY0_SWRST | - OTG_SYS_LINKSWRST_UOTG | - OTG_SYS_PHYLINK_SWRESET); - writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); - - /* HSIC phy configuration */ - phyhsic = (HSIC_CTRL_REFCLKDIV_12 | - HSIC_CTRL_REFCLKSEL | - HSIC_CTRL_PHYSWRST); - writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); - writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); - udelay(10); - phyhsic &= ~HSIC_CTRL_PHYSWRST; - writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); - writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); - - udelay(80); - - /* enable EHCI DMA burst */ - ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL); - ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN | - HOST_EHCICTRL_ENAINCR4 | - HOST_EHCICTRL_ENAINCR8 | - HOST_EHCICTRL_ENAINCR16); - writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL); - - /* set ohci_suspend_on_n */ - ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL); - ohcictrl |= HOST_OHCICTRL_SUSPLGCY; - writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL); -} - -static void samsung_usbphy_enable(struct samsung_usbphy *sphy) -{ - void __iomem *regs = sphy->regs; - u32 phypwr; - u32 phyclk; - u32 rstcon; - - /* set clock frequency for PLL */ - phyclk = sphy->ref_clk_freq; - phypwr = readl(regs + SAMSUNG_PHYPWR); - rstcon = readl(regs + SAMSUNG_RSTCON); - - switch (sphy->drv_data->cpu_type) { - case TYPE_S3C64XX: - phyclk &= ~PHYCLK_COMMON_ON_N; - phypwr &= ~PHYPWR_NORMAL_MASK; - rstcon |= RSTCON_SWRST; - break; - case TYPE_EXYNOS4210: - phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; - rstcon |= RSTCON_SWRST; - default: - break; - } - - writel(phyclk, regs + SAMSUNG_PHYCLK); - /* Configure PHY0 for normal operation*/ - writel(phypwr, regs + SAMSUNG_PHYPWR); - /* reset all ports of PHY and Link */ - writel(rstcon, regs + SAMSUNG_RSTCON); - udelay(10); - rstcon &= ~RSTCON_SWRST; - writel(rstcon, regs + SAMSUNG_RSTCON); -} - -static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy) -{ - void __iomem *regs = sphy->regs; - u32 phyhost; - u32 phyotg; - u32 phyhsic; - - if (atomic_dec_return(&sphy->phy_usage) > 0) { - dev_info(sphy->dev, "still being used\n"); - return; - } - - phyhsic = (HSIC_CTRL_REFCLKDIV_12 | - HSIC_CTRL_REFCLKSEL | - HSIC_CTRL_SIDDQ | - HSIC_CTRL_FORCESLEEP | - HSIC_CTRL_FORCESUSPEND); - writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); - writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); - - phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); - phyhost |= (HOST_CTRL0_SIDDQ | - HOST_CTRL0_FORCESUSPEND | - HOST_CTRL0_FORCESLEEP | - HOST_CTRL0_PHYSWRST | - HOST_CTRL0_PHYSWRSTALL); - writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); - - phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); - phyotg |= (OTG_SYS_FORCESUSPEND | - OTG_SYS_SIDDQ_UOTG | - OTG_SYS_FORCESLEEP); - writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); -} - -static void samsung_usbphy_disable(struct samsung_usbphy *sphy) -{ - void __iomem *regs = sphy->regs; - u32 phypwr; - - phypwr = readl(regs + SAMSUNG_PHYPWR); - - switch (sphy->drv_data->cpu_type) { - case TYPE_S3C64XX: - phypwr |= PHYPWR_NORMAL_MASK; - break; - case TYPE_EXYNOS4210: - phypwr |= PHYPWR_NORMAL_MASK_PHY0; - default: - break; - } - - /* Disable analog and otg block power */ - writel(phypwr, regs + SAMSUNG_PHYPWR); -} - -/* - * The function passed to the usb driver for phy initialization - */ -static int samsung_usbphy_init(struct usb_phy *phy) -{ - struct samsung_usbphy *sphy; - struct usb_bus *host = NULL; - unsigned long flags; - int ret = 0; - - sphy = phy_to_sphy(phy); - - host = phy->otg->host; - - /* Enable the phy clock */ - ret = clk_prepare_enable(sphy->clk); - if (ret) { - dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); - return ret; - } - - spin_lock_irqsave(&sphy->lock, flags); - - if (host) { - /* setting default phy-type for USB 2.0 */ - if (!strstr(dev_name(host->controller), "ehci") || - !strstr(dev_name(host->controller), "ohci")) - samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); - } else { - samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); - } - - /* Disable phy isolation */ - if (sphy->plat && sphy->plat->pmu_isolation) - sphy->plat->pmu_isolation(false); - else - samsung_usbphy_set_isolation(sphy, false); - - /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */ - samsung_usbphy_cfg_sel(sphy); - - /* Initialize usb phy registers */ - if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) - samsung_exynos5_usbphy_enable(sphy); - else - samsung_usbphy_enable(sphy); - - spin_unlock_irqrestore(&sphy->lock, flags); - - /* Disable the phy clock */ - clk_disable_unprepare(sphy->clk); - - return ret; -} - -/* - * The function passed to the usb driver for phy shutdown - */ -static void samsung_usbphy_shutdown(struct usb_phy *phy) -{ - struct samsung_usbphy *sphy; - struct usb_bus *host = NULL; - unsigned long flags; - - sphy = phy_to_sphy(phy); - - host = phy->otg->host; - - if (clk_prepare_enable(sphy->clk)) { - dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); - return; - } - - spin_lock_irqsave(&sphy->lock, flags); - - if (host) { - /* setting default phy-type for USB 2.0 */ - if (!strstr(dev_name(host->controller), "ehci") || - !strstr(dev_name(host->controller), "ohci")) - samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); - } else { - samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); - } - - /* De-initialize usb phy registers */ - if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) - samsung_exynos5_usbphy_disable(sphy); - else - samsung_usbphy_disable(sphy); - - /* Enable phy isolation */ - if (sphy->plat && sphy->plat->pmu_isolation) - sphy->plat->pmu_isolation(true); - else - samsung_usbphy_set_isolation(sphy, true); - - spin_unlock_irqrestore(&sphy->lock, flags); - - clk_disable_unprepare(sphy->clk); -} - -static const struct of_device_id samsung_usbphy_dt_match[]; - -static inline const struct samsung_usbphy_drvdata -*samsung_usbphy_get_driver_data(struct platform_device *pdev) -{ - if (pdev->dev.of_node) { - const struct of_device_id *match; - match = of_match_node(samsung_usbphy_dt_match, - pdev->dev.of_node); - return match->data; - } - - return (struct samsung_usbphy_drvdata *) - platform_get_device_id(pdev)->driver_data; -} - -static int samsung_usbphy_probe(struct platform_device *pdev) -{ - struct samsung_usbphy *sphy; - struct usb_otg *otg; - struct samsung_usbphy_data *pdata = pdev->dev.platform_data; - const struct samsung_usbphy_drvdata *drv_data; - struct device *dev = &pdev->dev; - struct resource *phy_mem; - void __iomem *phy_base; - struct clk *clk; - int ret; - - phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!phy_mem) { - dev_err(dev, "%s: missing mem resource\n", __func__); - return -ENODEV; - } - - phy_base = devm_ioremap_resource(dev, phy_mem); - if (IS_ERR(phy_base)) - return PTR_ERR(phy_base); - - sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); - if (!sphy) - return -ENOMEM; - - otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL); - if (!otg) - return -ENOMEM; - - drv_data = samsung_usbphy_get_driver_data(pdev); - - if (drv_data->cpu_type == TYPE_EXYNOS5250) - clk = devm_clk_get(dev, "usbhost"); - else - clk = devm_clk_get(dev, "otg"); - - if (IS_ERR(clk)) { - dev_err(dev, "Failed to get otg clock\n"); - return PTR_ERR(clk); - } - - sphy->dev = dev; - - if (dev->of_node) { - ret = samsung_usbphy_parse_dt(sphy); - if (ret < 0) - return ret; - } else { - if (!pdata) { - dev_err(dev, "no platform data specified\n"); - return -EINVAL; - } - } - - sphy->plat = pdata; - sphy->regs = phy_base; - sphy->clk = clk; - sphy->drv_data = drv_data; - sphy->phy.dev = sphy->dev; - sphy->phy.label = "samsung-usbphy"; - sphy->phy.init = samsung_usbphy_init; - sphy->phy.shutdown = samsung_usbphy_shutdown; - sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); - - sphy->phy.otg = otg; - sphy->phy.otg->phy = &sphy->phy; - sphy->phy.otg->set_host = samsung_usbphy_set_host; - - spin_lock_init(&sphy->lock); - - platform_set_drvdata(pdev, sphy); - - return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2); -} - -static int samsung_usbphy_remove(struct platform_device *pdev) -{ - struct samsung_usbphy *sphy = platform_get_drvdata(pdev); - - usb_remove_phy(&sphy->phy); - - if (sphy->pmuregs) - iounmap(sphy->pmuregs); - if (sphy->sysreg) - iounmap(sphy->sysreg); - - return 0; -} - -static const struct samsung_usbphy_drvdata usbphy_s3c64xx = { - .cpu_type = TYPE_S3C64XX, - .devphy_en_mask = S3C64XX_USBPHY_ENABLE, -}; - -static const struct samsung_usbphy_drvdata usbphy_exynos4 = { - .cpu_type = TYPE_EXYNOS4210, - .devphy_en_mask = EXYNOS_USBPHY_ENABLE, - .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, -}; - -static struct samsung_usbphy_drvdata usbphy_exynos5 = { - .cpu_type = TYPE_EXYNOS5250, - .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, - .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, -}; - -#ifdef CONFIG_OF -static const struct of_device_id samsung_usbphy_dt_match[] = { - { - .compatible = "samsung,s3c64xx-usbphy", - .data = &usbphy_s3c64xx, - }, { - .compatible = "samsung,exynos4210-usbphy", - .data = &usbphy_exynos4, - }, { - .compatible = "samsung,exynos5250-usbphy", - .data = &usbphy_exynos5 - }, - {}, -}; -MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match); -#endif - -static struct platform_device_id samsung_usbphy_driver_ids[] = { - { - .name = "s3c64xx-usbphy", - .driver_data = (unsigned long)&usbphy_s3c64xx, - }, { - .name = "exynos4210-usbphy", - .driver_data = (unsigned long)&usbphy_exynos4, - }, { - .name = "exynos5250-usbphy", - .driver_data = (unsigned long)&usbphy_exynos5, - }, - {}, -}; - -MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids); - -static struct platform_driver samsung_usbphy_driver = { - .probe = samsung_usbphy_probe, - .remove = samsung_usbphy_remove, - .id_table = samsung_usbphy_driver_ids, - .driver = { - .name = "samsung-usbphy", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(samsung_usbphy_dt_match), - }, -}; - -module_platform_driver(samsung_usbphy_driver); - -MODULE_DESCRIPTION("Samsung USB phy controller"); -MODULE_AUTHOR("Praveen Paneri "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:samsung-usbphy"); +EXPORT_SYMBOL_GPL(samsung_usbphy_get_refclk_freq); diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h new file mode 100644 index 000000000000..481737d743d5 --- /dev/null +++ b/drivers/usb/phy/phy-samsung-usb.h @@ -0,0 +1,247 @@ +/* linux/drivers/usb/phy/phy-samsung-usb.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and + * OHCI-EXYNOS controllers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +/* Register definitions */ + +#define SAMSUNG_PHYPWR (0x00) + +#define PHYPWR_NORMAL_MASK (0x19 << 0) +#define PHYPWR_OTG_DISABLE (0x1 << 4) +#define PHYPWR_ANALOG_POWERDOWN (0x1 << 3) +#define PHYPWR_FORCE_SUSPEND (0x1 << 1) +/* For Exynos4 */ +#define PHYPWR_NORMAL_MASK_PHY0 (0x39 << 0) +#define PHYPWR_SLEEP_PHY0 (0x1 << 5) + +#define SAMSUNG_PHYCLK (0x04) + +#define PHYCLK_MODE_USB11 (0x1 << 6) +#define PHYCLK_EXT_OSC (0x1 << 5) +#define PHYCLK_COMMON_ON_N (0x1 << 4) +#define PHYCLK_ID_PULL (0x1 << 2) +#define PHYCLK_CLKSEL_MASK (0x3 << 0) +#define PHYCLK_CLKSEL_48M (0x0 << 0) +#define PHYCLK_CLKSEL_12M (0x2 << 0) +#define PHYCLK_CLKSEL_24M (0x3 << 0) + +#define SAMSUNG_RSTCON (0x08) + +#define RSTCON_PHYLINK_SWRST (0x1 << 2) +#define RSTCON_HLINK_SWRST (0x1 << 1) +#define RSTCON_SWRST (0x1 << 0) + +/* EXYNOS5 */ +#define EXYNOS5_PHY_HOST_CTRL0 (0x00) + +#define HOST_CTRL0_PHYSWRSTALL (0x1 << 31) + +#define HOST_CTRL0_REFCLKSEL_MASK (0x3 << 19) +#define HOST_CTRL0_REFCLKSEL_XTAL (0x0 << 19) +#define HOST_CTRL0_REFCLKSEL_EXTL (0x1 << 19) +#define HOST_CTRL0_REFCLKSEL_CLKCORE (0x2 << 19) + +#define HOST_CTRL0_FSEL_MASK (0x7 << 16) +#define HOST_CTRL0_FSEL(_x) ((_x) << 16) + +#define FSEL_CLKSEL_50M (0x7) +#define FSEL_CLKSEL_24M (0x5) +#define FSEL_CLKSEL_20M (0x4) +#define FSEL_CLKSEL_19200K (0x3) +#define FSEL_CLKSEL_12M (0x2) +#define FSEL_CLKSEL_10M (0x1) +#define FSEL_CLKSEL_9600K (0x0) + +#define HOST_CTRL0_TESTBURNIN (0x1 << 11) +#define HOST_CTRL0_RETENABLE (0x1 << 10) +#define HOST_CTRL0_COMMONON_N (0x1 << 9) +#define HOST_CTRL0_SIDDQ (0x1 << 6) +#define HOST_CTRL0_FORCESLEEP (0x1 << 5) +#define HOST_CTRL0_FORCESUSPEND (0x1 << 4) +#define HOST_CTRL0_WORDINTERFACE (0x1 << 3) +#define HOST_CTRL0_UTMISWRST (0x1 << 2) +#define HOST_CTRL0_LINKSWRST (0x1 << 1) +#define HOST_CTRL0_PHYSWRST (0x1 << 0) + +#define EXYNOS5_PHY_HOST_TUNE0 (0x04) + +#define EXYNOS5_PHY_HSIC_CTRL1 (0x10) + +#define EXYNOS5_PHY_HSIC_TUNE1 (0x14) + +#define EXYNOS5_PHY_HSIC_CTRL2 (0x20) + +#define EXYNOS5_PHY_HSIC_TUNE2 (0x24) + +#define HSIC_CTRL_REFCLKSEL_MASK (0x3 << 23) +#define HSIC_CTRL_REFCLKSEL (0x2 << 23) + +#define HSIC_CTRL_REFCLKDIV_MASK (0x7f << 16) +#define HSIC_CTRL_REFCLKDIV(_x) ((_x) << 16) +#define HSIC_CTRL_REFCLKDIV_12 (0x24 << 16) +#define HSIC_CTRL_REFCLKDIV_15 (0x1c << 16) +#define HSIC_CTRL_REFCLKDIV_16 (0x1a << 16) +#define HSIC_CTRL_REFCLKDIV_19_2 (0x15 << 16) +#define HSIC_CTRL_REFCLKDIV_20 (0x14 << 16) + +#define HSIC_CTRL_SIDDQ (0x1 << 6) +#define HSIC_CTRL_FORCESLEEP (0x1 << 5) +#define HSIC_CTRL_FORCESUSPEND (0x1 << 4) +#define HSIC_CTRL_WORDINTERFACE (0x1 << 3) +#define HSIC_CTRL_UTMISWRST (0x1 << 2) +#define HSIC_CTRL_PHYSWRST (0x1 << 0) + +#define EXYNOS5_PHY_HOST_EHCICTRL (0x30) + +#define HOST_EHCICTRL_ENAINCRXALIGN (0x1 << 29) +#define HOST_EHCICTRL_ENAINCR4 (0x1 << 28) +#define HOST_EHCICTRL_ENAINCR8 (0x1 << 27) +#define HOST_EHCICTRL_ENAINCR16 (0x1 << 26) + +#define EXYNOS5_PHY_HOST_OHCICTRL (0x34) + +#define HOST_OHCICTRL_SUSPLGCY (0x1 << 3) +#define HOST_OHCICTRL_APPSTARTCLK (0x1 << 2) +#define HOST_OHCICTRL_CNTSEL (0x1 << 1) +#define HOST_OHCICTRL_CLKCKTRST (0x1 << 0) + +#define EXYNOS5_PHY_OTG_SYS (0x38) + +#define OTG_SYS_PHYLINK_SWRESET (0x1 << 14) +#define OTG_SYS_LINKSWRST_UOTG (0x1 << 13) +#define OTG_SYS_PHY0_SWRST (0x1 << 12) + +#define OTG_SYS_REFCLKSEL_MASK (0x3 << 9) +#define OTG_SYS_REFCLKSEL_XTAL (0x0 << 9) +#define OTG_SYS_REFCLKSEL_EXTL (0x1 << 9) +#define OTG_SYS_REFCLKSEL_CLKCORE (0x2 << 9) + +#define OTG_SYS_IDPULLUP_UOTG (0x1 << 8) +#define OTG_SYS_COMMON_ON (0x1 << 7) + +#define OTG_SYS_FSEL_MASK (0x7 << 4) +#define OTG_SYS_FSEL(_x) ((_x) << 4) + +#define OTG_SYS_FORCESLEEP (0x1 << 3) +#define OTG_SYS_OTGDISABLE (0x1 << 2) +#define OTG_SYS_SIDDQ_UOTG (0x1 << 1) +#define OTG_SYS_FORCESUSPEND (0x1 << 0) + +#define EXYNOS5_PHY_OTG_TUNE (0x40) + +#ifndef MHZ +#define MHZ (1000*1000) +#endif + +#ifndef KHZ +#define KHZ (1000) +#endif + +#define EXYNOS_USBHOST_PHY_CTRL_OFFSET (0x4) +#define S3C64XX_USBPHY_ENABLE (0x1 << 16) +#define EXYNOS_USBPHY_ENABLE (0x1 << 0) +#define EXYNOS_USB20PHY_CFG_HOST_LINK (0x1 << 0) + +enum samsung_cpu_type { + TYPE_S3C64XX, + TYPE_EXYNOS4210, + TYPE_EXYNOS5250, +}; + +/* + * struct samsung_usbphy_drvdata - driver data for various SoC variants + * @cpu_type: machine identifier + * @devphy_en_mask: device phy enable mask for PHY CONTROL register + * @hostphy_en_mask: host phy enable mask for PHY CONTROL register + * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from + * mapped address of system controller. + * @hostphy_reg_offset: offset to HOST PHY CONTROL register from + * mapped address of system controller. + * + * Here we have a separate mask for device type phy. + * Having different masks for host and device type phy helps + * in setting independent masks in case of SoCs like S5PV210, + * in which PHY0 and PHY1 enable bits belong to same register + * placed at position 0 and 1 respectively. + * Although for newer SoCs like exynos these bits belong to + * different registers altogether placed at position 0. + */ +struct samsung_usbphy_drvdata { + int cpu_type; + int devphy_en_mask; + int hostphy_en_mask; + u32 devphy_reg_offset; + u32 hostphy_reg_offset; +}; + +/* + * struct samsung_usbphy - transceiver driver state + * @phy: transceiver structure + * @plat: platform data + * @dev: The parent device supplied to the probe function + * @clk: usb phy clock + * @regs: usb phy controller registers memory base + * @pmuregs: USB device PHY_CONTROL register memory base + * @sysreg: USB2.0 PHY_CFG register memory base + * @ref_clk_freq: reference clock frequency selection + * @drv_data: driver data available for different SoCs + * @phy_type: Samsung SoCs specific phy types: #HOST + * #DEVICE + * @phy_usage: usage count for phy + * @lock: lock for phy operations + */ +struct samsung_usbphy { + struct usb_phy phy; + struct samsung_usbphy_data *plat; + struct device *dev; + struct clk *clk; + void __iomem *regs; + void __iomem *pmuregs; + void __iomem *sysreg; + int ref_clk_freq; + const struct samsung_usbphy_drvdata *drv_data; + enum samsung_usb_phy_type phy_type; + atomic_t phy_usage; + spinlock_t lock; +}; + +#define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy) + +static const struct of_device_id samsung_usbphy_dt_match[]; + +static inline const struct samsung_usbphy_drvdata +*samsung_usbphy_get_driver_data(struct platform_device *pdev) +{ + if (pdev->dev.of_node) { + const struct of_device_id *match; + match = of_match_node(samsung_usbphy_dt_match, + pdev->dev.of_node); + return match->data; + } + + return (struct samsung_usbphy_drvdata *) + platform_get_device_id(pdev)->driver_data; +} + +extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy); +extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on); +extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy); +extern int samsung_usbphy_set_type(struct usb_phy *phy, + enum samsung_usb_phy_type phy_type); +extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy); diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c new file mode 100644 index 000000000000..dce968151505 --- /dev/null +++ b/drivers/usb/phy/phy-samsung-usb2.c @@ -0,0 +1,509 @@ +/* linux/drivers/usb/phy/phy-samsung-usb2.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Praveen Paneri + * + * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and + * OHCI-EXYNOS controllers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "phy-samsung-usb.h" + +static int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host) +{ + if (!otg) + return -ENODEV; + + if (!otg->host) + otg->host = host; + + return 0; +} + +static bool exynos5_phyhost_is_on(void *regs) +{ + u32 reg; + + reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0); + + return !(reg & HOST_CTRL0_SIDDQ); +} + +static void samsung_exynos5_usb2phy_enable(struct samsung_usbphy *sphy) +{ + void __iomem *regs = sphy->regs; + u32 phyclk = sphy->ref_clk_freq; + u32 phyhost; + u32 phyotg; + u32 phyhsic; + u32 ehcictrl; + u32 ohcictrl; + + /* + * phy_usage helps in keeping usage count for phy + * so that the first consumer enabling the phy is also + * the last consumer to disable it. + */ + + atomic_inc(&sphy->phy_usage); + + if (exynos5_phyhost_is_on(regs)) { + dev_info(sphy->dev, "Already power on PHY\n"); + return; + } + + /* Host configuration */ + phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); + + /* phy reference clock configuration */ + phyhost &= ~HOST_CTRL0_FSEL_MASK; + phyhost |= HOST_CTRL0_FSEL(phyclk); + + /* host phy reset */ + phyhost &= ~(HOST_CTRL0_PHYSWRST | + HOST_CTRL0_PHYSWRSTALL | + HOST_CTRL0_SIDDQ | + /* Enable normal mode of operation */ + HOST_CTRL0_FORCESUSPEND | + HOST_CTRL0_FORCESLEEP); + + /* Link reset */ + phyhost |= (HOST_CTRL0_LINKSWRST | + HOST_CTRL0_UTMISWRST | + /* COMMON Block configuration during suspend */ + HOST_CTRL0_COMMONON_N); + writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); + udelay(10); + phyhost &= ~(HOST_CTRL0_LINKSWRST | + HOST_CTRL0_UTMISWRST); + writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); + + /* OTG configuration */ + phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); + + /* phy reference clock configuration */ + phyotg &= ~OTG_SYS_FSEL_MASK; + phyotg |= OTG_SYS_FSEL(phyclk); + + /* Enable normal mode of operation */ + phyotg &= ~(OTG_SYS_FORCESUSPEND | + OTG_SYS_SIDDQ_UOTG | + OTG_SYS_FORCESLEEP | + OTG_SYS_REFCLKSEL_MASK | + /* COMMON Block configuration during suspend */ + OTG_SYS_COMMON_ON); + + /* OTG phy & link reset */ + phyotg |= (OTG_SYS_PHY0_SWRST | + OTG_SYS_LINKSWRST_UOTG | + OTG_SYS_PHYLINK_SWRESET | + OTG_SYS_OTGDISABLE | + /* Set phy refclk */ + OTG_SYS_REFCLKSEL_CLKCORE); + + writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); + udelay(10); + phyotg &= ~(OTG_SYS_PHY0_SWRST | + OTG_SYS_LINKSWRST_UOTG | + OTG_SYS_PHYLINK_SWRESET); + writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); + + /* HSIC phy configuration */ + phyhsic = (HSIC_CTRL_REFCLKDIV_12 | + HSIC_CTRL_REFCLKSEL | + HSIC_CTRL_PHYSWRST); + writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); + writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); + udelay(10); + phyhsic &= ~HSIC_CTRL_PHYSWRST; + writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); + writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); + + udelay(80); + + /* enable EHCI DMA burst */ + ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL); + ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN | + HOST_EHCICTRL_ENAINCR4 | + HOST_EHCICTRL_ENAINCR8 | + HOST_EHCICTRL_ENAINCR16); + writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL); + + /* set ohci_suspend_on_n */ + ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL); + ohcictrl |= HOST_OHCICTRL_SUSPLGCY; + writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL); +} + +static void samsung_usb2phy_enable(struct samsung_usbphy *sphy) +{ + void __iomem *regs = sphy->regs; + u32 phypwr; + u32 phyclk; + u32 rstcon; + + /* set clock frequency for PLL */ + phyclk = sphy->ref_clk_freq; + phypwr = readl(regs + SAMSUNG_PHYPWR); + rstcon = readl(regs + SAMSUNG_RSTCON); + + switch (sphy->drv_data->cpu_type) { + case TYPE_S3C64XX: + phyclk &= ~PHYCLK_COMMON_ON_N; + phypwr &= ~PHYPWR_NORMAL_MASK; + rstcon |= RSTCON_SWRST; + break; + case TYPE_EXYNOS4210: + phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; + rstcon |= RSTCON_SWRST; + default: + break; + } + + writel(phyclk, regs + SAMSUNG_PHYCLK); + /* Configure PHY0 for normal operation*/ + writel(phypwr, regs + SAMSUNG_PHYPWR); + /* reset all ports of PHY and Link */ + writel(rstcon, regs + SAMSUNG_RSTCON); + udelay(10); + rstcon &= ~RSTCON_SWRST; + writel(rstcon, regs + SAMSUNG_RSTCON); +} + +static void samsung_exynos5_usb2phy_disable(struct samsung_usbphy *sphy) +{ + void __iomem *regs = sphy->regs; + u32 phyhost; + u32 phyotg; + u32 phyhsic; + + if (atomic_dec_return(&sphy->phy_usage) > 0) { + dev_info(sphy->dev, "still being used\n"); + return; + } + + phyhsic = (HSIC_CTRL_REFCLKDIV_12 | + HSIC_CTRL_REFCLKSEL | + HSIC_CTRL_SIDDQ | + HSIC_CTRL_FORCESLEEP | + HSIC_CTRL_FORCESUSPEND); + writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1); + writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2); + + phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0); + phyhost |= (HOST_CTRL0_SIDDQ | + HOST_CTRL0_FORCESUSPEND | + HOST_CTRL0_FORCESLEEP | + HOST_CTRL0_PHYSWRST | + HOST_CTRL0_PHYSWRSTALL); + writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0); + + phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS); + phyotg |= (OTG_SYS_FORCESUSPEND | + OTG_SYS_SIDDQ_UOTG | + OTG_SYS_FORCESLEEP); + writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS); +} + +static void samsung_usb2phy_disable(struct samsung_usbphy *sphy) +{ + void __iomem *regs = sphy->regs; + u32 phypwr; + + phypwr = readl(regs + SAMSUNG_PHYPWR); + + switch (sphy->drv_data->cpu_type) { + case TYPE_S3C64XX: + phypwr |= PHYPWR_NORMAL_MASK; + break; + case TYPE_EXYNOS4210: + phypwr |= PHYPWR_NORMAL_MASK_PHY0; + default: + break; + } + + /* Disable analog and otg block power */ + writel(phypwr, regs + SAMSUNG_PHYPWR); +} + +/* + * The function passed to the usb driver for phy initialization + */ +static int samsung_usb2phy_init(struct usb_phy *phy) +{ + struct samsung_usbphy *sphy; + struct usb_bus *host = NULL; + unsigned long flags; + int ret = 0; + + sphy = phy_to_sphy(phy); + + host = phy->otg->host; + + /* Enable the phy clock */ + ret = clk_prepare_enable(sphy->clk); + if (ret) { + dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); + return ret; + } + + spin_lock_irqsave(&sphy->lock, flags); + + if (host) { + /* setting default phy-type for USB 2.0 */ + if (!strstr(dev_name(host->controller), "ehci") || + !strstr(dev_name(host->controller), "ohci")) + samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); + } else { + samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); + } + + /* Disable phy isolation */ + if (sphy->plat && sphy->plat->pmu_isolation) + sphy->plat->pmu_isolation(false); + else + samsung_usbphy_set_isolation(sphy, false); + + /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */ + samsung_usbphy_cfg_sel(sphy); + + /* Initialize usb phy registers */ + if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) + samsung_exynos5_usb2phy_enable(sphy); + else + samsung_usb2phy_enable(sphy); + + spin_unlock_irqrestore(&sphy->lock, flags); + + /* Disable the phy clock */ + clk_disable_unprepare(sphy->clk); + + return ret; +} + +/* + * The function passed to the usb driver for phy shutdown + */ +static void samsung_usb2phy_shutdown(struct usb_phy *phy) +{ + struct samsung_usbphy *sphy; + struct usb_bus *host = NULL; + unsigned long flags; + + sphy = phy_to_sphy(phy); + + host = phy->otg->host; + + if (clk_prepare_enable(sphy->clk)) { + dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); + return; + } + + spin_lock_irqsave(&sphy->lock, flags); + + if (host) { + /* setting default phy-type for USB 2.0 */ + if (!strstr(dev_name(host->controller), "ehci") || + !strstr(dev_name(host->controller), "ohci")) + samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST); + } else { + samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); + } + + /* De-initialize usb phy registers */ + if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) + samsung_exynos5_usb2phy_disable(sphy); + else + samsung_usb2phy_disable(sphy); + + /* Enable phy isolation */ + if (sphy->plat && sphy->plat->pmu_isolation) + sphy->plat->pmu_isolation(true); + else + samsung_usbphy_set_isolation(sphy, true); + + spin_unlock_irqrestore(&sphy->lock, flags); + + clk_disable_unprepare(sphy->clk); +} + +static int samsung_usb2phy_probe(struct platform_device *pdev) +{ + struct samsung_usbphy *sphy; + struct usb_otg *otg; + struct samsung_usbphy_data *pdata = pdev->dev.platform_data; + const struct samsung_usbphy_drvdata *drv_data; + struct device *dev = &pdev->dev; + struct resource *phy_mem; + void __iomem *phy_base; + struct clk *clk; + int ret; + + phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!phy_mem) { + dev_err(dev, "%s: missing mem resource\n", __func__); + return -ENODEV; + } + + phy_base = devm_ioremap_resource(dev, phy_mem); + if (IS_ERR(phy_base)) + return PTR_ERR(phy_base); + + sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); + if (!sphy) + return -ENOMEM; + + otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL); + if (!otg) + return -ENOMEM; + + drv_data = samsung_usbphy_get_driver_data(pdev); + + if (drv_data->cpu_type == TYPE_EXYNOS5250) + clk = devm_clk_get(dev, "usbhost"); + else + clk = devm_clk_get(dev, "otg"); + + if (IS_ERR(clk)) { + dev_err(dev, "Failed to get otg clock\n"); + return PTR_ERR(clk); + } + + sphy->dev = dev; + + if (dev->of_node) { + ret = samsung_usbphy_parse_dt(sphy); + if (ret < 0) + return ret; + } else { + if (!pdata) { + dev_err(dev, "no platform data specified\n"); + return -EINVAL; + } + } + + sphy->plat = pdata; + sphy->regs = phy_base; + sphy->clk = clk; + sphy->drv_data = drv_data; + sphy->phy.dev = sphy->dev; + sphy->phy.label = "samsung-usb2phy"; + sphy->phy.init = samsung_usb2phy_init; + sphy->phy.shutdown = samsung_usb2phy_shutdown; + sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); + + sphy->phy.otg = otg; + sphy->phy.otg->phy = &sphy->phy; + sphy->phy.otg->set_host = samsung_usbphy_set_host; + + spin_lock_init(&sphy->lock); + + platform_set_drvdata(pdev, sphy); + + return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2); +} + +static int samsung_usb2phy_remove(struct platform_device *pdev) +{ + struct samsung_usbphy *sphy = platform_get_drvdata(pdev); + + usb_remove_phy(&sphy->phy); + + if (sphy->pmuregs) + iounmap(sphy->pmuregs); + if (sphy->sysreg) + iounmap(sphy->sysreg); + + return 0; +} + +static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = { + .cpu_type = TYPE_S3C64XX, + .devphy_en_mask = S3C64XX_USBPHY_ENABLE, +}; + +static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { + .cpu_type = TYPE_EXYNOS4210, + .devphy_en_mask = EXYNOS_USBPHY_ENABLE, + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, +}; + +static struct samsung_usbphy_drvdata usb2phy_exynos5 = { + .cpu_type = TYPE_EXYNOS5250, + .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, + .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, +}; + +#ifdef CONFIG_OF +static const struct of_device_id samsung_usbphy_dt_match[] = { + { + .compatible = "samsung,s3c64xx-usb2phy", + .data = &usb2phy_s3c64xx, + }, { + .compatible = "samsung,exynos4210-usb2phy", + .data = &usb2phy_exynos4, + }, { + .compatible = "samsung,exynos5250-usb2phy", + .data = &usb2phy_exynos5 + }, + {}, +}; +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match); +#endif + +static struct platform_device_id samsung_usbphy_driver_ids[] = { + { + .name = "s3c64xx-usb2phy", + .driver_data = (unsigned long)&usb2phy_s3c64xx, + }, { + .name = "exynos4210-usb2phy", + .driver_data = (unsigned long)&usb2phy_exynos4, + }, { + .name = "exynos5250-usb2phy", + .driver_data = (unsigned long)&usb2phy_exynos5, + }, + {}, +}; + +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids); + +static struct platform_driver samsung_usb2phy_driver = { + .probe = samsung_usb2phy_probe, + .remove = samsung_usb2phy_remove, + .id_table = samsung_usbphy_driver_ids, + .driver = { + .name = "samsung-usb2phy", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(samsung_usbphy_dt_match), + }, +}; + +module_platform_driver(samsung_usb2phy_driver); + +MODULE_DESCRIPTION("Samsung USB 2.0 phy controller"); +MODULE_AUTHOR("Praveen Paneri "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:samsung-usb2phy"); From b52767581765d3d1a1ba7106674791e540574704 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Thu, 14 Mar 2013 15:59:11 +0530 Subject: [PATCH 194/303] usb: phy: samsung: Add PHY support for USB 3.0 controller Adding PHY driver support for USB 3.0 controller for Samsung's SoCs. Signed-off-by: Vivek Gautam Acked-by: Kukjin Kim Signed-off-by: Felipe Balbi --- .../bindings/usb/samsung-usbphy.txt | 54 +++ drivers/usb/phy/Kconfig | 7 + drivers/usb/phy/Makefile | 1 + drivers/usb/phy/phy-samsung-usb.h | 80 ++++ drivers/usb/phy/phy-samsung-usb3.c | 349 ++++++++++++++++++ 5 files changed, 491 insertions(+) create mode 100644 drivers/usb/phy/phy-samsung-usb3.c diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt index 96940abe9a57..f575302e5173 100644 --- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt +++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt @@ -61,3 +61,57 @@ Example: 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>; + }; + }; diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index e8cd52ac5c05..7e8fe0f0b8c6 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -99,6 +99,13 @@ config SAMSUNG_USB2PHY Enable this to support Samsung USB 2.0 (High Speed) PHY controller driver for Samsung SoCs. +config SAMSUNG_USB3PHY + tristate "Samsung USB 3.0 PHY controller Driver" + select SAMSUNG_USBPHY + help + Enable this to support Samsung USB 3.0 (Super Speed) phy controller + for samsung SoCs. + config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 8cd355f051f6..33863c09f3dc 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o +obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o obj-$(CONFIG_TWL6030_USB) += phy-twl6030-usb.o obj-$(CONFIG_USB_EHCI_TEGRA) += phy-tegra-usb.o diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h index 481737d743d5..70a9cae5e37f 100644 --- a/drivers/usb/phy/phy-samsung-usb.h +++ b/drivers/usb/phy/phy-samsung-usb.h @@ -145,6 +145,86 @@ #define EXYNOS5_PHY_OTG_TUNE (0x40) +/* EXYNOS5: USB 3.0 DRD */ +#define EXYNOS5_DRD_LINKSYSTEM (0x04) + +#define LINKSYSTEM_FLADJ_MASK (0x3f << 1) +#define LINKSYSTEM_FLADJ(_x) ((_x) << 1) +#define LINKSYSTEM_XHCI_VERSION_CONTROL (0x1 << 27) + +#define EXYNOS5_DRD_PHYUTMI (0x08) + +#define PHYUTMI_OTGDISABLE (0x1 << 6) +#define PHYUTMI_FORCESUSPEND (0x1 << 1) +#define PHYUTMI_FORCESLEEP (0x1 << 0) + +#define EXYNOS5_DRD_PHYPIPE (0x0c) + +#define EXYNOS5_DRD_PHYCLKRST (0x10) + +#define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23) +#define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23) + +#define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21) +#define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21) + +#define PHYCLKRST_SSC_EN (0x1 << 20) +#define PHYCLKRST_REF_SSP_EN (0x1 << 19) +#define PHYCLKRST_REF_CLKDIV2 (0x1 << 18) + +#define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x02 << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11) +#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11) + +#define PHYCLKRST_FSEL_MASK (0x3f << 5) +#define PHYCLKRST_FSEL(_x) ((_x) << 5) +#define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5) +#define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5) +#define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5) +#define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5) + +#define PHYCLKRST_RETENABLEN (0x1 << 4) + +#define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2) +#define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2) +#define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2) + +#define PHYCLKRST_PORTRESET (0x1 << 1) +#define PHYCLKRST_COMMONONN (0x1 << 0) + +#define EXYNOS5_DRD_PHYREG0 (0x14) +#define EXYNOS5_DRD_PHYREG1 (0x18) + +#define EXYNOS5_DRD_PHYPARAM0 (0x1c) + +#define PHYPARAM0_REF_USE_PAD (0x1 << 31) +#define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26) +#define PHYPARAM0_REF_LOSLEVEL (0x9 << 26) + +#define EXYNOS5_DRD_PHYPARAM1 (0x20) + +#define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0) +#define PHYPARAM1_PCS_TXDEEMPH (0x1c) + +#define EXYNOS5_DRD_PHYTERM (0x24) + +#define EXYNOS5_DRD_PHYTEST (0x28) + +#define PHYTEST_POWERDOWN_SSP (0x1 << 3) +#define PHYTEST_POWERDOWN_HSP (0x1 << 2) + +#define EXYNOS5_DRD_PHYADP (0x2c) + +#define EXYNOS5_DRD_PHYBATCHG (0x30) + +#define PHYBATCHG_UTMI_CLKSEL (0x1 << 2) + +#define EXYNOS5_DRD_PHYRESUME (0x34) +#define EXYNOS5_DRD_LINKPORT (0x44) + #ifndef MHZ #define MHZ (1000*1000) #endif diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c new file mode 100644 index 000000000000..54f641860f9e --- /dev/null +++ b/drivers/usb/phy/phy-samsung-usb3.c @@ -0,0 +1,349 @@ +/* linux/drivers/usb/phy/phy-samsung-usb3.c + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Author: Vivek Gautam + * + * Samsung USB 3.0 PHY transceiver; talks to DWC3 controller. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "phy-samsung-usb.h" + +/* + * Sets the phy clk as EXTREFCLK (XXTI) which is internal clock from clock core. + */ +static u32 samsung_usb3phy_set_refclk(struct samsung_usbphy *sphy) +{ + u32 reg; + u32 refclk; + + refclk = sphy->ref_clk_freq; + + reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK | + PHYCLKRST_FSEL(refclk); + + switch (refclk) { + case FSEL_CLKSEL_50M: + reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF | + PHYCLKRST_SSC_REFCLKSEL(0x00)); + break; + case FSEL_CLKSEL_20M: + reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF | + PHYCLKRST_SSC_REFCLKSEL(0x00)); + break; + case FSEL_CLKSEL_19200K: + reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF | + PHYCLKRST_SSC_REFCLKSEL(0x88)); + break; + case FSEL_CLKSEL_24M: + default: + reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF | + PHYCLKRST_SSC_REFCLKSEL(0x88)); + break; + } + + return reg; +} + +static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy) +{ + void __iomem *regs = sphy->regs; + u32 phyparam0; + u32 phyparam1; + u32 linksystem; + u32 phybatchg; + u32 phytest; + u32 phyclkrst; + + /* Reset USB 3.0 PHY */ + writel(0x0, regs + EXYNOS5_DRD_PHYREG0); + + phyparam0 = readl(regs + EXYNOS5_DRD_PHYPARAM0); + /* Select PHY CLK source */ + phyparam0 &= ~PHYPARAM0_REF_USE_PAD; + /* Set Loss-of-Signal Detector sensitivity */ + phyparam0 &= ~PHYPARAM0_REF_LOSLEVEL_MASK; + phyparam0 |= PHYPARAM0_REF_LOSLEVEL; + writel(phyparam0, regs + EXYNOS5_DRD_PHYPARAM0); + + writel(0x0, regs + EXYNOS5_DRD_PHYRESUME); + + /* + * Setting the Frame length Adj value[6:1] to default 0x20 + * See xHCI 1.0 spec, 5.2.4 + */ + linksystem = LINKSYSTEM_XHCI_VERSION_CONTROL | + LINKSYSTEM_FLADJ(0x20); + writel(linksystem, regs + EXYNOS5_DRD_LINKSYSTEM); + + phyparam1 = readl(regs + EXYNOS5_DRD_PHYPARAM1); + /* Set Tx De-Emphasis level */ + phyparam1 &= ~PHYPARAM1_PCS_TXDEEMPH_MASK; + phyparam1 |= PHYPARAM1_PCS_TXDEEMPH; + writel(phyparam1, regs + EXYNOS5_DRD_PHYPARAM1); + + phybatchg = readl(regs + EXYNOS5_DRD_PHYBATCHG); + phybatchg |= PHYBATCHG_UTMI_CLKSEL; + writel(phybatchg, regs + EXYNOS5_DRD_PHYBATCHG); + + /* PHYTEST POWERDOWN Control */ + phytest = readl(regs + EXYNOS5_DRD_PHYTEST); + phytest &= ~(PHYTEST_POWERDOWN_SSP | + PHYTEST_POWERDOWN_HSP); + writel(phytest, regs + EXYNOS5_DRD_PHYTEST); + + /* UTMI Power Control */ + writel(PHYUTMI_OTGDISABLE, regs + EXYNOS5_DRD_PHYUTMI); + + phyclkrst = samsung_usb3phy_set_refclk(sphy); + + phyclkrst |= PHYCLKRST_PORTRESET | + /* Digital power supply in normal operating mode */ + PHYCLKRST_RETENABLEN | + /* Enable ref clock for SS function */ + PHYCLKRST_REF_SSP_EN | + /* Enable spread spectrum */ + PHYCLKRST_SSC_EN | + /* Power down HS Bias and PLL blocks in suspend mode */ + PHYCLKRST_COMMONONN; + + writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); + + udelay(10); + + phyclkrst &= ~(PHYCLKRST_PORTRESET); + writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); + + return 0; +} + +static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy) +{ + u32 phyutmi; + u32 phyclkrst; + u32 phytest; + void __iomem *regs = sphy->regs; + + phyutmi = PHYUTMI_OTGDISABLE | + PHYUTMI_FORCESUSPEND | + PHYUTMI_FORCESLEEP; + writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI); + + /* Resetting the PHYCLKRST enable bits to reduce leakage current */ + phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST); + phyclkrst &= ~(PHYCLKRST_REF_SSP_EN | + PHYCLKRST_SSC_EN | + PHYCLKRST_COMMONONN); + writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); + + /* Control PHYTEST to remove leakage current */ + phytest = readl(regs + EXYNOS5_DRD_PHYTEST); + phytest |= (PHYTEST_POWERDOWN_SSP | + PHYTEST_POWERDOWN_HSP); + writel(phytest, regs + EXYNOS5_DRD_PHYTEST); +} + +static int samsung_usb3phy_init(struct usb_phy *phy) +{ + struct samsung_usbphy *sphy; + unsigned long flags; + int ret = 0; + + sphy = phy_to_sphy(phy); + + /* Enable the phy clock */ + ret = clk_prepare_enable(sphy->clk); + if (ret) { + dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); + return ret; + } + + spin_lock_irqsave(&sphy->lock, flags); + + /* setting default phy-type for USB 3.0 */ + samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); + + /* Disable phy isolation */ + samsung_usbphy_set_isolation(sphy, false); + + /* Initialize usb phy registers */ + samsung_exynos5_usb3phy_enable(sphy); + + spin_unlock_irqrestore(&sphy->lock, flags); + + /* Disable the phy clock */ + clk_disable_unprepare(sphy->clk); + + return ret; +} + +/* + * The function passed to the usb driver for phy shutdown + */ +static void samsung_usb3phy_shutdown(struct usb_phy *phy) +{ + struct samsung_usbphy *sphy; + unsigned long flags; + + sphy = phy_to_sphy(phy); + + if (clk_prepare_enable(sphy->clk)) { + dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__); + return; + } + + spin_lock_irqsave(&sphy->lock, flags); + + /* setting default phy-type for USB 3.0 */ + samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); + + /* De-initialize usb phy registers */ + samsung_exynos5_usb3phy_disable(sphy); + + /* Enable phy isolation */ + samsung_usbphy_set_isolation(sphy, true); + + spin_unlock_irqrestore(&sphy->lock, flags); + + clk_disable_unprepare(sphy->clk); +} + +static int samsung_usb3phy_probe(struct platform_device *pdev) +{ + struct samsung_usbphy *sphy; + struct samsung_usbphy_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct resource *phy_mem; + void __iomem *phy_base; + struct clk *clk; + int ret; + + phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!phy_mem) { + dev_err(dev, "%s: missing mem resource\n", __func__); + return -ENODEV; + } + + phy_base = devm_request_and_ioremap(dev, phy_mem); + if (!phy_base) { + dev_err(dev, "%s: register mapping failed\n", __func__); + return -ENXIO; + } + + sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); + if (!sphy) + return -ENOMEM; + + clk = devm_clk_get(dev, "usbdrd30"); + if (IS_ERR(clk)) { + dev_err(dev, "Failed to get device clock\n"); + return PTR_ERR(clk); + } + + sphy->dev = dev; + + if (dev->of_node) { + ret = samsung_usbphy_parse_dt(sphy); + if (ret < 0) + return ret; + } else { + if (!pdata) { + dev_err(dev, "no platform data specified\n"); + return -EINVAL; + } + } + + sphy->plat = pdata; + sphy->regs = phy_base; + sphy->clk = clk; + sphy->phy.dev = sphy->dev; + sphy->phy.label = "samsung-usb3phy"; + sphy->phy.init = samsung_usb3phy_init; + sphy->phy.shutdown = samsung_usb3phy_shutdown; + sphy->drv_data = samsung_usbphy_get_driver_data(pdev); + sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); + + spin_lock_init(&sphy->lock); + + platform_set_drvdata(pdev, sphy); + + return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3); +} + +static int samsung_usb3phy_remove(struct platform_device *pdev) +{ + struct samsung_usbphy *sphy = platform_get_drvdata(pdev); + + usb_remove_phy(&sphy->phy); + + if (sphy->pmuregs) + iounmap(sphy->pmuregs); + if (sphy->sysreg) + iounmap(sphy->sysreg); + + return 0; +} + +static struct samsung_usbphy_drvdata usb3phy_exynos5 = { + .cpu_type = TYPE_EXYNOS5250, + .devphy_en_mask = EXYNOS_USBPHY_ENABLE, +}; + +#ifdef CONFIG_OF +static const struct of_device_id samsung_usbphy_dt_match[] = { + { + .compatible = "samsung,exynos5250-usb3phy", + .data = &usb3phy_exynos5 + }, + {}, +}; +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match); +#endif + +static struct platform_device_id samsung_usbphy_driver_ids[] = { + { + .name = "exynos5250-usb3phy", + .driver_data = (unsigned long)&usb3phy_exynos5, + }, + {}, +}; + +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids); + +static struct platform_driver samsung_usb3phy_driver = { + .probe = samsung_usb3phy_probe, + .remove = samsung_usb3phy_remove, + .id_table = samsung_usbphy_driver_ids, + .driver = { + .name = "samsung-usb3phy", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(samsung_usbphy_dt_match), + }, +}; + +module_platform_driver(samsung_usb3phy_driver); + +MODULE_DESCRIPTION("Samsung USB 3.0 phy controller"); +MODULE_AUTHOR("Vivek Gautam "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:samsung-usb3phy"); From adcf20dcd2629112c467f30a2c057479979ae64c Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Thu, 14 Mar 2013 18:09:49 +0530 Subject: [PATCH 195/303] usb: dwc3: exynos: Use of_platform API to create dwc3 core pdev Used of_platform_populate() to create dwc3 core platform_device from device tree data. Additionally some cleanup is also done. Signed-off-by: Vivek Gautam CC: Felipe Balbi CC: Kukjin Kim Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-exynos.c | 56 +++++++++++++++------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index e12e45248862..f77ec75e2d1e 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -22,9 +22,9 @@ #include #include #include +#include struct dwc3_exynos { - struct platform_device *dwc3; struct platform_device *usb2_phy; struct platform_device *usb3_phy; struct device *dev; @@ -86,21 +86,30 @@ err1: return ret; } +static int dwc3_exynos_remove_child(struct device *dev, void *unused) +{ + struct platform_device *pdev = to_platform_device(dev); + + platform_device_unregister(pdev); + + return 0; +} + static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32); static int dwc3_exynos_probe(struct platform_device *pdev) { - struct platform_device *dwc3; struct dwc3_exynos *exynos; struct clk *clk; struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; int ret = -ENOMEM; exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL); if (!exynos) { dev_err(dev, "not enough memory\n"); - return -ENOMEM; + goto err1; } /* @@ -108,21 +117,15 @@ static int dwc3_exynos_probe(struct platform_device *pdev) * Since shared usb code relies on it, set it here for now. * Once we move to full device tree support this will vanish off. */ - if (!pdev->dev.dma_mask) - pdev->dev.dma_mask = &dwc3_exynos_dma_mask; + if (!dev->dma_mask) + dev->dma_mask = &dwc3_exynos_dma_mask; platform_set_drvdata(pdev, exynos); ret = dwc3_exynos_register_phys(exynos); if (ret) { dev_err(dev, "couldn't register PHYs\n"); - return ret; - } - - dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); - if (!dwc3) { - dev_err(dev, "couldn't allocate dwc3 device\n"); - return -ENOMEM; + goto err1; } clk = devm_clk_get(dev, "usbdrd30"); @@ -132,27 +135,20 @@ static int dwc3_exynos_probe(struct platform_device *pdev) goto err1; } - dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask); - - dwc3->dev.parent = dev; - dwc3->dev.dma_mask = dev->dma_mask; - dwc3->dev.dma_parms = dev->dma_parms; - exynos->dwc3 = dwc3; exynos->dev = dev; exynos->clk = clk; clk_enable(exynos->clk); - ret = platform_device_add_resources(dwc3, pdev->resource, - pdev->num_resources); - if (ret) { - dev_err(dev, "couldn't add resources to dwc3 device\n"); - goto err2; - } - - ret = platform_device_add(dwc3); - if (ret) { - dev_err(dev, "failed to register dwc3 device\n"); + if (node) { + ret = of_platform_populate(node, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to add dwc3 core\n"); + goto err2; + } + } else { + dev_err(dev, "no device node, failed to add dwc3 core\n"); + ret = -ENODEV; goto err2; } @@ -161,8 +157,6 @@ static int dwc3_exynos_probe(struct platform_device *pdev) err2: clk_disable(clk); err1: - platform_device_put(dwc3); - return ret; } @@ -170,9 +164,9 @@ static int dwc3_exynos_remove(struct platform_device *pdev) { struct dwc3_exynos *exynos = platform_get_drvdata(pdev); - platform_device_unregister(exynos->dwc3); platform_device_unregister(exynos->usb2_phy); platform_device_unregister(exynos->usb3_phy); + device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child); clk_disable(exynos->clk); From ddb5147cea10308fac7d4ea44cbd164929199e03 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Thu, 14 Mar 2013 16:14:58 +0530 Subject: [PATCH 196/303] usb: dwc3: exynos: use clk_prepare_enable and clk_disable_unprepare Convert clk_enable/clk_disable to clk_prepare_enable/clk_disable_unprepare calls as required by common clock framework. Signed-off-by: Vivek Gautam CC: Kukjin Kim Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-exynos.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index f77ec75e2d1e..1ea7bd8af6ae 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -138,7 +138,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev) exynos->dev = dev; exynos->clk = clk; - clk_enable(exynos->clk); + clk_prepare_enable(exynos->clk); if (node) { ret = of_platform_populate(node, NULL, NULL, dev); @@ -155,7 +155,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev) return 0; err2: - clk_disable(clk); + clk_disable_unprepare(clk); err1: return ret; } @@ -168,7 +168,7 @@ static int dwc3_exynos_remove(struct platform_device *pdev) 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; } From f9e612002fc50b3ae7cd1349eb2387e5430b44d9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 1 Mar 2013 20:46:22 +0100 Subject: [PATCH 197/303] usb: gadget: uvc: clarify comment about string descriptors The comment that describes string descriptors allocation isn't clear, fix it. Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 92efd6ec48af..dd372ce9f3e2 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -800,7 +800,10 @@ uvc_bind_config(struct usb_configuration *c, uvc->desc.hs_streaming = hs_streaming; uvc->desc.ss_streaming = ss_streaming; - /* Allocate string descriptor numbers. */ + /* String descriptors are global, we only need to allocate string IDs + * for the first UVC function. UVC functions beyond the first (if any) + * will reuse the same IDs. + */ if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) { ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings); if (ret) From 912ca429fc87ceb63ae9ae00eff08212aad890c5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 1 Mar 2013 20:46:23 +0100 Subject: [PATCH 198/303] usb: gadget: uvc: Rename STATUS_BYTECOUNT to UVC_STATUS_MAX_PACKET_SIZE Descriptive names make the code more readable. Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index dd372ce9f3e2..1851490c67cd 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -79,7 +79,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = { #define UVC_INTF_VIDEO_CONTROL 0 #define UVC_INTF_VIDEO_STREAMING 1 -#define STATUS_BYTECOUNT 16 /* 16 bytes status */ +#define UVC_STATUS_MAX_PACKET_SIZE 16 /* 16 bytes status */ static struct usb_interface_assoc_descriptor uvc_iad __initdata = { .bLength = sizeof(uvc_iad), @@ -109,7 +109,7 @@ static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), .bInterval = 8, }; @@ -117,7 +117,7 @@ static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = { .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, .bDescriptorType = USB_DT_CS_ENDPOINT, .bDescriptorSubType = UVC_EP_INTERRUPT, - .wMaxTransferSize = cpu_to_le16(STATUS_BYTECOUNT), + .wMaxTransferSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), }; static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { @@ -169,7 +169,7 @@ static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), .bInterval = 8, }; @@ -180,7 +180,7 @@ static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { /* the following 3 values can be tweaked if necessary */ /* .bMaxBurst = 0, */ /* .bmAttributes = 0, */ - .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT), + .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), }; static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { From ee6a4d870b722a57aa57abe7f12539bac9c01555 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 1 Mar 2013 20:46:24 +0100 Subject: [PATCH 199/303] usb: gadget: uvc: Fix coding style issues introduced by SS support Let's keep the code consistent, people might want to read it. Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 58 +++++++++++++++++++------------------- drivers/usb/gadget/f_uvc.h | 12 ++++---- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 1851490c67cd..c13b8b07c791 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -164,43 +164,43 @@ static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { /* super speed support */ static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), - .bInterval = 8, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), + .bInterval = 8, }; static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { - .bLength = sizeof uvc_ss_control_comp, - .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bLength = sizeof(uvc_ss_control_comp), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, /* the following 3 values can be tweaked if necessary */ - /* .bMaxBurst = 0, */ - /* .bmAttributes = 0, */ - .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), }; static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .wMaxPacketSize = cpu_to_le16(1024), - .bInterval = 4, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .wMaxPacketSize = cpu_to_le16(1024), + .bInterval = 4, }; static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = { - .bLength = sizeof uvc_ss_streaming_comp, - .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + .bLength = sizeof(uvc_ss_streaming_comp), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, /* the following 3 values can be tweaked if necessary */ - .bMaxBurst = 0, - .bmAttributes = 0, - .wBytesPerInterval = cpu_to_le16(1024), + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = cpu_to_le16(1024), }; static const struct usb_descriptor_header * const uvc_fs_streaming[] = { @@ -514,13 +514,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) } for (src = (const struct usb_descriptor_header **)uvc_control_desc; - *src; ++src) { + *src; ++src) { control_size += (*src)->bLength; bytes += (*src)->bLength; n_desc++; } for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; - *src; ++src) { + *src; ++src) { streaming_size += (*src)->bLength; bytes += (*src)->bLength; n_desc++; @@ -775,23 +775,23 @@ uvc_bind_config(struct usb_configuration *c, /* Validate the descriptors. */ if (fs_control == NULL || fs_control[0] == NULL || - fs_control[0]->bDescriptorSubType != UVC_VC_HEADER) + fs_control[0]->bDescriptorSubType != UVC_VC_HEADER) goto error; if (ss_control == NULL || ss_control[0] == NULL || - ss_control[0]->bDescriptorSubType != UVC_VC_HEADER) + ss_control[0]->bDescriptorSubType != UVC_VC_HEADER) goto error; if (fs_streaming == NULL || fs_streaming[0] == NULL || - fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) + fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) goto error; if (hs_streaming == NULL || hs_streaming[0] == NULL || - hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) + hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) goto error; if (ss_streaming == NULL || ss_streaming[0] == NULL || - ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) + ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) goto error; uvc->desc.fs_control = fs_control; diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/f_uvc.h index c3d258d30188..ec52752f7326 100644 --- a/drivers/usb/gadget/f_uvc.h +++ b/drivers/usb/gadget/f_uvc.h @@ -16,12 +16,12 @@ #include #include -extern int uvc_bind_config(struct usb_configuration *c, - const struct uvc_descriptor_header * const *fs_control, - const struct uvc_descriptor_header * const *hs_control, - const struct uvc_descriptor_header * const *fs_streaming, - const struct uvc_descriptor_header * const *hs_streaming, - const struct uvc_descriptor_header * const *ss_streaming); +int uvc_bind_config(struct usb_configuration *c, + const struct uvc_descriptor_header * const *fs_control, + const struct uvc_descriptor_header * const *hs_control, + const struct uvc_descriptor_header * const *fs_streaming, + const struct uvc_descriptor_header * const *hs_streaming, + const struct uvc_descriptor_header * const *ss_streaming); #endif /* _F_UVC_H_ */ From 48eee0b41a1c6e979e4b47d75bb3f2493c1b5fb9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 1 Mar 2013 20:46:25 +0100 Subject: [PATCH 200/303] usb: gadget: uvc: Merge the SS/HS/FS control endpoint descriptors The descriptors are identical, there's no need to have several copies of them. Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 52 +++++++++++++------------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index c13b8b07c791..8e4827c3afb5 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -104,7 +104,7 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = { .iInterface = 0, }; -static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = { +static struct usb_endpoint_descriptor uvc_control_ep __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, @@ -113,6 +113,15 @@ static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = { .bInterval = 8, }; +static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { + .bLength = sizeof(uvc_ss_control_comp), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + /* The following 3 values can be tweaked if necessary. */ + .bMaxBurst = 0, + .bmAttributes = 0, + .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), +}; + static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = { .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, .bDescriptorType = USB_DT_CS_ENDPOINT, @@ -144,7 +153,7 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = { .iInterface = 0, }; -static struct usb_endpoint_descriptor uvc_fs_streaming_ep = { +static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, @@ -153,7 +162,7 @@ static struct usb_endpoint_descriptor uvc_fs_streaming_ep = { .bInterval = 1, }; -static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { +static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, @@ -162,27 +171,6 @@ static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { .bInterval = 1, }; -/* super speed support */ -static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), - .bInterval = 8, -}; - -static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { - .bLength = sizeof(uvc_ss_control_comp), - .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, - - /* the following 3 values can be tweaked if necessary */ - .bMaxBurst = 0, - .bmAttributes = 0, - .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), -}; - static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -193,11 +181,10 @@ static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { .bInterval = 4, }; -static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = { +static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = { .bLength = sizeof(uvc_ss_streaming_comp), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, - - /* the following 3 values can be tweaked if necessary */ + /* The following 3 values can be tweaked if necessary. */ .bMaxBurst = 0, .bmAttributes = 0, .wBytesPerInterval = cpu_to_le16(1024), @@ -454,7 +441,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) const struct uvc_descriptor_header * const *uvc_streaming_cls; const struct usb_descriptor_header * const *uvc_streaming_std; const struct usb_descriptor_header * const *src; - static struct usb_endpoint_descriptor *uvc_control_ep; struct usb_descriptor_header **dst; struct usb_descriptor_header **hdr; unsigned int control_size; @@ -468,14 +454,12 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) uvc_control_desc = uvc->desc.ss_control; uvc_streaming_cls = uvc->desc.ss_streaming; uvc_streaming_std = uvc_ss_streaming; - uvc_control_ep = &uvc_ss_control_ep; break; case USB_SPEED_HIGH: uvc_control_desc = uvc->desc.fs_control; uvc_streaming_cls = uvc->desc.hs_streaming; uvc_streaming_std = uvc_hs_streaming; - uvc_control_ep = &uvc_fs_control_ep; break; case USB_SPEED_FULL: @@ -483,7 +467,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) uvc_control_desc = uvc->desc.fs_control; uvc_streaming_cls = uvc->desc.fs_streaming; uvc_streaming_std = uvc_fs_streaming; - uvc_control_ep = &uvc_fs_control_ep; break; } @@ -494,6 +477,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) * Class-specific UVC control descriptors * uvc_control_ep * uvc_control_cs_ep + * uvc_ss_control_comp (for SS only) * uvc_streaming_intf_alt0 * Class-specific UVC streaming descriptors * uvc_{fs|hs}_streaming @@ -503,7 +487,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) control_size = 0; streaming_size = 0; bytes = uvc_iad.bLength + uvc_control_intf.bLength - + uvc_control_ep->bLength + uvc_control_cs_ep.bLength + + uvc_control_ep.bLength + uvc_control_cs_ep.bLength + uvc_streaming_intf_alt0.bLength; if (speed == USB_SPEED_SUPER) { @@ -549,7 +533,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) uvc_control_header->bInCollection = 1; uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf; - UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep); + UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep); if (speed == USB_SPEED_SUPER) UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp); @@ -619,7 +603,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc_fs_streaming_ep.bInterval = streaming_interval; /* Allocate endpoints. */ - ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep); + ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); if (!ep) { INFO(cdev, "Unable to allocate control EP\n"); goto error; From 20777dde026eb4b915ce577f830231c00c3f9292 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 1 Mar 2013 20:46:26 +0100 Subject: [PATCH 201/303] usb: gadget: uvc: Merge the streaming maxpacket and mult parameters Compute the multiplier from the maximum packet size based on the speed. Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 120 ++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 8e4827c3afb5..7189dbe20014 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -33,19 +33,15 @@ unsigned int uvc_gadget_trace_param; /*-------------------------------------------------------------------------*/ /* module parameters specific to the Video streaming endpoint */ -static unsigned streaming_interval = 1; +static unsigned int streaming_interval = 1; module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(streaming_interval, "1 - 16"); -static unsigned streaming_maxpacket = 1024; +static unsigned int streaming_maxpacket = 1024; module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)"); +MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)"); -static unsigned streaming_mult; -module_param(streaming_mult, uint, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)"); - -static unsigned streaming_maxburst; +static unsigned int streaming_maxburst; module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); @@ -158,8 +154,11 @@ static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .wMaxPacketSize = cpu_to_le16(512), - .bInterval = 1, + /* The wMaxPacketSize and bInterval values will be initialized from + * module parameters. + */ + .wMaxPacketSize = 0, + .bInterval = 0, }; static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { @@ -167,8 +166,11 @@ static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .wMaxPacketSize = cpu_to_le16(1024), - .bInterval = 1, + /* The wMaxPacketSize and bInterval values will be initialized from + * module parameters. + */ + .wMaxPacketSize = 0, + .bInterval = 0, }; static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { @@ -177,8 +179,11 @@ static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_ISOC, - .wMaxPacketSize = cpu_to_le16(1024), - .bInterval = 4, + /* The wMaxPacketSize and bInterval values will be initialized from + * module parameters. + */ + .wMaxPacketSize = 0, + .bInterval = 0, }; static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = { @@ -579,29 +584,50 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct uvc_device *uvc = to_uvc(f); + unsigned int max_packet_mult; + unsigned int max_packet_size; struct usb_ep *ep; int ret = -EINVAL; INFO(cdev, "uvc_function_bind\n"); - /* sanity check the streaming endpoint module parameters */ - if (streaming_interval < 1) - streaming_interval = 1; - if (streaming_interval > 16) - streaming_interval = 16; - if (streaming_mult > 2) - streaming_mult = 2; - if (streaming_maxburst > 15) - streaming_maxburst = 15; - - /* - * fill in the FS video streaming specific descriptors from the - * module parameters + /* Sanity check the streaming endpoint module parameters. */ - uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ? - 1023 : streaming_maxpacket; + streaming_interval = clamp(streaming_interval, 1U, 16U); + streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U); + streaming_maxburst = min(streaming_maxburst, 15U); + + /* Fill in the FS/HS/SS Video Streaming specific descriptors from the + * module parameters. + * + * NOTE: We assume that the user knows what they are doing and won't + * give parameters that their UDC doesn't support. + */ + if (streaming_maxpacket <= 1024) { + max_packet_mult = 1; + max_packet_size = streaming_maxpacket; + } else if (streaming_maxpacket <= 2048) { + max_packet_mult = 2; + max_packet_size = streaming_maxpacket / 2; + } else { + max_packet_mult = 3; + max_packet_size = streaming_maxpacket / 3; + } + + uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U); uvc_fs_streaming_ep.bInterval = streaming_interval; + uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size; + uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11); + uvc_hs_streaming_ep.bInterval = streaming_interval; + + uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size; + uvc_ss_streaming_ep.bInterval = streaming_interval; + uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; + uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; + uvc_ss_streaming_comp.wBytesPerInterval = + max_packet_size * max_packet_mult * streaming_maxburst; + /* Allocate endpoints. */ ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); if (!ep) { @@ -619,6 +645,11 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc->video.ep = ep; ep->driver_data = uvc; + uvc_hs_streaming_ep.bEndpointAddress = + uvc_fs_streaming_ep.bEndpointAddress; + uvc_ss_streaming_ep.bEndpointAddress = + uvc_fs_streaming_ep.bEndpointAddress; + /* Allocate interface IDs. */ if ((ret = usb_interface_id(c, f)) < 0) goto error; @@ -632,37 +663,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc_streaming_intf_alt1.bInterfaceNumber = ret; uvc->streaming_intf = ret; - /* sanity check the streaming endpoint module parameters */ - if (streaming_maxpacket > 1024) - streaming_maxpacket = 1024; - /* - * Fill in the HS descriptors from the module parameters for the Video - * Streaming endpoint. - * NOTE: We assume that the user knows what they are doing and won't - * give parameters that their UDC doesn't support. - */ - uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket; - uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11; - uvc_hs_streaming_ep.bInterval = streaming_interval; - uvc_hs_streaming_ep.bEndpointAddress = - uvc_fs_streaming_ep.bEndpointAddress; - - /* - * Fill in the SS descriptors from the module parameters for the Video - * Streaming endpoint. - * NOTE: We assume that the user knows what they are doing and won't - * give parameters that their UDC doesn't support. - */ - uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket; - uvc_ss_streaming_ep.bInterval = streaming_interval; - uvc_ss_streaming_comp.bmAttributes = streaming_mult; - uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; - uvc_ss_streaming_comp.wBytesPerInterval = - streaming_maxpacket * (streaming_mult + 1) * - (streaming_maxburst + 1); - uvc_ss_streaming_ep.bEndpointAddress = - uvc_fs_streaming_ep.bEndpointAddress; - /* Copy descriptors */ f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); if (gadget_is_dualspeed(cdev->gadget)) From 0485ec0d3ba9ce96ab5064b05a06e672c9d2c973 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 1 Mar 2013 20:46:27 +0100 Subject: [PATCH 202/303] usb: gadget: uvc: Configure the streaming endpoint based on the speed Call the appropriate usb_ep_autoconf*() function depending on the device speed, and pass it the corresponding streaming endpoint. Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 7189dbe20014..87b5306d1255 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -549,8 +549,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) UVC_COPY_DESCRIPTORS(mem, dst, (const struct usb_descriptor_header**)uvc_streaming_cls); uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size); - uvc_streaming_header->bEndpointAddress = - uvc_fs_streaming_ep.bEndpointAddress; + uvc_streaming_header->bEndpointAddress = uvc->video.ep->address; UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std); @@ -637,7 +636,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc->control_ep = ep; ep->driver_data = uvc; - ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); + if (gadget_is_superspeed(c->cdev->gadget)) + ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep, + &uvc_ss_streaming_comp); + else if (gadget_is_dualspeed(cdev->gadget)) + ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep); + else + ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); + if (!ep) { INFO(cdev, "Unable to allocate streaming EP\n"); goto error; @@ -645,10 +651,9 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc->video.ep = ep; ep->driver_data = uvc; - uvc_hs_streaming_ep.bEndpointAddress = - uvc_fs_streaming_ep.bEndpointAddress; - uvc_ss_streaming_ep.bEndpointAddress = - uvc_fs_streaming_ep.bEndpointAddress; + uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; + uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; + uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; /* Allocate interface IDs. */ if ((ret = usb_interface_id(c, f)) < 0) From 609a0532a4d713819092a9311ffe89faa6bac617 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Fri, 1 Mar 2013 20:46:28 +0100 Subject: [PATCH 203/303] usb: gadget: uvc: Add fix for UVC compliance test suite assertion 6.3.90 failure As per UVC compliance test specification's assertion number 6.3.90 related to 'Standard VS Isochronous Video Data Endpoint Descriptor Assertions', the bits D3..2 of 'bmAttributes' field of Standard VS Isochronous Video Data Endpoint Descriptor should be 01 (binary) to indicate that the synchronization type is ASYNCHRONOUS. This mandatory requirement has been captured in section 3.10.1.1 of the UVC Video Class Specification version 1.1 This patch adds a fix for the same. Signed-off-by: Bhupesh Sharma Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 87b5306d1255..76ec10fa5f2b 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -153,7 +153,8 @@ static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .bmAttributes = USB_ENDPOINT_SYNC_ASYNC + | USB_ENDPOINT_XFER_ISOC, /* The wMaxPacketSize and bInterval values will be initialized from * module parameters. */ @@ -165,7 +166,8 @@ static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .bmAttributes = USB_ENDPOINT_SYNC_ASYNC + | USB_ENDPOINT_XFER_ISOC, /* The wMaxPacketSize and bInterval values will be initialized from * module parameters. */ @@ -178,7 +180,8 @@ static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_ISOC, + .bmAttributes = USB_ENDPOINT_SYNC_ASYNC + | USB_ENDPOINT_XFER_ISOC, /* The wMaxPacketSize and bInterval values will be initialized from * module parameters. */ From 43ff05e20c6e2428fe2deb1dc0fed008743e66a3 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Fri, 1 Mar 2013 20:46:29 +0100 Subject: [PATCH 204/303] usb: gadget: uvc: Add fix for UVC compliance test suite's assertion 6.1.25 failure As per the UVC compliance test suite's assertion 6.1.25, the `iFunction` field of the Interface Association Descriptor (IAD) should the match the `iInterface` field of the standard Video Control (VC) Interface Descriptor for this Video Interface Collection (VIC). This mandatory case is captured in section 3.11 of the USB Video Class Compliance specification revision 1.1 This patch fixes this test assertion's failure and has been tested on Linux FC16, WinXP, WIN7 and WIN8 High speed and Super Speed hosts for successful enumeration. Signed-off-by: Bhupesh Sharma [Merged the association and control string descriptors] Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 76ec10fa5f2b..49939e44ed74 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -51,13 +51,11 @@ MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); /* string IDs are assigned dynamically */ -#define UVC_STRING_ASSOCIATION_IDX 0 -#define UVC_STRING_CONTROL_IDX 1 -#define UVC_STRING_STREAMING_IDX 2 +#define UVC_STRING_CONTROL_IDX 0 +#define UVC_STRING_STREAMING_IDX 1 static struct usb_string uvc_en_us_strings[] = { - [UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera", - [UVC_STRING_CONTROL_IDX].s = "Video Control", + [UVC_STRING_CONTROL_IDX].s = "UVC Camera", [UVC_STRING_STREAMING_IDX].s = "Video Streaming", { } }; @@ -572,7 +570,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) uvc->control_ep->driver_data = NULL; uvc->video.ep->driver_data = NULL; - uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0; + uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0; usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); kfree(uvc->control_buf); @@ -796,12 +794,12 @@ uvc_bind_config(struct usb_configuration *c, * for the first UVC function. UVC functions beyond the first (if any) * will reuse the same IDs. */ - if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) { + if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) { ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings); if (ret) goto error; uvc_iad.iFunction = - uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id; + uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id; uvc_control_intf.iInterface = uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id; ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id; From 41837c352fd8d804dbe978c29e57ec8217df1d51 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Fri, 1 Mar 2013 20:46:30 +0100 Subject: [PATCH 205/303] usb: gadget: uvc: Delay the status stage when setting alternate setting 1 This patch adds the support in UVC webcam gadget design for providing USB_GADGET_DELAYED_STATUS in response to a set_interface(alt setting 1) command issue by the Host. The current UVC webcam gadget design generates a STREAMON event corresponding to a set_interface(alt setting 1) command from the Host. This STREAMON event will eventually be routed to a real V4L2 device. To start video streaming, it may be required to perform some register writes to a camera sensor device over slow external busses like I2C or SPI. So, it makes sense to ensure that we delay the STATUS stage of the set_interface (alt setting 1) command. Otherwise, a lot of ISOC IN tokens sent by the Host will be replied to by zero-length packets by the webcam device. On certain Hosts this may even lead to ISOC URBs been cancelled from the Host side. So, as soon as we finish doing all the "streaming" related stuff on the real V4L2 device, we call a STREAMON ioctl on the UVC side and from here we call the 'usb_composite_setup_continue' function to complete the status stage of the set_interface(alt setting 1) command. Further, we need to ensure that we queue no video buffers on the UVC webcam gadget, until we de-queue a video buffer from the V4L2 device. So, the application should call the STREAMON on UVC side only when it has dequeued sufficient buffers from the V4L2 side and queued them to the UVC gadget. Signed-off-by: Bhupesh Sharma Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_uvc.c | 15 +++++++++------ drivers/usb/gadget/uvc.h | 1 + drivers/usb/gadget/uvc_v4l2.c | 14 +++++++++++++- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 49939e44ed74..38dcedddc52c 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -266,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) return 0; } +void uvc_function_setup_continue(struct uvc_device *uvc) +{ + struct usb_composite_dev *cdev = uvc->func.config->cdev; + + usb_composite_setup_continue(cdev); +} + static int uvc_function_get_alt(struct usb_function *f, unsigned interface) { @@ -328,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) v4l2_event_queue(uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_CONNECTED; - break; + return 0; case 1: if (uvc->state != UVC_STATE_CONNECTED) @@ -345,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMON; v4l2_event_queue(uvc->vdev, &v4l2_event); - - uvc->state = UVC_STATE_STREAMING; - break; + return USB_GADGET_DELAYED_STATUS; default: return -EINVAL; } - - return 0; } static void diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index 7e90b1d12d09..817e9e19cecf 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -188,6 +188,7 @@ struct uvc_file_handle * Functions */ +extern void uvc_function_setup_continue(struct uvc_device *uvc); extern void uvc_endpoint_stream(struct uvc_device *dev); extern void uvc_function_connect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index 0080d073bd5e..2bb5af8d2b23 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -253,7 +253,19 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (*type != video->queue.type) return -EINVAL; - return uvc_video_enable(video, 1); + /* Enable UVC video. */ + ret = uvc_video_enable(video, 1); + if (ret < 0) + return ret; + + /* + * Complete the alternate setting selection setup phase now that + * userspace is ready to provide video frames. + */ + uvc_function_setup_continue(uvc); + uvc->state = UVC_STATE_STREAMING; + + return 0; } case VIDIOC_STREAMOFF: From 326b0e613bc858434198120a17d34308f82c27a8 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Fri, 1 Mar 2013 20:46:31 +0100 Subject: [PATCH 206/303] usb: gadget: uvc: Make video streaming buffer size comply with USB3.0 SS As per the USB3.0 specs, the bandwidth requirements of a UVC's video streaming endpoint will change to support super-speed. These changes will be dependent on whether the UVC video streaming endpoint is Bulk or Isochronous: - If video streaming endpoint is Isochronous: As per Section 4.4.8.2 (Isochronous Transfer Bandwidth Requirements) of the USB3.0 specs: A SuperSpeed isochronous endpoint can move up to three burst transactions of up to 16 maximum sized packets (3 * 16 * 1024 bytes) per service interval. - If video streaming endpoint is Bulk: As per 4.4.6.1 (Bulk Transfer Data Packet Size) of the USB3.0 specs: An endpoint for bulk transfers shall set the maximum data packet payload size in its endpoint descriptor to 1024 bytes. It also specifies the burst size that the endpoint can accept from or transmit on the SuperSpeed bus. The allowable burst size for a bulk endpoint shall be in the range of 1 to 16. So, in the Isochronous case, we can define the USB request's buffer to be equal to = (Maximum packet size) * (bMaxBurst + 1) * (Mult + 1), so that the UDC driver can try to send out this buffer in one Isochronous service interval. The same computation will hold good for the Bulk case as the Mult value is 0 here and we can have a USB request buffer of maximum 16 * 1024 bytes size, which can be sent out by the UDC driver as per the Bulk bandwidth allocation on the USB3 bus. This patch adds the above-mentioned support and is also USB2.0 backward compliant. Signed-off-by: Bhupesh Sharma Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/uvc_video.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c index 885c393ee470..fac99a97b782 100644 --- a/drivers/usb/gadget/uvc_video.c +++ b/drivers/usb/gadget/uvc_video.c @@ -229,13 +229,18 @@ uvc_video_free_requests(struct uvc_video *video) static int uvc_video_alloc_requests(struct uvc_video *video) { + unsigned int req_size; unsigned int i; int ret = -ENOMEM; BUG_ON(video->req_size); + req_size = video->ep->maxpacket + * max_t(unsigned int, video->ep->maxburst, 1) + * (video->ep->mult + 1); + for (i = 0; i < UVC_NUM_REQUESTS; ++i) { - video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL); + video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL); if (video->req_buffer[i] == NULL) goto error; @@ -251,7 +256,8 @@ uvc_video_alloc_requests(struct uvc_video *video) list_add_tail(&video->req[i]->list, &video->req_free); } - video->req_size = video->ep->maxpacket; + video->req_size = req_size; + return 0; error: From 6854bcdc6ff92e3a9c24940a3c5ebb446950c974 Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Fri, 1 Mar 2013 20:46:32 +0100 Subject: [PATCH 207/303] usb: gadget: uvc: Use GFP_ATOMIC under spin lock Found using the following semantic patch: @@ @@ spin_lock_irqsave(...); ... when != spin_unlock_irqrestore(...); * GFP_KERNEL Signed-off-by: Cyril Roelandt Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/uvc_video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c index fac99a97b782..ec4bcc4a2290 100644 --- a/drivers/usb/gadget/uvc_video.c +++ b/drivers/usb/gadget/uvc_video.c @@ -314,7 +314,8 @@ uvc_video_pump(struct uvc_video *video) video->encode(req, video, buf); /* Queue the USB request */ - if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) { + ret = usb_ep_queue(video->ep, req, GFP_ATOMIC); + if (ret < 0) { printk(KERN_INFO "Failed to queue request (%d)\n", ret); usb_ep_set_halt(video->ep); spin_unlock_irqrestore(&video->queue.irqlock, flags); From c3ec830d8925d904f8826d52227d7dfb5dee922c Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Fri, 1 Mar 2013 20:46:33 +0100 Subject: [PATCH 208/303] usb: gadget: uvc: Use strlcpy instead of strncpy For NULL terminated string, better notice '\0' in the end. Signed-off-by: Chen Gang Signed-off-by: Laurent Pinchart Tested-by: Bhupesh Sharma Signed-off-by: Felipe Balbi --- drivers/usb/gadget/uvc_v4l2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index 2bb5af8d2b23..a6c728ab6aba 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -177,9 +177,9 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) struct v4l2_capability *cap = arg; memset(cap, 0, sizeof *cap); - strncpy(cap->driver, "g_uvc", sizeof(cap->driver)); - strncpy(cap->card, cdev->gadget->name, sizeof(cap->card)); - strncpy(cap->bus_info, dev_name(&cdev->gadget->dev), + strlcpy(cap->driver, "g_uvc", sizeof(cap->driver)); + strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card)); + strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev), sizeof cap->bus_info); cap->version = DRIVER_VERSION_NUMBER; cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; From eee44da0453cfe9125f4297e4244fe1d6fb1c653 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 7 Mar 2013 18:51:46 +0530 Subject: [PATCH 209/303] usb: musb: omap2430: replace *_* with *-* in property names No functional change. Replace *_* with *-* in property names of otg to follow the general convention. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/omap-usb.txt | 12 ++++++------ drivers/usb/musb/omap2430.c | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt index 1b9f55fd96c0..662f0f1d2315 100644 --- a/Documentation/devicetree/bindings/usb/omap-usb.txt +++ b/Documentation/devicetree/bindings/usb/omap-usb.txt @@ -8,10 +8,10 @@ OMAP MUSB GLUE and disconnect. - multipoint : Should be "1" indicating the musb controller supports multipoint. This is a MUSB configuration-specific setting. - - num_eps : Specifies the number of endpoints. This is also a + - num-eps : Specifies the number of endpoints. This is also a MUSB configuration-specific setting. Should be set to "16" - - ram_bits : Specifies the ram address size. Should be set to "12" - - interface_type : This is a board specific setting to describe the type of + - ram-bits : Specifies the ram address size. Should be set to "12" + - interface-type : This is a board specific setting to describe the type of interface between the controller and the phy. It should be "0" or "1" specifying ULPI and UTMI respectively. - mode : Should be "3" to represent OTG. "1" signifies HOST and "2" @@ -29,14 +29,14 @@ usb_otg_hs: usb_otg_hs@4a0ab000 { ti,hwmods = "usb_otg_hs"; ti,has-mailbox; multipoint = <1>; - num_eps = <16>; - ram_bits = <12>; + num-eps = <16>; + ram-bits = <12>; ctrl-module = <&omap_control_usb>; }; Board specific device node entry &usb_otg_hs { - interface_type = <1>; + interface-type = <1>; mode = <3>; power = <50>; }; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 8ba9bb2a91a7..e7b5eae5a141 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -526,10 +526,10 @@ static int omap2430_probe(struct platform_device *pdev) } of_property_read_u32(np, "mode", (u32 *)&pdata->mode); - of_property_read_u32(np, "interface_type", + of_property_read_u32(np, "interface-type", (u32 *)&data->interface_type); - of_property_read_u32(np, "num_eps", (u32 *)&config->num_eps); - of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits); + of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); + of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); of_property_read_u32(np, "power", (u32 *)&pdata->power); config->multipoint = of_property_read_bool(np, "multipoint"); pdata->has_mailbox = of_property_read_bool(np, From a33bb2120851407b5703343596d5c2181cfc75b4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Mar 2013 16:00:58 +0200 Subject: [PATCH 210/303] usb: dwc3: omap: fix sparse warning our global '_omap' pointer wasn't marked static. This patch solves the following sparse warning: warning: symbol '_omap' was not declared. \ Should it be static? Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 2fe9723ff1df..6de734f494bd 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -126,7 +126,7 @@ struct dwc3_omap { u32 dma_status:1; }; -struct dwc3_omap *_omap; +static struct dwc3_omap *_omap; static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset) { From a5eaaa1f33e771fa1651a4a7652b8a5f9fa7f6c1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 Mar 2013 11:01:05 +0300 Subject: [PATCH 211/303] usb: gadget: uvc: use capped length value "req->length" is a capped version of "data->length". Signed-off-by: Dan Carpenter Acked-by: Laurent Pinchart Signed-off-by: Felipe Balbi --- drivers/usb/gadget/uvc_v4l2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index a6c728ab6aba..bb140dd93164 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -42,7 +42,7 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) req->length = min_t(unsigned int, uvc->event_length, data->length); req->zero = data->length < uvc->event_length; - memcpy(req->buf, data->data, data->length); + memcpy(req->buf, data->data, req->length); return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL); } From bb467cf5693b59c76c22b73dd383920a87f37b16 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 14 Mar 2013 11:53:56 +0530 Subject: [PATCH 212/303] usb: musb: omap: remove the check before calling otg_set_vbus No functional change. otg_set_vbus is already protected so removed the check before calling otg_set_vbus. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/musb/omap2430.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index e7b5eae5a141..018373d1c2c4 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -174,8 +174,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) } } - if (otg->set_vbus) - otg_set_vbus(otg, 1); + otg_set_vbus(otg, 1); } else { musb->is_active = 1; otg->default_a = 1; @@ -296,10 +295,9 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) pm_runtime_put_autosuspend(dev); } - if (data->interface_type == MUSB_INTERFACE_UTMI) { - if (musb->xceiv->otg->set_vbus) - otg_set_vbus(musb->xceiv->otg, 0); - } + if (data->interface_type == MUSB_INTERFACE_UTMI) + otg_set_vbus(musb->xceiv->otg, 0); + omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DISCONNECT); break; From 3bf6db9bbe4ad7b08b714c1857a703c1ef1b1e83 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 14 Mar 2013 11:53:58 +0530 Subject: [PATCH 213/303] usb: musb: omap: add usb_phy_init in omap2430_musb_init Some PHYs load too early (twl4030) making omap glue to miss cable connect events if the board is booted with cable connected. So adding usb_phy_init in omap2430_musb_init lets PHYs to report events once glue is ready. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/musb/omap2430.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 018373d1c2c4..ec460eaed842 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -391,6 +391,8 @@ static int omap2430_musb_init(struct musb *musb) if (glue->status != OMAP_MUSB_UNKNOWN) omap_musb_set_mailbox(glue); + usb_phy_init(musb->xceiv); + pm_runtime_put_noidle(musb->controller); return 0; From b7fa5c2aec5be083eb2719b405089703608e9bc6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 14 Mar 2013 17:59:06 +0200 Subject: [PATCH 214/303] usb: phy: return -ENXIO when PHY layer isn't enabled in cases where PHY layer isn't enabled, we want to still return an error code (actually an error pointer) so that our users don't need to cope with either error pointer of NULL. This will simplify users as below: - return IS_ERR(phy) ? PTR_ERR(phy) : -ENODEV; + return PTR_ERR(phy); Acked-by: Kishon Vijay Abraham I Reported-by: Alan Stern Signed-off-by: Felipe Balbi --- include/linux/usb/phy.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index b7c2217c585f..6b5978f57633 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -197,29 +197,29 @@ extern int usb_bind_phy(const char *dev_name, u8 index, #else static inline struct usb_phy *usb_get_phy(enum usb_phy_type type) { - return NULL; + return ERR_PTR(-ENXIO); } static inline struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type) { - return NULL; + return ERR_PTR(-ENXIO); } static inline struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) { - return NULL; + return ERR_PTR(-ENXIO); } static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index) { - return NULL; + return ERR_PTR(-ENXIO); } static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, const char *phandle, u8 index) { - return NULL; + return ERR_PTR(-ENXIO); } static inline void usb_put_phy(struct usb_phy *x) From 9166902c435b4847c1987188294407b24e76d9e6 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Fri, 15 Mar 2013 18:58:51 +0530 Subject: [PATCH 215/303] usb: phy: twl4030: use devres API for regulator get and request irq Used devres APIs devm_request_threaded_irq and devm_regulator_get for requesting irq and for getting regulator respectively. Signed-off-by: Kishon Vijay Abraham I Tested-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl4030-usb.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index a994715a3101..e14b03e7ad70 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -432,7 +432,7 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl) /* Initialize 3.1V regulator */ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); - twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); + twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1"); if (IS_ERR(twl->usb3v1)) return -ENODEV; @@ -441,18 +441,18 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl) /* Initialize 1.5V regulator */ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); - twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); + twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5"); if (IS_ERR(twl->usb1v5)) - goto fail1; + return -ENODEV; twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); /* Initialize 1.8V regulator */ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); - twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); + twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8"); if (IS_ERR(twl->usb1v8)) - goto fail2; + return -ENODEV; twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); @@ -461,14 +461,6 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl) TWL4030_PM_MASTER_PROTECT_KEY); return 0; - -fail2: - regulator_put(twl->usb1v5); - twl->usb1v5 = NULL; -fail1: - regulator_put(twl->usb3v1); - twl->usb3v1 = NULL; - return -ENODEV; } static ssize_t twl4030_usb_vbus_show(struct device *dev, @@ -640,9 +632,9 @@ static int twl4030_usb_probe(struct platform_device *pdev) * need both handles, otherwise just one suffices. */ twl->irq_enabled = true; - status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | - IRQF_ONESHOT, "twl4030_usb", twl); + status = devm_request_threaded_irq(twl->dev, twl->irq, NULL, + twl4030_usb_irq, IRQF_TRIGGER_FALLING | + IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl); if (status < 0) { dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", twl->irq, status); @@ -663,7 +655,6 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; - free_irq(twl->irq, twl); device_remove_file(twl->dev, &dev_attr_vbus); /* set transceiver mode to power on defaults */ @@ -685,9 +676,6 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) if (!twl->asleep) twl4030_phy_power(twl, 0); - regulator_put(twl->usb1v5); - regulator_put(twl->usb1v8); - regulator_put(twl->usb3v1); return 0; } From 817e5f33d0c12f24bdfebe88c96ca2e968756da4 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Fri, 15 Mar 2013 18:58:52 +0530 Subject: [PATCH 216/303] usb: phy: twl4030: fix cold plug on OMAP3 Having twl4030_usb_phy_init() (detects if a cable is connected before twl4030 is probed) in twl4030 probe makes cable connect events to be missed by musb glue, since it gets loaded after twl4030. Having twl4030_usb_phy_init as a usb_phy ops lets twl4030_usb_phy_init to be called when glue is ready. Signed-off-by: Kishon Vijay Abraham I Tested-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl4030-usb.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index e14b03e7ad70..1986c782346f 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -510,8 +510,9 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) return IRQ_HANDLED; } -static void twl4030_usb_phy_init(struct twl4030_usb *twl) +static int twl4030_usb_phy_init(struct usb_phy *phy) { + struct twl4030_usb *twl = phy_to_twl(phy); enum omap_musb_vbus_id_status status; status = twl4030_usb_linkstat(twl); @@ -528,6 +529,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl) omap_musb_mailbox(twl->linkstat); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); + return 0; } static int twl4030_set_suspend(struct usb_phy *x, int suspend) @@ -604,6 +606,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) twl->phy.otg = otg; twl->phy.type = USB_PHY_TYPE_USB2; twl->phy.set_suspend = twl4030_set_suspend; + twl->phy.init = twl4030_usb_phy_init; otg->phy = &twl->phy; otg->set_host = twl4030_set_host; @@ -641,11 +644,6 @@ static int twl4030_usb_probe(struct platform_device *pdev) return status; } - /* Power down phy or make it work according to - * current link state. - */ - twl4030_usb_phy_init(twl); - dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); return 0; } From d105e7f86f890a530cdefc2a715121345de30dc2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 15 Mar 2013 10:52:08 +0200 Subject: [PATCH 217/303] usb: dwc3: fix PHY error handling PHY layer no longer returns NULL. It will return -ENXIO when PHY layer isn't enabled and we can use that to bail out instead of request a probe deferral. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c845e7087069..e2325adf9c14 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -434,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev) dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); } - if (IS_ERR_OR_NULL(dwc->usb2_phy)) { + if (IS_ERR(dwc->usb2_phy)) { + ret = PTR_ERR(dwc->usb2_phy); + + /* + * if -ENXIO is returned, it means PHY layer wasn't + * enabled, so it makes no sense to return -EPROBE_DEFER + * in that case, since no PHY driver will ever probe. + */ + if (ret == -ENXIO) + return ret; + dev_err(dev, "no usb2 phy configured\n"); return -EPROBE_DEFER; } - if (IS_ERR_OR_NULL(dwc->usb3_phy)) { + if (IS_ERR(dwc->usb3_phy)) { + ret = PTR_ERR(dwc->usb2_phy); + + /* + * if -ENXIO is returned, it means PHY layer wasn't + * enabled, so it makes no sense to return -EPROBE_DEFER + * in that case, since no PHY driver will ever probe. + */ + if (ret == -ENXIO) + return ret; + dev_err(dev, "no usb3 phy configured\n"); return -EPROBE_DEFER; } From 4dbb71612505de1d3d69d011199554f86273c5e9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 15 Mar 2013 10:54:59 +0200 Subject: [PATCH 218/303] usb: gadget: mv_udc_core: fix PHY error handling PHY layer no longer returns NULL. It will return -ENXIO when PHY layer isn't enabled and we can use that to bail out instead of request a probe deferral. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc_core.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index d550b2129133..9a68c051a5a8 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2127,16 +2127,19 @@ static int mv_udc_probe(struct platform_device *pdev) udc->dev = pdev; -#if IS_ENABLED(CONFIG_USB_PHY) if (pdata->mode == MV_USB_MODE_OTG) { udc->transceiver = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(udc->transceiver)) { + if (IS_ERR(udc->transceiver)) { + retval = PTR_ERR(udc->transceiver); + + if (retval == -ENXIO) + return retval; + udc->transceiver = NULL; - return -ENODEV; + return -EPROBE_DEFER; } } -#endif udc->clknum = pdata->clknum; for (clk_i = 0; clk_i < udc->clknum; clk_i++) { From f4f5ba5e7d9e087f044fe87f5a5421761274aa48 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 15 Mar 2013 10:56:19 +0200 Subject: [PATCH 219/303] usb: gadget: s3c-hsotg: fix PHY error handling PHY laye rno longer return NULL. We need to switch over from IS_ERR_OR_NULL() to IS_ERR(). Signed-off-by: Felipe Balbi --- drivers/usb/gadget/s3c-hsotg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index f1ceabff7cce..a3cdc32115d5 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3467,7 +3467,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev) } phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(phy)) { + if (IS_ERR(phy)) { /* Fallback for pdata */ plat = pdev->dev.platform_data; if (!plat) { From a90199bb947856c24d7bf78845d24f802e09db0a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 15 Mar 2013 10:57:40 +0200 Subject: [PATCH 220/303] usb: musb: omap2430: fix PHY error handling PHY layer no longer returns NULL. It will return -ENXIO when PHY layer isn't enabled and we can use that to bail out instead of request a probe deferral. Signed-off-by: Felipe Balbi --- drivers/usb/musb/omap2430.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index ec460eaed842..798e029e3db0 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -353,7 +353,12 @@ static int omap2430_musb_init(struct musb *musb) else musb->xceiv = devm_usb_get_phy_dev(dev, 0); - if (IS_ERR_OR_NULL(musb->xceiv)) { + if (IS_ERR(musb->xceiv)) { + status = PTR_ERR(musb->xceiv); + + if (status == -ENXIO) + return status; + pr_err("HS USB OTG: no transceiver configured\n"); return -EPROBE_DEFER; } From e299bd93e4fb8e3fa426d30e0a0796b99052a572 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 15 Mar 2013 11:02:56 +0200 Subject: [PATCH 221/303] usb: host: ehci-msm: fix PHY error handling PHY layer no longer returns NULL. We must switch from IS_ERR_OR_NULL() to IS_ERR(). Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-msm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 88a49c87e748..ebf410311957 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -145,7 +145,7 @@ static int ehci_msm_probe(struct platform_device *pdev) * management. */ phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(phy)) { + if (IS_ERR(phy)) { dev_err(&pdev->dev, "unable to find transceiver\n"); ret = -ENODEV; goto put_hcd; From 6f3ed4ec182d191d1ba48fbf5aed021d2d00dd37 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 15 Mar 2013 11:03:30 +0200 Subject: [PATCH 222/303] usb: host: ehci-mv: fix PHY error handling PHY layer no longer returns NULL. We must switch from IS_ERR_OR_NULL() to IS_ERR(). Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-mv.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 9751823395e1..38048200977c 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -240,12 +240,16 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->mode = pdata->mode; if (ehci_mv->mode == MV_USB_MODE_OTG) { -#if IS_ENABLED(CONFIG_USB_PHY) ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(ehci_mv->otg)) { - dev_err(&pdev->dev, - "unable to find transceiver\n"); - retval = -ENODEV; + if (IS_ERR(ehci_mv->otg)) { + retval = PTR_ERR(ehci_mv->otg); + + if (retval == -ENXIO) + dev_info(&pdev->dev, "MV_USB_MODE_OTG " + "must have CONFIG_USB_PHY enabled\n"); + else + dev_err(&pdev->dev, + "unable to find transceiver\n"); goto err_disable_clk; } @@ -258,11 +262,6 @@ static int mv_ehci_probe(struct platform_device *pdev) } /* otg will enable clock before use as host */ mv_ehci_disable(ehci_mv); -#else - dev_info(&pdev->dev, "MV_USB_MODE_OTG " - "must have CONFIG_USB_PHY enabled\n"); - goto err_disable_clk; -#endif } else { if (pdata->set_vbus) pdata->set_vbus(1); From a16283e11d4443430b826c7b131a244e494ac53c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 15 Mar 2013 11:04:15 +0200 Subject: [PATCH 223/303] usb: host: ehci-s5p: fix PHY error handling PHY layer no longer returns NULL. We must switch from IS_ERR_OR_NULL() to IS_ERR(). Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-s5p.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 20ebf6a8b7f4..867a92390ef9 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -139,7 +139,7 @@ static int s5p_ehci_probe(struct platform_device *pdev) return -ENOMEM; phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(phy)) { + if (IS_ERR(phy)) { /* Fallback to pdata */ if (!pdata) { dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); From 9ee1c7fbeab5b671d3b63f2dd33ad48235efcfe8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 15 Mar 2013 11:05:03 +0200 Subject: [PATCH 224/303] usb: host: ohci-exynos: fix PHY error handling PHY layer no longer returns NULL. We must switch from IS_ERR_OR_NULL() to IS_ERR(). Signed-off-by: Felipe Balbi --- drivers/usb/host/ohci-exynos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index e3b7e85120e4..4b469e050208 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -128,7 +128,7 @@ static int exynos_ohci_probe(struct platform_device *pdev) return -ENOMEM; phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); - if (IS_ERR_OR_NULL(phy)) { + if (IS_ERR(phy)) { /* Fallback to pdata */ if (!pdata) { dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); From 399e0f4f00adbfdea2122c1daec0d4015f56cc7a Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Fri, 8 Mar 2013 10:27:05 +0800 Subject: [PATCH 225/303] usb: musb: ux500_dma: add missing MEM resource check Fix dma_controller_create() fail path in case memory resource is missing. Acked-by: Linus Walleij Signed-off-by: Virupax Sadashivpetimath Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/musb/ux500_dma.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index c3a584cf01bb..2df9b7d1ddc6 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -374,12 +374,17 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba controller = kzalloc(sizeof(*controller), GFP_KERNEL); if (!controller) - return NULL; + goto kzalloc_fail; controller->private_data = musb; /* Save physical address for DMA controller. */ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!iomem) { + dev_err(musb->controller, "no memory resource defined\n"); + goto plat_get_fail; + } + controller->phy_base = (dma_addr_t) iomem->start; controller->controller.start = ux500_dma_controller_start; @@ -391,4 +396,9 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba controller->controller.is_compatible = ux500_dma_is_compatible; return &controller->controller; + +plat_get_fail: + kfree(controller); +kzalloc_fail: + return NULL; } From 996a9d26d37c7dca27b7e9830a49daa74a2603b7 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Fri, 8 Mar 2013 10:27:06 +0800 Subject: [PATCH 226/303] usb: musb: ux500: implement musb_set_vbus Add ux500_musb_set_vbus() implementation for ux500. This is based on the version originally developed inside ST-Ericsson. Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri [ balbi@ti.com: fix a build error due to missing otg_state_string() ] Signed-off-by: Felipe Balbi --- drivers/usb/musb/ux500.c | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 13a392913769..0332fcd286f7 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -36,6 +36,68 @@ struct ux500_glue { }; #define glue_to_musb(g) platform_get_drvdata(g->musb) +static void ux500_musb_set_vbus(struct musb *musb, int is_on) +{ + u8 devctl; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + /* HDRC controls CPEN, but beware current surges during device + * connect. They can trigger transient overcurrent conditions + * that must be ignored. + */ + + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + + if (is_on) { + if (musb->xceiv->state == OTG_STATE_A_IDLE) { + /* start the session */ + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + /* + * Wait for the musb to set as A device to enable the + * VBUS + */ + while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) { + + if (time_after(jiffies, timeout)) { + dev_err(musb->controller, + "configured as A device timeout"); + break; + } + } + + } else { + musb->is_active = 1; + musb->xceiv->otg->default_a = 1; + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; + devctl |= MUSB_DEVCTL_SESSION; + MUSB_HST_MODE(musb); + } + } else { + musb->is_active = 0; + + /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping + * right to B_IDLE... + */ + musb->xceiv->otg->default_a = 0; + devctl &= ~MUSB_DEVCTL_SESSION; + MUSB_DEV_MODE(musb); + } + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + + /* + * Devctl values will be updated after vbus goes below + * session_valid. The time taken depends on the capacitance + * on VBUS line. The max discharge time can be upto 1 sec + * as per the spec. Typically on our platform, it is 200ms + */ + if (!is_on) + mdelay(200); + + dev_dbg(musb->controller, "VBUS %s, devctl %02x\n", + usb_otg_state_string(musb->xceiv->state), + musb_readb(musb->mregs, MUSB_DEVCTL)); +} + static irqreturn_t ux500_musb_interrupt(int irq, void *__hci) { unsigned long flags; @@ -79,6 +141,8 @@ static int ux500_musb_exit(struct musb *musb) static const struct musb_platform_ops ux500_ops = { .init = ux500_musb_init, .exit = ux500_musb_exit, + + .set_vbus = ux500_musb_set_vbus, }; static int ux500_probe(struct platform_device *pdev) From 0135522c48982cf1d456d863272e911fdf8a17da Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Fri, 8 Mar 2013 10:27:07 +0800 Subject: [PATCH 227/303] usb: musb: ux500: add otg notifier support Add transceiver notifier event handling to the ux500 driver to set vbus on specific transceiver events. Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri [ balbi@ti.com: fix build error due to missing otg_state_string() ] Signed-off-by: Felipe Balbi --- drivers/usb/musb/ux500.c | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 0332fcd286f7..0ae9472a68a8 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -98,6 +98,37 @@ static void ux500_musb_set_vbus(struct musb *musb, int is_on) musb_readb(musb->mregs, MUSB_DEVCTL)); } +static int musb_otg_notifications(struct notifier_block *nb, + unsigned long event, void *unused) +{ + struct musb *musb = container_of(nb, struct musb, nb); + + dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n", + event, usb_otg_state_string(musb->xceiv->state)); + + switch (event) { + case USB_EVENT_ID: + dev_dbg(musb->controller, "ID GND\n"); + ux500_musb_set_vbus(musb, 1); + break; + case USB_EVENT_VBUS: + dev_dbg(musb->controller, "VBUS Connect\n"); + ux500_musb_set_vbus(musb, 0); + break; + case USB_EVENT_NONE: + dev_dbg(musb->controller, "VBUS Disconnect\n"); + if (is_host_active(musb)) + ux500_musb_set_vbus(musb, 0); + else + musb->xceiv->state = OTG_STATE_B_IDLE; + break; + default: + dev_dbg(musb->controller, "ID float\n"); + return NOTIFY_DONE; + } + return NOTIFY_OK; +} + static irqreturn_t ux500_musb_interrupt(int irq, void *__hci) { unsigned long flags; @@ -120,12 +151,21 @@ static irqreturn_t ux500_musb_interrupt(int irq, void *__hci) static int ux500_musb_init(struct musb *musb) { + int status; + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) { pr_err("HS USB OTG: no transceiver configured\n"); return -EPROBE_DEFER; } + musb->nb.notifier_call = musb_otg_notifications; + status = usb_register_notifier(musb->xceiv, &musb->nb); + if (status < 0) { + dev_dbg(musb->controller, "notification register failed\n"); + return status; + } + musb->isr = ux500_musb_interrupt; return 0; @@ -133,6 +173,8 @@ static int ux500_musb_init(struct musb *musb) static int ux500_musb_exit(struct musb *musb) { + usb_unregister_notifier(musb->xceiv, &musb->nb); + usb_put_phy(musb->xceiv); return 0; From 73f226cbd79adb5f3f25ee14c18900bb4a9acd15 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Fri, 8 Mar 2013 10:27:08 +0800 Subject: [PATCH 228/303] usb: otg: ab8500-usb: drop support for ab8500 pre v2.0 AB8500 versions preceding 2.0 were only used internally by ST-Ericsson and are not supported anymore. This patch drops all v1.0 and v1.1 support code. Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 139 +++---------------------------- 1 file changed, 11 insertions(+), 128 deletions(-) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 2d86f26a0183..9f5e0e4ab02a 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -42,10 +42,8 @@ #define AB8500_BIT_WD_CTRL_ENABLE (1 << 0) #define AB8500_BIT_WD_CTRL_KICK (1 << 1) -#define AB8500_V1x_LINK_STAT_WAIT (HZ/10) #define AB8500_WD_KICK_DELAY_US 100 /* usec */ #define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */ -#define AB8500_WD_V10_DISABLE_DELAY_MS 100 /* ms */ /* Usb line status register */ enum ab8500_usb_link_status { @@ -70,16 +68,12 @@ enum ab8500_usb_link_status { struct ab8500_usb { struct usb_phy phy; struct device *dev; - int irq_num_id_rise; - int irq_num_id_fall; - int irq_num_vbus_rise; - int irq_num_vbus_fall; + struct ab8500 *ab8500; int irq_num_link_status; unsigned vbus_draw; struct delayed_work dwork; struct work_struct phy_dis_work; unsigned long link_status_wait; - int rev; }; static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) @@ -102,10 +96,7 @@ static void ab8500_usb_wd_workaround(struct ab8500_usb *ab) (AB8500_BIT_WD_CTRL_ENABLE | AB8500_BIT_WD_CTRL_KICK)); - if (ab->rev > 0x10) /* v1.1 v2.0 */ - udelay(AB8500_WD_V11_DISABLE_DELAY_US); - else /* v1.0 */ - msleep(AB8500_WD_V10_DISABLE_DELAY_MS); + udelay(AB8500_WD_V11_DISABLE_DELAY_US); abx500_set_register_interruptible(ab->dev, AB8500_SYS_CTRL2_BLOCK, @@ -225,29 +216,6 @@ static void ab8500_usb_delayed_work(struct work_struct *work) ab8500_usb_link_status_update(ab); } -static irqreturn_t ab8500_usb_v1x_common_irq(int irq, void *data) -{ - struct ab8500_usb *ab = (struct ab8500_usb *) data; - - /* Wait for link status to become stable. */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); - - return IRQ_HANDLED; -} - -static irqreturn_t ab8500_usb_v1x_vbus_fall_irq(int irq, void *data) -{ - struct ab8500_usb *ab = (struct ab8500_usb *) data; - - /* Link status will not be updated till phy is disabled. */ - ab8500_usb_peri_phy_dis(ab); - - /* Wait for link status to become stable. */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); - - return IRQ_HANDLED; -} - static irqreturn_t ab8500_usb_v20_irq(int irq, void *data) { struct ab8500_usb *ab = (struct ab8500_usb *) data; @@ -361,86 +329,7 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) static void ab8500_usb_irq_free(struct ab8500_usb *ab) { - if (ab->rev < 0x20) { - free_irq(ab->irq_num_id_rise, ab); - free_irq(ab->irq_num_id_fall, ab); - free_irq(ab->irq_num_vbus_rise, ab); - free_irq(ab->irq_num_vbus_fall, ab); - } else { - free_irq(ab->irq_num_link_status, ab); - } -} - -static int ab8500_usb_v1x_res_setup(struct platform_device *pdev, - struct ab8500_usb *ab) -{ - int err; - - ab->irq_num_id_rise = platform_get_irq_byname(pdev, "ID_WAKEUP_R"); - if (ab->irq_num_id_rise < 0) { - dev_err(&pdev->dev, "ID rise irq not found\n"); - return ab->irq_num_id_rise; - } - err = request_threaded_irq(ab->irq_num_id_rise, NULL, - ab8500_usb_v1x_common_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-id-rise", ab); - if (err < 0) { - dev_err(ab->dev, "request_irq failed for ID rise irq\n"); - goto fail0; - } - - ab->irq_num_id_fall = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); - if (ab->irq_num_id_fall < 0) { - dev_err(&pdev->dev, "ID fall irq not found\n"); - return ab->irq_num_id_fall; - } - err = request_threaded_irq(ab->irq_num_id_fall, NULL, - ab8500_usb_v1x_common_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-id-fall", ab); - if (err < 0) { - dev_err(ab->dev, "request_irq failed for ID fall irq\n"); - goto fail1; - } - - ab->irq_num_vbus_rise = platform_get_irq_byname(pdev, "VBUS_DET_R"); - if (ab->irq_num_vbus_rise < 0) { - dev_err(&pdev->dev, "VBUS rise irq not found\n"); - return ab->irq_num_vbus_rise; - } - err = request_threaded_irq(ab->irq_num_vbus_rise, NULL, - ab8500_usb_v1x_common_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-vbus-rise", ab); - if (err < 0) { - dev_err(ab->dev, "request_irq failed for Vbus rise irq\n"); - goto fail2; - } - - ab->irq_num_vbus_fall = platform_get_irq_byname(pdev, "VBUS_DET_F"); - if (ab->irq_num_vbus_fall < 0) { - dev_err(&pdev->dev, "VBUS fall irq not found\n"); - return ab->irq_num_vbus_fall; - } - err = request_threaded_irq(ab->irq_num_vbus_fall, NULL, - ab8500_usb_v1x_vbus_fall_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-vbus-fall", ab); - if (err < 0) { - dev_err(ab->dev, "request_irq failed for Vbus fall irq\n"); - goto fail3; - } - - return 0; -fail3: - free_irq(ab->irq_num_vbus_rise, ab); -fail2: - free_irq(ab->irq_num_id_fall, ab); -fail1: - free_irq(ab->irq_num_id_rise, ab); -fail0: - return err; + free_irq(ab->irq_num_link_status, ab); } static int ab8500_usb_v2_res_setup(struct platform_device *pdev, @@ -471,16 +360,16 @@ static int ab8500_usb_v2_res_setup(struct platform_device *pdev, static int ab8500_usb_probe(struct platform_device *pdev) { struct ab8500_usb *ab; + struct ab8500 *ab8500; struct usb_otg *otg; int err; int rev; + ab8500 = dev_get_drvdata(pdev->dev.parent); rev = abx500_get_chip_id(&pdev->dev); - if (rev < 0) { - dev_err(&pdev->dev, "Chip id read failed\n"); - return rev; - } else if (rev < 0x10) { - dev_err(&pdev->dev, "Unsupported AB8500 chip\n"); + + if (is_ab8500_1p1_or_earlier(ab8500)) { + dev_err(&pdev->dev, "Unsupported AB8500 chip rev=%d\n", rev); return -ENODEV; } @@ -495,7 +384,7 @@ static int ab8500_usb_probe(struct platform_device *pdev) } ab->dev = &pdev->dev; - ab->rev = rev; + ab->ab8500 = ab8500; ab->phy.dev = ab->dev; ab->phy.otg = otg; ab->phy.label = "ab8500"; @@ -519,13 +408,7 @@ static int ab8500_usb_probe(struct platform_device *pdev) /* all: Disable phy when called from set_host and set_peripheral */ INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); - if (ab->rev < 0x20) { - err = ab8500_usb_v1x_res_setup(pdev, ab); - ab->link_status_wait = AB8500_V1x_LINK_STAT_WAIT; - } else { - err = ab8500_usb_v2_res_setup(pdev, ab); - } - + err = ab8500_usb_v2_res_setup(pdev, ab); if (err < 0) goto fail0; @@ -535,7 +418,7 @@ static int ab8500_usb_probe(struct platform_device *pdev) goto fail1; } - dev_info(&pdev->dev, "AB8500 usb driver initialized\n"); + dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev); return 0; fail1: From af6882be363d3a7bf0f72dd17ac2a639c4da0059 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Fri, 8 Mar 2013 10:27:09 +0800 Subject: [PATCH 229/303] usb: phy: ab8500-usb: update irq handling code Update irq handling code to notify all possible link status changes of AB8500 and AB8505 to the ux500-musb glue driver. The additional event codes will be used for pm-runtime implementation, and are defined in a separate ux500-specific header. This also modify the irq registration code to use devm_* helpers and drop all non necessary fail path code. Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/musb/ux500.c | 7 +- drivers/usb/phy/phy-ab8500-usb.c | 448 ++++++++++++++++++++++++------- include/linux/usb/musb-ux500.h | 31 +++ 3 files changed, 386 insertions(+), 100 deletions(-) create mode 100644 include/linux/usb/musb-ux500.h diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 0ae9472a68a8..88795f532370 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "musb_core.h" @@ -107,15 +108,15 @@ static int musb_otg_notifications(struct notifier_block *nb, event, usb_otg_state_string(musb->xceiv->state)); switch (event) { - case USB_EVENT_ID: + case UX500_MUSB_ID: dev_dbg(musb->controller, "ID GND\n"); ux500_musb_set_vbus(musb, 1); break; - case USB_EVENT_VBUS: + case UX500_MUSB_VBUS: dev_dbg(musb->controller, "VBUS Connect\n"); ux500_musb_set_vbus(musb, 0); break; - case USB_EVENT_NONE: + case UX500_MUSB_NONE: dev_dbg(musb->controller, "VBUS Disconnect\n"); if (is_host_active(musb)) ux500_musb_set_vbus(musb, 0); diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 9f5e0e4ab02a..351b0369a611 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -31,9 +31,11 @@ #include #include #include +#include #define AB8500_MAIN_WD_CTRL_REG 0x01 #define AB8500_USB_LINE_STAT_REG 0x80 +#define AB8505_USB_LINE_STAT_REG 0x94 #define AB8500_USB_PHY_CTRL_REG 0x8A #define AB8500_BIT_OTG_STAT_ID (1 << 0) @@ -44,36 +46,76 @@ #define AB8500_WD_KICK_DELAY_US 100 /* usec */ #define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */ +#define AB8500_V20_31952_DISABLE_DELAY_US 100 /* usec */ /* Usb line status register */ enum ab8500_usb_link_status { - USB_LINK_NOT_CONFIGURED = 0, - USB_LINK_STD_HOST_NC, - USB_LINK_STD_HOST_C_NS, - USB_LINK_STD_HOST_C_S, - USB_LINK_HOST_CHG_NM, - USB_LINK_HOST_CHG_HS, - USB_LINK_HOST_CHG_HS_CHIRP, - USB_LINK_DEDICATED_CHG, - USB_LINK_ACA_RID_A, - USB_LINK_ACA_RID_B, - USB_LINK_ACA_RID_C_NM, - USB_LINK_ACA_RID_C_HS, - USB_LINK_ACA_RID_C_HS_CHIRP, - USB_LINK_HM_IDGND, - USB_LINK_RESERVED, - USB_LINK_NOT_VALID_LINK + USB_LINK_NOT_CONFIGURED_8500 = 0, + USB_LINK_STD_HOST_NC_8500, + USB_LINK_STD_HOST_C_NS_8500, + USB_LINK_STD_HOST_C_S_8500, + USB_LINK_HOST_CHG_NM_8500, + USB_LINK_HOST_CHG_HS_8500, + USB_LINK_HOST_CHG_HS_CHIRP_8500, + USB_LINK_DEDICATED_CHG_8500, + USB_LINK_ACA_RID_A_8500, + USB_LINK_ACA_RID_B_8500, + USB_LINK_ACA_RID_C_NM_8500, + USB_LINK_ACA_RID_C_HS_8500, + USB_LINK_ACA_RID_C_HS_CHIRP_8500, + USB_LINK_HM_IDGND_8500, + USB_LINK_RESERVED_8500, + USB_LINK_NOT_VALID_LINK_8500, +}; + +enum ab8505_usb_link_status { + USB_LINK_NOT_CONFIGURED_8505 = 0, + USB_LINK_STD_HOST_NC_8505, + USB_LINK_STD_HOST_C_NS_8505, + USB_LINK_STD_HOST_C_S_8505, + USB_LINK_CDP_8505, + USB_LINK_RESERVED0_8505, + USB_LINK_RESERVED1_8505, + USB_LINK_DEDICATED_CHG_8505, + USB_LINK_ACA_RID_A_8505, + USB_LINK_ACA_RID_B_8505, + USB_LINK_ACA_RID_C_NM_8505, + USB_LINK_RESERVED2_8505, + USB_LINK_RESERVED3_8505, + USB_LINK_HM_IDGND_8505, + USB_LINK_CHARGERPORT_NOT_OK_8505, + USB_LINK_CHARGER_DM_HIGH_8505, + USB_LINK_PHYEN_NO_VBUS_NO_IDGND_8505, + USB_LINK_STD_UPSTREAM_NO_IDGNG_NO_VBUS_8505, + USB_LINK_STD_UPSTREAM_8505, + USB_LINK_CHARGER_SE1_8505, + USB_LINK_CARKIT_CHGR_1_8505, + USB_LINK_CARKIT_CHGR_2_8505, + USB_LINK_ACA_DOCK_CHGR_8505, + USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_8505, + USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_8505, + USB_LINK_SAMSUNG_UART_CBL_PHY_EN_8505, + USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_8505, + USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8505, +}; + +enum ab8500_usb_mode { + USB_IDLE = 0, + USB_PERIPHERAL, + USB_HOST, + USB_DEDICATED_CHG }; struct ab8500_usb { struct usb_phy phy; struct device *dev; struct ab8500 *ab8500; - int irq_num_link_status; unsigned vbus_draw; struct delayed_work dwork; struct work_struct phy_dis_work; unsigned long link_status_wait; + enum ab8500_usb_mode mode; + int previous_link_status_state; }; static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) @@ -104,6 +146,17 @@ static void ab8500_usb_wd_workaround(struct ab8500_usb *ab) 0); } +static void ab8500_usb_wd_linkstatus(struct ab8500_usb *ab, u8 bit) +{ + /* Workaround for v2.0 bug # 31952 */ + if (is_ab8500_2p0(ab->ab8500)) { + abx500_mask_and_set_register_interruptible(ab->dev, + AB8500_USB, AB8500_USB_PHY_CTRL_REG, + bit, bit); + udelay(AB8500_V20_31952_DISABLE_DELAY_US); + } +} + static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host, bool enable) { @@ -139,90 +192,274 @@ static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host, #define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_ctrl(ab, false, true) #define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_ctrl(ab, false, false) -static int ab8500_usb_link_status_update(struct ab8500_usb *ab) +static int ab8505_usb_link_status_update(struct ab8500_usb *ab, + enum ab8505_usb_link_status lsts) { - u8 reg; - enum ab8500_usb_link_status lsts; - void *v = NULL; - enum usb_phy_events event; + enum ux500_musb_vbus_id_status event = 0; - abx500_get_register_interruptible(ab->dev, - AB8500_USB, - AB8500_USB_LINE_STAT_REG, - ®); + dev_dbg(ab->dev, "ab8505_usb_link_status_update %d\n", lsts); - lsts = (reg >> 3) & 0x0F; + /* + * Spurious link_status interrupts are seen at the time of + * disconnection of a device in RIDA state + */ + if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8505 && + (lsts == USB_LINK_STD_HOST_NC_8505)) + return 0; + + ab->previous_link_status_state = lsts; switch (lsts) { - case USB_LINK_NOT_CONFIGURED: - case USB_LINK_RESERVED: - case USB_LINK_NOT_VALID_LINK: - /* TODO: Disable regulators. */ - ab8500_usb_host_phy_dis(ab); - ab8500_usb_peri_phy_dis(ab); - ab->phy.state = OTG_STATE_B_IDLE; + case USB_LINK_ACA_RID_B_8505: + event = UX500_MUSB_RIDB; + case USB_LINK_NOT_CONFIGURED_8505: + case USB_LINK_RESERVED0_8505: + case USB_LINK_RESERVED1_8505: + case USB_LINK_RESERVED2_8505: + case USB_LINK_RESERVED3_8505: + ab->mode = USB_IDLE; ab->phy.otg->default_a = false; ab->vbus_draw = 0; - event = USB_EVENT_NONE; + if (event != UX500_MUSB_RIDB) + event = UX500_MUSB_NONE; + /* + * Fallback to default B_IDLE as nothing + * is connected + */ + ab->phy.state = OTG_STATE_B_IDLE; break; - case USB_LINK_STD_HOST_NC: - case USB_LINK_STD_HOST_C_NS: - case USB_LINK_STD_HOST_C_S: - case USB_LINK_HOST_CHG_NM: - case USB_LINK_HOST_CHG_HS: - case USB_LINK_HOST_CHG_HS_CHIRP: - if (ab->phy.otg->gadget) { - /* TODO: Enable regulators. */ + case USB_LINK_ACA_RID_C_NM_8505: + event = UX500_MUSB_RIDC; + case USB_LINK_STD_HOST_NC_8505: + case USB_LINK_STD_HOST_C_NS_8505: + case USB_LINK_STD_HOST_C_S_8505: + case USB_LINK_CDP_8505: + if (ab->mode == USB_IDLE) { + ab->mode = USB_PERIPHERAL; ab8500_usb_peri_phy_en(ab); - v = ab->phy.otg->gadget; + atomic_notifier_call_chain(&ab->phy.notifier, + UX500_MUSB_PREPARE, &ab->vbus_draw); } - event = USB_EVENT_VBUS; + if (event != UX500_MUSB_RIDC) + event = UX500_MUSB_VBUS; break; - case USB_LINK_HM_IDGND: - if (ab->phy.otg->host) { - /* TODO: Enable regulators. */ + case USB_LINK_ACA_RID_A_8505: + case USB_LINK_ACA_DOCK_CHGR_8505: + event = UX500_MUSB_RIDA; + case USB_LINK_HM_IDGND_8505: + if (ab->mode == USB_IDLE) { + ab->mode = USB_HOST; ab8500_usb_host_phy_en(ab); - v = ab->phy.otg->host; + atomic_notifier_call_chain(&ab->phy.notifier, + UX500_MUSB_PREPARE, &ab->vbus_draw); } - ab->phy.state = OTG_STATE_A_IDLE; ab->phy.otg->default_a = true; - event = USB_EVENT_ID; + if (event != UX500_MUSB_RIDA) + event = UX500_MUSB_ID; + atomic_notifier_call_chain(&ab->phy.notifier, + event, &ab->vbus_draw); break; - case USB_LINK_ACA_RID_A: - case USB_LINK_ACA_RID_B: - /* TODO */ - case USB_LINK_ACA_RID_C_NM: - case USB_LINK_ACA_RID_C_HS: - case USB_LINK_ACA_RID_C_HS_CHIRP: - case USB_LINK_DEDICATED_CHG: - /* TODO: vbus_draw */ - event = USB_EVENT_CHARGER; + case USB_LINK_DEDICATED_CHG_8505: + ab->mode = USB_DEDICATED_CHG; + event = UX500_MUSB_CHARGER; + atomic_notifier_call_chain(&ab->phy.notifier, + event, &ab->vbus_draw); + break; + + default: break; } - atomic_notifier_call_chain(&ab->phy.notifier, event, v); + return 0; +} + +static int ab8500_usb_link_status_update(struct ab8500_usb *ab, + enum ab8500_usb_link_status lsts) +{ + enum ux500_musb_vbus_id_status event = 0; + + dev_dbg(ab->dev, "ab8500_usb_link_status_update %d\n", lsts); + + /* + * Spurious link_status interrupts are seen in case of a + * disconnection of a device in IDGND and RIDA stage + */ + if (ab->previous_link_status_state == USB_LINK_HM_IDGND_8500 && + (lsts == USB_LINK_STD_HOST_C_NS_8500 || + lsts == USB_LINK_STD_HOST_NC_8500)) + return 0; + + if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8500 && + lsts == USB_LINK_STD_HOST_NC_8500) + return 0; + + ab->previous_link_status_state = lsts; + + switch (lsts) { + case USB_LINK_ACA_RID_B_8500: + event = UX500_MUSB_RIDB; + case USB_LINK_NOT_CONFIGURED_8500: + case USB_LINK_NOT_VALID_LINK_8500: + ab->mode = USB_IDLE; + ab->phy.otg->default_a = false; + ab->vbus_draw = 0; + if (event != UX500_MUSB_RIDB) + event = UX500_MUSB_NONE; + /* Fallback to default B_IDLE as nothing is connected */ + ab->phy.state = OTG_STATE_B_IDLE; + break; + + case USB_LINK_ACA_RID_C_NM_8500: + case USB_LINK_ACA_RID_C_HS_8500: + case USB_LINK_ACA_RID_C_HS_CHIRP_8500: + event = UX500_MUSB_RIDC; + case USB_LINK_STD_HOST_NC_8500: + case USB_LINK_STD_HOST_C_NS_8500: + case USB_LINK_STD_HOST_C_S_8500: + case USB_LINK_HOST_CHG_NM_8500: + case USB_LINK_HOST_CHG_HS_8500: + case USB_LINK_HOST_CHG_HS_CHIRP_8500: + if (ab->mode == USB_IDLE) { + ab->mode = USB_PERIPHERAL; + ab8500_usb_peri_phy_en(ab); + atomic_notifier_call_chain(&ab->phy.notifier, + UX500_MUSB_PREPARE, &ab->vbus_draw); + } + if (event != UX500_MUSB_RIDC) + event = UX500_MUSB_VBUS; + break; + + case USB_LINK_ACA_RID_A_8500: + event = UX500_MUSB_RIDA; + case USB_LINK_HM_IDGND_8500: + if (ab->mode == USB_IDLE) { + ab->mode = USB_HOST; + ab8500_usb_host_phy_en(ab); + atomic_notifier_call_chain(&ab->phy.notifier, + UX500_MUSB_PREPARE, &ab->vbus_draw); + } + ab->phy.otg->default_a = true; + if (event != UX500_MUSB_RIDA) + event = UX500_MUSB_ID; + atomic_notifier_call_chain(&ab->phy.notifier, + event, &ab->vbus_draw); + break; + + case USB_LINK_DEDICATED_CHG_8500: + ab->mode = USB_DEDICATED_CHG; + event = UX500_MUSB_CHARGER; + atomic_notifier_call_chain(&ab->phy.notifier, + event, &ab->vbus_draw); + break; + + case USB_LINK_RESERVED_8500: + break; + } return 0; } +/* + * Connection Sequence: + * 1. Link Status Interrupt + * 2. Enable AB clock + * 3. Enable AB regulators + * 4. Enable USB phy + * 5. Reset the musb controller + * 6. Switch the ULPI GPIO pins to fucntion mode + * 7. Enable the musb Peripheral5 clock + * 8. Restore MUSB context + */ +static int abx500_usb_link_status_update(struct ab8500_usb *ab) +{ + u8 reg; + int ret = 0; + + if (is_ab8500(ab->ab8500)) { + enum ab8500_usb_link_status lsts; + + abx500_get_register_interruptible(ab->dev, + AB8500_USB, AB8500_USB_LINE_STAT_REG, ®); + lsts = (reg >> 3) & 0x0F; + ret = ab8500_usb_link_status_update(ab, lsts); + } else if (is_ab8505(ab->ab8500)) { + enum ab8505_usb_link_status lsts; + + abx500_get_register_interruptible(ab->dev, + AB8500_USB, AB8505_USB_LINE_STAT_REG, ®); + lsts = (reg >> 3) & 0x1F; + ret = ab8505_usb_link_status_update(ab, lsts); + } + + return ret; +} + +/* + * Disconnection Sequence: + * 1. Disconect Interrupt + * 2. Disable regulators + * 3. Disable AB clock + * 4. Disable the Phy + * 5. Link Status Interrupt + * 6. Disable Musb Clock + */ +static irqreturn_t ab8500_usb_disconnect_irq(int irq, void *data) +{ + struct ab8500_usb *ab = (struct ab8500_usb *) data; + enum usb_phy_events event = UX500_MUSB_NONE; + + /* Link status will not be updated till phy is disabled. */ + if (ab->mode == USB_HOST) { + ab->phy.otg->default_a = false; + ab->vbus_draw = 0; + atomic_notifier_call_chain(&ab->phy.notifier, + event, &ab->vbus_draw); + ab8500_usb_host_phy_dis(ab); + ab->mode = USB_IDLE; + } + + if (ab->mode == USB_PERIPHERAL) { + atomic_notifier_call_chain(&ab->phy.notifier, + event, &ab->vbus_draw); + ab8500_usb_peri_phy_dis(ab); + atomic_notifier_call_chain(&ab->phy.notifier, + UX500_MUSB_CLEAN, &ab->vbus_draw); + ab->mode = USB_IDLE; + ab->phy.otg->default_a = false; + ab->vbus_draw = 0; + } + + if (is_ab8500_2p0(ab->ab8500)) { + if (ab->mode == USB_DEDICATED_CHG) { + ab8500_usb_wd_linkstatus(ab, + AB8500_BIT_PHY_CTRL_DEVICE_EN); + abx500_mask_and_set_register_interruptible(ab->dev, + AB8500_USB, AB8500_USB_PHY_CTRL_REG, + AB8500_BIT_PHY_CTRL_DEVICE_EN, 0); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t ab8500_usb_link_status_irq(int irq, void *data) +{ + struct ab8500_usb *ab = (struct ab8500_usb *) data; + + abx500_usb_link_status_update(ab); + + return IRQ_HANDLED; +} + static void ab8500_usb_delayed_work(struct work_struct *work) { struct ab8500_usb *ab = container_of(work, struct ab8500_usb, dwork.work); - ab8500_usb_link_status_update(ab); -} - -static irqreturn_t ab8500_usb_v20_irq(int irq, void *data) -{ - struct ab8500_usb *ab = (struct ab8500_usb *) data; - - ab8500_usb_link_status_update(ab); - - return IRQ_HANDLED; + abx500_usb_link_status_update(ab); } static void ab8500_usb_phy_disable_work(struct work_struct *work) @@ -250,7 +487,7 @@ static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA) if (mA) atomic_notifier_call_chain(&ab->phy.notifier, - USB_EVENT_ENUMERATED, ab->phy.otg->gadget); + UX500_MUSB_ENUMERATED, ab->phy.otg->gadget); return 0; } @@ -327,30 +564,48 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) return 0; } -static void ab8500_usb_irq_free(struct ab8500_usb *ab) -{ - free_irq(ab->irq_num_link_status, ab); -} - -static int ab8500_usb_v2_res_setup(struct platform_device *pdev, - struct ab8500_usb *ab) +static int ab8500_usb_irq_setup(struct platform_device *pdev, + struct ab8500_usb *ab) { int err; + int irq; - ab->irq_num_link_status = platform_get_irq_byname(pdev, - "USB_LINK_STATUS"); - if (ab->irq_num_link_status < 0) { + irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS"); + if (irq < 0) { dev_err(&pdev->dev, "Link status irq not found\n"); - return ab->irq_num_link_status; + return irq; + } + err = devm_request_threaded_irq(&pdev->dev, irq, NULL, + ab8500_usb_link_status_irq, + IRQF_NO_SUSPEND | IRQF_SHARED, "usb-link-status", ab); + if (err < 0) { + dev_err(ab->dev, "request_irq failed for link status irq\n"); + return err; } - err = request_threaded_irq(ab->irq_num_link_status, NULL, - ab8500_usb_v20_irq, - IRQF_NO_SUSPEND | IRQF_SHARED, - "usb-link-status", ab); + irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); + if (irq < 0) { + dev_err(&pdev->dev, "ID fall irq not found\n"); + return irq; + } + err = devm_request_threaded_irq(&pdev->dev, irq, NULL, + ab8500_usb_disconnect_irq, + IRQF_NO_SUSPEND | IRQF_SHARED, "usb-id-fall", ab); if (err < 0) { - dev_err(ab->dev, - "request_irq failed for link status irq\n"); + dev_err(ab->dev, "request_irq failed for ID fall irq\n"); + return err; + } + + irq = platform_get_irq_byname(pdev, "VBUS_DET_F"); + if (irq < 0) { + dev_err(&pdev->dev, "VBUS fall irq not found\n"); + return irq; + } + err = devm_request_threaded_irq(&pdev->dev, irq, NULL, + ab8500_usb_disconnect_irq, + IRQF_NO_SUSPEND | IRQF_SHARED, "usb-vbus-fall", ab); + if (err < 0) { + dev_err(ab->dev, "request_irq failed for Vbus fall irq\n"); return err; } @@ -408,22 +663,23 @@ static int ab8500_usb_probe(struct platform_device *pdev) /* all: Disable phy when called from set_host and set_peripheral */ INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); - err = ab8500_usb_v2_res_setup(pdev, ab); + err = ab8500_usb_irq_setup(pdev, ab); if (err < 0) - goto fail0; + goto fail; err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2); if (err) { dev_err(&pdev->dev, "Can't register transceiver\n"); - goto fail1; + goto fail; } + /* Needed to enable ID detection. */ + ab8500_usb_wd_workaround(ab); + dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev); return 0; -fail1: - ab8500_usb_irq_free(ab); -fail0: +fail: kfree(otg); kfree(ab); return err; @@ -433,8 +689,6 @@ static int ab8500_usb_remove(struct platform_device *pdev) { struct ab8500_usb *ab = platform_get_drvdata(pdev); - ab8500_usb_irq_free(ab); - cancel_delayed_work_sync(&ab->dwork); cancel_work_sync(&ab->phy_dis_work); diff --git a/include/linux/usb/musb-ux500.h b/include/linux/usb/musb-ux500.h new file mode 100644 index 000000000000..1e2c7130f6e1 --- /dev/null +++ b/include/linux/usb/musb-ux500.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2013 ST-Ericsson AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MUSB_UX500_H__ +#define __MUSB_UX500_H__ + +enum ux500_musb_vbus_id_status { + UX500_MUSB_NONE = 0, + UX500_MUSB_VBUS, + UX500_MUSB_ID, + UX500_MUSB_CHARGER, + UX500_MUSB_ENUMERATED, + UX500_MUSB_RIDA, + UX500_MUSB_RIDB, + UX500_MUSB_RIDC, + UX500_MUSB_PREPARE, + UX500_MUSB_CLEAN, +}; + +#endif /* __MUSB_UX500_H__ */ From b64a15930c35c3c1046533aadcfe4f3233e70c20 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 19 Mar 2013 10:14:35 +0200 Subject: [PATCH 230/303] usb: phy: samsung: fix sparse warning Fix the following sparse warning: drivers/usb/phy/phy-samsung-usb2.c:50:26: sparse: incorrect type in argument 1 (different address spaces) drivers/usb/phy/phy-samsung-usb2.c:50:26: expected void const volatile [noderef] *addr drivers/usb/phy/phy-samsung-usb2.c:50:26: got void * Cc: Vivek Gautam Cc: Kukjin Kim Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-samsung-usb2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c index dce968151505..45ffe036dacc 100644 --- a/drivers/usb/phy/phy-samsung-usb2.c +++ b/drivers/usb/phy/phy-samsung-usb2.c @@ -43,7 +43,7 @@ static int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host) return 0; } -static bool exynos5_phyhost_is_on(void *regs) +static bool exynos5_phyhost_is_on(void __iomem *regs) { u32 reg; From e8d891fb7b8fe4ee7311820594323d46dbc31d45 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 20 Mar 2013 08:01:53 +0200 Subject: [PATCH 231/303] usb: phy: gpio-vbus: don't ignore regulator APIs return value Due to recent changes to regulator API, all users which don't check regulator_{en,dis}able()'s return value will generate compile warnings. Add such checks to gpio-vbus. Cc: Mark Brown Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-gpio-vbus-usb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c index a7d4ac591982..4c76074e518d 100644 --- a/drivers/usb/phy/phy-gpio-vbus-usb.c +++ b/drivers/usb/phy/phy-gpio-vbus-usb.c @@ -61,6 +61,7 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA) { struct regulator *vbus_draw = gpio_vbus->vbus_draw; int enabled; + int ret; if (!vbus_draw) return; @@ -69,12 +70,16 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA) if (mA) { regulator_set_current_limit(vbus_draw, 0, 1000 * mA); if (!enabled) { - regulator_enable(vbus_draw); + ret = regulator_enable(vbus_draw); + if (ret < 0) + return; gpio_vbus->vbus_draw_enabled = 1; } } else { if (enabled) { - regulator_disable(vbus_draw); + ret = regulator_disable(vbus_draw); + if (ret < 0) + return; gpio_vbus->vbus_draw_enabled = 0; } } From 75f32ec1de7a4c905ba2007972d981f96c977eb2 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 20 Mar 2013 14:18:28 +0200 Subject: [PATCH 232/303] arm: tegra: fix Kconfig select clauses USB_ULPI and USB_ULPI_VIEWPORT shouldn't really be selected directly by anyone, but since Tegra still needs some time before turning ulpi viewport into a proper PHY driver, we need to keep the selects in place. This patch just fixes the conditional select so that it will continue to build after merging the latest PHY layer changes. Acked-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- arch/arm/mach-tegra/Kconfig | 8 ++++---- drivers/usb/host/Kconfig | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index d1c4893894ce..dbc653ea851c 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -18,8 +18,8 @@ config ARCH_TEGRA_2x_SOC select PL310_ERRATA_727915 if CACHE_L2X0 select PL310_ERRATA_769419 if CACHE_L2X0 select USB_ARCH_HAS_EHCI if USB_SUPPORT - select USB_ULPI if USB - select USB_ULPI_VIEWPORT if USB_SUPPORT + select USB_ULPI if USB_PHY + select USB_ULPI_VIEWPORT if USB_PHY help Support for NVIDIA Tegra AP20 and T20 processors, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller @@ -37,8 +37,8 @@ config ARCH_TEGRA_3x_SOC select PINCTRL_TEGRA30 select PL310_ERRATA_769419 if CACHE_L2X0 select USB_ARCH_HAS_EHCI if USB_SUPPORT - select USB_ULPI if USB - select USB_ULPI_VIEWPORT if USB_SUPPORT + select USB_ULPI if USB_PHY + select USB_ULPI_VIEWPORT if USB_PHY help Support for NVIDIA Tegra T30 processor family, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index ba1347ccb9dd..1b58587b7be9 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -179,6 +179,7 @@ config USB_EHCI_TEGRA boolean "NVIDIA Tegra HCD support" depends on USB_EHCI_HCD && ARCH_TEGRA select USB_EHCI_ROOT_HUB_TT + select USB_PHY help This driver enables support for the internal USB Host Controllers found in NVIDIA Tegra SoCs. The controllers are EHCI compliant. From 44a50d088aad18a1a2709091bf25a108f967f8c9 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 17 Mar 2013 20:23:21 +0200 Subject: [PATCH 233/303] usb: phy: twl4030-usb: don't enable PHY during init There is no need to do it, otg.set_suspend(false) (which itself comes from runtime_pm OMAP glue calls) will enable it later anyway. This used to be the place where things were enabled if booted with cable connected before runtime_pm conversion, but now can be dropped. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl4030-usb.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index 1986c782346f..4ad234cc6c9e 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -515,19 +515,17 @@ static int twl4030_usb_phy_init(struct usb_phy *phy) struct twl4030_usb *twl = phy_to_twl(phy); enum omap_musb_vbus_id_status status; - status = twl4030_usb_linkstat(twl); - if (status > 0) { - if (status == OMAP_MUSB_VBUS_OFF || - status == OMAP_MUSB_ID_FLOAT) { - __twl4030_phy_power(twl, 0); - twl->asleep = 1; - } else { - __twl4030_phy_resume(twl); - twl->asleep = 0; - } + /* + * Start in sleep state, we'll get called through set_suspend() + * callback when musb is runtime resumed and it's time to start. + */ + __twl4030_phy_power(twl, 0); + twl->asleep = 1; + status = twl4030_usb_linkstat(twl); + if (status > 0) omap_musb_mailbox(twl->linkstat); - } + sysfs_notify(&twl->dev->kobj, NULL, "vbus"); return 0; } From ca4f70ce78de9a2fa09741f80cf7bda2f4256ecc Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 17 Mar 2013 20:23:22 +0200 Subject: [PATCH 234/303] usb: phy: twl4030-usb: ignore duplicate events In some rare cases we may get multiple interrupts that will generate duplicate omap_musb_mailbox() calls. This is a problem because each VBUS/ID event generates runtime_pm call in OMAP glue code, causing unbalanced gets or puts and breaking PM. The same goes for initial state, glue already defaults to "no cable" state, so only bother it if we have VBUS or ID. Signed-off-by: Grazvydas Ignotas Reviewed-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl4030-usb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index 4ad234cc6c9e..7ff67ce373dc 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -483,9 +483,10 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) { struct twl4030_usb *twl = _twl; enum omap_musb_vbus_id_status status; + enum omap_musb_vbus_id_status status_prev = twl->linkstat; status = twl4030_usb_linkstat(twl); - if (status > 0) { + if (status > 0 && status != status_prev) { /* FIXME add a set_power() method so that B-devices can * configure the charger appropriately. It's not always * correct to consume VBUS power, and how much current to @@ -523,7 +524,7 @@ static int twl4030_usb_phy_init(struct usb_phy *phy) twl->asleep = 1; status = twl4030_usb_linkstat(twl); - if (status > 0) + if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) omap_musb_mailbox(twl->linkstat); sysfs_notify(&twl->dev->kobj, NULL, "vbus"); From 15460de7f3d9cf0846af1cfdb4a3995d2f270ce7 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 17 Mar 2013 20:23:23 +0200 Subject: [PATCH 235/303] usb: phy: twl4030-usb: don't switch the phy on/off needlessly With runtime_pm in place there is no longer need to turn the phy on/off in OTG layer on cable connect/disconnect, OMAP glue does this through otg.set_suspend() callback after it's called through omap_musb_mailbox() on VBUS/ID interrupt. Not doing this will save power when cable is connected but no gadget driver is loaded. This will also have side effect of automatic USB charging no longer working without twl4030_charger driver, because a regulator needed for charging will no longer be enabled, so be sure to enable charger driver if charging is needed. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl4030-usb.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index 7ff67ce373dc..f4ec53a58103 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -498,12 +498,6 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) * USB_LINK_VBUS state. musb_hdrc won't care until it * starts to handle softconnect right. */ - if (status == OMAP_MUSB_VBUS_OFF || - status == OMAP_MUSB_ID_FLOAT) - twl4030_phy_suspend(twl, 0); - else - twl4030_phy_resume(twl); - omap_musb_mailbox(twl->linkstat); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); From 249751f22380386042056cce6a73c934f5b942a3 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 17 Mar 2013 20:23:24 +0200 Subject: [PATCH 236/303] usb: phy: twl4030-usb: poll for ID disconnect On pandora, STS_USB interrupt doesn't arrive on USB host cable disconnect for some reason while VBUS is driven by twl itself, but STS_HW_CONDITIONS is updated correctly. It does work fine when PHY is powered down though. To work around that we have to poll. This patch also moves twl->linkstat update code to callers so that changes can be handled in thread safe way (as polling work can trigger at the same time as real irq now). TI PSP kernels have similar workarounds, so (many?) more boards are likely affected. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl4030-usb.c | 64 +++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index f4ec53a58103..61fe7e29c9c3 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -163,6 +163,8 @@ struct twl4030_usb { bool vbus_supplied; u8 asleep; bool irq_enabled; + + struct delayed_work id_workaround_work; }; /* internal define on top of container_of */ @@ -287,10 +289,6 @@ static enum omap_musb_vbus_id_status * are registered, and that both are active... */ - spin_lock_irq(&twl->lock); - twl->linkstat = linkstat; - spin_unlock_irq(&twl->lock); - return linkstat; } @@ -412,6 +410,16 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) __twl4030_phy_resume(twl); twl->asleep = 0; dev_dbg(twl->dev, "%s\n", __func__); + + /* + * XXX When VBUS gets driven after musb goes to A mode, + * ID_PRES related interrupts no longer arrive, why? + * Register itself is updated fine though, so we must poll. + */ + if (twl->linkstat == OMAP_MUSB_ID_GROUND) { + cancel_delayed_work(&twl->id_workaround_work); + schedule_delayed_work(&twl->id_workaround_work, HZ); + } } static int twl4030_usb_ldo_init(struct twl4030_usb *twl) @@ -483,10 +491,18 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) { struct twl4030_usb *twl = _twl; enum omap_musb_vbus_id_status status; - enum omap_musb_vbus_id_status status_prev = twl->linkstat; + bool status_changed = false; status = twl4030_usb_linkstat(twl); - if (status > 0 && status != status_prev) { + + spin_lock_irq(&twl->lock); + if (status >= 0 && status != twl->linkstat) { + twl->linkstat = status; + status_changed = true; + } + spin_unlock_irq(&twl->lock); + + if (status_changed) { /* FIXME add a set_power() method so that B-devices can * configure the charger appropriately. It's not always * correct to consume VBUS power, and how much current to @@ -498,13 +514,42 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) * USB_LINK_VBUS state. musb_hdrc won't care until it * starts to handle softconnect right. */ - omap_musb_mailbox(twl->linkstat); + omap_musb_mailbox(status); } sysfs_notify(&twl->dev->kobj, NULL, "vbus"); return IRQ_HANDLED; } +static void twl4030_id_workaround_work(struct work_struct *work) +{ + struct twl4030_usb *twl = container_of(work, struct twl4030_usb, + id_workaround_work.work); + enum omap_musb_vbus_id_status status; + bool status_changed = false; + + status = twl4030_usb_linkstat(twl); + + spin_lock_irq(&twl->lock); + if (status >= 0 && status != twl->linkstat) { + twl->linkstat = status; + status_changed = true; + } + spin_unlock_irq(&twl->lock); + + if (status_changed) { + dev_dbg(twl->dev, "handle missing status change to %d\n", + status); + omap_musb_mailbox(status); + } + + /* don't schedule during sleep - irq works right then */ + if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { + cancel_delayed_work(&twl->id_workaround_work); + schedule_delayed_work(&twl->id_workaround_work, HZ); + } +} + static int twl4030_usb_phy_init(struct usb_phy *phy) { struct twl4030_usb *twl = phy_to_twl(phy); @@ -518,6 +563,8 @@ static int twl4030_usb_phy_init(struct usb_phy *phy) twl->asleep = 1; status = twl4030_usb_linkstat(twl); + twl->linkstat = status; + if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) omap_musb_mailbox(twl->linkstat); @@ -608,6 +655,8 @@ static int twl4030_usb_probe(struct platform_device *pdev) /* init spinlock for workqueue */ spin_lock_init(&twl->lock); + INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work); + err = twl4030_usb_ldo_init(twl); if (err) { dev_err(&pdev->dev, "ldo init failed\n"); @@ -646,6 +695,7 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; + cancel_delayed_work(&twl->id_workaround_work); device_remove_file(twl->dev, &dev_attr_vbus); /* set transceiver mode to power on defaults */ From 4261b8f3538c1cae63e30110a164614ea2f10299 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 15 Mar 2013 11:04:39 +0200 Subject: [PATCH 237/303] usb: host: ehci-tegra: fix PHY error handling PHY layer no longer returns NULL, we must switch from IS_ERR_OR_NULL() to IS_ERR(). Acked-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-tegra.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index fafbc819ab18..1d2488cc55f1 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -768,14 +768,12 @@ static int tegra_ehci_probe(struct platform_device *pdev) goto fail; } -#if IS_ENABLED(CONFIG_USB_PHY) if (pdata->operating_mode == TEGRA_USB_OTG) { tegra->transceiver = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); - if (!IS_ERR_OR_NULL(tegra->transceiver)) + if (!IS_ERR(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, &hcd->self); } -#endif err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { @@ -794,10 +792,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) return err; fail: -#if IS_ENABLED(CONFIG_USB_PHY) - if (!IS_ERR_OR_NULL(tegra->transceiver)) + if (!IS_ERR(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); -#endif usb_phy_shutdown(hcd->phy); fail_io: clk_disable_unprepare(tegra->clk); @@ -815,10 +811,8 @@ static int tegra_ehci_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); -#if IS_ENABLED(CONFIG_USB_PHY) - if (!IS_ERR_OR_NULL(tegra->transceiver)) + if (!IS_ERR(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); -#endif usb_phy_shutdown(hcd->phy); usb_remove_hcd(hcd); From e5615112807c27dd256f0bd8fc8b1f6f5e1b90af Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 10 Mar 2013 02:48:55 +0200 Subject: [PATCH 238/303] usb: musb: core: honour initial transceiver state As the usb transceiver driver usually starts first, it should already have default_a variable set according to ID pin state, so don't override it. In case default_a was not changed by trasceiver, it will default to 0 and this code will work as before. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 6bd879257e4c..5fbabc0037b4 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1952,9 +1952,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb_write_ulpi_buscontrol(musb->mregs, busctl); } - MUSB_DEV_MODE(musb); - musb->xceiv->otg->default_a = 0; - musb->xceiv->state = OTG_STATE_B_IDLE; + if (musb->xceiv->otg->default_a) { + MUSB_HST_MODE(musb); + musb->xceiv->state = OTG_STATE_A_IDLE; + } else { + MUSB_DEV_MODE(musb); + musb->xceiv->state = OTG_STATE_B_IDLE; + } status = musb_gadget_setup(musb); From e21de10cd8b1338200d96038aa66fb966fcf6ed0 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 10 Mar 2013 02:49:14 +0200 Subject: [PATCH 239/303] usb: musb: gadget: clear gadget_driver when gadget is stopped Some musb glue drivers use gadget_driver pointer to know if any gadget drivers are loaded at some moment and base further decisions on it, like to do runtime suspend/resume or not. Right now the pointer is left alone on stop and OMAP musb glue later does wrong runtime_pm decisions because of it. Clear the gadget_driver pointer on remove, it's invalid after stop anyway. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index e8408883ab0d..ff6ba3adf5fe 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1934,6 +1934,7 @@ static int musb_gadget_stop(struct usb_gadget *g, dev_dbg(musb->controller, "unregistering driver %s\n", driver->function); musb->is_active = 0; + musb->gadget_driver = NULL; musb_platform_try_idle(musb, 0); spin_unlock_irqrestore(&musb->lock, flags); From 54485116cd77b361864c17c40c3280b97b6fbecc Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 10 Mar 2013 02:49:28 +0200 Subject: [PATCH 240/303] usb: musb: core: log VBUS error VBUS_ERROR is a serious error that the driver often doesn't recover from in my tests, so we should at least inform the user about it. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 5fbabc0037b4..37a261a6bb6a 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -603,7 +603,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, break; } - dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", + dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller, + "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", usb_otg_state_string(musb->xceiv->state), devctl, ({ char *s; From 4895a2ee5d1bc88d9876c4082062c1cb3df5cdd4 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 19 Mar 2013 01:28:56 +0000 Subject: [PATCH 241/303] usb: gadget: mv_u3d: make mv_u3d_pm_ops static Make mv_u3d_pm_ops static because mv_u3d_pm_ops is not exported. Also, CONFIG_PM_SLEEP is used to remove unnecessary ifdefs. Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index e91281d2aa21..49f9da462f00 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -2002,7 +2002,7 @@ err_pdata: return retval; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int mv_u3d_suspend(struct device *dev) { struct mv_u3d *u3d = dev_get_drvdata(dev); @@ -2045,10 +2045,10 @@ static int mv_u3d_resume(struct device *dev) return 0; } - -SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume); #endif +static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume); + static void mv_u3d_shutdown(struct platform_device *dev) { struct mv_u3d *u3d = dev_get_drvdata(&dev->dev); @@ -2066,9 +2066,7 @@ static struct platform_driver mv_u3d_driver = { .driver = { .owner = THIS_MODULE, .name = "mv-u3d", -#ifdef CONFIG_PM .pm = &mv_u3d_pm_ops, -#endif }, }; From a10713a59af2da6b80d9cad398fdd4f6d23a202c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 09:11:17 +0200 Subject: [PATCH 242/303] usb: gadget: mv_u3d: remove unused headers none of those headers are used by the driver, removing them still compiles fine. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index 49f9da462f00..29153bf67cb4 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -30,9 +30,6 @@ #include #include #include -#include -#include -#include #include "mv_u3d.h" From af593da481aec9ce1fba8aef3ee1a2b868744968 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 09:12:23 +0200 Subject: [PATCH 243/303] usb: gadget: mv_u3d: remove outdated selects USB_GADGET_{DUAL,SUPER}SPEED symbols have been removed by commit 85b8614 (usb: gadget: get rid of USB_GADGET_{DUAL,SUPER}SPEED), for some reason mv_u3d_core was lost. Remove those selects now. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 7ad108a3555d..af5cc35063d9 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -325,8 +325,6 @@ config USB_MV_UDC config USB_MV_U3D tristate "MARVELL PXA2128 USB 3.0 controller" depends on CPU_MMP3 - select USB_GADGET_DUALSPEED - select USB_GADGET_SUPERSPEED help MARVELL PXA2128 Processor series include a super speed USB3.0 device controller, which support super speed USB peripheral. From e6667ef7ac27d61dd36b1215da1e9ac719dcb769 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 09:14:25 +0200 Subject: [PATCH 244/303] usb: gadget: mv_u3d: fix sparse warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following sparse warnings: drivers/usb/gadget/mv_u3d_core.c: In function ‘mv_u3d_ep_queue’: drivers/usb/gadget/mv_u3d_core.c:812:2: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/usb/gadget/mv_u3d_core.c:822:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/usb/gadget/mv_u3d_core.c:823:4: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/usb/gadget/mv_u3d_core.c:823:28: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/usb/gadget/mv_u3d_core.c: In function ‘mv_u3d_ep_dequeue’: drivers/usb/gadget/mv_u3d_core.c:905:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/usb/gadget/mv_u3d_core.c: In function ‘mv_u3d_probe’: drivers/usb/gadget/mv_u3d_core.c:1840:3: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/usb/gadget/mv_u3d_core.c:1855:51: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/usb/gadget/mv_u3d_core.c:1855:17: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] drivers/usb/gadget/mv_u3d_core.c:1858:53: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] drivers/usb/gadget/mv_u3d_core.c:1858:18: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] drivers/usb/gadget/mv_u3d_core.c: In function ‘mv_u3d_irq_process_tr_complete’: drivers/usb/gadget/mv_u3d_core.c:163:21: warning: ‘remaining_length’ may be used uninitialized in this function [-Wmaybe-uninitialized] drivers/usb/gadget/mv_u3d_core.c:125:28: note: ‘remaining_length’ was declared here Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index 29153bf67cb4..5a6f87cf718a 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -122,7 +122,7 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index, struct mv_u3d_trb *curr_trb; dma_addr_t cur_deq_lo; struct mv_u3d_ep_context *curr_ep_context; - int trb_complete, actual, remaining_length; + int trb_complete, actual, remaining_length = 0; int direction, ep_num; int retval = 0; u32 tmp, status, length; @@ -809,19 +809,19 @@ mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) return 0; } - dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n", - __func__, _ep->name, (u32)req); + dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n", + __func__, _ep->name, req); /* catch various bogus parameters */ if (!req->req.complete || !req->req.buf || !list_empty(&req->queue)) { dev_err(u3d->dev, - "%s, bad params, _req: 0x%x," - "req->req.complete: 0x%x, req->req.buf: 0x%x," + "%s, bad params, _req: 0x%p," + "req->req.complete: 0x%p, req->req.buf: 0x%p," "list_empty: 0x%x\n", - __func__, (u32)_req, - (u32)req->req.complete, (u32)req->req.buf, - (u32)list_empty(&req->queue)); + __func__, _req, + req->req.complete, req->req.buf, + list_empty(&req->queue)); return -EINVAL; } if (unlikely(!ep->ep.desc)) { @@ -902,7 +902,7 @@ static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) struct mv_u3d_req, queue); /* Point first TRB of next request to the EP context. */ - iowrite32((u32) next_req->trb_head, + iowrite32((unsigned long) next_req->trb_head, &ep_context->trb_addr_lo); } else { struct mv_u3d_ep_context *ep_context; @@ -1837,8 +1837,9 @@ static int mv_u3d_probe(struct platform_device *dev) retval = -EBUSY; goto err_map_cap_regs; } else { - dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n", - (unsigned int)r->start, (unsigned int)u3d->cap_regs); + dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n", + (unsigned long) r->start, + (unsigned long) u3d->cap_regs); } /* we will access controller register, so enable the u3d controller */ @@ -1852,10 +1853,10 @@ static int mv_u3d_probe(struct platform_device *dev) } } - u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs + u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs + MV_U3D_USB3_OP_REGS_OFFSET); - u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs + u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs + ioread32(&u3d->cap_regs->vuoff)); u3d->max_eps = 16; From 60630c2eabd40fb119a1b88af364003d2915b370 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 09:15:45 +0200 Subject: [PATCH 245/303] usb: gadget: mv_u3d: drop ARCH dependency this driver compiles fine everywhere which means we can use linux-next to compile it for us frequently. By dropping the arch dependency, we also ensure driver writers don't add virtual arch-depdencies to the driver by e.g. using the wrong headers. While at that, fix Marvell's USB3 PHY dependency, that's the driver which depends on CPU_MM3, not mv_u3d_core. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 - drivers/usb/phy/Kconfig | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index af5cc35063d9..261b1e305131 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -324,7 +324,6 @@ config USB_MV_UDC config USB_MV_U3D tristate "MARVELL PXA2128 USB 3.0 controller" - depends on CPU_MMP3 help MARVELL PXA2128 Processor series include a super speed USB3.0 device controller, which support super speed USB peripheral. diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 7e8fe0f0b8c6..372db48fa269 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -45,7 +45,7 @@ config ISP1301_OMAP config MV_U3D_PHY bool "Marvell USB 3.0 PHY controller Driver" - depends on USB_MV_U3D + depends on CPU_MMP3 help Enable this to support Marvell USB 3.0 phy controller for Marvell SoC. From 69147121abf569bf3655a2000c6511f1f016d9f8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 21 Mar 2013 12:19:31 +0200 Subject: [PATCH 246/303] usb: gadget: net2272: fix sparse warnings Fix the following sparse warnings: drivers/usb/gadget/net2272.c:916:13: warning: Using plain integer as NULL pointer drivers/usb/gadget/net2272.c:1624:9: warning: Using plain integer as NULL pointer drivers/usb/gadget/net2272.c:1552:30: warning: right shift by bigger than source value Note that the last warning is an actual bug, since ep->dma is a one bit value which is shifted by one bit in code. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2272.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 03e41049ed30..ce450a18aa19 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -911,7 +911,7 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) } } } - if (likely(req != 0)) + if (likely(req)) list_add_tail(&req->queue, &ep->queue); if (likely(!list_empty(&ep->queue))) @@ -1538,7 +1538,7 @@ net2272_handle_dma(struct net2272_ep *ep) | (ep->dev->dma_eot_polarity << EOT_POLARITY) | (ep->dev->dma_dack_polarity << DACK_POLARITY) | (ep->dev->dma_dreq_polarity << DREQ_POLARITY) - | ((ep->dma >> 1) << DMA_ENDPOINT_SELECT)); + | (ep->dma << DMA_ENDPOINT_SELECT)); ep->dev->dma_busy = 0; @@ -1611,7 +1611,7 @@ net2272_handle_ep(struct net2272_ep *ep) ep->irqs++; dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n", - ep->ep.name, stat0, stat1, req ? &req->req : 0); + ep->ep.name, stat0, stat1, req ? &req->req : NULL); net2272_ep_write(ep, EP_STAT0, stat0 & ~((1 << NAK_OUT_PACKETS) From ad303db62d280fb8e5b4174273f4fb8b03b64747 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 16:47:52 +0200 Subject: [PATCH 247/303] usb: gadget: net2280: fix sparse warnings fix the following sparse warnings: drivers/usb/gadget/net2280.c:2063:13: warning: Using plain integer as NULL pointer drivers/usb/gadget/net2280.c:2321:68: warning: Using plain integer as NULL pointer drivers/usb/gadget/net2280.c:2349:68: warning: Using plain integer as NULL pointer drivers/usb/gadget/net2280.c:2371:68: warning: Using plain integer as NULL pointer Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/net2280.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 691cc658ddf9..e869188bc2b1 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2060,7 +2060,7 @@ static void handle_ep_small (struct net2280_ep *ep) return; /* manual DMA queue advance after short OUT */ - if (likely (ep->dma != 0)) { + if (likely (ep->dma)) { if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) { u32 count; int stopped = ep->stopped; @@ -2318,7 +2318,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) /* hw handles device and interface status */ if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT)) goto delegate; - if ((e = get_ep_by_addr (dev, w_index)) == 0 + if ((e = get_ep_by_addr (dev, w_index)) == NULL || w_length > 2) goto do_stall; @@ -2346,7 +2346,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) if (w_value != USB_ENDPOINT_HALT || w_length != 0) goto do_stall; - if ((e = get_ep_by_addr (dev, w_index)) == 0) + if ((e = get_ep_by_addr (dev, w_index)) == NULL) goto do_stall; if (e->wedged) { VDEBUG(dev, "%s wedged, halt not cleared\n", @@ -2368,7 +2368,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) if (w_value != USB_ENDPOINT_HALT || w_length != 0) goto do_stall; - if ((e = get_ep_by_addr (dev, w_index)) == 0) + if ((e = get_ep_by_addr (dev, w_index)) == NULL) goto do_stall; if (e->ep.name == ep0name) goto do_stall; From 814cf212f9d9e8a270e8cded8452c1c992fb21da Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 16:50:47 +0200 Subject: [PATCH 248/303] usb: gadget: dummy: fix sparse warning fix the following sparse warning: drivers/usb/gadget/dummy_hcd.c:1912:12: warning: symbol 'usb3_bos_desc' was not declared. Should it be static? Acked-by: Michal Nazarewicz Signed-off-by: Felipe Balbi --- drivers/usb/gadget/dummy_hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index ce751555f6ba..a792e322f4f1 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1906,7 +1906,7 @@ done: } /* usb 3.0 root hub device descriptor */ -struct { +static struct { struct usb_bos_descriptor bos; struct usb_ss_cap_descriptor ss_cap; } __packed usb3_bos_desc = { From 3f8b620124d2f331b71936a8d17e0fa493182632 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 16:54:01 +0200 Subject: [PATCH 249/303] usb: gadget: pch_udc: fix sparse warnings fix the following sparse warnings: drivers/usb/gadget/pch_udc.c:1483:9: warning: context imbalance in 'complete_req' - unexpected unlock drivers/usb/gadget/pch_udc.c:2408:28: warning: context imbalance in 'pch_udc_svc_control_out' - unexpected unlock Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pch_udc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 44aacf7192ab..24174e1d1564 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -1440,6 +1440,8 @@ static void pch_vbus_gpio_free(struct pch_udc_dev *dev) */ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req, int status) + __releases(&dev->lock) + __acquires(&dev->lock) { struct pch_udc_dev *dev; unsigned halted = ep->halted; @@ -2381,6 +2383,8 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev) * @dev: Reference to the device structure */ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) + __releases(&dev->lock) + __acquires(&dev->lock) { u32 stat; int setup_supported; From 94a06018dead7fc5f92238ececf31ed601ee528c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 16:58:18 +0200 Subject: [PATCH 250/303] usb: gadget: mv_udc_core: fix sparse warnings fix the following sparse warnings: drivers/usb/gadget/mv_udc_core.c:1850:6: warning: symbol 'irq_process_reset' was not declared. Should it be static? drivers/usb/gadget/mv_udc_core.c:247:9: warning: context imbalance in 'done' - unexpected unlock drivers/usb/gadget/mv_udc_core.c:1692:25: warning: context imbalance in 'handle_setup_packet' - unexpected unlock Note that there are still other sparse warnings which aren't trivial to fix, so I left them out: drivers/usb/gadget/mv_udc_core.c:848:34: warning: incorrect type in argument 1 (different address spaces) drivers/usb/gadget/mv_udc_core.c:848:34: expected void const volatile [noderef] *addr drivers/usb/gadget/mv_udc_core.c:848:34: got unsigned int * drivers/usb/gadget/mv_udc_core.c:849:42: warning: incorrect type in argument 2 (different address spaces) drivers/usb/gadget/mv_udc_core.c:849:42: expected void volatile [noderef] *addr drivers/usb/gadget/mv_udc_core.c:849:42: got unsigned int * Acked-by: Neil Zhang Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 9a68c051a5a8..88be74e6297d 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -212,6 +212,8 @@ static int process_ep_req(struct mv_udc *udc, int index, * request is still in progress. */ static void done(struct mv_ep *ep, struct mv_req *req, int status) + __releases(&ep->udc->lock) + __acquires(&ep->udc->lock) { struct mv_udc *udc = NULL; unsigned char stopped = ep->stopped; @@ -1651,6 +1653,8 @@ out: static void handle_setup_packet(struct mv_udc *udc, u8 ep_num, struct usb_ctrlrequest *setup) + __releases(&ep->udc->lock) + __acquires(&ep->udc->lock) { bool delegate = false; @@ -1847,7 +1851,7 @@ static void irq_process_tr_complete(struct mv_udc *udc) } } -void irq_process_reset(struct mv_udc *udc) +static void irq_process_reset(struct mv_udc *udc) { u32 tmp; unsigned int loops; From 6fbb2f7daeeeb0865fc9b7799607f4cb5481a96e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 17:01:42 +0200 Subject: [PATCH 251/303] usb: gadget: mv_u3d: fix sparse warnings fix the following sparse warnings: drivers/usb/gadget/mv_u3d_core.c:223:20: warning: context imbalance in 'mv_u3d_done' - unexpected unlock drivers/usb/gadget/mv_u3d_core.c:1562:25: warning: context imbalance in 'mv_u3d_handle_setup_packet' - unexpected unlock Note that the non-trivial sparse warnings are left out of this commit due to lack of HW to test: drivers/usb/gadget/mv_u3d_core.c:906:42: warning: incorrect type in argument 2 (different address spaces) drivers/usb/gadget/mv_u3d_core.c:906:42: expected void [noderef] * drivers/usb/gadget/mv_u3d_core.c:906:42: got unsigned int * Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index 5a6f87cf718a..9675227a9529 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -186,6 +186,8 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index, */ static void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status) + __releases(&ep->udc->lock) + __acquires(&ep->udc->lock) { struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d; @@ -1520,6 +1522,8 @@ static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup) static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num, struct usb_ctrlrequest *setup) + __releases(&u3c->lock) + __acquires(&u3c->lock) { bool delegate = false; From 6b0cfc656f8a649fbfbe11e76e0aa301ee26879e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 22 Mar 2013 17:03:32 +0200 Subject: [PATCH 252/303] usb: musb: ux500_dma: fix sparse warning fix the following sparse warning: drivers/usb/musb/ux500_dma.c:60:6: warning: symbol 'ux500_dma_callback' was not declared. Should it be static? Signed-off-by: Felipe Balbi --- drivers/usb/musb/ux500_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index 2df9b7d1ddc6..f417b7e49bb5 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -57,7 +57,7 @@ struct ux500_dma_controller { }; /* Work function invoked from DMA callback to handle rx transfers. */ -void ux500_dma_callback(void *private_data) +static void ux500_dma_callback(void *private_data) { struct dma_channel *channel = private_data; struct ux500_dma_channel *ux500_channel = channel->private_data; From f65f4f40fb23b64a59adbe8629e8e7e6fea279cf Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 24 Mar 2013 17:36:53 +0200 Subject: [PATCH 253/303] usb: phy: twl4030-usb: check if vbus is driven by twl itself At least on pandora, STS_VBUS gets set even when VBUS is driven by twl itself. Reporting VBUS in this case confuses OMAP musb glue and charger driver, so check if OTG VBUS charge pump is on before reporting VBUS event to avoid this problem. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl4030-usb.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index 61fe7e29c9c3..3f9858fbebc2 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -248,6 +248,25 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) /*-------------------------------------------------------------------------*/ +static bool twl4030_is_driving_vbus(struct twl4030_usb *twl) +{ + int ret; + + ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS); + if (ret < 0 || !(ret & PHY_DPLL_CLK)) + /* + * if clocks are off, registers are not updated, + * but we can assume we don't drive VBUS in this case + */ + return false; + + ret = twl4030_usb_read(twl, ULPI_OTG_CTRL); + if (ret < 0) + return false; + + return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false; +} + static enum omap_musb_vbus_id_status twl4030_usb_linkstat(struct twl4030_usb *twl) { @@ -270,13 +289,19 @@ static enum omap_musb_vbus_id_status if (status < 0) dev_err(twl->dev, "USB link status err %d\n", status); else if (status & (BIT(7) | BIT(2))) { - if (status & (BIT(7))) - twl->vbus_supplied = true; + if (status & BIT(7)) { + if (twl4030_is_driving_vbus(twl)) + status &= ~BIT(7); + else + twl->vbus_supplied = true; + } if (status & BIT(2)) linkstat = OMAP_MUSB_ID_GROUND; - else + else if (status & BIT(7)) linkstat = OMAP_MUSB_VBUS_VALID; + else + linkstat = OMAP_MUSB_VBUS_OFF; } else { if (twl->linkstat != OMAP_MUSB_UNKNOWN) linkstat = OMAP_MUSB_VBUS_OFF; From 2c1fe89db1cfa9826c94e848c14dc68de0e2b0d5 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 24 Mar 2013 17:36:54 +0200 Subject: [PATCH 254/303] usb: musb: omap2430: turn off vbus on cable disconnect On USB_EVENT_ID event the musb glue enables VBUS by calling omap2430_musb_set_vbus(musb, 1) that sets the session bit, but on USB_EVENT_NONE reverse action is never made, and that breaks PM. Disable VBUS on USB_EVENT_NONE to be sure musb session is ended on cable unplug so that PM works. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/musb/omap2430.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 798e029e3db0..3551f1a30c65 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -291,6 +291,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) musb->xceiv->last_event = USB_EVENT_NONE; if (musb->gadget_driver) { + omap2430_musb_set_vbus(musb, 0); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); } From b65ae0f1a7b98c370967cf161ee87011e3ecdd77 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sun, 24 Mar 2013 17:36:55 +0200 Subject: [PATCH 255/303] usb: musb: gadget: use platform callback to enable vbus On some platform configurations (like OMAP3+twl4030) it's the platform code that enables VBUS, not OTG transceiver, so call vbus platform callback instead, it will then call the transceiver if needed. This fixes a use case where USB cable is plugged first and gadget driver is loaded later after that. Signed-off-by: Grazvydas Ignotas Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ff6ba3adf5fe..4be48651b5a8 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1848,9 +1848,8 @@ static int musb_gadget_start(struct usb_gadget *g, goto err; } - if ((musb->xceiv->last_event == USB_EVENT_ID) - && otg->set_vbus) - otg_set_vbus(otg, 1); + if (musb->xceiv->last_event == USB_EVENT_ID) + musb_platform_set_vbus(musb, 1); hcd->self.uses_pio_for_control = 1; From 1919811fe635de4689b4f31a20da3d50196cf43f Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Mon, 25 Mar 2013 03:06:52 -0400 Subject: [PATCH 256/303] usb: gadget: mv_udc_core: remove unused clock The origianl understanding of clock is wrong. The UDC controller only have one clock input. Passing clock name by pdata is wrong. The clock is defined by device iteself. Signed-off-by: Chao Xie Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_udc.h | 3 +-- drivers/usb/gadget/mv_udc_core.c | 27 +++++++-------------------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index 9073436d8b24..be77f207dbaf 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h @@ -222,8 +222,7 @@ struct mv_udc { struct mv_usb_platform_data *pdata; /* some SOC has mutiple clock sources for USB*/ - unsigned int clknum; - struct clk *clk[0]; + struct clk *clk; }; /* endpoint data structure */ diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 88be74e6297d..c2a57023e467 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -974,18 +974,12 @@ static struct usb_ep_ops mv_ep_ops = { static void udc_clock_enable(struct mv_udc *udc) { - unsigned int i; - - for (i = 0; i < udc->clknum; i++) - clk_prepare_enable(udc->clk[i]); + clk_prepare_enable(udc->clk); } static void udc_clock_disable(struct mv_udc *udc) { - unsigned int i; - - for (i = 0; i < udc->clknum; i++) - clk_disable_unprepare(udc->clk[i]); + clk_disable_unprepare(udc->clk); } static void udc_stop(struct mv_udc *udc) @@ -2109,7 +2103,6 @@ static int mv_udc_probe(struct platform_device *pdev) struct mv_usb_platform_data *pdata = pdev->dev.platform_data; struct mv_udc *udc; int retval = 0; - int clk_i = 0; struct resource *r; size_t size; @@ -2118,8 +2111,7 @@ static int mv_udc_probe(struct platform_device *pdev) return -ENODEV; } - size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum; - udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL); if (udc == NULL) { dev_err(&pdev->dev, "failed to allocate memory for udc\n"); return -ENOMEM; @@ -2145,15 +2137,10 @@ static int mv_udc_probe(struct platform_device *pdev) } } - udc->clknum = pdata->clknum; - for (clk_i = 0; clk_i < udc->clknum; clk_i++) { - udc->clk[clk_i] = devm_clk_get(&pdev->dev, - pdata->clkname[clk_i]); - if (IS_ERR(udc->clk[clk_i])) { - retval = PTR_ERR(udc->clk[clk_i]); - return retval; - } - } + /* udc only have one sysclk. */ + udc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(udc->clk)) + return PTR_ERR(udc->clk); r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs"); if (r == NULL) { From df18fedae5f7870529a0a79193e24e67f56d995e Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Mon, 25 Mar 2013 03:06:53 -0400 Subject: [PATCH 257/303] usb: otg: mv_otg: remove unused clock The origianl understanding of clock is wrong. The OTG controller only have one clock input. Passing clock name by pdata is wrong. The clock is defined by device iteself. Signed-off-by: Chao Xie Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-mv-usb.c | 28 +++++++--------------------- drivers/usb/phy/phy-mv-usb.h | 3 +-- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c index 6872bf0a3681..c987bbe27851 100644 --- a/drivers/usb/phy/phy-mv-usb.c +++ b/drivers/usb/phy/phy-mv-usb.c @@ -237,18 +237,12 @@ static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on) static void otg_clock_enable(struct mv_otg *mvotg) { - unsigned int i; - - for (i = 0; i < mvotg->clknum; i++) - clk_prepare_enable(mvotg->clk[i]); + clk_prepare_enable(mvotg->clk); } static void otg_clock_disable(struct mv_otg *mvotg) { - unsigned int i; - - for (i = 0; i < mvotg->clknum; i++) - clk_disable_unprepare(mvotg->clk[i]); + clk_disable_unprepare(mvotg->clk); } static int mv_otg_enable_internal(struct mv_otg *mvotg) @@ -684,16 +678,14 @@ static int mv_otg_probe(struct platform_device *pdev) struct mv_otg *mvotg; struct usb_otg *otg; struct resource *r; - int retval = 0, clk_i, i; - size_t size; + int retval = 0, i; if (pdata == NULL) { dev_err(&pdev->dev, "failed to get platform data\n"); return -ENODEV; } - size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum; - mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL); if (!mvotg) { dev_err(&pdev->dev, "failed to allocate memory!\n"); return -ENOMEM; @@ -708,15 +700,9 @@ static int mv_otg_probe(struct platform_device *pdev) mvotg->pdev = pdev; mvotg->pdata = pdata; - mvotg->clknum = pdata->clknum; - for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) { - mvotg->clk[clk_i] = devm_clk_get(&pdev->dev, - pdata->clkname[clk_i]); - if (IS_ERR(mvotg->clk[clk_i])) { - retval = PTR_ERR(mvotg->clk[clk_i]); - return retval; - } - } + mvotg->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(mvotg->clk)) + return PTR_ERR(mvotg->clk); mvotg->qwork = create_singlethread_workqueue("mv_otg_queue"); if (!mvotg->qwork) { diff --git a/drivers/usb/phy/phy-mv-usb.h b/drivers/usb/phy/phy-mv-usb.h index 8a9e351b36ba..551da6eb0ba8 100644 --- a/drivers/usb/phy/phy-mv-usb.h +++ b/drivers/usb/phy/phy-mv-usb.h @@ -158,8 +158,7 @@ struct mv_otg { unsigned int active; unsigned int clock_gating; - unsigned int clknum; - struct clk *clk[0]; + struct clk *clk; }; #endif From b7e159c29548955a61439d217181d67409bf8bc7 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Mon, 25 Mar 2013 03:06:54 -0400 Subject: [PATCH 258/303] usb: ehci: mv_ehci: remove unused clock The origianl understanding of clock is wrong. The EHCI controller only have one clock input. Passing clock name by pdata is wrong. The clock is defined by device iteself. Acked-by: Alan Stern Signed-off-by: Chao Xie Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-mv.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 38048200977c..6bad41af1c4e 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -33,25 +33,17 @@ struct ehci_hcd_mv { struct mv_usb_platform_data *pdata; - /* clock source and total clock number */ - unsigned int clknum; - struct clk *clk[0]; + struct clk *clk; }; static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv) { - unsigned int i; - - for (i = 0; i < ehci_mv->clknum; i++) - clk_prepare_enable(ehci_mv->clk[i]); + clk_prepare_enable(ehci_mv->clk); } static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) { - unsigned int i; - - for (i = 0; i < ehci_mv->clknum; i++) - clk_disable_unprepare(ehci_mv->clk[i]); + clk_disable_unprepare(ehci_mv->clk); } static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) @@ -144,9 +136,8 @@ static int mv_ehci_probe(struct platform_device *pdev) struct ehci_hcd *ehci; struct ehci_hcd_mv *ehci_mv; struct resource *r; - int clk_i, retval = -ENODEV; + int retval = -ENODEV; u32 offset; - size_t size; if (!pdata) { dev_err(&pdev->dev, "missing platform_data\n"); @@ -160,8 +151,7 @@ static int mv_ehci_probe(struct platform_device *pdev) if (!hcd) return -ENOMEM; - size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum; - ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL); if (ehci_mv == NULL) { dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n"); retval = -ENOMEM; @@ -172,16 +162,11 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->pdata = pdata; ehci_mv->hcd = hcd; - ehci_mv->clknum = pdata->clknum; - for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) { - ehci_mv->clk[clk_i] = - devm_clk_get(&pdev->dev, pdata->clkname[clk_i]); - if (IS_ERR(ehci_mv->clk[clk_i])) { - dev_err(&pdev->dev, "error get clck \"%s\"\n", - pdata->clkname[clk_i]); - retval = PTR_ERR(ehci_mv->clk[clk_i]); - goto err_clear_drvdata; - } + ehci_mv->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ehci_mv->clk)) { + dev_err(&pdev->dev, "error getting clock\n"); + retval = PTR_ERR(ehci_mv->clk); + goto err_clear_drvdata; } r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs"); From 8f75d400984bb0bf538e1df7ec483076b83e7a62 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Mon, 25 Mar 2013 03:06:55 -0400 Subject: [PATCH 259/303] arm: mmp: remove clock from usb pdata for aspenite The clock name will directly get by driver. Removing the name from pdata. Acked-by: Haojian Zhuang Signed-off-by: Chao Xie Signed-off-by: Felipe Balbi --- arch/arm/mach-mmp/aspenite.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index 9f64d5632e07..76901f4ce611 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -223,13 +223,7 @@ static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = { }; #if defined(CONFIG_USB_EHCI_MV) -static char *pxa168_sph_clock_name[] = { - [0] = "PXA168-USBCLK", -}; - static struct mv_usb_platform_data pxa168_sph_pdata = { - .clknum = 1, - .clkname = pxa168_sph_clock_name, .mode = MV_USB_MODE_HOST, .phy_init = pxa_usb_phy_init, .phy_deinit = pxa_usb_phy_deinit, From 1805e811f00623465900238d4863fc9433e0b99e Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Mon, 25 Mar 2013 03:06:56 -0400 Subject: [PATCH 260/303] arm: mmp: remove clock name from usb pdata for ttc The clock name will directly get by driver. Removing the name from pdata. Acked-by: Haojian Zhuang Signed-off-by: Chao Xie Signed-off-by: Felipe Balbi --- arch/arm/mach-mmp/ttc_dkb.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c index 22a9058f9f4d..6528a5fa6a26 100644 --- a/arch/arm/mach-mmp/ttc_dkb.c +++ b/arch/arm/mach-mmp/ttc_dkb.c @@ -162,13 +162,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = { #ifdef CONFIG_USB_SUPPORT #if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O) -static char *pxa910_usb_clock_name[] = { - [0] = "U2OCLK", -}; - static struct mv_usb_platform_data ttc_usb_pdata = { - .clknum = 1, - .clkname = pxa910_usb_clock_name, .vbus = NULL, .mode = MV_USB_MODE_OTG, .otg_force_a_bus_req = 1, From 65cd3f2b877ed11faa0899524746d27ed2d5aa75 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 2 Apr 2013 11:12:11 +0300 Subject: [PATCH 261/303] usb: gadget: mv_u3d_core: remove unused clock The origianl understanding of clock is wrong. The UDC controller only have one clock input. Passing clock name by pdata is wrong. The clock is defined by device iteself. Cc: Chao Xie Cc: Yu Xu Signed-off-by: Felipe Balbi --- drivers/usb/gadget/mv_u3d_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index 9675227a9529..58288e9cf728 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -1821,7 +1821,7 @@ static int mv_u3d_probe(struct platform_device *dev) u3d->dev = &dev->dev; u3d->vbus = pdata->vbus; - u3d->clk = clk_get(&dev->dev, pdata->clkname[0]); + u3d->clk = clk_get(&dev->dev, NULL); if (IS_ERR(u3d->clk)) { retval = PTR_ERR(u3d->clk); goto err_get_clk; From ef096542642874de10909f02686447a96a66ad14 Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Mon, 25 Mar 2013 03:06:57 -0400 Subject: [PATCH 262/303] usb: mv_usb: remove clock name from pdata Using pdata to pass clock name is not correct. Directly get clock from usb drivers. Signed-off-by: Chao Xie Signed-off-by: Felipe Balbi --- include/linux/platform_data/mv_usb.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/platform_data/mv_usb.h b/include/linux/platform_data/mv_usb.h index 944b01dd103e..98b7925f1a2d 100644 --- a/include/linux/platform_data/mv_usb.h +++ b/include/linux/platform_data/mv_usb.h @@ -34,8 +34,6 @@ struct mv_usb_addon_irq { }; struct mv_usb_platform_data { - unsigned int clknum; - char **clkname; struct mv_usb_addon_irq *id; /* Only valid for OTG. ID pin change*/ struct mv_usb_addon_irq *vbus; /* valid for OTG/UDC. VBUS change*/ From 225da3e3cb1f0db9e4cb7fa2a7dc3a360d1cf788 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 31 Mar 2013 18:34:43 -0700 Subject: [PATCH 263/303] usb: renesas_usbhs: fixup sparse errors for common.c This patch fixup below sparse errors CHECK ${RENESAS_USB}/common.c ${RENESAS_USB}/common.c:313:17: error: incompatible types in conditional expression (different base types) ${RENESAS_USB}/common.c:322:17: error: incompatible types in conditional expression (different base types) ${RENESAS_USB}/common.c:384:17: error: incompatible types in conditional expression (different base types) ${RENESAS_USB}/common.c:524:9: error: incompatible types in conditional expression (different base types) ${RENESAS_USB}/common.c:545:9: error: incompatible types in conditional expression (different base types) ${RENESAS_USB}/common.c:574:9: error: incompatible types in conditional expression (different base types) ${RENESAS_USB}/common.c:606:9: error: incompatible types in conditional expression (different base types) ${RENESAS_USB}/mod_gadget.c:233:28: warning: symbol 'req_clear_feature' was not declared. Should it be static? ${RENESAS_USB}/mod_gadget.c:274:28: warning: symbol 'req_set_feature' was not declared. Should it be static? ${RENESAS_USB}/mod_gadget.c:375:28: warning: symbol 'req_get_status' was not declared. Should it be static? [ balbi@ti.com : added three sparse fixes to mod_gadget.c ] Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- arch/arm/mach-shmobile/board-armadillo800eva.c | 8 ++++++-- arch/arm/mach-shmobile/board-kzm9g.c | 8 ++++++-- arch/arm/mach-shmobile/board-mackerel.c | 12 +++++++++--- arch/sh/boards/mach-ecovec24/setup.c | 4 +++- drivers/usb/renesas_usbhs/mod_gadget.c | 6 +++--- include/linux/usb/renesas_usbhs.h | 6 +++--- 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index f2ec0777cfbe..ff8b7ba9b93c 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -169,7 +169,7 @@ static int usbhsf_get_id(struct platform_device *pdev) return USBHS_GADGET; } -static void usbhsf_power_ctrl(struct platform_device *pdev, +static int usbhsf_power_ctrl(struct platform_device *pdev, void __iomem *base, int enable) { struct usbhsf_private *priv = usbhsf_get_priv(pdev); @@ -223,6 +223,8 @@ static void usbhsf_power_ctrl(struct platform_device *pdev, clk_disable(priv->pci); /* usb work around */ clk_disable(priv->usb24); /* usb work around */ } + + return 0; } static int usbhsf_get_vbus(struct platform_device *pdev) @@ -239,7 +241,7 @@ static irqreturn_t usbhsf_interrupt(int irq, void *data) return IRQ_HANDLED; } -static void usbhsf_hardware_exit(struct platform_device *pdev) +static int usbhsf_hardware_exit(struct platform_device *pdev) { struct usbhsf_private *priv = usbhsf_get_priv(pdev); @@ -264,6 +266,8 @@ static void usbhsf_hardware_exit(struct platform_device *pdev) priv->usbh_base = NULL; free_irq(IRQ7, pdev); + + return 0; } static int usbhsf_hardware_init(struct platform_device *pdev) diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c index 7f3a6b7e7b7c..a385f570bbfc 100644 --- a/arch/arm/mach-shmobile/board-kzm9g.c +++ b/arch/arm/mach-shmobile/board-kzm9g.c @@ -155,12 +155,14 @@ static int usbhs_get_vbus(struct platform_device *pdev) return !((1 << 7) & __raw_readw(priv->cr2)); } -static void usbhs_phy_reset(struct platform_device *pdev) +static int usbhs_phy_reset(struct platform_device *pdev) { struct usbhs_private *priv = usbhs_get_priv(pdev); /* init phy */ __raw_writew(0x8a0a, priv->cr2); + + return 0; } static int usbhs_get_id(struct platform_device *pdev) @@ -202,7 +204,7 @@ static int usbhs_hardware_init(struct platform_device *pdev) return 0; } -static void usbhs_hardware_exit(struct platform_device *pdev) +static int usbhs_hardware_exit(struct platform_device *pdev) { struct usbhs_private *priv = usbhs_get_priv(pdev); @@ -210,6 +212,8 @@ static void usbhs_hardware_exit(struct platform_device *pdev) __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy); free_irq(IRQ15, pdev); + + return 0; } static u32 usbhs_pipe_cfg[] = { diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index db968a585ff0..979237c18dad 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -596,12 +596,14 @@ static int usbhs_get_vbus(struct platform_device *pdev) return usbhs_is_connected(usbhs_get_priv(pdev)); } -static void usbhs_phy_reset(struct platform_device *pdev) +static int usbhs_phy_reset(struct platform_device *pdev) { struct usbhs_private *priv = usbhs_get_priv(pdev); /* init phy */ __raw_writew(0x8a0a, priv->usbcrcaddr); + + return 0; } static int usbhs0_get_id(struct platform_device *pdev) @@ -628,11 +630,13 @@ static int usbhs0_hardware_init(struct platform_device *pdev) return 0; } -static void usbhs0_hardware_exit(struct platform_device *pdev) +static int usbhs0_hardware_exit(struct platform_device *pdev) { struct usbhs_private *priv = usbhs_get_priv(pdev); cancel_delayed_work_sync(&priv->work); + + return 0; } static struct usbhs_private usbhs0_private = { @@ -735,7 +739,7 @@ static int usbhs1_hardware_init(struct platform_device *pdev) return 0; } -static void usbhs1_hardware_exit(struct platform_device *pdev) +static int usbhs1_hardware_exit(struct platform_device *pdev) { struct usbhs_private *priv = usbhs_get_priv(pdev); @@ -743,6 +747,8 @@ static void usbhs1_hardware_exit(struct platform_device *pdev) __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr); free_irq(IRQ8, pdev); + + return 0; } static int usbhs1_get_id(struct platform_device *pdev) diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index aaff7671101b..764530c85aa9 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -254,11 +254,13 @@ static int usbhs_get_id(struct platform_device *pdev) return gpio_get_value(GPIO_PTB3); } -static void usbhs_phy_reset(struct platform_device *pdev) +static int usbhs_phy_reset(struct platform_device *pdev) { /* enable vbus if HOST */ if (!gpio_get_value(GPIO_PTB3)) gpio_set_value(GPIO_PTB5, 1); + + return 0; } static struct renesas_usbhs_platform_info usbhs_info = { diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index c2781bc9dabe..ed4949faa70d 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -230,7 +230,7 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv, return 0; } -struct usbhsg_recip_handle req_clear_feature = { +static struct usbhsg_recip_handle req_clear_feature = { .name = "clear feature", .device = usbhsg_recip_handler_std_control_done, .interface = usbhsg_recip_handler_std_control_done, @@ -271,7 +271,7 @@ static int usbhsg_recip_handler_std_set_endpoint(struct usbhs_priv *priv, return 0; } -struct usbhsg_recip_handle req_set_feature = { +static struct usbhsg_recip_handle req_set_feature = { .name = "set feature", .device = usbhsg_recip_handler_std_set_device, .interface = usbhsg_recip_handler_std_control_done, @@ -372,7 +372,7 @@ static int usbhsg_recip_handler_std_get_endpoint(struct usbhs_priv *priv, return 0; } -struct usbhsg_recip_handle req_get_status = { +static struct usbhsg_recip_handle req_get_status = { .name = "get status", .device = usbhsg_recip_handler_std_get_device, .interface = usbhsg_recip_handler_std_get_interface, diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h index c5d36c65c33b..e452ba6ec6bd 100644 --- a/include/linux/usb/renesas_usbhs.h +++ b/include/linux/usb/renesas_usbhs.h @@ -62,14 +62,14 @@ struct renesas_usbhs_platform_callback { * Hardware exit function for platform. * it is called when driver was removed */ - void (*hardware_exit)(struct platform_device *pdev); + int (*hardware_exit)(struct platform_device *pdev); /* * option: * * for board specific clock control */ - void (*power_ctrl)(struct platform_device *pdev, + int (*power_ctrl)(struct platform_device *pdev, void __iomem *base, int enable); /* @@ -77,7 +77,7 @@ struct renesas_usbhs_platform_callback { * * Phy reset for platform */ - void (*phy_reset)(struct platform_device *pdev); + int (*phy_reset)(struct platform_device *pdev); /* * get USB ID function From d692522577c051058efbe9e3c8aef68a4c36e4f7 Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Thu, 28 Mar 2013 15:11:52 +0530 Subject: [PATCH 264/303] usb: gadget/uvc: Port UVC webcam gadget to use videobuf2 framework This patch reworks the videobuffer management logic present in the UVC webcam gadget and ports it to use the "more apt" videobuf2 framework for video buffer management. To support routing video data captured from a real V4L2 video capture device with a "zero copy" operation on videobuffers (as they pass from the V4L2 domain to UVC domain via a user-space application), we need to support USER_PTR IO method at the UVC gadget side. So the V4L2 capture device driver can still continue to use MMAP IO method and now the user-space application can just pass a pointer to the video buffers being dequeued from the V4L2 device side while queueing them at the UVC gadget end. This ensures that we have a "zero-copy" design as the videobuffers pass from the V4L2 capture device to the UVC gadget. Note that there will still be a need to apply UVC specific payload headers on top of each UVC payload data, which will still require a copy operation to be performed in the 'encode' routines of the UVC gadget. This patch also addresses one issue found out while porting the UVC gadget to videobuf2 framework: - In case the usb requests queued by the gadget get completed with a status of -ESHUTDOWN (disconnected from host), the queue of videobuf2 should be cancelled to ensure that the application space daemon is not left in a state waiting for a vb2 to be successfully absorbed at the USB side. Signed-off-by: Bhupesh Sharma Signed-off-by: Laurent Pinchart --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/uvc_queue.c | 562 ++++++++++----------------------- drivers/usb/gadget/uvc_queue.h | 32 +- drivers/usb/gadget/uvc_v4l2.c | 37 +-- drivers/usb/gadget/uvc_video.c | 17 +- 5 files changed, 208 insertions(+), 441 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 261b1e305131..1deaddee9dd4 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -949,6 +949,7 @@ config USB_G_WEBCAM tristate "USB Webcam Gadget" depends on VIDEO_DEV select USB_LIBCOMPOSITE + select VIDEOBUF2_VMALLOC help The Webcam Gadget acts as a composite USB Audio and Video Class device. It provides a userspace API to process UVC control requests diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c index 104ae9c81251..31397954c889 100644 --- a/drivers/usb/gadget/uvc_queue.c +++ b/drivers/usb/gadget/uvc_queue.c @@ -10,6 +10,7 @@ * (at your option) any later version. */ +#include #include #include #include @@ -18,7 +19,8 @@ #include #include #include -#include + +#include #include "uvc.h" @@ -28,330 +30,175 @@ * Video queues is initialized by uvc_queue_init(). The function performs * basic initialization of the uvc_video_queue struct and never fails. * - * Video buffer allocation and freeing are performed by uvc_alloc_buffers and - * uvc_free_buffers respectively. The former acquires the video queue lock, - * while the later must be called with the lock held (so that allocation can - * free previously allocated buffers). Trying to free buffers that are mapped - * to user space will return -EBUSY. - * - * Video buffers are managed using two queues. However, unlike most USB video - * drivers that use an in queue and an out queue, we use a main queue to hold - * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to - * hold empty buffers. This design (copied from video-buf) minimizes locking - * in interrupt, as only one queue is shared between interrupt and user - * contexts. - * - * Use cases - * --------- - * - * Unless stated otherwise, all operations that modify the irq buffers queue - * are protected by the irq spinlock. - * - * 1. The user queues the buffers, starts streaming and dequeues a buffer. - * - * The buffers are added to the main and irq queues. Both operations are - * protected by the queue lock, and the later is protected by the irq - * spinlock as well. - * - * The completion handler fetches a buffer from the irq queue and fills it - * with video data. If no buffer is available (irq queue empty), the handler - * returns immediately. - * - * When the buffer is full, the completion handler removes it from the irq - * queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue. - * At that point, any process waiting on the buffer will be woken up. If a - * process tries to dequeue a buffer after it has been marked ready, the - * dequeing will succeed immediately. - * - * 2. Buffers are queued, user is waiting on a buffer and the device gets - * disconnected. - * - * When the device is disconnected, the kernel calls the completion handler - * with an appropriate status code. The handler marks all buffers in the - * irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so - * that any process waiting on a buffer gets woken up. - * - * Waking up up the first buffer on the irq list is not enough, as the - * process waiting on the buffer might restart the dequeue operation - * immediately. - * + * Video buffers are managed by videobuf2. The driver uses a mutex to protect + * the videobuf2 queue operations by serializing calls to videobuf2 and a + * spinlock to protect the IRQ queue that holds the buffers to be processed by + * the driver. */ -static void -uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) +/* ----------------------------------------------------------------------------- + * videobuf2 queue operations + */ + +static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) { - mutex_init(&queue->mutex); - spin_lock_init(&queue->irqlock); - INIT_LIST_HEAD(&queue->mainqueue); - INIT_LIST_HEAD(&queue->irqqueue); - queue->type = type; + struct uvc_video_queue *queue = vb2_get_drv_priv(vq); + struct uvc_video *video = container_of(queue, struct uvc_video, queue); + + if (*nbuffers > UVC_MAX_VIDEO_BUFFERS) + *nbuffers = UVC_MAX_VIDEO_BUFFERS; + + *nplanes = 1; + + sizes[0] = video->imagesize; + + return 0; } -/* - * Free the video buffers. - * - * This function must be called with the queue lock held. - */ -static int uvc_free_buffers(struct uvc_video_queue *queue) +static int uvc_buffer_prepare(struct vb2_buffer *vb) { - unsigned int i; + struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); + struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); - for (i = 0; i < queue->count; ++i) { - if (queue->buffer[i].vma_use_count != 0) - return -EBUSY; + if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT && + vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { + uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); + return -EINVAL; } - if (queue->count) { - vfree(queue->mem); - queue->count = 0; + if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED)) + return -ENODEV; + + buf->state = UVC_BUF_STATE_QUEUED; + buf->mem = vb2_plane_vaddr(vb, 0); + buf->length = vb2_plane_size(vb, 0); + if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + buf->bytesused = 0; + else + buf->bytesused = vb2_get_plane_payload(vb, 0); + + return 0; +} + +static void uvc_buffer_queue(struct vb2_buffer *vb) +{ + struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); + struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); + unsigned long flags; + + spin_lock_irqsave(&queue->irqlock, flags); + + if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) { + list_add_tail(&buf->queue, &queue->irqqueue); + } else { + /* If the device is disconnected return the buffer to userspace + * directly. The next QBUF call will fail with -ENODEV. + */ + buf->state = UVC_BUF_STATE_ERROR; + vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); } + spin_unlock_irqrestore(&queue->irqlock, flags); +} + +static struct vb2_ops uvc_queue_qops = { + .queue_setup = uvc_queue_setup, + .buf_prepare = uvc_buffer_prepare, + .buf_queue = uvc_buffer_queue, +}; + +static int uvc_queue_init(struct uvc_video_queue *queue, + enum v4l2_buf_type type) +{ + int ret; + + queue->queue.type = type; + queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; + queue->queue.drv_priv = queue; + queue->queue.buf_struct_size = sizeof(struct uvc_buffer); + queue->queue.ops = &uvc_queue_qops; + queue->queue.mem_ops = &vb2_vmalloc_memops; + ret = vb2_queue_init(&queue->queue); + if (ret) + return ret; + + mutex_init(&queue->mutex); + spin_lock_init(&queue->irqlock); + INIT_LIST_HEAD(&queue->irqqueue); + queue->flags = 0; + return 0; } /* - * Allocate the video buffers. - * - * Pages are reserved to make sure they will not be swapped, as they will be - * filled in the URB completion handler. - * - * Buffers will be individually mapped, so they must all be page aligned. + * Free the video buffers. */ -static int -uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, - unsigned int buflength) +static void uvc_free_buffers(struct uvc_video_queue *queue) { - unsigned int bufsize = PAGE_ALIGN(buflength); - unsigned int i; - void *mem = NULL; - int ret; - - if (nbuffers > UVC_MAX_VIDEO_BUFFERS) - nbuffers = UVC_MAX_VIDEO_BUFFERS; - mutex_lock(&queue->mutex); - - if ((ret = uvc_free_buffers(queue)) < 0) - goto done; - - /* Bail out if no buffers should be allocated. */ - if (nbuffers == 0) - goto done; - - /* Decrement the number of buffers until allocation succeeds. */ - for (; nbuffers > 0; --nbuffers) { - mem = vmalloc_32(nbuffers * bufsize); - if (mem != NULL) - break; - } - - if (mem == NULL) { - ret = -ENOMEM; - goto done; - } - - for (i = 0; i < nbuffers; ++i) { - memset(&queue->buffer[i], 0, sizeof queue->buffer[i]); - queue->buffer[i].buf.index = i; - queue->buffer[i].buf.m.offset = i * bufsize; - queue->buffer[i].buf.length = buflength; - queue->buffer[i].buf.type = queue->type; - queue->buffer[i].buf.sequence = 0; - queue->buffer[i].buf.field = V4L2_FIELD_NONE; - queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; - queue->buffer[i].buf.flags = 0; - init_waitqueue_head(&queue->buffer[i].wait); - } - - queue->mem = mem; - queue->count = nbuffers; - queue->buf_size = bufsize; - ret = nbuffers; - -done: + vb2_queue_release(&queue->queue); mutex_unlock(&queue->mutex); - return ret; -} - -static void __uvc_query_buffer(struct uvc_buffer *buf, - struct v4l2_buffer *v4l2_buf) -{ - memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf); - - if (buf->vma_use_count) - v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED; - - switch (buf->state) { - case UVC_BUF_STATE_ERROR: - case UVC_BUF_STATE_DONE: - v4l2_buf->flags |= V4L2_BUF_FLAG_DONE; - break; - case UVC_BUF_STATE_QUEUED: - case UVC_BUF_STATE_ACTIVE: - v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; - break; - case UVC_BUF_STATE_IDLE: - default: - break; - } -} - -static int -uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf) -{ - int ret = 0; - - mutex_lock(&queue->mutex); - if (v4l2_buf->index >= queue->count) { - ret = -EINVAL; - goto done; - } - - __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf); - -done: - mutex_unlock(&queue->mutex); - return ret; } /* - * Queue a video buffer. Attempting to queue a buffer that has already been - * queued will return -EINVAL. + * Allocate the video buffers. */ -static int -uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf) +static int uvc_alloc_buffers(struct uvc_video_queue *queue, + struct v4l2_requestbuffers *rb) { - struct uvc_buffer *buf; - unsigned long flags; - int ret = 0; - - uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index); - - if (v4l2_buf->type != queue->type || - v4l2_buf->memory != V4L2_MEMORY_MMAP) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " - "and/or memory (%u).\n", v4l2_buf->type, - v4l2_buf->memory); - return -EINVAL; - } + int ret; mutex_lock(&queue->mutex); - if (v4l2_buf->index >= queue->count) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); - ret = -EINVAL; - goto done; - } - - buf = &queue->buffer[v4l2_buf->index]; - if (buf->state != UVC_BUF_STATE_IDLE) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state " - "(%u).\n", buf->state); - ret = -EINVAL; - goto done; - } - - if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && - v4l2_buf->bytesused > buf->buf.length) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); - ret = -EINVAL; - goto done; - } - - if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - buf->buf.bytesused = 0; - else - buf->buf.bytesused = v4l2_buf->bytesused; - - spin_lock_irqsave(&queue->irqlock, flags); - if (queue->flags & UVC_QUEUE_DISCONNECTED) { - spin_unlock_irqrestore(&queue->irqlock, flags); - ret = -ENODEV; - goto done; - } - buf->state = UVC_BUF_STATE_QUEUED; - - ret = (queue->flags & UVC_QUEUE_PAUSED) != 0; - queue->flags &= ~UVC_QUEUE_PAUSED; - - list_add_tail(&buf->stream, &queue->mainqueue); - list_add_tail(&buf->queue, &queue->irqqueue); - spin_unlock_irqrestore(&queue->irqlock, flags); - -done: + ret = vb2_reqbufs(&queue->queue, rb); mutex_unlock(&queue->mutex); + + return ret ? ret : rb->count; +} + +static int uvc_query_buffer(struct uvc_video_queue *queue, + struct v4l2_buffer *buf) +{ + int ret; + + mutex_lock(&queue->mutex); + ret = vb2_querybuf(&queue->queue, buf); + mutex_unlock(&queue->mutex); + return ret; } -static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) +static int uvc_queue_buffer(struct uvc_video_queue *queue, + struct v4l2_buffer *buf) { - if (nonblocking) { - return (buf->state != UVC_BUF_STATE_QUEUED && - buf->state != UVC_BUF_STATE_ACTIVE) - ? 0 : -EAGAIN; - } + unsigned long flags; + int ret; - return wait_event_interruptible(buf->wait, - buf->state != UVC_BUF_STATE_QUEUED && - buf->state != UVC_BUF_STATE_ACTIVE); + mutex_lock(&queue->mutex); + ret = vb2_qbuf(&queue->queue, buf); + spin_lock_irqsave(&queue->irqlock, flags); + ret = (queue->flags & UVC_QUEUE_PAUSED) != 0; + queue->flags &= ~UVC_QUEUE_PAUSED; + spin_unlock_irqrestore(&queue->irqlock, flags); + mutex_unlock(&queue->mutex); + + return ret; } /* * Dequeue a video buffer. If nonblocking is false, block until a buffer is * available. */ -static int -uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf, - int nonblocking) +static int uvc_dequeue_buffer(struct uvc_video_queue *queue, + struct v4l2_buffer *buf, int nonblocking) { - struct uvc_buffer *buf; - int ret = 0; - - if (v4l2_buf->type != queue->type || - v4l2_buf->memory != V4L2_MEMORY_MMAP) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " - "and/or memory (%u).\n", v4l2_buf->type, - v4l2_buf->memory); - return -EINVAL; - } + int ret; mutex_lock(&queue->mutex); - if (list_empty(&queue->mainqueue)) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n"); - ret = -EINVAL; - goto done; - } - - buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); - if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0) - goto done; - - uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n", - buf->buf.index, buf->state, buf->buf.bytesused); - - switch (buf->state) { - case UVC_BUF_STATE_ERROR: - uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data " - "(transmission error).\n"); - ret = -EIO; - case UVC_BUF_STATE_DONE: - buf->state = UVC_BUF_STATE_IDLE; - break; - - case UVC_BUF_STATE_IDLE: - case UVC_BUF_STATE_QUEUED: - case UVC_BUF_STATE_ACTIVE: - default: - uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " - "(driver bug?).\n", buf->state); - ret = -EINVAL; - goto done; - } - - list_del(&buf->stream); - __uvc_query_buffer(buf, v4l2_buf); - -done: + ret = vb2_dqbuf(&queue->queue, buf, nonblocking); mutex_unlock(&queue->mutex); + return ret; } @@ -361,103 +208,27 @@ done: * This function implements video queue polling and is intended to be used by * the device poll handler. */ -static unsigned int -uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, - poll_table *wait) +static unsigned int uvc_queue_poll(struct uvc_video_queue *queue, + struct file *file, poll_table *wait) { - struct uvc_buffer *buf; - unsigned int mask = 0; + unsigned int ret; mutex_lock(&queue->mutex); - if (list_empty(&queue->mainqueue)) - goto done; - - buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); - - poll_wait(file, &buf->wait, wait); - if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) - mask |= POLLOUT | POLLWRNORM; - -done: + ret = vb2_poll(&queue->queue, file, wait); mutex_unlock(&queue->mutex); - return mask; + + return ret; } -/* - * VMA operations. - */ -static void uvc_vm_open(struct vm_area_struct *vma) +static int uvc_queue_mmap(struct uvc_video_queue *queue, + struct vm_area_struct *vma) { - struct uvc_buffer *buffer = vma->vm_private_data; - buffer->vma_use_count++; -} - -static void uvc_vm_close(struct vm_area_struct *vma) -{ - struct uvc_buffer *buffer = vma->vm_private_data; - buffer->vma_use_count--; -} - -static struct vm_operations_struct uvc_vm_ops = { - .open = uvc_vm_open, - .close = uvc_vm_close, -}; - -/* - * Memory-map a buffer. - * - * This function implements video buffer memory mapping and is intended to be - * used by the device mmap handler. - */ -static int -uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) -{ - struct uvc_buffer *uninitialized_var(buffer); - struct page *page; - unsigned long addr, start, size; - unsigned int i; - int ret = 0; - - start = vma->vm_start; - size = vma->vm_end - vma->vm_start; + int ret; mutex_lock(&queue->mutex); - - for (i = 0; i < queue->count; ++i) { - buffer = &queue->buffer[i]; - if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) - break; - } - - if (i == queue->count || size != queue->buf_size) { - ret = -EINVAL; - goto done; - } - - /* - * VM_IO marks the area as being an mmaped region for I/O to a - * device. It also prevents the region from being core dumped. - */ - vma->vm_flags |= VM_IO; - - addr = (unsigned long)queue->mem + buffer->buf.m.offset; - while (size > 0) { - page = vmalloc_to_page((void *)addr); - if ((ret = vm_insert_page(vma, start, page)) < 0) - goto done; - - start += PAGE_SIZE; - addr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &uvc_vm_ops; - vma->vm_private_data = buffer; - uvc_vm_open(vma); - -done: + ret = vb2_mmap(&queue->queue, vma); mutex_unlock(&queue->mutex); + return ret; } @@ -484,7 +255,7 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) queue); list_del(&buf->queue); buf->state = UVC_BUF_STATE_ERROR; - wake_up(&buf->wait); + vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); } /* This must be protected by the irqlock spinlock to avoid race * conditions between uvc_queue_buffer and the disconnection event that @@ -516,26 +287,33 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) */ static int uvc_queue_enable(struct uvc_video_queue *queue, int enable) { - unsigned int i; + unsigned long flags; int ret = 0; mutex_lock(&queue->mutex); if (enable) { - if (uvc_queue_streaming(queue)) { - ret = -EBUSY; + ret = vb2_streamon(&queue->queue, queue->queue.type); + if (ret < 0) goto done; - } + queue->sequence = 0; - queue->flags |= UVC_QUEUE_STREAMING; queue->buf_used = 0; } else { - uvc_queue_cancel(queue, 0); - INIT_LIST_HEAD(&queue->mainqueue); + ret = vb2_streamoff(&queue->queue, queue->queue.type); + if (ret < 0) + goto done; - for (i = 0; i < queue->count; ++i) - queue->buffer[i].state = UVC_BUF_STATE_IDLE; + spin_lock_irqsave(&queue->irqlock, flags); + INIT_LIST_HEAD(&queue->irqqueue); - queue->flags &= ~UVC_QUEUE_STREAMING; + /* + * FIXME: We need to clear the DISCONNECTED flag to ensure that + * applications will be able to queue buffers for the next + * streaming run. However, clearing it here doesn't guarantee + * that the device will be reconnected in the meantime. + */ + queue->flags &= ~UVC_QUEUE_DISCONNECTED; + spin_unlock_irqrestore(&queue->irqlock, flags); } done: @@ -544,15 +322,15 @@ done: } /* called with &queue_irqlock held.. */ -static struct uvc_buffer * -uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) +static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, + struct uvc_buffer *buf) { struct uvc_buffer *nextbuf; if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && - buf->buf.length != buf->buf.bytesused) { + buf->length != buf->bytesused) { buf->state = UVC_BUF_STATE_QUEUED; - buf->buf.bytesused = 0; + vb2_set_plane_payload(&buf->buf, 0, 0); return buf; } @@ -563,10 +341,18 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) else nextbuf = NULL; - buf->buf.sequence = queue->sequence++; - do_gettimeofday(&buf->buf.timestamp); + /* + * FIXME: with videobuf2, the sequence number or timestamp fields + * are valid only for video capture devices and the UVC gadget usually + * is a video output device. Keeping these until the specs are clear on + * this aspect. + */ + buf->buf.v4l2_buf.sequence = queue->sequence++; + do_gettimeofday(&buf->buf.v4l2_buf.timestamp); + + vb2_set_plane_payload(&buf->buf, 0, buf->bytesused); + vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE); - wake_up(&buf->wait); return nextbuf; } diff --git a/drivers/usb/gadget/uvc_queue.h b/drivers/usb/gadget/uvc_queue.h index 1812a8ecc5d0..8e76ce982f1e 100644 --- a/drivers/usb/gadget/uvc_queue.h +++ b/drivers/usb/gadget/uvc_queue.h @@ -6,6 +6,7 @@ #include #include #include +#include /* Maximum frame size in bytes, for sanity checking. */ #define UVC_MAX_FRAME_SIZE (16*1024*1024) @@ -25,42 +26,35 @@ enum uvc_buffer_state { }; struct uvc_buffer { - unsigned long vma_use_count; - struct list_head stream; - - /* Touched by interrupt handler. */ - struct v4l2_buffer buf; + struct vb2_buffer buf; struct list_head queue; - wait_queue_head_t wait; + enum uvc_buffer_state state; + void *mem; + unsigned int length; + unsigned int bytesused; }; -#define UVC_QUEUE_STREAMING (1 << 0) -#define UVC_QUEUE_DISCONNECTED (1 << 1) -#define UVC_QUEUE_DROP_INCOMPLETE (1 << 2) -#define UVC_QUEUE_PAUSED (1 << 3) +#define UVC_QUEUE_DISCONNECTED (1 << 0) +#define UVC_QUEUE_DROP_INCOMPLETE (1 << 1) +#define UVC_QUEUE_PAUSED (1 << 2) struct uvc_video_queue { - enum v4l2_buf_type type; + struct vb2_queue queue; + struct mutex mutex; /* Protects queue */ - void *mem; unsigned int flags; __u32 sequence; - unsigned int count; - unsigned int buf_size; unsigned int buf_used; - struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS]; - struct mutex mutex; /* protects buffers and mainqueue */ - spinlock_t irqlock; /* protects irqqueue */ - struct list_head mainqueue; + spinlock_t irqlock; /* Protects flags and irqqueue */ struct list_head irqqueue; }; static inline int uvc_queue_streaming(struct uvc_video_queue *queue) { - return queue->flags & UVC_QUEUE_STREAMING; + return vb2_is_streaming(&queue->queue); } #endif /* __KERNEL__ */ diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index bb140dd93164..c058867ea4fb 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -147,16 +147,13 @@ uvc_v4l2_release(struct file *file) uvc_function_disconnect(uvc); uvc_video_enable(video, 0); - mutex_lock(&video->queue.mutex); - if (uvc_free_buffers(&video->queue) < 0) - printk(KERN_ERR "uvc_v4l2_release: Unable to free " - "buffers.\n"); - mutex_unlock(&video->queue.mutex); + uvc_free_buffers(&video->queue); file->private_data = NULL; v4l2_fh_del(&handle->vfh); v4l2_fh_exit(&handle->vfh); kfree(handle); + return 0; } @@ -191,7 +188,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_format *fmt = arg; - if (fmt->type != video->queue.type) + if (fmt->type != video->queue.queue.type) return -EINVAL; return uvc_v4l2_get_format(video, fmt); @@ -201,7 +198,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_format *fmt = arg; - if (fmt->type != video->queue.type) + if (fmt->type != video->queue.queue.type) return -EINVAL; return uvc_v4l2_set_format(video, fmt); @@ -212,16 +209,13 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_requestbuffers *rb = arg; - if (rb->type != video->queue.type || - rb->memory != V4L2_MEMORY_MMAP) + if (rb->type != video->queue.queue.type) return -EINVAL; - ret = uvc_alloc_buffers(&video->queue, rb->count, - video->imagesize); + ret = uvc_alloc_buffers(&video->queue, rb); if (ret < 0) return ret; - rb->count = ret; ret = 0; break; } @@ -230,9 +224,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { struct v4l2_buffer *buf = arg; - if (buf->type != video->queue.type) - return -EINVAL; - return uvc_query_buffer(&video->queue, buf); } @@ -250,7 +241,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { int *type = arg; - if (*type != video->queue.type) + if (*type != video->queue.queue.type) return -EINVAL; /* Enable UVC video. */ @@ -272,14 +263,14 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) { int *type = arg; - if (*type != video->queue.type) + if (*type != video->queue.queue.type) return -EINVAL; return uvc_video_enable(video, 0); } /* Events */ - case VIDIOC_DQEVENT: + case VIDIOC_DQEVENT: { struct v4l2_event *event = arg; @@ -344,16 +335,8 @@ uvc_v4l2_poll(struct file *file, poll_table *wait) { struct video_device *vdev = video_devdata(file); struct uvc_device *uvc = video_get_drvdata(vdev); - struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); - unsigned int mask = 0; - poll_wait(file, &handle->vfh.wait, wait); - if (v4l2_event_pending(&handle->vfh)) - mask |= POLLPRI; - - mask |= uvc_queue_poll(&uvc->video.queue, file, wait); - - return mask; + return uvc_queue_poll(&uvc->video.queue, file, wait); } static struct v4l2_file_operations uvc_v4l2_fops = { diff --git a/drivers/usb/gadget/uvc_video.c b/drivers/usb/gadget/uvc_video.c index ec4bcc4a2290..71e896d4c5ae 100644 --- a/drivers/usb/gadget/uvc_video.c +++ b/drivers/usb/gadget/uvc_video.c @@ -32,7 +32,7 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf, data[0] = 2; data[1] = UVC_STREAM_EOH | video->fid; - if (buf->buf.bytesused - video->queue.buf_used <= len - 2) + if (buf->bytesused - video->queue.buf_used <= len - 2) data[1] |= UVC_STREAM_EOF; return 2; @@ -47,8 +47,8 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf, void *mem; /* Copy video data to the USB buffer. */ - mem = queue->mem + buf->buf.m.offset + queue->buf_used; - nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used); + mem = buf->mem + queue->buf_used; + nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used); memcpy(data, mem, nbytes); queue->buf_used += nbytes; @@ -82,7 +82,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, req->length = video->req_size - len; req->zero = video->payload_size == video->max_payload_size; - if (buf->buf.bytesused == video->queue.buf_used) { + if (buf->bytesused == video->queue.buf_used) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; uvc_queue_next_buffer(&video->queue, buf); @@ -92,7 +92,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, } if (video->payload_size == video->max_payload_size || - buf->buf.bytesused == video->queue.buf_used) + buf->bytesused == video->queue.buf_used) video->payload_size = 0; } @@ -115,7 +115,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, req->length = video->req_size - len; - if (buf->buf.bytesused == video->queue.buf_used) { + if (buf->bytesused == video->queue.buf_used) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; uvc_queue_next_buffer(&video->queue, buf); @@ -161,6 +161,7 @@ static void uvc_video_complete(struct usb_ep *ep, struct usb_request *req) { struct uvc_video *video = req->context; + struct uvc_video_queue *queue = &video->queue; struct uvc_buffer *buf; unsigned long flags; int ret; @@ -169,13 +170,15 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) case 0: break; - case -ESHUTDOWN: + case -ESHUTDOWN: /* disconnect from host. */ printk(KERN_INFO "VS request cancelled.\n"); + uvc_queue_cancel(queue, 1); goto requeue; default: printk(KERN_INFO "VS request completed with status %d.\n", req->status); + uvc_queue_cancel(queue, 0); goto requeue; } From 2f1d57069338b14fcf4765ae2c25fc377da45b1f Mon Sep 17 00:00:00 2001 From: Bhupesh Sharma Date: Thu, 28 Mar 2013 15:11:53 +0530 Subject: [PATCH 265/303] usb: gadget/uvc: Add support for 'get_unmapped_area' for MMUless architectures This patch adds the support for 'get_unmapped_area' in UVC gadget which is called when the 'mmap' system call is executed on MMUless architectures. Signed-off-by: Bhupesh Sharma Signed-off-by: Laurent Pinchart --- drivers/usb/gadget/uvc_queue.c | 18 ++++++++++++++++++ drivers/usb/gadget/uvc_v4l2.c | 15 +++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c index 31397954c889..7ce27e35550b 100644 --- a/drivers/usb/gadget/uvc_queue.c +++ b/drivers/usb/gadget/uvc_queue.c @@ -232,6 +232,24 @@ static int uvc_queue_mmap(struct uvc_video_queue *queue, return ret; } +#ifndef CONFIG_MMU +/* + * Get unmapped area. + * + * NO-MMU arch need this function to make mmap() work correctly. + */ +static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, + unsigned long pgoff) +{ + unsigned long ret; + + mutex_lock(&queue->mutex); + ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); + mutex_unlock(&queue->mutex); + return ret; +} +#endif + /* * Cancel the video buffers queue. * diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index c058867ea4fb..ad48e81155e2 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -339,6 +339,18 @@ uvc_v4l2_poll(struct file *file, poll_table *wait) return uvc_queue_poll(&uvc->video.queue, file, wait); } +#ifndef CONFIG_MMU +static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct video_device *vdev = video_devdata(file); + struct uvc_device *uvc = video_get_drvdata(vdev); + + return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff); +} +#endif + static struct v4l2_file_operations uvc_v4l2_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, @@ -346,5 +358,8 @@ static struct v4l2_file_operations uvc_v4l2_fops = { .ioctl = uvc_v4l2_ioctl, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, +#ifndef CONFIG_MMU + .get_unmapped_area = uvc_v4l2_get_unmapped_area, +#endif }; From 8408fd1d83e39bf856d31a36b70bcc53527702fd Mon Sep 17 00:00:00 2001 From: Ruslan Bilovol Date: Fri, 29 Mar 2013 19:15:21 +0200 Subject: [PATCH 266/303] usb: musb: implement (un)map_urb_for_dma hooks MUSB controller cannot work in DMA mode with misaligned buffers, switching in PIO mode. HCD core has hooks that allow to override the default DMA mapping and unmapping routines for host controllers that have special DMA requirements, such as alignment constraints. It is observed that work in PIO mode is slow and it's better to align buffers properly before passing them to MUSB This increased throughput 80->120 MBits/s over musb@omap4 with USB Gigabit Ethernet adapter attached. Some ideas are taken from ehci-tegra.c Signed-off-by: Ruslan Bilovol Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_host.c | 117 +++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 51e9e8a38444..8914dec49f01 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2465,6 +2465,118 @@ static int musb_bus_resume(struct usb_hcd *hcd) return 0; } + +#ifndef CONFIG_MUSB_PIO_ONLY + +#define MUSB_USB_DMA_ALIGN 4 + +struct musb_temp_buffer { + void *kmalloc_ptr; + void *old_xfer_buffer; + u8 data[0]; +}; + +static void musb_free_temp_buffer(struct urb *urb) +{ + enum dma_data_direction dir; + struct musb_temp_buffer *temp; + + if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) + return; + + dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + + temp = container_of(urb->transfer_buffer, struct musb_temp_buffer, + data); + + if (dir == DMA_FROM_DEVICE) { + memcpy(temp->old_xfer_buffer, temp->data, + urb->transfer_buffer_length); + } + urb->transfer_buffer = temp->old_xfer_buffer; + kfree(temp->kmalloc_ptr); + + urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; +} + +static int musb_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags) +{ + enum dma_data_direction dir; + struct musb_temp_buffer *temp; + void *kmalloc_ptr; + size_t kmalloc_size; + + if (urb->num_sgs || urb->sg || + urb->transfer_buffer_length == 0 || + !((uintptr_t)urb->transfer_buffer & (MUSB_USB_DMA_ALIGN - 1))) + return 0; + + dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + + /* Allocate a buffer with enough padding for alignment */ + kmalloc_size = urb->transfer_buffer_length + + sizeof(struct musb_temp_buffer) + MUSB_USB_DMA_ALIGN - 1; + + kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); + if (!kmalloc_ptr) + return -ENOMEM; + + /* Position our struct temp_buffer such that data is aligned */ + temp = PTR_ALIGN(kmalloc_ptr, MUSB_USB_DMA_ALIGN); + + + temp->kmalloc_ptr = kmalloc_ptr; + temp->old_xfer_buffer = urb->transfer_buffer; + if (dir == DMA_TO_DEVICE) + memcpy(temp->data, urb->transfer_buffer, + urb->transfer_buffer_length); + urb->transfer_buffer = temp->data; + + urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; + + return 0; +} + +static int musb_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, + gfp_t mem_flags) +{ + struct musb *musb = hcd_to_musb(hcd); + int ret; + + /* + * The DMA engine in RTL1.8 and above cannot handle + * DMA addresses that are not aligned to a 4 byte boundary. + * For such engine implemented (un)map_urb_for_dma hooks. + * Do not use these hooks for RTL<1.8 + */ + if (musb->hwvers < MUSB_HWVERS_1800) + return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); + + ret = musb_alloc_temp_buffer(urb, mem_flags); + if (ret) + return ret; + + ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); + if (ret) + musb_free_temp_buffer(urb); + + return ret; +} + +static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) +{ + struct musb *musb = hcd_to_musb(hcd); + + usb_hcd_unmap_urb_for_dma(hcd, urb); + + /* Do not use this hook for RTL<1.8 (see description above) */ + if (musb->hwvers < MUSB_HWVERS_1800) + return; + + musb_free_temp_buffer(urb); +} +#endif /* !CONFIG_MUSB_PIO_ONLY */ + const struct hc_driver musb_hc_driver = { .description = "musb-hcd", .product_desc = "MUSB HDRC host driver", @@ -2484,6 +2596,11 @@ const struct hc_driver musb_hc_driver = { .urb_dequeue = musb_urb_dequeue, .endpoint_disable = musb_h_disable, +#ifndef CONFIG_MUSB_PIO_ONLY + .map_urb_for_dma = musb_map_urb_for_dma, + .unmap_urb_for_dma = musb_unmap_urb_for_dma, +#endif + .hub_status_data = musb_hub_status_data, .hub_control = musb_hub_control, .bus_suspend = musb_bus_suspend, From 96449f097e3874af0e8ddd721d3ebeed2ec389da Mon Sep 17 00:00:00 2001 From: Ravi Babu Date: Tue, 2 Apr 2013 13:21:54 +0530 Subject: [PATCH 267/303] usb: musb: dsps: print babble message only when musb is active host The musb controller uses single bit defintion for both reset and babble events. The babble event is valid only when controller is active a-host, and hence print the babble message only when the controller is active a-host. Signed-off-by: Ravi Babu Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 1ea553d2b77f..3a18e44e9391 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -335,7 +335,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set. * Also, DRVVBUS pulses for SRP (but not at 5V) ... */ - if (usbintr & MUSB_INTR_BABBLE) + if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE) pr_info("CAUTION: musb: Babble Interrupt Occurred\n"); if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) { From 538bf07d897008e87eca49cde5970545f3814ac7 Mon Sep 17 00:00:00 2001 From: Ravi Babu Date: Tue, 2 Apr 2013 13:22:42 +0530 Subject: [PATCH 268/303] usb: musb: gadget: read ep0 fifo only if rxcount is non zero avoid reading fifo rxcount is zero of fifo is empty, hence read fifo only if rxcount is non-zero Signed-off-by: Ravi Babu Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget_ep0.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index c9c1ac4e075f..2af45a0c8930 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -505,8 +505,10 @@ static void ep0_rxstate(struct musb *musb) req->status = -EOVERFLOW; count = len; } - musb_read_fifo(&musb->endpoints[0], count, buf); - req->actual += count; + if (count > 0) { + musb_read_fifo(&musb->endpoints[0], count, buf); + req->actual += count; + } csr = MUSB_CSR0_P_SVDRXPKTRDY; if (count < 64 || req->actual == req->length) { musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; From 19fda7cd59eac8e537f63a4d9bd5973bf78a8c38 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 26 Mar 2013 01:52:48 +0000 Subject: [PATCH 269/303] usb: dwc3: add CONFIG_PM_SLEEP to suspend/resume functions Add CONFIG_PM_SLEEP to suspend/resume functions to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SET_SYSTEM_SLEEP_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. Unnecessary CONFIG_PM ifdefs are removed. drivers/usb/dwc3/core.c:682:12: warning: 'dwc3_suspend' defined but not used [-Wunused-function] drivers/usb/dwc3/core.c:709:12: warning: 'dwc3_resume' defined but not used [-Wunused-function] drivers/usb/dwc3/dwc3-omap.c:430:12: warning: 'dwc3_omap_suspend' defined but not used [-Wunused-function] drivers/usb/dwc3/dwc3-omap.c:440:12: warning: 'dwc3_omap_resume' defined but not used [-Wunused-function] drivers/usb/dwc3/dwc3-exynos.c:185:12: warning: 'dwc3_exynos_suspend' defined but not used [-Wunused-function] drivers/usb/dwc3/dwc3-exynos.c:194:12: warning: 'dwc3_exynos_resume' defined but not used [-Wunused-function] Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 2 +- drivers/usb/dwc3/dwc3-exynos.c | 4 ++-- drivers/usb/dwc3/dwc3-omap.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index e2325adf9c14..c35d49d39b76 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -634,7 +634,7 @@ static int dwc3_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int dwc3_prepare(struct device *dev) { struct dwc3 *dwc = dev_get_drvdata(dev); diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index 1ea7bd8af6ae..a8afe6e26621 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -181,7 +181,7 @@ static const struct of_device_id exynos_dwc3_match[] = { MODULE_DEVICE_TABLE(of, exynos_dwc3_match); #endif -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int dwc3_exynos_suspend(struct device *dev) { struct dwc3_exynos *exynos = dev_get_drvdata(dev); @@ -212,7 +212,7 @@ static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = { #define DEV_PM_OPS (&dwc3_exynos_dev_pm_ops) #else #define DEV_PM_OPS NULL -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */ static struct platform_driver dwc3_exynos_driver = { .probe = dwc3_exynos_probe, diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 6de734f494bd..34638b92500d 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -410,7 +410,7 @@ static const struct of_device_id of_dwc3_match[] = { }; MODULE_DEVICE_TABLE(of, of_dwc3_match); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int dwc3_omap_prepare(struct device *dev) { struct dwc3_omap *omap = dev_get_drvdata(dev); @@ -461,7 +461,7 @@ static const struct dev_pm_ops dwc3_omap_dev_pm_ops = { #define DEV_PM_OPS (&dwc3_omap_dev_pm_ops) #else #define DEV_PM_OPS NULL -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */ static struct platform_driver dwc3_omap_driver = { .probe = dwc3_omap_probe, From 9770a16fd9d9c5a91378d53732be1d2ec599bfcf Mon Sep 17 00:00:00 2001 From: Yuan-Hsin Chen Date: Tue, 2 Apr 2013 11:15:28 +0000 Subject: [PATCH 270/303] usb: gadget: fusb300_udc: add FUSB300_EPSET0_STL_CLR for clearing EP0 stall The final version of fusb300 controller adds EPSET0_STL_CLR for clearing EP0 stall and also removes EPSET0_EPn_TX0BYTE. fusb300_udc driver is tested on FARADAY platform a369 with FUSB300 FPGA v1.8 Signed-off-by: Yuan-Hsin Chen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fusb300_udc.c | 2 +- drivers/usb/gadget/fusb300_udc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index d05355389dd6..db0d2917987a 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep) if (reg & FUSB300_EPSET0_STL) { printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep); - reg &= ~FUSB300_EPSET0_STL; + reg |= FUSB300_EPSET0_STL_CLR; iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep)); } } diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h index 6ba444ae8dd5..ae811d8d38b4 100644 --- a/drivers/usb/gadget/fusb300_udc.h +++ b/drivers/usb/gadget/fusb300_udc.h @@ -111,8 +111,8 @@ /* * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 ) * */ +#define FUSB300_EPSET0_STL_CLR (1 << 3) #define FUSB300_EPSET0_CLRSEQNUM (1 << 2) -#define FUSB300_EPSET0_EPn_TX0BYTE (1 << 1) #define FUSB300_EPSET0_STL (1 << 0) /* From 1cb5e9ee033f89d3241013cfff8300cc0195a62d Mon Sep 17 00:00:00 2001 From: Yuan-Hsin Chen Date: Tue, 2 Apr 2013 11:18:08 +0000 Subject: [PATCH 271/303] usb: gadget: fusb300_udc: bug fix of not doing idma reset for each time Enter IDMA_RESET only when the controller has been reset or the device has been plugged in to or out from a host. In IDMA_RESET, we should disable the corresponding PRD interrupt. Also there is a redundant space eliminated. fusb300_udc driver is tested on FARADAY platform a369 with FUSB300 FPGA v1.8 Signed-off-by: Yuan-Hsin Chen Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fusb300_udc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index db0d2917987a..cec8871b77f9 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -930,12 +930,15 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep) fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0, FUSB300_IGR0_EPn_PRD_INT(ep->epnum)); + return; + IDMA_RESET: - fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0, - FUSB300_IGER0_EEPn_PRD_INT(ep->epnum)); + reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0); + reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum); + iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0); } -static void fusb300_set_idma(struct fusb300_ep *ep, +static void fusb300_set_idma(struct fusb300_ep *ep, struct fusb300_request *req) { int ret; From c5dbc220b327dc1ff5e0b1d829c091347511ed83 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 2 Apr 2013 17:06:28 +0300 Subject: [PATCH 272/303] usb: gadget: udc-core: prevent a memory leak udc-core would leak 'udc' memory in some error cases. Fix it by kfree()ing udc on error path. Reported-by: Dan Carpenter Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 7999cc656979..c6c2b5611b43 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -240,6 +240,7 @@ err3: err2: put_device(&gadget->dev); + kfree(udc); err1: return ret; From 50757b24944ede7ab07165cdb57c995456b6e916 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 2 Apr 2013 17:13:40 +0300 Subject: [PATCH 273/303] usb: gadget: pxa27x_udc: fix Section Mismatches Remove all section annotations to fix the following section mismatches: >> WARNING: drivers/usb/gadget/pxa27x_udc.o(.text+0x597c): Section mismatch in reference from the function .pxa_udc_probe() to the function .init.text:.udc_init_data.constprop.11() The function .pxa_udc_probe() references the function __init .udc_init_data.constprop.11(). This is often because .pxa_udc_probe lacks a __init annotation or the annotation of .udc_init_data.constprop.11 is wrong. -- >> WARNING: drivers/usb/gadget/pxa27x_udc.o(.text+0x5a04): Section mismatch in reference from the function .pxa_udc_probe() to the function .init.text:.pxa_ep_setup() The function .pxa_udc_probe() references the function __init .pxa_ep_setup(). This is often because .pxa_udc_probe lacks a __init annotation or the annotation of .pxa_ep_setup is wrong. Reported-by: Fengguang Wu Signed-off-by: Felipe Balbi --- drivers/usb/gadget/pxa27x_udc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index ad954c49d061..6b4c7d95853f 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -609,7 +609,7 @@ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in) * * Find the physical pxa27x ep, and setup its UDCCR */ -static __init void pxa_ep_setup(struct pxa_ep *ep) +static void pxa_ep_setup(struct pxa_ep *ep) { u32 new_udccr; @@ -631,7 +631,7 @@ static __init void pxa_ep_setup(struct pxa_ep *ep) * * Setup all pxa physical endpoints, except ep0 */ -static __init void pxa_eps_setup(struct pxa_udc *dev) +static void pxa_eps_setup(struct pxa_udc *dev) { unsigned int i; @@ -1716,7 +1716,7 @@ static void udc_disable(struct pxa_udc *udc) * Initializes gadget endpoint list, endpoints locks. No action is taken * on the hardware. */ -static __init void udc_init_data(struct pxa_udc *dev) +static void udc_init_data(struct pxa_udc *dev) { int i; struct pxa_ep *ep; @@ -2490,7 +2490,7 @@ err_clk: * pxa_udc_remove - removes the udc device driver * @_dev: platform device */ -static int __exit pxa_udc_remove(struct platform_device *_dev) +static int pxa_udc_remove(struct platform_device *_dev) { struct pxa_udc *udc = platform_get_drvdata(_dev); int gpio = udc->mach->gpio_pullup; @@ -2609,7 +2609,7 @@ static struct platform_driver udc_driver = { .owner = THIS_MODULE, }, .probe = pxa_udc_probe, - .remove = __exit_p(pxa_udc_remove), + .remove = pxa_udc_remove, .shutdown = pxa_udc_shutdown, #ifdef CONFIG_PM .suspend = pxa_udc_suspend, From f4362b1dd7262e3c81f295154b601065f8810186 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Tue, 26 Mar 2013 14:44:03 +0530 Subject: [PATCH 274/303] usb: phy: samsung: convert to devm_ioremap_resource() Use the newly introduced devm_ioremap_resource() instead of devm_request_and_ioremap() which provides more consistent error handling. devm_ioremap_resource() provides its own error messages; so all explicit error messages can be removed from the failure code paths. Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-samsung-usb3.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c index 54f641860f9e..133f3d0c554f 100644 --- a/drivers/usb/phy/phy-samsung-usb3.c +++ b/drivers/usb/phy/phy-samsung-usb3.c @@ -244,11 +244,9 @@ static int samsung_usb3phy_probe(struct platform_device *pdev) return -ENODEV; } - phy_base = devm_request_and_ioremap(dev, phy_mem); - if (!phy_base) { - dev_err(dev, "%s: register mapping failed\n", __func__); - return -ENXIO; - } + phy_base = devm_ioremap_resource(dev, phy_mem); + if (IS_ERR(phy_base)) + return PTR_ERR(phy_base); sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); if (!sphy) From 3ee1f2e6e51581d5cb9c312161a9a9b2f18f25bf Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 3 Apr 2013 10:45:02 +0200 Subject: [PATCH 275/303] usb: musb: ux500_dma: drop references to U5500 Drop references to deprecated U5500 platform in driver comments. Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/musb/ux500_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index f417b7e49bb5..338120641145 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -1,7 +1,7 @@ /* * drivers/usb/musb/ux500_dma.c * - * U8500 and U5500 DMA support code + * U8500 DMA support code * * Copyright (C) 2009 STMicroelectronics * Copyright (C) 2011 ST-Ericsson SA From 81ef6724302e0c7ba3f087403de24760601b1839 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 3 Apr 2013 10:45:03 +0200 Subject: [PATCH 276/303] usb: phy: ab8500-usb: convert to devm_kzalloc Convert local data allocation to devm_kzalloc and drop unnecessary fail path code. Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 351b0369a611..ab6dd072ae25 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -628,15 +628,13 @@ static int ab8500_usb_probe(struct platform_device *pdev) return -ENODEV; } - ab = kzalloc(sizeof *ab, GFP_KERNEL); + ab = devm_kzalloc(&pdev->dev, sizeof(*ab), GFP_KERNEL); if (!ab) return -ENOMEM; - otg = kzalloc(sizeof *otg, GFP_KERNEL); - if (!otg) { - kfree(ab); + otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); + if (!otg) return -ENOMEM; - } ab->dev = &pdev->dev; ab->ab8500 = ab8500; @@ -665,12 +663,12 @@ static int ab8500_usb_probe(struct platform_device *pdev) err = ab8500_usb_irq_setup(pdev, ab); if (err < 0) - goto fail; + return err; err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2); if (err) { dev_err(&pdev->dev, "Can't register transceiver\n"); - goto fail; + return err; } /* Needed to enable ID detection. */ @@ -679,10 +677,6 @@ static int ab8500_usb_probe(struct platform_device *pdev) dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev); return 0; -fail: - kfree(otg); - kfree(ab); - return err; } static int ab8500_usb_remove(struct platform_device *pdev) @@ -700,9 +694,6 @@ static int ab8500_usb_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - kfree(ab->phy.otg); - kfree(ab); - return 0; } From 7124631aa892712fc8b317ff34d25c14dee6f63d Mon Sep 17 00:00:00 2001 From: Sakethram Bommisetti Date: Wed, 3 Apr 2013 10:45:04 +0200 Subject: [PATCH 277/303] usb: phy: ab8500-usb: set phy tuning values Set phy tuning values proposed by the hardware teams for AB8500 and AB8505 to improve USB eye diagram performances. Signed-off-by: Sakethram Bommisetti Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 87 ++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index ab6dd072ae25..5b92a59804eb 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -33,11 +33,22 @@ #include #include +/* Bank AB8500_SYS_CTRL2_BLOCK */ #define AB8500_MAIN_WD_CTRL_REG 0x01 + +/* Bank AB8500_USB */ #define AB8500_USB_LINE_STAT_REG 0x80 #define AB8505_USB_LINE_STAT_REG 0x94 #define AB8500_USB_PHY_CTRL_REG 0x8A +/* Bank AB8500_DEVELOPMENT */ +#define AB8500_BANK12_ACCESS 0x00 + +/* Bank AB8500_DEBUG */ +#define AB8500_USB_PHY_TUNE1 0x05 +#define AB8500_USB_PHY_TUNE2 0x06 +#define AB8500_USB_PHY_TUNE3 0x07 + #define AB8500_BIT_OTG_STAT_ID (1 << 0) #define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0) #define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1) @@ -671,6 +682,82 @@ static int ab8500_usb_probe(struct platform_device *pdev) return err; } + /* Phy tuning values for AB8500 */ + if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { + /* Enable the PBT/Bank 0x12 access */ + err = abx500_set_register_interruptible(ab->dev, + AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01); + if (err < 0) + dev_err(ab->dev, "Failed to enable bank12 access err=%d\n", + err); + + err = abx500_set_register_interruptible(ab->dev, + AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8); + if (err < 0) + dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n", + err); + + err = abx500_set_register_interruptible(ab->dev, + AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x00); + if (err < 0) + dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n", + err); + + err = abx500_set_register_interruptible(ab->dev, + AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78); + if (err < 0) + dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n", + err); + + /* Switch to normal mode/disable Bank 0x12 access */ + err = abx500_set_register_interruptible(ab->dev, + AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x00); + if (err < 0) + dev_err(ab->dev, "Failed to switch bank12 access err=%d\n", + err); + } + + /* Phy tuning values for AB8505 */ + if (is_ab8505(ab->ab8500)) { + /* Enable the PBT/Bank 0x12 access */ + err = abx500_mask_and_set_register_interruptible(ab->dev, + AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, + 0x01, 0x01); + if (err < 0) + dev_err(ab->dev, "Failed to enable bank12 access err=%d\n", + err); + + err = abx500_mask_and_set_register_interruptible(ab->dev, + AB8500_DEBUG, AB8500_USB_PHY_TUNE1, + 0xC8, 0xC8); + if (err < 0) + dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n", + err); + + err = abx500_mask_and_set_register_interruptible(ab->dev, + AB8500_DEBUG, AB8500_USB_PHY_TUNE2, + 0x60, 0x60); + if (err < 0) + dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n", + err); + + err = abx500_mask_and_set_register_interruptible(ab->dev, + AB8500_DEBUG, AB8500_USB_PHY_TUNE3, + 0xFC, 0x80); + + if (err < 0) + dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n", + err); + + /* Switch to normal mode/disable Bank 0x12 access */ + err = abx500_mask_and_set_register_interruptible(ab->dev, + AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, + 0x00, 0x00); + if (err < 0) + dev_err(ab->dev, "Failed to switch bank12 access err=%d\n", + err); + } + /* Needed to enable ID detection. */ ab8500_usb_wd_workaround(ab); From c2a0ab6bd5ccf031f87bc678152fb70befea5786 Mon Sep 17 00:00:00 2001 From: Sakethram Bommisetti Date: Wed, 3 Apr 2013 10:45:05 +0200 Subject: [PATCH 278/303] usb: phy: ab8500-usb: fix eye diagram for ab8500 v2.0 AB8500 v2.0 has eye diagram issues when drawing more than 100mA from VBUS. Force charging current to 100mA in case of standard host. Signed-off-by: Sakethram Bommisetti Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 5b92a59804eb..441b2954cffd 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -485,6 +485,19 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work) ab8500_usb_peri_phy_dis(ab); } +static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA) +{ + /* + * AB8500 V2 has eye diagram issues when drawing more than 100mA from + * VBUS. Set charging current to 100mA in case of standard host + */ + if (is_ab8500_2p0_or_earlier(ab->ab8500)) + if (mA > 100) + mA = 100; + + return mA; +} + static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA) { struct ab8500_usb *ab; @@ -494,6 +507,8 @@ static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA) ab = phy_to_ab(phy); + mA = ab8500_eyediagram_workaroud(ab, mA); + ab->vbus_draw = mA; if (mA) From e65b36c02613764aa703ef0be0a3c2c57ea91625 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 3 Apr 2013 10:45:06 +0200 Subject: [PATCH 279/303] usb: phy: ab8500-usb: add regulator support Add initial regulator support to ab8500-usb by introducing necessary devm_regulator_get(). Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 441b2954cffd..1bc24d4c25e7 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -32,6 +32,7 @@ #include #include #include +#include /* Bank AB8500_SYS_CTRL2_BLOCK */ #define AB8500_MAIN_WD_CTRL_REG 0x01 @@ -126,6 +127,9 @@ struct ab8500_usb { struct work_struct phy_dis_work; unsigned long link_status_wait; enum ab8500_usb_mode mode; + struct regulator *v_ape; + struct regulator *v_musb; + struct regulator *v_ulpi; int previous_link_status_state; }; @@ -590,6 +594,34 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) return 0; } +static int ab8500_usb_regulator_get(struct ab8500_usb *ab) +{ + int err; + + ab->v_ape = devm_regulator_get(ab->dev, "v-ape"); + if (IS_ERR(ab->v_ape)) { + dev_err(ab->dev, "Could not get v-ape supply\n"); + err = PTR_ERR(ab->v_ape); + return err; + } + + ab->v_ulpi = devm_regulator_get(ab->dev, "vddulpivio18"); + if (IS_ERR(ab->v_ulpi)) { + dev_err(ab->dev, "Could not get vddulpivio18 supply\n"); + err = PTR_ERR(ab->v_ulpi); + return err; + } + + ab->v_musb = devm_regulator_get(ab->dev, "musb_1v8"); + if (IS_ERR(ab->v_musb)) { + dev_err(ab->dev, "Could not get musb_1v8 supply\n"); + err = PTR_ERR(ab->v_musb); + return err; + } + + return 0; +} + static int ab8500_usb_irq_setup(struct platform_device *pdev, struct ab8500_usb *ab) { @@ -687,6 +719,10 @@ static int ab8500_usb_probe(struct platform_device *pdev) /* all: Disable phy when called from set_host and set_peripheral */ INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); + err = ab8500_usb_regulator_get(ab); + if (err) + return err; + err = ab8500_usb_irq_setup(pdev, ab); if (err < 0) return err; From c0ea70646ad66a83f09562621babae4700c2f322 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 3 Apr 2013 10:45:07 +0200 Subject: [PATCH 280/303] usb: phy: ab8500-usb: split ab8500_usb_phy_ctrl Split ab8500_usb_phy_ctrl into separate enable/disable functions to make the code more linear and readable. Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 57 +++++++++++++++----------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 1bc24d4c25e7..58b194b72432 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -172,40 +172,37 @@ static void ab8500_usb_wd_linkstatus(struct ab8500_usb *ab, u8 bit) } } -static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host, - bool enable) +static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host) { - u8 ctrl_reg; - abx500_get_register_interruptible(ab->dev, - AB8500_USB, - AB8500_USB_PHY_CTRL_REG, - &ctrl_reg); - if (sel_host) { - if (enable) - ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN; - else - ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN; - } else { - if (enable) - ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN; - else - ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN; - } + u8 bit; + bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN : + AB8500_BIT_PHY_CTRL_DEVICE_EN; - abx500_set_register_interruptible(ab->dev, - AB8500_USB, - AB8500_USB_PHY_CTRL_REG, - ctrl_reg); - - /* Needed to enable the phy.*/ - if (enable) - ab8500_usb_wd_workaround(ab); + abx500_mask_and_set_register_interruptible(ab->dev, + AB8500_USB, AB8500_USB_PHY_CTRL_REG, + bit, bit); } -#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_ctrl(ab, true, true) -#define ab8500_usb_host_phy_dis(ab) ab8500_usb_phy_ctrl(ab, true, false) -#define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_ctrl(ab, false, true) -#define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_ctrl(ab, false, false) +static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) +{ + u8 bit; + bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN : + AB8500_BIT_PHY_CTRL_DEVICE_EN; + + ab8500_usb_wd_linkstatus(ab, bit); + + abx500_mask_and_set_register_interruptible(ab->dev, + AB8500_USB, AB8500_USB_PHY_CTRL_REG, + bit, 0); + + /* Needed to disable the phy.*/ + ab8500_usb_wd_workaround(ab); +} + +#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_enable(ab, true) +#define ab8500_usb_host_phy_dis(ab) ab8500_usb_phy_disable(ab, true) +#define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_enable(ab, false) +#define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_disable(ab, false) static int ab8505_usb_link_status_update(struct ab8500_usb *ab, enum ab8505_usb_link_status lsts) From 54dfbb08051c2fa666bd4ce6cb7626b9e2a80655 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 3 Apr 2013 10:45:08 +0200 Subject: [PATCH 281/303] usb: phy: ab8500-usb: enable/disable regulator on phy events Add ab8500_usb_regulator_{enable,disable} functions to control USB phy regulators on corresponding ab8500_usb_phy_{enable,disable} events. This contains some workaround and optimization for specific AB8500 versions. Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Sakethram Bommisetti Signed-off-by: Praveena Nadahally Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 68 +++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 58b194b72432..96b4854f25df 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -130,6 +130,7 @@ struct ab8500_usb { struct regulator *v_ape; struct regulator *v_musb; struct regulator *v_ulpi; + int saved_v_ulpi; int previous_link_status_state; }; @@ -161,6 +162,67 @@ static void ab8500_usb_wd_workaround(struct ab8500_usb *ab) 0); } +static void ab8500_usb_regulator_enable(struct ab8500_usb *ab) +{ + int ret, volt; + + regulator_enable(ab->v_ape); + + if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { + ab->saved_v_ulpi = regulator_get_voltage(ab->v_ulpi); + if (ab->saved_v_ulpi < 0) + dev_err(ab->dev, "Failed to get v_ulpi voltage\n"); + + ret = regulator_set_voltage(ab->v_ulpi, 1300000, 1350000); + if (ret < 0) + dev_err(ab->dev, "Failed to set the Vintcore to 1.3V, ret=%d\n", + ret); + + ret = regulator_set_optimum_mode(ab->v_ulpi, 28000); + if (ret < 0) + dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n", + ret); + } + + regulator_enable(ab->v_ulpi); + + if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { + volt = regulator_get_voltage(ab->v_ulpi); + if ((volt != 1300000) && (volt != 1350000)) + dev_err(ab->dev, "Vintcore is not set to 1.3V volt=%d\n", + volt); + } + + regulator_enable(ab->v_musb); +} + +static void ab8500_usb_regulator_disable(struct ab8500_usb *ab) +{ + int ret; + + regulator_disable(ab->v_musb); + + regulator_disable(ab->v_ulpi); + + /* USB is not the only consumer of Vintcore, restore old settings */ + if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { + if (ab->saved_v_ulpi > 0) { + ret = regulator_set_voltage(ab->v_ulpi, + ab->saved_v_ulpi, ab->saved_v_ulpi); + if (ret < 0) + dev_err(ab->dev, "Failed to set the Vintcore to %duV, ret=%d\n", + ab->saved_v_ulpi, ret); + } + + ret = regulator_set_optimum_mode(ab->v_ulpi, 0); + if (ret < 0) + dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n", + ret); + } + + regulator_disable(ab->v_ape); +} + static void ab8500_usb_wd_linkstatus(struct ab8500_usb *ab, u8 bit) { /* Workaround for v2.0 bug # 31952 */ @@ -178,6 +240,8 @@ static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host) bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN : AB8500_BIT_PHY_CTRL_DEVICE_EN; + ab8500_usb_regulator_enable(ab); + abx500_mask_and_set_register_interruptible(ab->dev, AB8500_USB, AB8500_USB_PHY_CTRL_REG, bit, bit); @@ -197,6 +261,8 @@ static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) /* Needed to disable the phy.*/ ab8500_usb_wd_workaround(ab); + + ab8500_usb_regulator_disable(ab); } #define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_enable(ab, true) @@ -544,7 +610,6 @@ static int ab8500_usb_set_peripheral(struct usb_otg *otg, */ if (!gadget) { - /* TODO: Disable regulators. */ otg->gadget = NULL; schedule_work(&ab->phy_dis_work); } else { @@ -576,7 +641,6 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) */ if (!host) { - /* TODO: Disable regulators. */ otg->host = NULL; schedule_work(&ab->phy_dis_work); } else { From f5ef7b42823945d979ebd957e79bf66dc6a5e3d1 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Wed, 3 Apr 2013 10:45:09 +0200 Subject: [PATCH 282/303] usb: phy: ab8500-usb: fix unbalanced clock and regulator disable warnings To prevent clock and regulator frameworks from complaining, only disable the host or peripheral phy if they were enabled. Reported-by: Sakethram Bommisetti Signed-off-by: Mian Yousaf Kaukab Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 96b4854f25df..fec260ee67d3 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -888,8 +888,10 @@ static int ab8500_usb_remove(struct platform_device *pdev) usb_remove_phy(&ab->phy); - ab8500_usb_host_phy_dis(ab); - ab8500_usb_peri_phy_dis(ab); + if (ab->mode == USB_HOST) + ab8500_usb_host_phy_dis(ab); + else if (ab->mode == USB_PERIPHERAL) + ab8500_usb_peri_phy_dis(ab); platform_set_drvdata(pdev, NULL); From 77f4396ecb3396e518da60f915bbd4726732fd70 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 3 Apr 2013 10:45:10 +0200 Subject: [PATCH 283/303] usb: phy: ab8500-usb: fix last notifier arguments Fix last ab->phy.notifier call to use vbus_draw as notifier argument, as that's used in ab8500_charger to control charging current. Also drop a related TODO comment, and the additional ux500_musb_set_vbus(musb, 0), as with this patch it was causing an erratic behaviour of gadget ep0 state machine. Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/musb/ux500.c | 1 - drivers/usb/phy/phy-ab8500-usb.c | 10 +++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 88795f532370..2c80004e0a83 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -114,7 +114,6 @@ static int musb_otg_notifications(struct notifier_block *nb, break; case UX500_MUSB_VBUS: dev_dbg(musb->controller, "VBUS Connect\n"); - ux500_musb_set_vbus(musb, 0); break; case UX500_MUSB_NONE: dev_dbg(musb->controller, "VBUS Disconnect\n"); diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index fec260ee67d3..888dad65bf9b 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -578,16 +578,12 @@ static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA) ab->vbus_draw = mA; - if (mA) - atomic_notifier_call_chain(&ab->phy.notifier, - UX500_MUSB_ENUMERATED, ab->phy.otg->gadget); + atomic_notifier_call_chain(&ab->phy.notifier, + UX500_MUSB_VBUS, &ab->vbus_draw); + return 0; } -/* TODO: Implement some way for charging or other drivers to read - * ab->vbus_draw. - */ - static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend) { /* TODO */ From 899f0f561b51506f40eb78c9c4aaeeabf97cf35c Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Wed, 3 Apr 2013 10:45:11 +0200 Subject: [PATCH 284/303] usb: phy: ab8500-usb: adopt pinctrl support Amend the ab8500-usb driver to optionally take a pin control handle and set the state of the pins to "default" on ab8500_usb_phy_enable and to "sleep" on ab8500_usb_phy_disable. The pinctrl handle is released on ab8500_usb_phy_disable because USB pins are shared with ab8505_micro_usb_iddet driver. Signed-off-by: Patrice Chotard Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 888dad65bf9b..90a3278d2820 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -33,6 +33,7 @@ #include #include #include +#include /* Bank AB8500_SYS_CTRL2_BLOCK */ #define AB8500_MAIN_WD_CTRL_REG 0x01 @@ -132,6 +133,8 @@ struct ab8500_usb { struct regulator *v_ulpi; int saved_v_ulpi; int previous_link_status_state; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_sleep; }; static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) @@ -240,6 +243,11 @@ static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host) bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN : AB8500_BIT_PHY_CTRL_DEVICE_EN; + /* mux and configure USB pins to DEFAULT state */ + ab->pinctrl = pinctrl_get_select(ab->dev, PINCTRL_STATE_DEFAULT); + if (IS_ERR(ab->pinctrl)) + dev_err(ab->dev, "could not get/set default pinstate\n"); + ab8500_usb_regulator_enable(ab); abx500_mask_and_set_register_interruptible(ab->dev, @@ -263,6 +271,22 @@ static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) ab8500_usb_wd_workaround(ab); ab8500_usb_regulator_disable(ab); + + if (!IS_ERR(ab->pinctrl)) { + /* configure USB pins to SLEEP state */ + ab->pins_sleep = pinctrl_lookup_state(ab->pinctrl, + PINCTRL_STATE_SLEEP); + + if (IS_ERR(ab->pins_sleep)) + dev_dbg(ab->dev, "could not get sleep pinstate\n"); + else if (pinctrl_select_state(ab->pinctrl, ab->pins_sleep)) + dev_err(ab->dev, "could not set pins to sleep state\n"); + + /* as USB pins are shared with idddet, release them to allow + * iddet to request them + */ + pinctrl_put(ab->pinctrl); + } } #define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_enable(ab, true) From 8db12231bccc5ebf414b267af68c5a8c1e4432dd Mon Sep 17 00:00:00 2001 From: Sakethram Bommisetti Date: Wed, 3 Apr 2013 10:45:12 +0200 Subject: [PATCH 285/303] usb: phy: ab8500-usb: drop link status delayed work ab8500_usb_delayed_work was implemented as a workaroud for the internal only and now unsupported v1.0 version of AB850. This patch removes the delayed work and just leave a link status update call at probe time. Signed-off-by: Sakethram Bommisetti Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 90a3278d2820..a1c103fc26ec 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -124,9 +124,7 @@ struct ab8500_usb { struct device *dev; struct ab8500 *ab8500; unsigned vbus_draw; - struct delayed_work dwork; struct work_struct phy_dis_work; - unsigned long link_status_wait; enum ab8500_usb_mode mode; struct regulator *v_ape; struct regulator *v_musb; @@ -556,14 +554,6 @@ static irqreturn_t ab8500_usb_link_status_irq(int irq, void *data) return IRQ_HANDLED; } -static void ab8500_usb_delayed_work(struct work_struct *work) -{ - struct ab8500_usb *ab = container_of(work, struct ab8500_usb, - dwork.work); - - abx500_usb_link_status_update(ab); -} - static void ab8500_usb_phy_disable_work(struct work_struct *work) { struct ab8500_usb *ab = container_of(work, struct ab8500_usb, @@ -635,12 +625,6 @@ static int ab8500_usb_set_peripheral(struct usb_otg *otg, } else { otg->gadget = gadget; otg->phy->state = OTG_STATE_B_IDLE; - - /* Phy will not be enabled if cable is already - * plugged-in. Schedule to enable phy. - * Use same delay to avoid any race condition. - */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); } return 0; @@ -665,11 +649,6 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) schedule_work(&ab->phy_dis_work); } else { otg->host = host; - /* Phy will not be enabled if cable is already - * plugged-in. Schedule to enable phy. - * Use same delay to avoid any race condition. - */ - schedule_delayed_work(&ab->dwork, ab->link_status_wait); } return 0; @@ -792,11 +771,6 @@ static int ab8500_usb_probe(struct platform_device *pdev) ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier); - /* v1: Wait for link status to become stable. - * all: Updates form set_host and set_peripheral as they are atomic. - */ - INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work); - /* all: Disable phy when called from set_host and set_peripheral */ INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); @@ -893,6 +867,8 @@ static int ab8500_usb_probe(struct platform_device *pdev) /* Needed to enable ID detection. */ ab8500_usb_wd_workaround(ab); + abx500_usb_link_status_update(ab); + dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev); return 0; @@ -902,8 +878,6 @@ static int ab8500_usb_remove(struct platform_device *pdev) { struct ab8500_usb *ab = platform_get_drvdata(pdev); - cancel_delayed_work_sync(&ab->dwork); - cancel_work_sync(&ab->phy_dis_work); usb_remove_phy(&ab->phy); From 588233733804aeaf16335a32904aaa4d15b9bddd Mon Sep 17 00:00:00 2001 From: Sakethram Bommisetti Date: Wed, 3 Apr 2013 10:45:13 +0200 Subject: [PATCH 286/303] usb: phy: ab8500-usb: call phy_dis_work only when necessary Modify ab8500_usb_set_peripheral() and ab8500_usb_set_host() code to schedule phy_dis_work only when necessary in order to prevent regulator count mismatch during reboot/shutdown. Signed-off-by: Sakethram Bommisetti Acked-by: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index a1c103fc26ec..749614cf6e2b 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -614,17 +614,16 @@ static int ab8500_usb_set_peripheral(struct usb_otg *otg, ab = phy_to_ab(otg->phy); + ab->phy.otg->gadget = gadget; + /* Some drivers call this function in atomic context. * Do not update ab8500 registers directly till this * is fixed. */ - if (!gadget) { - otg->gadget = NULL; + if ((ab->mode != USB_IDLE) && (!gadget)) { + ab->mode = USB_IDLE; schedule_work(&ab->phy_dis_work); - } else { - otg->gadget = gadget; - otg->phy->state = OTG_STATE_B_IDLE; } return 0; @@ -639,16 +638,16 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) ab = phy_to_ab(otg->phy); + ab->phy.otg->host = host; + /* Some drivers call this function in atomic context. * Do not update ab8500 registers directly till this * is fixed. */ - if (!host) { - otg->host = NULL; + if ((ab->mode != USB_IDLE) && (!host)) { + ab->mode = USB_IDLE; schedule_work(&ab->phy_dis_work); - } else { - otg->host = host; } return 0; From 15761826eecda192f4d1527e08c32193a03e94b7 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 25 Jan 2013 14:09:17 +0100 Subject: [PATCH 287/303] usb: gadget: nokia: use function framework for ACM This patch converts the acm_ms gadget to make use of the function framework to request the ACM function. The "old" include interface for acm is now removed since nokia was the last user of it (for ACM). Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/f_acm.c | 83 ++++++------------------------ drivers/usb/gadget/nokia.c | 96 +++++++++++++++++++++++------------ drivers/usb/gadget/u_serial.h | 1 - 4 files changed, 79 insertions(+), 102 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 1deaddee9dd4..e1d3e0803cd5 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -831,6 +831,7 @@ config USB_G_NOKIA depends on PHONET select USB_LIBCOMPOSITE select USB_U_SERIAL + select USB_F_ACM help The Nokia composite gadget provides support for acm, obex and phonet in only one composite gadget driver. diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index 1ae180baa597..61b33d23be72 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -715,72 +715,6 @@ fail: return status; } -static struct f_acm *acm_alloc_basic_func(void) -{ - struct f_acm *acm; - - acm = kzalloc(sizeof(*acm), GFP_KERNEL); - if (!acm) - return NULL; - - spin_lock_init(&acm->lock); - - acm->port.connect = acm_connect; - acm->port.disconnect = acm_disconnect; - acm->port.send_break = acm_send_break; - - acm->port.func.name = "acm"; - /* descriptors are per-instance copies */ - acm->port.func.bind = acm_bind; - acm->port.func.set_alt = acm_set_alt; - acm->port.func.setup = acm_setup; - acm->port.func.disable = acm_disable; - - return acm; -} - -#ifdef USB_FACM_INCLUDED -static void -acm_old_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct f_acm *acm = func_to_acm(f); - - usb_free_all_descriptors(f); - if (acm->notify_req) - gs_free_req(acm->notify, acm->notify_req); - kfree(acm); -} - -/** - * acm_bind_config - add a CDC ACM function to a configuration - * @c: the configuration to support the CDC ACM instance - * @port_num: /dev/ttyGS* port this interface will use - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - * - */ -int acm_bind_config(struct usb_configuration *c, u8 port_num) -{ - struct f_acm *acm; - int status; - - /* allocate and initialize one new instance */ - acm = acm_alloc_basic_func(); - if (!acm) - return -ENOMEM; - - acm->port_num = port_num; - acm->port.func.unbind = acm_old_unbind; - - status = usb_add_function(c, &acm->port.func); - if (status) - kfree(acm); - return status; -} - -#else - static void acm_unbind(struct usb_configuration *c, struct usb_function *f) { struct f_acm *acm = func_to_acm(f); @@ -803,10 +737,24 @@ static struct usb_function *acm_alloc_func(struct usb_function_instance *fi) struct f_serial_opts *opts; struct f_acm *acm; - acm = acm_alloc_basic_func(); + acm = kzalloc(sizeof(*acm), GFP_KERNEL); if (!acm) return ERR_PTR(-ENOMEM); + spin_lock_init(&acm->lock); + + acm->port.connect = acm_connect; + acm->port.disconnect = acm_disconnect; + acm->port.send_break = acm_send_break; + + acm->port.func.name = "acm"; + acm->port.func.strings = acm_strings; + /* descriptors are per-instance copies */ + acm->port.func.bind = acm_bind; + acm->port.func.set_alt = acm_set_alt; + acm->port.func.setup = acm_setup; + acm->port.func.disable = acm_disable; + opts = container_of(fi, struct f_serial_opts, func_inst); acm->port_num = opts->port_num; acm->port.func.unbind = acm_unbind; @@ -835,4 +783,3 @@ static struct usb_function_instance *acm_alloc_instance(void) } DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func); MODULE_LICENSE("GPL"); -#endif diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index def37403989a..c3ad777a2bd1 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -37,8 +37,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#define USB_FACM_INCLUDED -#include "f_acm.c" #include "f_ecm.c" #include "f_obex.c" #include "f_serial.c" @@ -98,7 +96,8 @@ MODULE_AUTHOR("Felipe Balbi"); MODULE_LICENSE("GPL"); /*-------------------------------------------------------------------------*/ - +static struct usb_function *f_acm_cfg1; +static struct usb_function *f_acm_cfg2; static u8 hostaddr[ETH_ALEN]; enum { @@ -110,33 +109,6 @@ enum { static unsigned char tty_lines[TTY_PORTS_MAX]; -static int __init nokia_bind_config(struct usb_configuration *c) -{ - int status = 0; - - status = phonet_bind_config(c); - if (status) - printk(KERN_DEBUG "could not bind phonet config\n"); - - status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]); - if (status) - printk(KERN_DEBUG "could not bind obex config %d\n", 0); - - status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]); - if (status) - printk(KERN_DEBUG "could not bind obex config %d\n", 0); - - status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]); - if (status) - printk(KERN_DEBUG "could not bind acm config\n"); - - status = ecm_bind_config(c, hostaddr); - if (status) - printk(KERN_DEBUG "could not bind ecm config\n"); - - return status; -} - static struct usb_configuration nokia_config_500ma_driver = { .label = "Bus Powered", .bConfigurationValue = 1, @@ -153,9 +125,55 @@ static struct usb_configuration nokia_config_100ma_driver = { .MaxPower = 100, }; +static struct usb_function_instance *fi_acm; + +static int __init nokia_bind_config(struct usb_configuration *c) +{ + struct usb_function *f_acm; + int status = 0; + + status = phonet_bind_config(c); + if (status) + printk(KERN_DEBUG "could not bind phonet config\n"); + + status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]); + if (status) + printk(KERN_DEBUG "could not bind obex config %d\n", 0); + + status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]); + if (status) + printk(KERN_DEBUG "could not bind obex config %d\n", 0); + + f_acm = usb_get_function(fi_acm); + if (IS_ERR(f_acm)) + return PTR_ERR(f_acm); + + status = usb_add_function(c, f_acm); + if (status) + goto err_conf; + + status = ecm_bind_config(c, hostaddr); + if (status) { + pr_debug("could not bind ecm config %d\n", status); + goto err_ecm; + } + if (c == &nokia_config_500ma_driver) + f_acm_cfg1 = f_acm; + else + f_acm_cfg2 = f_acm; + + return status; +err_ecm: + usb_remove_function(c, f_acm); +err_conf: + usb_put_function(f_acm); + return status; +} + static int __init nokia_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; + struct f_serial_opts *opts; int status; int cur_line; @@ -185,22 +203,32 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) if (!gadget_supports_altsettings(gadget)) goto err_usb; + fi_acm = usb_get_function_instance("acm"); + if (IS_ERR(fi_acm)) + goto err_usb; + opts = container_of(fi_acm, struct f_serial_opts, func_inst); + opts->port_num = tty_lines[TTY_PORT_ACM]; + /* finally register the configuration */ status = usb_add_config(cdev, &nokia_config_500ma_driver, nokia_bind_config); if (status < 0) - goto err_usb; + goto err_acm_inst; status = usb_add_config(cdev, &nokia_config_100ma_driver, nokia_bind_config); if (status < 0) - goto err_usb; + goto err_put_cfg1; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME); return 0; +err_put_cfg1: + usb_put_function(f_acm_cfg1); +err_acm_inst: + usb_put_function_instance(fi_acm); err_usb: gether_cleanup(); err_ether: @@ -217,6 +245,9 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev) { int i; + usb_put_function(f_acm_cfg1); + usb_put_function(f_acm_cfg2); + usb_put_function_instance(fi_acm); gphonet_cleanup(); for (i = 0; i < TTY_PORTS_MAX; i++) @@ -247,4 +278,3 @@ static void __exit nokia_cleanup(void) usb_composite_unregister(&nokia_driver); } module_exit(nokia_cleanup); - diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h index 66ce73a00509..c20210c0babd 100644 --- a/drivers/usb/gadget/u_serial.h +++ b/drivers/usb/gadget/u_serial.h @@ -65,7 +65,6 @@ int gserial_connect(struct gserial *, u8 port_num); void gserial_disconnect(struct gserial *); /* functions are bound to configurations by a config or gadget driver */ -int acm_bind_config(struct usb_configuration *c, u8 port_num); int gser_bind_config(struct usb_configuration *c, u8 port_num); int obex_bind_config(struct usb_configuration *c, u8 port_num); From d6a0143985489e470a118605352f4b18df0ce142 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 23 Dec 2012 21:10:12 +0100 Subject: [PATCH 288/303] usb: gadget: move the global the_dev variable to their users the u_ether.c file has a global variable named the_dev which keeps a pointer to the network device after it has been created via gether_setup_name(). It is only used internally by u_ether. This patches moves the variable to its users and passes it via the port.ioport where it is saved later anyway. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/cdc2.c | 14 +++++++------- drivers/usb/gadget/ether.c | 20 ++++++++++---------- drivers/usb/gadget/f_ecm.c | 4 +++- drivers/usb/gadget/f_eem.c | 3 ++- drivers/usb/gadget/f_ncm.c | 4 +++- drivers/usb/gadget/f_rndis.c | 3 ++- drivers/usb/gadget/f_subset.c | 4 +++- drivers/usb/gadget/g_ffs.c | 35 +++++++++++++++++++++-------------- drivers/usb/gadget/multi.c | 15 ++++++++------- drivers/usb/gadget/ncm.c | 13 +++++++------ drivers/usb/gadget/nokia.c | 13 ++++++++----- drivers/usb/gadget/u_ether.c | 32 ++++++++++---------------------- drivers/usb/gadget/u_ether.h | 27 ++++++++++++++++----------- 13 files changed, 100 insertions(+), 87 deletions(-) diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index a7d6f7026757..61023aae9865 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -103,7 +103,7 @@ static struct usb_gadget_strings *dev_strings[] = { }; static u8 hostaddr[ETH_ALEN]; - +static struct eth_dev *the_dev; /*-------------------------------------------------------------------------*/ static struct usb_function *f_acm; static struct usb_function_instance *fi_serial; @@ -122,7 +122,7 @@ static int __init cdc_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - status = ecm_bind_config(c, hostaddr); + status = ecm_bind_config(c, hostaddr, the_dev); if (status < 0) return status; @@ -169,9 +169,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) } /* set up network link layer */ - status = gether_setup(cdev->gadget, hostaddr); - if (status < 0) - return status; + the_dev = gether_setup(cdev->gadget, hostaddr); + if (IS_ERR(the_dev)) + return PTR_ERR(the_dev); /* set up serial link layer */ status = gserial_alloc_line(&tty_line); @@ -202,7 +202,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) fail1: gserial_free_line(tty_line); fail0: - gether_cleanup(); + gether_cleanup(the_dev); return status; } @@ -211,7 +211,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev) usb_put_function(f_acm); usb_put_function_instance(fi_serial); gserial_free_line(tty_line); - gether_cleanup(); + gether_cleanup(the_dev); return 0; } diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 18c3f423706e..56c8ecae9bc3 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = { }; static u8 hostaddr[ETH_ALEN]; - +static struct eth_dev *the_dev; /*-------------------------------------------------------------------------*/ /* @@ -224,7 +224,7 @@ static int __init rndis_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - return rndis_bind_config(c, hostaddr); + return rndis_bind_config(c, hostaddr, the_dev); } static struct usb_configuration rndis_config_driver = { @@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c) } if (use_eem) - return eem_bind_config(c); + return eem_bind_config(c, the_dev); else if (can_support_ecm(c->cdev->gadget)) - return ecm_bind_config(c, hostaddr); + return ecm_bind_config(c, hostaddr, the_dev); else - return geth_bind_config(c, hostaddr); + return geth_bind_config(c, hostaddr, the_dev); } static struct usb_configuration eth_config_driver = { @@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev) int status; /* set up network link layer */ - status = gether_setup(cdev->gadget, hostaddr); - if (status < 0) - return status; + the_dev = gether_setup(cdev->gadget, hostaddr); + if (IS_ERR(the_dev)) + return PTR_ERR(the_dev); /* set up main config label and device descriptor */ if (use_eem) { @@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev) return 0; fail: - gether_cleanup(); + gether_cleanup(the_dev); return status; } static int __exit eth_unbind(struct usb_composite_dev *cdev) { - gether_cleanup(); + gether_cleanup(the_dev); return 0; } diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 83420a310fb7..d893d6929079 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f) * for calling @gether_cleanup() before module unload. */ int -ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + struct eth_dev *dev) { struct f_ecm *ecm; int status; @@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr); ecm_string_defs[1].s = ecm->ethaddr; + ecm->port.ioport = dev; ecm->port.cdc_filter = DEFAULT_FILTER; ecm->port.func.name = "cdc_ethernet"; diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index cf0ebee85563..f4e0bbef602a 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -528,7 +528,7 @@ error: * Caller must have called @gether_setup(). Caller is also responsible * for calling @gether_cleanup() before module unload. */ -int __init eem_bind_config(struct usb_configuration *c) +int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev) { struct f_eem *eem; int status; @@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c) if (!eem) return -ENOMEM; + eem->port.ioport = dev; eem->port.cdc_filter = DEFAULT_FILTER; eem->port.func.name = "cdc_eem"; diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index 5e7557e23ecc..ee19bc8d0040 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f) * Caller must have called @gether_setup(). Caller is also responsible * for calling @gether_cleanup() before module unload. */ -int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + struct eth_dev *dev) { struct f_ncm *ncm; int status; @@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) spin_lock_init(&ncm->lock); ncm_reset_values(ncm); + ncm->port.ioport = dev; ncm->port.is_fixed = true; ncm->port.func.name = "cdc_network"; diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 71beeb833558..970c9057757f 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -814,7 +814,7 @@ static inline bool can_support_rndis(struct usb_configuration *c) int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - u32 vendorID, const char *manufacturer) + u32 vendorID, const char *manufacturer, struct eth_dev *dev) { struct f_rndis *rndis; int status; @@ -847,6 +847,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], rndis->vendorID = vendorID; rndis->manufacturer = manufacturer; + rndis->port.ioport = dev; /* RNDIS activates when the host changes this filter */ rndis->port.cdc_filter = 0; diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index f172bd152fbb..185d6f5e4e4d 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f) * Caller must have called @gether_setup(). Caller is also responsible * for calling @gether_cleanup() before module unload. */ -int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + struct eth_dev *dev) { struct f_gether *geth; int status; @@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr); geth_string_defs[1].s = geth->ethaddr; + geth->port.ioport = dev; geth->port.cdc_filter = DEFAULT_FILTER; geth->port.func.name = "cdc_subset"; diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 3953dd4d7186..a07dd177e845 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -13,7 +13,6 @@ #define pr_fmt(fmt) "g_ffs: " fmt #include - /* * kbuild is not very cooperative with respect to linking separately * compiled library objects into one module. So for now we won't use @@ -38,13 +37,16 @@ # include "u_ether.c" static u8 gfs_hostaddr[ETH_ALEN]; +static struct eth_dev *the_dev; # ifdef CONFIG_USB_FUNCTIONFS_ETH -static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); +static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + struct eth_dev *dev); # endif #else -# define gether_cleanup() do { } while (0) -# define gether_setup(gadget, hostaddr) ((int)0) +# define the_dev NULL +# define gether_cleanup(dev) do { } while (0) # define gfs_hostaddr NULL +struct eth_dev; #endif #include "f_fs.c" @@ -137,7 +139,8 @@ static struct usb_gadget_strings *gfs_dev_strings[] = { struct gfs_configuration { struct usb_configuration c; - int (*eth)(struct usb_configuration *c, u8 *ethaddr); + int (*eth)(struct usb_configuration *c, u8 *ethaddr, + struct eth_dev *dev); } gfs_configurations[] = { #ifdef CONFIG_USB_FUNCTIONFS_RNDIS { @@ -346,10 +349,13 @@ static int gfs_bind(struct usb_composite_dev *cdev) if (missing_funcs) return -ENODEV; - - ret = gether_setup(cdev->gadget, gfs_hostaddr); - if (unlikely(ret < 0)) +#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS + the_dev = gether_setup(cdev->gadget, gfs_hostaddr); +#endif + if (IS_ERR(the_dev)) { + ret = PTR_ERR(the_dev); goto error_quick; + } gfs_ether_setup = true; ret = usb_string_ids_tab(cdev, gfs_strings); @@ -386,7 +392,7 @@ error_unbind: for (i = 0; i < func_num; i++) functionfs_unbind(ffs_tab[i].ffs_data); error: - gether_cleanup(); + gether_cleanup(the_dev); error_quick: gfs_ether_setup = false; return ret; @@ -410,7 +416,7 @@ static int gfs_unbind(struct usb_composite_dev *cdev) * do...? */ if (gfs_ether_setup) - gether_cleanup(); + gether_cleanup(the_dev); gfs_ether_setup = false; for (i = func_num; --i; ) @@ -440,7 +446,7 @@ static int gfs_do_config(struct usb_configuration *c) } if (gc->eth) { - ret = gc->eth(c, gfs_hostaddr); + ret = gc->eth(c, gfs_hostaddr, the_dev); if (unlikely(ret < 0)) return ret; } @@ -469,11 +475,12 @@ static int gfs_do_config(struct usb_configuration *c) #ifdef CONFIG_USB_FUNCTIONFS_ETH -static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + struct eth_dev *dev) { return can_support_ecm(c->cdev->gadget) - ? ecm_bind_config(c, ethaddr) - : geth_bind_config(c, ethaddr); + ? ecm_bind_config(c, ethaddr, dev) + : geth_bind_config(c, ethaddr, dev); } #endif diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 20bbbf917fc2..34427553271e 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -137,6 +137,7 @@ static u8 hostaddr[ETH_ALEN]; static unsigned char tty_line; static struct usb_function_instance *fi_acm; +static struct eth_dev *the_dev; /********** RNDIS **********/ @@ -152,7 +153,7 @@ static __init int rndis_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - ret = rndis_bind_config(c, hostaddr); + ret = rndis_bind_config(c, hostaddr, the_dev); if (ret < 0) return ret; @@ -214,7 +215,7 @@ static __init int cdc_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - ret = ecm_bind_config(c, hostaddr); + ret = ecm_bind_config(c, hostaddr, the_dev); if (ret < 0) return ret; @@ -279,9 +280,9 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) } /* set up network link layer */ - status = gether_setup(cdev->gadget, hostaddr); - if (status < 0) - return status; + the_dev = gether_setup(cdev->gadget, hostaddr); + if (IS_ERR(the_dev)) + return PTR_ERR(the_dev); /* set up serial link layer */ status = gserial_alloc_line(&tty_line); @@ -337,7 +338,7 @@ fail1: fail0dot5: gserial_free_line(tty_line); fail0: - gether_cleanup(); + gether_cleanup(the_dev); return status; } @@ -351,7 +352,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev) #endif usb_put_function_instance(fi_acm); gserial_free_line(tty_line); - gether_cleanup(); + gether_cleanup(the_dev); return 0; } diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index a22ad9af0565..3b02fd4649ce 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -111,6 +111,7 @@ static struct usb_gadget_strings *dev_strings[] = { NULL, }; +struct eth_dev *the_dev; static u8 hostaddr[ETH_ALEN]; /*-------------------------------------------------------------------------*/ @@ -124,7 +125,7 @@ static int __init ncm_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - return ncm_bind_config(c, hostaddr); + return ncm_bind_config(c, hostaddr, the_dev); } static struct usb_configuration ncm_config_driver = { @@ -143,9 +144,9 @@ static int __init gncm_bind(struct usb_composite_dev *cdev) int status; /* set up network link layer */ - status = gether_setup(cdev->gadget, hostaddr); - if (status < 0) - return status; + the_dev = gether_setup(cdev->gadget, hostaddr); + if (IS_ERR(the_dev)) + return PTR_ERR(the_dev); /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. @@ -168,13 +169,13 @@ static int __init gncm_bind(struct usb_composite_dev *cdev) return 0; fail: - gether_cleanup(); + gether_cleanup(the_dev); return status; } static int __exit gncm_unbind(struct usb_composite_dev *cdev) { - gether_cleanup(); + gether_cleanup(the_dev); return 0; } diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index c3ad777a2bd1..0c13ddd78bef 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -99,6 +99,7 @@ MODULE_LICENSE("GPL"); static struct usb_function *f_acm_cfg1; static struct usb_function *f_acm_cfg2; static u8 hostaddr[ETH_ALEN]; +static struct eth_dev *the_dev; enum { TTY_PORT_OBEX0, @@ -152,7 +153,7 @@ static int __init nokia_bind_config(struct usb_configuration *c) if (status) goto err_conf; - status = ecm_bind_config(c, hostaddr); + status = ecm_bind_config(c, hostaddr, the_dev); if (status) { pr_debug("could not bind ecm config %d\n", status); goto err_ecm; @@ -187,9 +188,11 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) goto err_ether; } - status = gether_setup(cdev->gadget, hostaddr); - if (status < 0) + the_dev = gether_setup(cdev->gadget, hostaddr); + if (IS_ERR(the_dev)) { + status = PTR_ERR(the_dev); goto err_ether; + } status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) @@ -230,7 +233,7 @@ err_put_cfg1: err_acm_inst: usb_put_function_instance(fi_acm); err_usb: - gether_cleanup(); + gether_cleanup(the_dev); err_ether: cur_line--; while (cur_line >= 0) @@ -253,7 +256,7 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev) for (i = 0; i < TTY_PORTS_MAX; i++) gserial_free_line(tty_lines[i]); - gether_cleanup(); + gether_cleanup(the_dev); return 0; } diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index a0aa721d8b21..4b76124ce96b 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -50,7 +50,6 @@ struct eth_dev { /* lock is held while accessing port_usb - * or updating its backlink port_usb->ioport */ spinlock_t lock; struct gether *port_usb; @@ -729,8 +728,6 @@ static int get_ether_addr(const char *str, u8 *dev_addr) return 1; } -static struct eth_dev *the_dev; - static const struct net_device_ops eth_netdev_ops = { .ndo_open = eth_open, .ndo_stop = eth_stop, @@ -758,19 +755,16 @@ static struct device_type gadget_type = { * * Returns negative errno, or zero on success */ -int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], +struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], const char *netname) { struct eth_dev *dev; struct net_device *net; int status; - if (the_dev) - return -EBUSY; - net = alloc_etherdev(sizeof *dev); if (!net) - return -ENOMEM; + return ERR_PTR(-ENOMEM); dev = netdev_priv(net); spin_lock_init(&dev->lock); @@ -807,12 +801,11 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], if (status < 0) { dev_dbg(&g->dev, "register_netdev failed, %d\n", status); free_netdev(net); + dev = ERR_PTR(status); } else { INFO(dev, "MAC %pM\n", net->dev_addr); INFO(dev, "HOST MAC %pM\n", dev->host_mac); - the_dev = dev; - /* two kinds of host-initiated state changes: * - iff DATA transfer is active, carrier is "on" * - tx queueing enabled if open *and* carrier is "on" @@ -820,7 +813,7 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], netif_carrier_off(net); } - return status; + return dev; } /** @@ -829,19 +822,16 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], * * This is called to free all resources allocated by @gether_setup(). */ -void gether_cleanup(void) +void gether_cleanup(struct eth_dev *dev) { - if (!the_dev) + if (!dev) return; - unregister_netdev(the_dev->net); - flush_work(&the_dev->work); - free_netdev(the_dev->net); - - the_dev = NULL; + unregister_netdev(dev->net); + flush_work(&dev->work); + free_netdev(dev->net); } - /** * gether_connect - notify network layer that USB link is active * @link: the USB link, set up with endpoints, descriptors matching @@ -860,7 +850,7 @@ void gether_cleanup(void) */ struct net_device *gether_connect(struct gether *link) { - struct eth_dev *dev = the_dev; + struct eth_dev *dev = link->ioport; int result = 0; if (!dev) @@ -895,7 +885,6 @@ struct net_device *gether_connect(struct gether *link) spin_lock(&dev->lock); dev->port_usb = link; - link->ioport = dev; if (netif_running(dev->net)) { if (link->open) link->open(link); @@ -989,6 +978,5 @@ void gether_disconnect(struct gether *link) spin_lock(&dev->lock); dev->port_usb = NULL; - link->ioport = NULL; spin_unlock(&dev->lock); } diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h index 6f4a1623d854..02522338a708 100644 --- a/drivers/usb/gadget/u_ether.h +++ b/drivers/usb/gadget/u_ether.h @@ -21,6 +21,7 @@ #include "gadget_chips.h" +struct eth_dev; /* * This represents the USB side of an "ethernet" link, managed by a USB @@ -70,7 +71,7 @@ struct gether { |USB_CDC_PACKET_TYPE_DIRECTED) /* variant of gether_setup that allows customizing network device name */ -int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], +struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], const char *netname); /* netdev setup/teardown as directed by the gadget driver */ @@ -86,12 +87,13 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], * * Returns negative errno, or zero on success */ -static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) +static inline struct eth_dev *gether_setup(struct usb_gadget *g, + u8 ethaddr[ETH_ALEN]) { return gether_setup_name(g, ethaddr, "usb"); } -void gether_cleanup(void); +void gether_cleanup(struct eth_dev *dev); /* connect/disconnect is handled by individual functions */ struct net_device *gether_connect(struct gether *); @@ -111,21 +113,24 @@ static inline bool can_support_ecm(struct usb_gadget *gadget) } /* each configuration may bind one instance of an ethernet link */ -int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); -int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); -int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); -int eem_bind_config(struct usb_configuration *c); +int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + struct eth_dev *dev); +int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + struct eth_dev *dev); +int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + struct eth_dev *dev); +int eem_bind_config(struct usb_configuration *c, struct eth_dev *dev); #ifdef USB_ETH_RNDIS int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - u32 vendorID, const char *manufacturer); + u32 vendorID, const char *manufacturer, struct eth_dev *dev); #else static inline int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], - u32 vendorID, const char *manufacturer) + u32 vendorID, const char *manufacturer, struct eth_dev *dev) { return 0; } @@ -145,9 +150,9 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], * for calling @gether_cleanup() before module unload. */ static inline int rndis_bind_config(struct usb_configuration *c, - u8 ethaddr[ETH_ALEN]) + u8 ethaddr[ETH_ALEN], struct eth_dev *dev) { - return rndis_bind_config_vendor(c, ethaddr, 0, NULL); + return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev); } From c4ed4ac198495895fd1620cba15184c3b2d399dc Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 23 Dec 2012 21:10:18 +0100 Subject: [PATCH 289/303] usb: gadget: push tty port allocation from gadget into f_acm It possible to allocate the tty port number within the "instance" structure of the function and there is no need to expose this information within the gadget and therefore it is removed here. This patch converts only f_acm and all its users. The other gadgets will follow once the function is converted to the function interface. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/acm_ms.c | 15 +-------------- drivers/usb/gadget/cdc2.c | 13 ------------- drivers/usb/gadget/f_acm.c | 7 +++++++ drivers/usb/gadget/multi.c | 14 +------------- drivers/usb/gadget/nokia.c | 4 ---- drivers/usb/gadget/serial.c | 20 ++++++++++---------- 6 files changed, 19 insertions(+), 54 deletions(-) diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 8f2b0e391534..4b947bb50f62 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); static struct fsg_common fsg_common; /*-------------------------------------------------------------------------*/ -static unsigned char tty_line; static struct usb_function *f_acm; static struct usb_function_instance *f_acm_inst; /* @@ -117,7 +116,6 @@ static struct usb_function_instance *f_acm_inst; */ static int __init acm_ms_do_config(struct usb_configuration *c) { - struct f_serial_opts *opts; int status; if (gadget_is_otg(c->cdev->gadget)) { @@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c) if (IS_ERR(f_acm_inst)) return PTR_ERR(f_acm_inst); - opts = container_of(f_acm_inst, struct f_serial_opts, func_inst); - opts->port_num = tty_line; - f_acm = usb_get_function(f_acm_inst); if (IS_ERR(f_acm)) { status = PTR_ERR(f_acm); @@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev) int status; void *retp; - /* set up serial link layer */ - status = gserial_alloc_line(&tty_line); - if (status < 0) - return status; - /* set up mass storage function */ retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); if (IS_ERR(retp)) { status = PTR_ERR(retp); - goto fail0; + return PTR_ERR(retp); } /* @@ -207,8 +197,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev) /* error recovery */ fail1: fsg_common_put(&fsg_common); -fail0: - gserial_free_line(tty_line); return status; } @@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev) { usb_put_function(f_acm); usb_put_function_instance(f_acm_inst); - gserial_free_line(tty_line); return 0; } diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 61023aae9865..c6ee6f1558c3 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -108,13 +108,11 @@ static struct eth_dev *the_dev; static struct usb_function *f_acm; static struct usb_function_instance *fi_serial; -static unsigned char tty_line; /* * We _always_ have both CDC ECM and CDC ACM functions. */ static int __init cdc_do_config(struct usb_configuration *c) { - struct f_serial_opts *opts; int status; if (gadget_is_otg(c->cdev->gadget)) { @@ -130,9 +128,6 @@ static int __init cdc_do_config(struct usb_configuration *c) if (IS_ERR(fi_serial)) return PTR_ERR(fi_serial); - opts = container_of(fi_serial, struct f_serial_opts, func_inst); - opts->port_num = tty_line; - f_acm = usb_get_function(fi_serial); if (IS_ERR(f_acm)) goto err_func_acm; @@ -173,11 +168,6 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) if (IS_ERR(the_dev)) return PTR_ERR(the_dev); - /* set up serial link layer */ - status = gserial_alloc_line(&tty_line); - if (status < 0) - goto fail0; - /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ @@ -200,8 +190,6 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) return 0; fail1: - gserial_free_line(tty_line); -fail0: gether_cleanup(the_dev); return status; } @@ -210,7 +198,6 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev) { usb_put_function(f_acm); usb_put_function_instance(fi_serial); - gserial_free_line(tty_line); gether_cleanup(the_dev); return 0; } diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index 61b33d23be72..ba7daaaad148 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -768,17 +768,24 @@ static void acm_free_instance(struct usb_function_instance *fi) struct f_serial_opts *opts; opts = container_of(fi, struct f_serial_opts, func_inst); + gserial_free_line(opts->port_num); kfree(opts); } static struct usb_function_instance *acm_alloc_instance(void) { struct f_serial_opts *opts; + int ret; opts = kzalloc(sizeof(*opts), GFP_KERNEL); if (!opts) return ERR_PTR(-ENOMEM); opts->func_inst.free_func_inst = acm_free_instance; + ret = gserial_alloc_line(&opts->port_num); + if (ret) { + kfree(opts); + return ERR_PTR(ret); + } return &opts->func_inst; } DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func); diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 34427553271e..a74ebefc7682 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -135,7 +135,6 @@ static struct fsg_common fsg_common; static u8 hostaddr[ETH_ALEN]; -static unsigned char tty_line; static struct usb_function_instance *fi_acm; static struct eth_dev *the_dev; @@ -270,7 +269,6 @@ static int cdc_config_register(struct usb_composite_dev *cdev) static int __ref multi_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; - struct f_serial_opts *opts; int status; if (!can_support_ecm(cdev->gadget)) { @@ -285,19 +283,12 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) return PTR_ERR(the_dev); /* set up serial link layer */ - status = gserial_alloc_line(&tty_line); - if (status < 0) - goto fail0; - fi_acm = usb_get_function_instance("acm"); if (IS_ERR(fi_acm)) { status = PTR_ERR(fi_acm); - goto fail0dot5; + goto fail0; } - opts = container_of(fi_acm, struct f_serial_opts, func_inst); - opts->port_num = tty_line; - /* set up mass storage function */ { void *retp; @@ -335,8 +326,6 @@ fail2: fsg_common_put(&fsg_common); fail1: usb_put_function_instance(fi_acm); -fail0dot5: - gserial_free_line(tty_line); fail0: gether_cleanup(the_dev); return status; @@ -351,7 +340,6 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev) usb_put_function(f_acm_rndis); #endif usb_put_function_instance(fi_acm); - gserial_free_line(tty_line); gether_cleanup(the_dev); return 0; } diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 0c13ddd78bef..b5fbf1a1cb3c 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -104,7 +104,6 @@ static struct eth_dev *the_dev; enum { TTY_PORT_OBEX0, TTY_PORT_OBEX1, - TTY_PORT_ACM, TTY_PORTS_MAX, }; @@ -174,7 +173,6 @@ err_conf: static int __init nokia_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; - struct f_serial_opts *opts; int status; int cur_line; @@ -209,8 +207,6 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) fi_acm = usb_get_function_instance("acm"); if (IS_ERR(fi_acm)) goto err_usb; - opts = container_of(fi_acm, struct f_serial_opts, func_inst); - opts->port_num = tty_lines[TTY_PORT_ACM]; /* finally register the configuration */ status = usb_add_config(cdev, &nokia_config_500ma_driver, diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 68d7bb06ebcb..c48ca1eb5442 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -169,15 +169,12 @@ static int serial_register_ports(struct usb_composite_dev *cdev, goto out; for (i = 0; i < n_ports; i++) { - struct f_serial_opts *opts; fi_serial[i] = usb_get_function_instance(f_name); if (IS_ERR(fi_serial[i])) { ret = PTR_ERR(fi_serial[i]); goto fail; } - opts = container_of(fi_serial[i], struct f_serial_opts, func_inst); - opts->port_num = tty_lines[i]; f_serial[i] = usb_get_function(fi_serial[i]); if (IS_ERR(f_serial[i])) { @@ -212,12 +209,14 @@ out: static int __init gs_bind(struct usb_composite_dev *cdev) { int status; - int cur_line; + int cur_line = 0; - for (cur_line = 0; cur_line < n_ports; cur_line++) { - status = gserial_alloc_line(&tty_lines[cur_line]); - if (status) - goto fail; + if (!use_acm) { + for (cur_line = 0; cur_line < n_ports; cur_line++) { + status = gserial_alloc_line(&tty_lines[cur_line]); + if (status) + goto fail; + } } /* Allocate string descriptor numbers ... note that string @@ -258,7 +257,7 @@ static int __init gs_bind(struct usb_composite_dev *cdev) fail: cur_line--; - while (cur_line >= 0) + while (cur_line >= 0 && !use_acm) gserial_free_line(tty_lines[cur_line--]); return status; } @@ -270,7 +269,8 @@ static int gs_unbind(struct usb_composite_dev *cdev) for (i = 0; i < n_ports; i++) { usb_put_function(f_serial[i]); usb_put_function_instance(fi_serial[i]); - gserial_free_line(tty_lines[i]); + if (!use_acm) + gserial_free_line(tty_lines[i]); } return 0; } From 88af8bbe4ef781031ad3370847553f3b42ba0076 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 23 Dec 2012 21:10:24 +0100 Subject: [PATCH 290/303] usb: gadget: the start of the configfs interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit |# modprobe dummy_hcd num=2 |# modprobe libcomposite |# lsmod |Module Size Used by |libcomposite 31648 0 |dummy_hcd 19871 0 |# mkdir /sys/kernel/config/usb_gadget/oha |# cd /sys/kernel/config/usb_gadget/oha |# mkdir configs/def.1 |# mkdir configs/def.2 |# mkdir functions/acm.ttyS1 |# mkdir strings/0x1 |mkdir: cannot create directory `strings/0x1': Invalid argument |# mkdir strings/0x409 |# mkdir strings/1033 |mkdir: cannot create directory `strings/1033': File exists |# mkdir strings/1032 |# mkdir configs/def.1/strings/0x409 |# mkdir configs/def.2/strings/0x409 |#find . -ls | 975 0 drwxr-xr-x 5 root root 0 Dec 23 17:40 . | 978 0 drwxr-xr-x 4 root root 0 Dec 23 17:43 ./strings | 4100 0 drwxr-xr-x 2 root root 0 Dec 23 17:43 ./strings/1032 | 995 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./strings/1032/serialnumber | 996 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./strings/1032/product | 997 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./strings/1032/manufacturer | 2002 0 drwxr-xr-x 2 root root 0 Dec 23 17:41 ./strings/0x409 | 998 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./strings/0x409/serialnumber | 999 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./strings/0x409/product | 1000 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./strings/0x409/manufacturer | 977 0 drwxr-xr-x 4 root root 0 Dec 23 17:41 ./configs | 4081 0 drwxr-xr-x 3 root root 0 Dec 23 17:41 ./configs/def.2 | 4082 0 drwxr-xr-x 3 root root 0 Dec 23 17:42 ./configs/def.2/strings | 2016 0 drwxr-xr-x 2 root root 0 Dec 23 17:42 ./configs/def.2/strings/0x409 | 1001 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./configs/def.2/strings/0x409/configuration | 1002 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./configs/def.2/bmAttributes | 1003 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./configs/def.2/MaxPower | 979 0 drwxr-xr-x 3 root root 0 Dec 23 17:42 ./configs/def.1 | 980 0 drwxr-xr-x 3 root root 0 Dec 23 17:42 ./configs/def.1/strings | 5122 0 drwxr-xr-x 2 root root 0 Dec 23 17:42 ./configs/def.1/strings/0x409 | 1004 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./configs/def.1/strings/0x409/configuration | 1005 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./configs/def.1/bmAttributes | 1006 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./configs/def.1/MaxPower | 976 0 drwxr-xr-x 3 root root 0 Dec 23 17:41 ./functions | 981 0 drwxr-xr-x 2 root root 0 Dec 23 17:41 ./functions/acm.ttyS1 | 1007 0 -r--r--r-- 1 root root 4096 Dec 23 17:43 ./functions/acm.ttyS1/port_num | 1008 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./UDC | 1009 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./bcdUSB | 1010 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./bcdDevice | 1011 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./idProduct | 1012 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./idVendor | 1013 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./bMaxPacketSize0 | 1014 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./bDeviceProtocol | 1015 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./bDeviceSubClass | 1016 0 -rw-r--r-- 1 root root 4096 Dec 23 17:43 ./bDeviceClass |# cat functions/acm.ttyS1/port_num |0 |# ls -lah /dev/ttyGS* |crw-rw---T 1 root dialout 252, 0 Dec 23 17:41 /dev/ttyGS0 | |# echo 0x1234 > idProduct |# echo 0xabcd > idVendor |# echo 1122 > strings/0x409/serialnumber |# echo "The manufacturer" > strings/0x409/manufacturer |# echo 1 > strings/1032/manufacturer |# echo 1sa > strings/1032/product |# echo tada > strings/1032/serialnumber |echo "Primary configuration" > configs/def.1/strings/0x409/configuration |# echo "Secondary configuration" > configs/def.2/strings/0x409/configuration |# ln -s functions/acm.ttyS1 configs/def.1/ |# ln -s functions/acm.ttyS1 configs/def.2/ |find configs/def.1/ -ls | 979 0 drwxr-xr-x 3 root root 0 Dec 23 17:49 configs/def.1/ | 6264 0 lrwxrwxrwx 1 root root 0 Dec 23 17:48 configs/def.1/acm.ttyS1 -> ../../../../usb_gadget/oha/functions/acm.ttyS1 | 980 0 drwxr-xr-x 3 root root 0 Dec 23 17:42 configs/def.1/strings | 5122 0 drwxr-xr-x 2 root root 0 Dec 23 17:49 configs/def.1/strings/0x409 | 6284 0 -rw-r--r-- 1 root root 4096 Dec 23 17:47 configs/def.1/strings/0x409/configuration | 6285 0 -rw-r--r-- 1 root root 4096 Dec 23 17:49 configs/def.1/bmAttributes | 6286 0 -rw-r--r-- 1 root root 4096 Dec 23 17:49 configs/def.1/MaxPower | |echo 120 > configs/def.1/MaxPower | |# ls -lh /sys/class/udc/ |total 0 |lrwxrwxrwx 1 root root 0 Dec 23 17:50 dummy_udc.0 -> ../../devices/platform/dummy_udc.0/udc/dummy_udc.0 |lrwxrwxrwx 1 root root 0 Dec 23 17:50 dummy_udc.1 -> ../../devices/platform/dummy_udc.1/udc/dummy_udc.1 |# echo dummy_udc.0 > UDC |# lsusb |Bus 001 Device 002: ID abcd:1234 Unknown | |lsusb -d abcd:1234 -v |Device Descriptor: … | idVendor 0xabcd Unknown | idProduct 0x1234 | bcdDevice 3.06 | iManufacturer 1 The manufacturer | iProduct 2 | iSerial 3 1122 | bNumConfigurations 2 … |echo "" > UDC v5…v6 - wired up strings with usb_gstrings_attach() - add UDC attribe. Write "udc-name" will bind the gadget. Write an empty string (it should contain \n since 0 bytes write get optimzed away) will unbind the UDC from the gadget. The name of available UDCs can be obtained from /sys/class/udc/ v4…v5 - string rework. This will add a strings folder incl. language code like strings/409/manufacturer as suggested by Alan. - rebased ontop reworked functions.c which has usb_function_instance which is used prior after "mkdir acm.instance" and can be directly used for configuration via configfs. v3…v4 - moved functions from the root folde down to the gadget as suggested by MichaÅ‚ - configs have now their own configs folder as suggested by MichaÅ‚. The folder is still name.bConfigurationValue where name becomes the sConfiguration. Is this usefull should we just stilc configs/bConfigurationValue/ ? - added configfs support to the ACM function. The port_num attribute is exported by f_acm. An argument has been added to the USB alloc function to distinguish between "old" (use facm_configure() to configure and configfs interface (expose a config_node). The port_num is currently a dumb counter. It will require some function re-work to make it work. scheduled for v5: - sym linking function into config. v2…v3 - replaced one ifndef by ifdef as suggested by MicahaÅ‚ - strstr()/strchr() function_make as suggested by MicahÅ‚ - replace [iSerialNumber|iProduct|iManufacturer] with [sSerialNumber|sProduct|sManufacturer] as suggested by Alan - added creation of config descriptors v1…v2 - moved gadgets from configfs' root directory into /udcs/ within our "usb_gadget" folder. Requested by Andrzej & MichaÅ‚ - use a dot as a delimiter between function's name and its instance's name as suggested by MichaÅ‚ - renamed all config_item_type, configfs_group_operations, make_group, drop_item as suggested by suggested by Andrzej to remain consisten within this file and within other configfs users - Since configfs.c and functions.c are now part of the udc-core module, the module itself is now called udc. Also added a tiny ifdef around init code becuase udc-core is subsys init and this is too early for configfs in the built-in case. In the module case, we can only have one init function. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/Makefile | 2 +- drivers/usb/gadget/composite.c | 1 + drivers/usb/gadget/configfs.c | 1003 +++++++++++++++++++++++++++ drivers/usb/gadget/f_acm.c | 55 ++ include/linux/usb/composite.h | 3 + include/linux/usb/gadget_configfs.h | 110 +++ 7 files changed, 1174 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/gadget/configfs.c create mode 100644 include/linux/usb/gadget_configfs.h diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index e1d3e0803cd5..74a29de8f254 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -493,6 +493,7 @@ endmenu # composite based drivers config USB_LIBCOMPOSITE tristate + select CONFIGFS_FS depends on USB_GADGET config USB_F_ACM diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 82fb22511356..96e72433cd31 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_GADGET) += udc-core.o obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o libcomposite-y := usbstring.o config.o epautoconf.o -libcomposite-y += composite.o functions.o +libcomposite-y += composite.o functions.o configfs.o obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2272) += net2272.o obj-$(CONFIG_USB_NET2280) += net2280.o diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index c0d62b278610..55f4df60f327 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev) kfree(cdev->req->buf); usb_ep_free_request(cdev->gadget->ep0, cdev->req); } + cdev->next_string_id = 0; device_remove_file(&cdev->gadget->dev, &dev_attr_suspended); } diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c new file mode 100644 index 000000000000..a34633a898a1 --- /dev/null +++ b/drivers/usb/gadget/configfs.c @@ -0,0 +1,1003 @@ +#include +#include +#include +#include +#include +#include + +int check_user_usb_string(const char *name, + struct usb_gadget_strings *stringtab_dev) +{ + unsigned primary_lang; + unsigned sub_lang; + u16 num; + int ret; + + ret = kstrtou16(name, 0, &num); + if (ret) + return ret; + + primary_lang = num & 0x3ff; + sub_lang = num >> 10; + + /* simple sanity check for valid langid */ + switch (primary_lang) { + case 0: + case 0x62 ... 0xfe: + case 0x100 ... 0x3ff: + return -EINVAL; + } + if (!sub_lang) + return -EINVAL; + + stringtab_dev->language = num; + return 0; +} + +#define MAX_NAME_LEN 40 +#define MAX_USB_STRING_LANGS 2 + +struct gadget_info { + struct config_group group; + struct config_group functions_group; + struct config_group configs_group; + struct config_group strings_group; + struct config_group *default_groups[4]; + + struct mutex lock; + struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; + struct list_head string_list; + struct list_head available_func; + + const char *udc_name; +#ifdef CONFIG_USB_OTG + struct usb_otg_descriptor otg; +#endif + struct usb_composite_driver composite; + struct usb_composite_dev cdev; +}; + +struct config_usb_cfg { + struct config_group group; + struct config_group strings_group; + struct config_group *default_groups[2]; + struct list_head string_list; + struct usb_configuration c; + struct list_head func_list; + struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1]; +}; + +struct gadget_strings { + struct usb_gadget_strings stringtab_dev; + struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX]; + char *manufacturer; + char *product; + char *serialnumber; + + struct config_group group; + struct list_head list; +}; + +struct gadget_config_name { + struct usb_gadget_strings stringtab_dev; + struct usb_string strings; + char *configuration; + + struct config_group group; + struct list_head list; +}; + +static int usb_string_copy(const char *s, char **s_copy) +{ + int ret; + char *str; + char *copy = *s_copy; + ret = strlen(s); + if (ret > 126) + return -EOVERFLOW; + + str = kstrdup(s, GFP_KERNEL); + if (!str) + return -ENOMEM; + if (str[ret - 1] == '\n') + str[ret - 1] = '\0'; + kfree(copy); + *s_copy = str; + return 0; +} + +CONFIGFS_ATTR_STRUCT(gadget_info); +CONFIGFS_ATTR_STRUCT(config_usb_cfg); + +#define GI_DEVICE_DESC_ITEM_ATTR(name) \ + static struct gadget_info_attribute gadget_cdev_desc_##name = \ + __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ + gadget_dev_desc_##name##_show, \ + gadget_dev_desc_##name##_store) + +#define GI_DEVICE_DESC_SIMPLE_R_u8(__name) \ + static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \ + char *page) \ +{ \ + return sprintf(page, "0x%02x\n", gi->cdev.desc.__name); \ +} + +#define GI_DEVICE_DESC_SIMPLE_R_u16(__name) \ + static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \ + char *page) \ +{ \ + return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \ +} + + +#define GI_DEVICE_DESC_SIMPLE_W_u8(_name) \ + static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \ + const char *page, size_t len) \ +{ \ + u8 val; \ + int ret; \ + ret = kstrtou8(page, 0, &val); \ + if (ret) \ + return ret; \ + gi->cdev.desc._name = val; \ + return len; \ +} + +#define GI_DEVICE_DESC_SIMPLE_W_u16(_name) \ + static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \ + const char *page, size_t len) \ +{ \ + u16 val; \ + int ret; \ + ret = kstrtou16(page, 0, &val); \ + if (ret) \ + return ret; \ + gi->cdev.desc._name = cpu_to_le16p(&val); \ + return len; \ +} + +#define GI_DEVICE_DESC_SIMPLE_RW(_name, _type) \ + GI_DEVICE_DESC_SIMPLE_R_##_type(_name) \ + GI_DEVICE_DESC_SIMPLE_W_##_type(_name) + +GI_DEVICE_DESC_SIMPLE_R_u16(bcdUSB); +GI_DEVICE_DESC_SIMPLE_RW(bDeviceClass, u8); +GI_DEVICE_DESC_SIMPLE_RW(bDeviceSubClass, u8); +GI_DEVICE_DESC_SIMPLE_RW(bDeviceProtocol, u8); +GI_DEVICE_DESC_SIMPLE_RW(bMaxPacketSize0, u8); +GI_DEVICE_DESC_SIMPLE_RW(idVendor, u16); +GI_DEVICE_DESC_SIMPLE_RW(idProduct, u16); +GI_DEVICE_DESC_SIMPLE_R_u16(bcdDevice); + +static ssize_t is_valid_bcd(u16 bcd_val) +{ + if ((bcd_val & 0xf) > 9) + return -EINVAL; + if (((bcd_val >> 4) & 0xf) > 9) + return -EINVAL; + if (((bcd_val >> 8) & 0xf) > 9) + return -EINVAL; + if (((bcd_val >> 12) & 0xf) > 9) + return -EINVAL; + return 0; +} + +static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi, + const char *page, size_t len) +{ + u16 bcdDevice; + int ret; + + ret = kstrtou16(page, 0, &bcdDevice); + if (ret) + return ret; + ret = is_valid_bcd(bcdDevice); + if (ret) + return ret; + + gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice); + return len; +} + +static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi, + const char *page, size_t len) +{ + u16 bcdUSB; + int ret; + + ret = kstrtou16(page, 0, &bcdUSB); + if (ret) + return ret; + ret = is_valid_bcd(bcdUSB); + if (ret) + return ret; + + gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB); + return len; +} + +static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page) +{ + return sprintf(page, "%s\n", gi->udc_name ?: ""); +} + +static int unregister_gadget(struct gadget_info *gi) +{ + int ret; + + if (!gi->udc_name) + return -ENODEV; + + ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver); + if (ret) + return ret; + kfree(gi->udc_name); + gi->udc_name = NULL; + return 0; +} + +static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi, + const char *page, size_t len) +{ + char *name; + int ret; + + name = kstrdup(page, GFP_KERNEL); + if (!name) + return -ENOMEM; + if (name[len - 1] == '\n') + name[len - 1] = '\0'; + + mutex_lock(&gi->lock); + + if (!strlen(name)) { + ret = unregister_gadget(gi); + if (ret) + goto err; + } else { + if (gi->udc_name) { + ret = -EBUSY; + goto err; + } + ret = udc_attach_driver(name, &gi->composite.gadget_driver); + if (ret) + goto err; + gi->udc_name = name; + } + mutex_unlock(&gi->lock); + return len; +err: + kfree(name); + mutex_unlock(&gi->lock); + return ret; +} + +GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass); +GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass); +GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol); +GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0); +GI_DEVICE_DESC_ITEM_ATTR(idVendor); +GI_DEVICE_DESC_ITEM_ATTR(idProduct); +GI_DEVICE_DESC_ITEM_ATTR(bcdDevice); +GI_DEVICE_DESC_ITEM_ATTR(bcdUSB); +GI_DEVICE_DESC_ITEM_ATTR(UDC); + +static struct configfs_attribute *gadget_root_attrs[] = { + &gadget_cdev_desc_bDeviceClass.attr, + &gadget_cdev_desc_bDeviceSubClass.attr, + &gadget_cdev_desc_bDeviceProtocol.attr, + &gadget_cdev_desc_bMaxPacketSize0.attr, + &gadget_cdev_desc_idVendor.attr, + &gadget_cdev_desc_idProduct.attr, + &gadget_cdev_desc_bcdDevice.attr, + &gadget_cdev_desc_bcdUSB.attr, + &gadget_cdev_desc_UDC.attr, + NULL, +}; + +static inline struct gadget_info *to_gadget_info(struct config_item *item) +{ + return container_of(to_config_group(item), struct gadget_info, group); +} + +static inline struct gadget_strings *to_gadget_strings(struct config_item *item) +{ + return container_of(to_config_group(item), struct gadget_strings, + group); +} + +static inline struct gadget_config_name *to_gadget_config_name( + struct config_item *item) +{ + return container_of(to_config_group(item), struct gadget_config_name, + group); +} + +static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item) +{ + return container_of(to_config_group(item), struct config_usb_cfg, + group); +} + +static inline struct usb_function_instance *to_usb_function_instance( + struct config_item *item) +{ + return container_of(to_config_group(item), + struct usb_function_instance, group); +} + +static void gadget_info_attr_release(struct config_item *item) +{ + struct gadget_info *gi = to_gadget_info(item); + + WARN_ON(!list_empty(&gi->cdev.configs)); + WARN_ON(!list_empty(&gi->string_list)); + WARN_ON(!list_empty(&gi->available_func)); + kfree(gi->composite.gadget_driver.function); + kfree(gi); +} + +CONFIGFS_ATTR_OPS(gadget_info); + +static struct configfs_item_operations gadget_root_item_ops = { + .release = gadget_info_attr_release, + .show_attribute = gadget_info_attr_show, + .store_attribute = gadget_info_attr_store, +}; + +static void gadget_config_attr_release(struct config_item *item) +{ + struct config_usb_cfg *cfg = to_config_usb_cfg(item); + + WARN_ON(!list_empty(&cfg->c.functions)); + list_del(&cfg->c.list); + kfree(cfg->c.label); + kfree(cfg); +} + +static int config_usb_cfg_link( + struct config_item *usb_cfg_ci, + struct config_item *usb_func_ci) +{ + struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci); + struct usb_composite_dev *cdev = cfg->c.cdev; + struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); + + struct config_group *group = to_config_group(usb_func_ci); + struct usb_function_instance *fi = container_of(group, + struct usb_function_instance, group); + struct usb_function_instance *a_fi; + struct usb_function *f; + int ret; + + mutex_lock(&gi->lock); + /* + * Make sure this function is from within our _this_ gadget and not + * from another gadget or a random directory. + * Also a function instance can only be linked once. + */ + list_for_each_entry(a_fi, &gi->available_func, cfs_list) { + if (a_fi == fi) + break; + } + if (a_fi != fi) { + ret = -EINVAL; + goto out; + } + + list_for_each_entry(f, &cfg->func_list, list) { + if (f->fi == fi) { + ret = -EEXIST; + goto out; + } + } + + f = usb_get_function(fi); + if (IS_ERR(f)) { + ret = PTR_ERR(f); + goto out; + } + + /* stash the function until we bind it to the gadget */ + list_add_tail(&f->list, &cfg->func_list); + ret = 0; +out: + mutex_unlock(&gi->lock); + return ret; +} + +static int config_usb_cfg_unlink( + struct config_item *usb_cfg_ci, + struct config_item *usb_func_ci) +{ + struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci); + struct usb_composite_dev *cdev = cfg->c.cdev; + struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev); + + struct config_group *group = to_config_group(usb_func_ci); + struct usb_function_instance *fi = container_of(group, + struct usb_function_instance, group); + struct usb_function *f; + + /* + * ideally I would like to forbid to unlink functions while a gadget is + * bound to an UDC. Since this isn't possible at the moment, we simply + * force an unbind, the function is available here and then we can + * remove the function. + */ + mutex_lock(&gi->lock); + if (gi->udc_name) + unregister_gadget(gi); + WARN_ON(gi->udc_name); + + list_for_each_entry(f, &cfg->func_list, list) { + if (f->fi == fi) { + list_del(&f->list); + usb_put_function(f); + mutex_unlock(&gi->lock); + return 0; + } + } + mutex_unlock(&gi->lock); + __WARN_printf("Unable to locate function to unbind\n"); + return 0; +} + +CONFIGFS_ATTR_OPS(config_usb_cfg); + +static struct configfs_item_operations gadget_config_item_ops = { + .release = gadget_config_attr_release, + .show_attribute = config_usb_cfg_attr_show, + .store_attribute = config_usb_cfg_attr_store, + .allow_link = config_usb_cfg_link, + .drop_link = config_usb_cfg_unlink, +}; + + +static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg, + char *page) +{ + return sprintf(page, "%u\n", cfg->c.MaxPower); +} + +static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg, + const char *page, size_t len) +{ + u16 val; + int ret; + ret = kstrtou16(page, 0, &val); + if (ret) + return ret; + if (DIV_ROUND_UP(val, 8) > 0xff) + return -ERANGE; + cfg->c.MaxPower = val; + return len; +} + +static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg, + char *page) +{ + return sprintf(page, "0x%02x\n", cfg->c.bmAttributes); +} + +static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg, + const char *page, size_t len) +{ + u8 val; + int ret; + ret = kstrtou8(page, 0, &val); + if (ret) + return ret; + if (!(val & USB_CONFIG_ATT_ONE)) + return -EINVAL; + if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER | + USB_CONFIG_ATT_WAKEUP)) + return -EINVAL; + cfg->c.bmAttributes = val; + return len; +} + +#define CFG_CONFIG_DESC_ITEM_ATTR(name) \ + static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \ + __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ + gadget_config_desc_##name##_show, \ + gadget_config_desc_##name##_store) + +CFG_CONFIG_DESC_ITEM_ATTR(MaxPower); +CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes); + +static struct configfs_attribute *gadget_config_attrs[] = { + &gadget_usb_cfg_MaxPower.attr, + &gadget_usb_cfg_bmAttributes.attr, + NULL, +}; + +static struct config_item_type gadget_config_type = { + .ct_item_ops = &gadget_config_item_ops, + .ct_attrs = gadget_config_attrs, + .ct_owner = THIS_MODULE, +}; + +static struct config_item_type gadget_root_type = { + .ct_item_ops = &gadget_root_item_ops, + .ct_attrs = gadget_root_attrs, + .ct_owner = THIS_MODULE, +}; + +static void composite_init_dev(struct usb_composite_dev *cdev) +{ + spin_lock_init(&cdev->lock); + INIT_LIST_HEAD(&cdev->configs); + INIT_LIST_HEAD(&cdev->gstrings); +} + +static struct config_group *function_make( + struct config_group *group, + const char *name) +{ + struct gadget_info *gi; + struct usb_function_instance *fi; + char buf[MAX_NAME_LEN]; + char *func_name; + char *instance_name; + int ret; + + ret = snprintf(buf, MAX_NAME_LEN, "%s", name); + if (ret >= MAX_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + + func_name = buf; + instance_name = strchr(func_name, '.'); + if (!instance_name) { + pr_err("Unable to locate . in FUNC.INSTANCE\n"); + return ERR_PTR(-EINVAL); + } + *instance_name = '\0'; + instance_name++; + + fi = usb_get_function_instance(func_name); + if (IS_ERR(fi)) + return ERR_PTR(PTR_ERR(fi)); + + ret = config_item_set_name(&fi->group.cg_item, name); + if (ret) { + usb_put_function_instance(fi); + return ERR_PTR(ret); + } + + gi = container_of(group, struct gadget_info, functions_group); + + mutex_lock(&gi->lock); + list_add_tail(&fi->cfs_list, &gi->available_func); + mutex_unlock(&gi->lock); + return &fi->group; +} + +static void function_drop( + struct config_group *group, + struct config_item *item) +{ + struct usb_function_instance *fi = to_usb_function_instance(item); + struct gadget_info *gi; + + gi = container_of(group, struct gadget_info, functions_group); + + mutex_lock(&gi->lock); + list_del(&fi->cfs_list); + mutex_unlock(&gi->lock); + config_item_put(item); +} + +static struct configfs_group_operations functions_ops = { + .make_group = &function_make, + .drop_item = &function_drop, +}; + +static struct config_item_type functions_type = { + .ct_group_ops = &functions_ops, + .ct_owner = THIS_MODULE, +}; + +CONFIGFS_ATTR_STRUCT(gadget_config_name); +GS_STRINGS_RW(gadget_config_name, configuration); + +static struct configfs_attribute *gadget_config_name_langid_attrs[] = { + &gadget_config_name_configuration.attr, + NULL, +}; + +static void gadget_config_name_attr_release(struct config_item *item) +{ + struct gadget_config_name *cn = to_gadget_config_name(item); + + kfree(cn->configuration); + + list_del(&cn->list); + kfree(cn); +} + +USB_CONFIG_STRING_RW_OPS(gadget_config_name); +USB_CONFIG_STRINGS_LANG(gadget_config_name, config_usb_cfg); + +static struct config_group *config_desc_make( + struct config_group *group, + const char *name) +{ + struct gadget_info *gi; + struct config_usb_cfg *cfg; + char buf[MAX_NAME_LEN]; + char *num_str; + u8 num; + int ret; + + gi = container_of(group, struct gadget_info, configs_group); + ret = snprintf(buf, MAX_NAME_LEN, "%s", name); + if (ret >= MAX_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + + num_str = strchr(buf, '.'); + if (!num_str) { + pr_err("Unable to locate . in name.bConfigurationValue\n"); + return ERR_PTR(-EINVAL); + } + + *num_str = '\0'; + num_str++; + + if (!strlen(buf)) + return ERR_PTR(-EINVAL); + + ret = kstrtou8(num_str, 0, &num); + if (ret) + return ERR_PTR(ret); + + cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) + return ERR_PTR(-ENOMEM); + cfg->c.label = kstrdup(buf, GFP_KERNEL); + if (!cfg->c.label) { + ret = -ENOMEM; + goto err; + } + cfg->c.bConfigurationValue = num; + cfg->c.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW; + cfg->c.bmAttributes = USB_CONFIG_ATT_ONE; + INIT_LIST_HEAD(&cfg->string_list); + INIT_LIST_HEAD(&cfg->func_list); + + cfg->group.default_groups = cfg->default_groups; + cfg->default_groups[0] = &cfg->strings_group; + + config_group_init_type_name(&cfg->group, name, + &gadget_config_type); + config_group_init_type_name(&cfg->strings_group, "strings", + &gadget_config_name_strings_type); + + ret = usb_add_config_only(&gi->cdev, &cfg->c); + if (ret) + goto err; + + return &cfg->group; +err: + kfree(cfg->c.label); + kfree(cfg); + return ERR_PTR(ret); +} + +static void config_desc_drop( + struct config_group *group, + struct config_item *item) +{ + config_item_put(item); +} + +static struct configfs_group_operations config_desc_ops = { + .make_group = &config_desc_make, + .drop_item = &config_desc_drop, +}; + +static struct config_item_type config_desc_type = { + .ct_group_ops = &config_desc_ops, + .ct_owner = THIS_MODULE, +}; + +CONFIGFS_ATTR_STRUCT(gadget_strings); +GS_STRINGS_RW(gadget_strings, manufacturer); +GS_STRINGS_RW(gadget_strings, product); +GS_STRINGS_RW(gadget_strings, serialnumber); + +static struct configfs_attribute *gadget_strings_langid_attrs[] = { + &gadget_strings_manufacturer.attr, + &gadget_strings_product.attr, + &gadget_strings_serialnumber.attr, + NULL, +}; + +static void gadget_strings_attr_release(struct config_item *item) +{ + struct gadget_strings *gs = to_gadget_strings(item); + + kfree(gs->manufacturer); + kfree(gs->product); + kfree(gs->serialnumber); + + list_del(&gs->list); + kfree(gs); +} + +USB_CONFIG_STRING_RW_OPS(gadget_strings); +USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info); + +static int configfs_do_nothing(struct usb_composite_dev *cdev) +{ + __WARN(); + return -EINVAL; +} + +int composite_dev_prepare(struct usb_composite_driver *composite, + struct usb_composite_dev *dev); + +static void purge_configs_funcs(struct gadget_info *gi) +{ + struct usb_configuration *c; + + list_for_each_entry(c, &gi->cdev.configs, list) { + struct usb_function *f, *tmp; + struct config_usb_cfg *cfg; + + cfg = container_of(c, struct config_usb_cfg, c); + + list_for_each_entry_safe(f, tmp, &c->functions, list) { + + list_move_tail(&f->list, &cfg->func_list); + if (f->unbind) { + dev_err(&gi->cdev.gadget->dev, "unbind function" + " '%s'/%p\n", f->name, f); + f->unbind(c, f); + } + } + c->next_interface_id = 0; + c->superspeed = 0; + c->highspeed = 0; + c->fullspeed = 0; + } +} + +static int configfs_composite_bind(struct usb_gadget *gadget, + struct usb_gadget_driver *gdriver) +{ + struct usb_composite_driver *composite = to_cdriver(gdriver); + struct gadget_info *gi = container_of(composite, + struct gadget_info, composite); + struct usb_composite_dev *cdev = &gi->cdev; + struct usb_configuration *c; + struct usb_string *s; + unsigned i; + int ret; + + /* the gi->lock is hold by the caller */ + cdev->gadget = gadget; + set_gadget_data(gadget, cdev); + ret = composite_dev_prepare(composite, cdev); + if (ret) + return ret; + /* and now the gadget bind */ + ret = -EINVAL; + + if (list_empty(&gi->cdev.configs)) { + pr_err("Need atleast one configuration in %s.\n", + gi->composite.name); + goto err_comp_cleanup; + } + + + list_for_each_entry(c, &gi->cdev.configs, list) { + struct config_usb_cfg *cfg; + + cfg = container_of(c, struct config_usb_cfg, c); + if (list_empty(&cfg->func_list)) { + pr_err("Config %s/%d of %s needs atleast one function.\n", + c->label, c->bConfigurationValue, + gi->composite.name); + goto err_comp_cleanup; + } + } + + /* init all strings */ + if (!list_empty(&gi->string_list)) { + struct gadget_strings *gs; + + i = 0; + list_for_each_entry(gs, &gi->string_list, list) { + + gi->gstrings[i] = &gs->stringtab_dev; + gs->stringtab_dev.strings = gs->strings; + gs->strings[USB_GADGET_MANUFACTURER_IDX].s = + gs->manufacturer; + gs->strings[USB_GADGET_PRODUCT_IDX].s = gs->product; + gs->strings[USB_GADGET_SERIAL_IDX].s = gs->serialnumber; + i++; + } + gi->gstrings[i] = NULL; + s = usb_gstrings_attach(&gi->cdev, gi->gstrings, + USB_GADGET_FIRST_AVAIL_IDX); + if (IS_ERR(s)) + goto err_comp_cleanup; + + gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id; + gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id; + gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id; + } + + /* Go through all configs, attach all functions */ + list_for_each_entry(c, &gi->cdev.configs, list) { + struct config_usb_cfg *cfg; + struct usb_function *f; + struct usb_function *tmp; + struct gadget_config_name *cn; + + cfg = container_of(c, struct config_usb_cfg, c); + if (!list_empty(&cfg->string_list)) { + i = 0; + list_for_each_entry(cn, &cfg->string_list, list) { + cfg->gstrings[i] = &cn->stringtab_dev; + cn->stringtab_dev.strings = &cn->strings; + cn->strings.s = cn->configuration; + i++; + } + cfg->gstrings[i] = NULL; + s = usb_gstrings_attach(&gi->cdev, cfg->gstrings, 1); + if (IS_ERR(s)) + goto err_comp_cleanup; + c->iConfiguration = s[0].id; + } + + list_for_each_entry_safe(f, tmp, &cfg->func_list, list) { + list_del(&f->list); + ret = usb_add_function(c, f); + if (ret) + goto err_purge_funcs; + } + usb_ep_autoconfig_reset(cdev->gadget); + } + usb_ep_autoconfig_reset(cdev->gadget); + return 0; + +err_purge_funcs: + purge_configs_funcs(gi); +err_comp_cleanup: + composite_dev_cleanup(cdev); + return ret; +} + +static void configfs_composite_unbind(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + struct gadget_info *gi; + + /* the gi->lock is hold by the caller */ + + cdev = get_gadget_data(gadget); + gi = container_of(cdev, struct gadget_info, cdev); + + purge_configs_funcs(gi); + composite_dev_cleanup(cdev); + usb_ep_autoconfig_reset(cdev->gadget); + cdev->gadget = NULL; + set_gadget_data(gadget, NULL); +} + +static const struct usb_gadget_driver configfs_driver_template = { + .bind = configfs_composite_bind, + .unbind = configfs_composite_unbind, + + .setup = composite_setup, + .disconnect = composite_disconnect, + + .max_speed = USB_SPEED_SUPER, + .driver = { + .owner = THIS_MODULE, + .name = "configfs-gadget", + }, +}; + +static struct config_group *gadgets_make( + struct config_group *group, + const char *name) +{ + struct gadget_info *gi; + + gi = kzalloc(sizeof(*gi), GFP_KERNEL); + if (!gi) + return ERR_PTR(-ENOMEM); + + gi->group.default_groups = gi->default_groups; + gi->group.default_groups[0] = &gi->functions_group; + gi->group.default_groups[1] = &gi->configs_group; + gi->group.default_groups[2] = &gi->strings_group; + + config_group_init_type_name(&gi->functions_group, "functions", + &functions_type); + config_group_init_type_name(&gi->configs_group, "configs", + &config_desc_type); + config_group_init_type_name(&gi->strings_group, "strings", + &gadget_strings_strings_type); + + gi->composite.bind = configfs_do_nothing; + gi->composite.unbind = configfs_do_nothing; + gi->composite.suspend = NULL; + gi->composite.resume = NULL; + gi->composite.max_speed = USB_SPEED_SUPER; + + mutex_init(&gi->lock); + INIT_LIST_HEAD(&gi->string_list); + INIT_LIST_HEAD(&gi->available_func); + + composite_init_dev(&gi->cdev); + gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE; + gi->cdev.desc.bDescriptorType = USB_DT_DEVICE; + gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice()); + + gi->composite.gadget_driver = configfs_driver_template; + + gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL); + gi->composite.name = gi->composite.gadget_driver.function; + + if (!gi->composite.gadget_driver.function) + goto err; + +#ifdef CONFIG_USB_OTG + gi->otg.bLength = sizeof(struct usb_otg_descriptor); + gi->otg.bDescriptorType = USB_DT_OTG; + gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP; +#endif + + config_group_init_type_name(&gi->group, name, + &gadget_root_type); + return &gi->group; +err: + kfree(gi); + return ERR_PTR(-ENOMEM); +} + +static void gadgets_drop(struct config_group *group, struct config_item *item) +{ + config_item_put(item); +} + +static struct configfs_group_operations gadgets_ops = { + .make_group = &gadgets_make, + .drop_item = &gadgets_drop, +}; + +static struct config_item_type gadgets_type = { + .ct_group_ops = &gadgets_ops, + .ct_owner = THIS_MODULE, +}; + +static struct configfs_subsystem gadget_subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = "usb_gadget", + .ci_type = &gadgets_type, + }, + }, + .su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex), +}; + +static int __init gadget_cfs_init(void) +{ + int ret; + + config_group_init(&gadget_subsys.su_group); + + ret = configfs_register_subsystem(&gadget_subsys); + return ret; +} +module_init(gadget_cfs_init); + +static void __exit gadget_cfs_exit(void) +{ + configfs_unregister_subsystem(&gadget_subsys); +} +module_exit(gadget_cfs_exit); diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index ba7daaaad148..4b7e33e5d9c6 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -763,6 +763,59 @@ static struct usb_function *acm_alloc_func(struct usb_function_instance *fi) return &acm->port.func; } +static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item) +{ + return container_of(to_config_group(item), struct f_serial_opts, + func_inst.group); +} + +CONFIGFS_ATTR_STRUCT(f_serial_opts); +static ssize_t f_acm_attr_show(struct config_item *item, + struct configfs_attribute *attr, + char *page) +{ + struct f_serial_opts *opts = to_f_serial_opts(item); + struct f_serial_opts_attribute *f_serial_opts_attr = + container_of(attr, struct f_serial_opts_attribute, attr); + ssize_t ret = 0; + + if (f_serial_opts_attr->show) + ret = f_serial_opts_attr->show(opts, page); + return ret; +} + +static void acm_attr_release(struct config_item *item) +{ + struct f_serial_opts *opts = to_f_serial_opts(item); + + usb_put_function_instance(&opts->func_inst); +} + +static struct configfs_item_operations acm_item_ops = { + .release = acm_attr_release, + .show_attribute = f_acm_attr_show, +}; + +static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page) +{ + return sprintf(page, "%u\n", opts->port_num); +} + +static struct f_serial_opts_attribute f_acm_port_num = + __CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show); + + +static struct configfs_attribute *acm_attrs[] = { + &f_acm_port_num.attr, + NULL, +}; + +static struct config_item_type acm_func_type = { + .ct_item_ops = &acm_item_ops, + .ct_attrs = acm_attrs, + .ct_owner = THIS_MODULE, +}; + static void acm_free_instance(struct usb_function_instance *fi) { struct f_serial_opts *opts; @@ -786,6 +839,8 @@ static struct usb_function_instance *acm_alloc_instance(void) kfree(opts); return ERR_PTR(ret); } + config_group_init_type_name(&opts->func_inst.group, "", + &acm_func_type); return &opts->func_inst; } DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 8860594d6364..5e61589fc166 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -39,6 +39,7 @@ #include #include #include +#include /* * USB function drivers should return USB_GADGET_DELAYED_STATUS if they @@ -464,6 +465,8 @@ struct usb_function_driver { }; struct usb_function_instance { + struct config_group group; + struct list_head cfs_list; struct usb_function_driver *fd; void (*free_func_inst)(struct usb_function_instance *inst); }; diff --git a/include/linux/usb/gadget_configfs.h b/include/linux/usb/gadget_configfs.h new file mode 100644 index 000000000000..d74c0ae989d5 --- /dev/null +++ b/include/linux/usb/gadget_configfs.h @@ -0,0 +1,110 @@ +#ifndef __GADGET_CONFIGFS__ +#define __GADGET_CONFIGFS__ + +#include + +int check_user_usb_string(const char *name, + struct usb_gadget_strings *stringtab_dev); + +#define GS_STRINGS_W(__struct, __name) \ + static ssize_t __struct##_##__name##_store(struct __struct *gs, \ + const char *page, size_t len) \ +{ \ + int ret; \ + \ + ret = usb_string_copy(page, &gs->__name); \ + if (ret) \ + return ret; \ + return len; \ +} + +#define GS_STRINGS_R(__struct, __name) \ + static ssize_t __struct##_##__name##_show(struct __struct *gs, \ + char *page) \ +{ \ + return sprintf(page, "%s\n", gs->__name ?: ""); \ +} + +#define GS_STRING_ITEM_ATTR(struct_name, name) \ + static struct struct_name##_attribute struct_name##_##name = \ + __CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \ + struct_name##_##name##_show, \ + struct_name##_##name##_store) + +#define GS_STRINGS_RW(struct_name, _name) \ + GS_STRINGS_R(struct_name, _name) \ + GS_STRINGS_W(struct_name, _name) \ + GS_STRING_ITEM_ATTR(struct_name, _name) + +#define USB_CONFIG_STRING_RW_OPS(struct_in) \ + CONFIGFS_ATTR_OPS(struct_in); \ + \ +static struct configfs_item_operations struct_in##_langid_item_ops = { \ + .release = struct_in##_attr_release, \ + .show_attribute = struct_in##_attr_show, \ + .store_attribute = struct_in##_attr_store, \ +}; \ + \ +static struct config_item_type struct_in##_langid_type = { \ + .ct_item_ops = &struct_in##_langid_item_ops, \ + .ct_attrs = struct_in##_langid_attrs, \ + .ct_owner = THIS_MODULE, \ +} + +#define USB_CONFIG_STRINGS_LANG(struct_in, struct_member) \ + static struct config_group *struct_in##_strings_make( \ + struct config_group *group, \ + const char *name) \ + { \ + struct struct_member *gi; \ + struct struct_in *gs; \ + struct struct_in *new; \ + int langs = 0; \ + int ret; \ + \ + new = kzalloc(sizeof(*new), GFP_KERNEL); \ + if (!new) \ + return ERR_PTR(-ENOMEM); \ + \ + ret = check_user_usb_string(name, &new->stringtab_dev); \ + if (ret) \ + goto err; \ + config_group_init_type_name(&new->group, name, \ + &struct_in##_langid_type); \ + \ + gi = container_of(group, struct struct_member, strings_group); \ + ret = -EEXIST; \ + list_for_each_entry(gs, &gi->string_list, list) { \ + if (gs->stringtab_dev.language == new->stringtab_dev.language) \ + goto err; \ + langs++; \ + } \ + ret = -EOVERFLOW; \ + if (langs >= MAX_USB_STRING_LANGS) \ + goto err; \ + \ + list_add_tail(&new->list, &gi->string_list); \ + return &new->group; \ +err: \ + kfree(new); \ + return ERR_PTR(ret); \ +} \ + \ +static void struct_in##_strings_drop( \ + struct config_group *group, \ + struct config_item *item) \ +{ \ + config_item_put(item); \ +} \ + \ +static struct configfs_group_operations struct_in##_strings_ops = { \ + .make_group = &struct_in##_strings_make, \ + .drop_item = &struct_in##_strings_drop, \ +}; \ + \ +static struct config_item_type struct_in##_strings_type = { \ + .ct_group_ops = &struct_in##_strings_ops, \ + .ct_owner = THIS_MODULE, \ +} + +#endif From 4f47a1be0fb2ce2ee166faeb3f08f22d70e09109 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 7 Feb 2013 14:36:27 +0100 Subject: [PATCH 291/303] usb: gadget: use consistent naming scheme for usb function modules In order to convert to configfs the USB functions need to be converted to the new interface from Sebastian, which also requires turning them into separate modules. Some of these modules will consist of just one object file, e.g. f_ncm.o. But some of the modules will eventually consist of more than one object file, e.g. for mass storage there will be f_mass_storage.o and storage_common.o. The resulting module cannot be called f_mass_storage.ko due to cyclic dependency. This patch introduces a naming scheme for the said resulting modules: usb_f_xxxxxx.ko e.g. usb_f_mass_storage.ko, usb_f_ss_lb.ko, usb_f_rndis.ko etc. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 96e72433cd31..b938e06382b7 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -36,9 +36,10 @@ obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o # USB Functions -obj-$(CONFIG_USB_F_ACM) += f_acm.o -f_ss_lb-y := f_loopback.o f_sourcesink.o -obj-$(CONFIG_USB_F_SS_LB) += f_ss_lb.o +usb_f_acm-y := f_acm.o +obj-$(CONFIG_USB_F_ACM) += usb_f_acm.o +usb_f_ss_lb-y := f_loopback.o f_sourcesink.o +obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o obj-$(CONFIG_USB_U_SERIAL) += u_serial.o # From 81f886cb7a5157d1b6562084a2ed96328e39f288 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 14 Mar 2013 16:11:57 +0100 Subject: [PATCH 292/303] usb: gadget: nokia: remove unused include f_serial.c isn't necessary in nokia.c, we can safely remove it. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/nokia.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index b5fbf1a1cb3c..f829a80f27f6 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -39,7 +39,6 @@ */ #include "f_ecm.c" #include "f_obex.c" -#include "f_serial.c" #include "f_phonet.c" #include "u_ether.c" From 60540ea2c51fa4feb475f689adce56297cb52010 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 18 Mar 2013 09:52:57 +0100 Subject: [PATCH 293/303] usb: gadget: f_serial: convert to new function interface with backward compatibility Converting f_serial to the new function interface requires converting the f_serial's function code and its users. This patch converts the f_serial.c to the new function interface. The file is now compiled into a separate usb_f_serial.ko module. The old function interface is provided by means of preprocessor conditional directives. After all users are converted, the old interface can be removed. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 3 + drivers/usb/gadget/Makefile | 2 + drivers/usb/gadget/f_serial.c | 131 +++++++++++++++++++++++++++------- drivers/usb/gadget/serial.c | 1 + 4 files changed, 110 insertions(+), 27 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 74a29de8f254..8a08efbb11e7 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -505,6 +505,9 @@ config USB_F_SS_LB config USB_U_SERIAL tristate +config USB_F_SERIAL + tristate + choice tristate "USB Gadget Drivers" default USB_ETH diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index b938e06382b7..34bb49a131e9 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -41,6 +41,8 @@ obj-$(CONFIG_USB_F_ACM) += usb_f_acm.o usb_f_ss_lb-y := f_loopback.o f_sourcesink.o obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o obj-$(CONFIG_USB_U_SERIAL) += u_serial.o +usb_f_serial-y := f_serial.o +obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o # # USB gadget drivers diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index da33cfb3031d..465789bd5c91 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -12,6 +12,7 @@ #include #include +#include #include #include "u_serial.h" @@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f) /* interface descriptor: */ -static struct usb_interface_descriptor gser_interface_desc __initdata = { +static struct usb_interface_descriptor gser_interface_desc = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, /* .bInterfaceNumber = DYNAMIC */ @@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = { /* full speed support: */ -static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = { +static struct usb_endpoint_descriptor gser_fs_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = { +static struct usb_endpoint_descriptor gser_fs_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_descriptor_header *gser_fs_function[] __initdata = { +static struct usb_descriptor_header *gser_fs_function[] = { (struct usb_descriptor_header *) &gser_interface_desc, (struct usb_descriptor_header *) &gser_fs_in_desc, (struct usb_descriptor_header *) &gser_fs_out_desc, @@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = { /* high speed support: */ -static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = { +static struct usb_endpoint_descriptor gser_hs_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = { +static struct usb_endpoint_descriptor gser_hs_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_descriptor_header *gser_hs_function[] __initdata = { +static struct usb_descriptor_header *gser_hs_function[] = { (struct usb_descriptor_header *) &gser_interface_desc, (struct usb_descriptor_header *) &gser_hs_in_desc, (struct usb_descriptor_header *) &gser_hs_out_desc, NULL, }; -static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = { +static struct usb_endpoint_descriptor gser_ss_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024), }; -static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = { +static struct usb_endpoint_descriptor gser_ss_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024), }; -static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = { +static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = { .bLength = sizeof gser_ss_bulk_comp_desc, .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, }; -static struct usb_descriptor_header *gser_ss_function[] __initdata = { +static struct usb_descriptor_header *gser_ss_function[] = { (struct usb_descriptor_header *) &gser_interface_desc, (struct usb_descriptor_header *) &gser_ss_in_desc, (struct usb_descriptor_header *) &gser_ss_bulk_comp_desc, @@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f) /* serial function driver setup/binding */ -static int __init -gser_bind(struct usb_configuration *c, struct usb_function *f) +static int gser_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_gser *gser = func_to_gser(f); int status; struct usb_ep *ep; + /* REVISIT might want instance-specific strings to help + * distinguish instances ... + */ + + /* maybe allocate device-global string ID */ + if (gser_string_defs[0].id == 0) { + status = usb_string_id(c->cdev); + if (status < 0) + return status; + gser_string_defs[0].id = status; + } + /* allocate instance-specific interface IDs */ status = usb_interface_id(c, f); if (status < 0) @@ -246,8 +258,10 @@ fail: return status; } +#ifdef USB_FSERIAL_INCLUDED + static void -gser_unbind(struct usb_configuration *c, struct usb_function *f) +gser_old_unbind(struct usb_configuration *c, struct usb_function *f) { usb_free_all_descriptors(f); kfree(func_to_gser(f)); @@ -266,18 +280,6 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num) struct f_gser *gser; int status; - /* REVISIT might want instance-specific strings to help - * distinguish instances ... - */ - - /* maybe allocate device-global string ID */ - if (gser_string_defs[0].id == 0) { - status = usb_string_id(c->cdev); - if (status < 0) - return status; - gser_string_defs[0].id = status; - } - /* allocate and initialize one new instance */ gser = kzalloc(sizeof *gser, GFP_KERNEL); if (!gser) @@ -288,7 +290,7 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num) gser->port.func.name = "gser"; gser->port.func.strings = gser_strings; gser->port.func.bind = gser_bind; - gser->port.func.unbind = gser_unbind; + gser->port.func.unbind = gser_old_unbind; gser->port.func.set_alt = gser_set_alt; gser->port.func.disable = gser_disable; @@ -297,3 +299,78 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num) kfree(gser); return status; } + +#else + +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); + } + + 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 */ + gser = kzalloc(sizeof(*gser), GFP_KERNEL); + if (!gser) + return ERR_PTR(-ENOMEM); + + opts = container_of(fi, struct f_serial_opts, func_inst); + + gser->port_num = opts->port_num; + + gser->port.func.name = "gser"; + gser->port.func.strings = gser_strings; + gser->port.func.bind = gser_bind; + gser->port.func.unbind = gser_unbind; + gser->port.func.set_alt = gser_set_alt; + gser->port.func.disable = gser_disable; + gser->port.func.free_func = gser_free; + + return &gser->port.func; +} + +DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Al Borchers"); +MODULE_AUTHOR("David Brownell"); + +#endif diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index c48ca1eb5442..07c1e802f917 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -37,6 +37,7 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "f_obex.c" +#define USB_FSERIAL_INCLUDED #include "f_serial.c" /*-------------------------------------------------------------------------*/ From 70cc3c024640a3c60e91d04789f9574a371a2db5 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 14 Mar 2013 16:02:12 +0100 Subject: [PATCH 294/303] usb: gadget: serial: convert to new interface of f_serial Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/serial.c | 25 +++++++------------------ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 8a08efbb11e7..93217fc86c12 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -762,6 +762,7 @@ config USB_G_SERIAL depends on TTY select USB_U_SERIAL select USB_F_ACM + select USB_F_SERIAL select USB_LIBCOMPOSITE help The Serial Gadget talks to the Linux-USB generic serial driver. diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 07c1e802f917..9d215c4c2275 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -37,8 +37,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "f_obex.c" -#define USB_FSERIAL_INCLUDED -#include "f_serial.c" /*-------------------------------------------------------------------------*/ USB_GADGET_COMPOSITE_OPTIONS(); @@ -139,16 +137,6 @@ static int __init serial_bind_obex_config(struct usb_configuration *c) return status; } -static int __init serial_bind_gser_config(struct usb_configuration *c) -{ - unsigned i; - int status = 0; - - for (i = 0; i < n_ports && status == 0; i++) - status = gser_bind_config(c, tty_lines[i]); - return status; -} - static struct usb_configuration serial_config_driver = { /* .label = f(use_acm) */ /* .bConfigurationValue = f(use_acm) */ @@ -212,7 +200,7 @@ static int __init gs_bind(struct usb_composite_dev *cdev) int status; int cur_line = 0; - if (!use_acm) { + if (use_obex) { for (cur_line = 0; cur_line < n_ports; cur_line++) { status = gserial_alloc_line(&tty_lines[cur_line]); if (status) @@ -245,9 +233,10 @@ static int __init gs_bind(struct usb_composite_dev *cdev) } else if (use_obex) status = usb_add_config(cdev, &serial_config_driver, serial_bind_obex_config); - else - status = usb_add_config(cdev, &serial_config_driver, - serial_bind_gser_config); + else { + status = serial_register_ports(cdev, &serial_config_driver, + "gser"); + } if (status < 0) goto fail; @@ -258,7 +247,7 @@ static int __init gs_bind(struct usb_composite_dev *cdev) fail: cur_line--; - while (cur_line >= 0 && !use_acm) + while (cur_line >= 0 && use_obex) gserial_free_line(tty_lines[cur_line--]); return status; } @@ -270,7 +259,7 @@ static int gs_unbind(struct usb_composite_dev *cdev) for (i = 0; i < n_ports; i++) { usb_put_function(f_serial[i]); usb_put_function_instance(fi_serial[i]); - if (!use_acm) + if (use_obex) gserial_free_line(tty_lines[i]); } return 0; From 9786b4561228099f579ad88912aa305812526ea1 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 14 Mar 2013 16:14:26 +0100 Subject: [PATCH 295/303] usb: gadget: f_serial: remove compatibility layer There are no old function interface users left, so the old interface can be removed. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_serial.c | 46 ----------------------------------- 1 file changed, 46 deletions(-) diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index 465789bd5c91..49c3d146f9b0 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -258,50 +258,6 @@ fail: return status; } -#ifdef USB_FSERIAL_INCLUDED - -static void -gser_old_unbind(struct usb_configuration *c, struct usb_function *f) -{ - usb_free_all_descriptors(f); - kfree(func_to_gser(f)); -} - -/** - * gser_bind_config - add a generic serial function to a configuration - * @c: the configuration to support the serial instance - * @port_num: /dev/ttyGS* port this interface will use - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - */ -int __init gser_bind_config(struct usb_configuration *c, u8 port_num) -{ - struct f_gser *gser; - int status; - - /* allocate and initialize one new instance */ - gser = kzalloc(sizeof *gser, GFP_KERNEL); - if (!gser) - return -ENOMEM; - - gser->port_num = port_num; - - gser->port.func.name = "gser"; - gser->port.func.strings = gser_strings; - gser->port.func.bind = gser_bind; - gser->port.func.unbind = gser_old_unbind; - gser->port.func.set_alt = gser_set_alt; - gser->port.func.disable = gser_disable; - - status = usb_add_function(c, &gser->port.func); - if (status) - kfree(gser); - return status; -} - -#else - static void gser_free_inst(struct usb_function_instance *f) { struct f_serial_opts *opts; @@ -372,5 +328,3 @@ DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Al Borchers"); MODULE_AUTHOR("David Brownell"); - -#endif From 0b6a1e6ff7e62a1ab5a8924bffb12c17c183308a Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Wed, 27 Mar 2013 09:12:03 +0100 Subject: [PATCH 296/303] usb: gadget: f_serial: add configfs support this patch implements the new configfs based interface on f_serial function driver. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_serial.c | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index 49c3d146f9b0..981113c9924d 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -258,6 +258,59 @@ fail: return status; } +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_serial_attr_show(struct config_item *item, + struct configfs_attribute *attr, + char *page) +{ + struct f_serial_opts *opts = to_f_serial_opts(item); + struct f_serial_opts_attribute *f_serial_opts_attr = + container_of(attr, struct f_serial_opts_attribute, attr); + ssize_t ret = 0; + + if (f_serial_opts_attr->show) + ret = f_serial_opts_attr->show(opts, page); + + return ret; +} + +static void serial_attr_release(struct config_item *item) +{ + struct f_serial_opts *opts = to_f_serial_opts(item); + + usb_put_function_instance(&opts->func_inst); +} + +static struct configfs_item_operations serial_item_ops = { + .release = serial_attr_release, + .show_attribute = f_serial_attr_show, +}; + +static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page) +{ + return sprintf(page, "%u\n", opts->port_num); +} + +static struct f_serial_opts_attribute f_serial_port_num = + __CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show); + +static struct configfs_attribute *acm_attrs[] = { + &f_serial_port_num.attr, + NULL, +}; + +static struct config_item_type serial_func_type = { + .ct_item_ops = &serial_item_ops, + .ct_attrs = acm_attrs, + .ct_owner = THIS_MODULE, +}; + static void gser_free_inst(struct usb_function_instance *f) { struct f_serial_opts *opts; @@ -282,6 +335,8 @@ static struct usb_function_instance *gser_alloc_inst(void) kfree(opts); return ERR_PTR(ret); } + config_group_init_type_name(&opts->func_inst.group, "", + &serial_func_type); return &opts->func_inst; } From 1d8fc2518c1cddef0902b0a2c51946732a0982fc Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 21 Mar 2013 15:33:42 +0100 Subject: [PATCH 297/303] usb: gadget: f_obex: convert to new function interface with backward compatibility Converting f_obex to the new function interface requires converting the f_obex's function code and its users. This patch converts the f_obex.c to the new function interface. The file is now compiled into a separate usb_f_obex.ko module. The old function interface is provided by means of preprocessor conditional directives. After all users are converted, the old interface can be removed. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 3 + drivers/usb/gadget/Makefile | 2 + drivers/usb/gadget/f_obex.c | 171 ++++++++++++++++++++++++++---------- drivers/usb/gadget/nokia.c | 2 +- drivers/usb/gadget/serial.c | 1 + 5 files changed, 132 insertions(+), 47 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 93217fc86c12..a5f67e14daf2 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -508,6 +508,9 @@ config USB_U_SERIAL config USB_F_SERIAL tristate +config USB_F_OBEX + tristate + choice tristate "USB Gadget Drivers" default USB_ETH diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 34bb49a131e9..6afd16659e78 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -43,6 +43,8 @@ obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o obj-$(CONFIG_USB_U_SERIAL) += u_serial.o usb_f_serial-y := f_serial.o obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o +usb_f_obex-y := f_obex.o +obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o # # USB gadget drivers diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 36a004563b82..439b666120c2 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c @@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = { /*-------------------------------------------------------------------------*/ -static struct usb_interface_descriptor obex_control_intf __initdata = { +static struct usb_interface_descriptor obex_control_intf = { .bLength = sizeof(obex_control_intf), .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = 0, @@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = { .bInterfaceSubClass = USB_CDC_SUBCLASS_OBEX, }; -static struct usb_interface_descriptor obex_data_nop_intf __initdata = { +static struct usb_interface_descriptor obex_data_nop_intf = { .bLength = sizeof(obex_data_nop_intf), .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = 1, @@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = { .bInterfaceClass = USB_CLASS_CDC_DATA, }; -static struct usb_interface_descriptor obex_data_intf __initdata = { +static struct usb_interface_descriptor obex_data_intf = { .bLength = sizeof(obex_data_intf), .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = 2, @@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = { .bInterfaceClass = USB_CLASS_CDC_DATA, }; -static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = { +static struct usb_cdc_header_desc obex_cdc_header_desc = { .bLength = sizeof(obex_cdc_header_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, .bcdCDC = cpu_to_le16(0x0120), }; -static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { +static struct usb_cdc_union_desc obex_cdc_union_desc = { .bLength = sizeof(obex_cdc_union_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_UNION_TYPE, @@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { .bSlaveInterface0 = 2, }; -static struct usb_cdc_obex_desc obex_desc __initdata = { +static struct usb_cdc_obex_desc obex_desc = { .bLength = sizeof(obex_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_OBEX_TYPE, @@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = { /* High-Speed Support */ -static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { +static struct usb_endpoint_descriptor obex_hs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { +static struct usb_endpoint_descriptor obex_hs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_descriptor_header *hs_function[] __initdata = { +static struct usb_descriptor_header *hs_function[] = { (struct usb_descriptor_header *) &obex_control_intf, (struct usb_descriptor_header *) &obex_cdc_header_desc, (struct usb_descriptor_header *) &obex_desc, @@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = { /* Full-Speed Support */ -static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = { +static struct usb_endpoint_descriptor obex_fs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = { +static struct usb_endpoint_descriptor obex_fs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_descriptor_header *fs_function[] __initdata = { +static struct usb_descriptor_header *fs_function[] = { (struct usb_descriptor_header *) &obex_control_intf, (struct usb_descriptor_header *) &obex_cdc_header_desc, (struct usb_descriptor_header *) &obex_desc, @@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g) /*-------------------------------------------------------------------------*/ -static int __init -obex_bind(struct usb_configuration *c, struct usb_function *f) +/* Some controllers can't support CDC OBEX ... */ +static inline bool can_support_obex(struct usb_configuration *c) +{ + /* Since the first interface is a NOP, we can ignore the + * issue of multi-interface support on most controllers. + * + * Altsettings are mandatory, however... + */ + if (!gadget_supports_altsettings(c->cdev->gadget)) + return false; + + /* everything else is *probably* fine ... */ + return true; +} + +static int obex_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_obex *obex = func_to_obex(f); int status; struct usb_ep *ep; + if (!can_support_obex(c)) + return -EINVAL; + + if (obex_string_defs[OBEX_CTRL_IDX].id == 0) { + status = usb_string_ids_tab(c->cdev, obex_string_defs); + if (status < 0) + return status; + obex_control_intf.iInterface = + obex_string_defs[OBEX_CTRL_IDX].id; + + status = obex_string_defs[OBEX_DATA_IDX].id; + obex_data_nop_intf.iInterface = status; + obex_data_intf.iInterface = status; + } + /* allocate instance-specific interface IDs, and patch descriptors */ status = usb_interface_id(c, f); @@ -376,29 +405,16 @@ fail: return status; } +#ifdef USBF_OBEX_INCLUDED + static void -obex_unbind(struct usb_configuration *c, struct usb_function *f) +obex_old_unbind(struct usb_configuration *c, struct usb_function *f) { obex_string_defs[OBEX_CTRL_IDX].id = 0; usb_free_all_descriptors(f); kfree(func_to_obex(f)); } -/* Some controllers can't support CDC OBEX ... */ -static inline bool can_support_obex(struct usb_configuration *c) -{ - /* Since the first interface is a NOP, we can ignore the - * issue of multi-interface support on most controllers. - * - * Altsettings are mandatory, however... - */ - if (!gadget_supports_altsettings(c->cdev->gadget)) - return false; - - /* everything else is *probably* fine ... */ - return true; -} - /** * obex_bind_config - add a CDC OBEX function to a configuration * @c: the configuration to support the CDC OBEX instance @@ -412,21 +428,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num) struct f_obex *obex; int status; - if (!can_support_obex(c)) - return -EINVAL; - - if (obex_string_defs[OBEX_CTRL_IDX].id == 0) { - status = usb_string_ids_tab(c->cdev, obex_string_defs); - if (status < 0) - return status; - obex_control_intf.iInterface = - obex_string_defs[OBEX_CTRL_IDX].id; - - status = obex_string_defs[OBEX_DATA_IDX].id; - obex_data_nop_intf.iInterface = status; - obex_data_intf.iInterface = status; - } - /* allocate and initialize one new instance */ obex = kzalloc(sizeof *obex, GFP_KERNEL); if (!obex) @@ -441,7 +442,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num) obex->port.func.strings = obex_strings; /* descriptors are per-instance copies */ obex->port.func.bind = obex_bind; - obex->port.func.unbind = obex_unbind; + obex->port.func.unbind = obex_old_unbind; obex->port.func.set_alt = obex_set_alt; obex->port.func.get_alt = obex_get_alt; obex->port.func.disable = obex_disable; @@ -453,5 +454,83 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num) return status; } +#else + +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); + } + + return &opts->func_inst; +} + +static void obex_free(struct usb_function *f) +{ + struct f_obex *obex; + + obex = func_to_obex(f); + kfree(obex); +} + +static void obex_unbind(struct usb_configuration *c, struct usb_function *f) +{ + obex_string_defs[OBEX_CTRL_IDX].id = 0; + usb_free_all_descriptors(f); +} + +struct usb_function *obex_alloc(struct usb_function_instance *fi) +{ + struct f_obex *obex; + struct f_serial_opts *opts; + + /* allocate and initialize one new instance */ + obex = kzalloc(sizeof(*obex), GFP_KERNEL); + if (!obex) + return ERR_PTR(-ENOMEM); + + opts = container_of(fi, struct f_serial_opts, func_inst); + + obex->port_num = opts->port_num; + + obex->port.connect = obex_connect; + obex->port.disconnect = obex_disconnect; + + obex->port.func.name = "obex"; + obex->port.func.strings = obex_strings; + /* descriptors are per-instance copies */ + obex->port.func.bind = obex_bind; + obex->port.func.unbind = obex_unbind; + obex->port.func.set_alt = obex_set_alt; + obex->port.func.get_alt = obex_get_alt; + obex->port.func.disable = obex_disable; + obex->port.func.free_func = obex_free; + + return &obex->port.func; +} + +DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc); + +#endif + MODULE_AUTHOR("Felipe Balbi"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index f829a80f27f6..eebdd0e0b1d6 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -37,7 +37,7 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "f_ecm.c" +#define USBF_OBEX_INCLUDED #include "f_obex.c" #include "f_phonet.c" #include "u_ether.c" diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 9d215c4c2275..664da6493239 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -36,6 +36,7 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ +#define USBF_OBEX_INCLUDED #include "f_obex.c" /*-------------------------------------------------------------------------*/ From d1412794b33ab0cb3dcc4c820e9595354b7e6e59 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Thu, 21 Mar 2013 09:22:30 +0100 Subject: [PATCH 298/303] usb: gadget: serial: convert to new interface of f_obex f_obex is now a self-contained module. We need to teach serial.c about it. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/serial.c | 42 +++---------------------------------- 2 files changed, 4 insertions(+), 39 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index a5f67e14daf2..86d5d804f1eb 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -766,6 +766,7 @@ config USB_G_SERIAL select USB_U_SERIAL select USB_F_ACM select USB_F_SERIAL + select USB_F_OBEX select USB_LIBCOMPOSITE help The Serial Gadget talks to the Linux-USB generic serial driver. diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 664da6493239..1f5f978d35d5 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -27,18 +28,6 @@ #define GS_LONG_NAME "Gadget Serial" #define GS_VERSION_NAME GS_LONG_NAME " " GS_VERSION_STR -/*-------------------------------------------------------------------------*/ - -/* - * Kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ -#define USBF_OBEX_INCLUDED -#include "f_obex.c" - /*-------------------------------------------------------------------------*/ USB_GADGET_COMPOSITE_OPTIONS(); @@ -126,17 +115,6 @@ module_param(n_ports, uint, 0); MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); /*-------------------------------------------------------------------------*/ -static unsigned char tty_lines[MAX_U_SERIAL_PORTS]; - -static int __init serial_bind_obex_config(struct usb_configuration *c) -{ - unsigned i; - int status = 0; - - for (i = 0; i < n_ports && status == 0; i++) - status = obex_bind_config(c, tty_lines[i]); - return status; -} static struct usb_configuration serial_config_driver = { /* .label = f(use_acm) */ @@ -199,15 +177,6 @@ out: static int __init gs_bind(struct usb_composite_dev *cdev) { int status; - int cur_line = 0; - - if (use_obex) { - for (cur_line = 0; cur_line < n_ports; cur_line++) { - status = gserial_alloc_line(&tty_lines[cur_line]); - if (status) - goto fail; - } - } /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. @@ -232,8 +201,8 @@ static int __init gs_bind(struct usb_composite_dev *cdev) "acm"); usb_ep_autoconfig_reset(cdev->gadget); } else if (use_obex) - status = usb_add_config(cdev, &serial_config_driver, - serial_bind_obex_config); + status = serial_register_ports(cdev, &serial_config_driver, + "obex"); else { status = serial_register_ports(cdev, &serial_config_driver, "gser"); @@ -247,9 +216,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev) return 0; fail: - cur_line--; - while (cur_line >= 0 && use_obex) - gserial_free_line(tty_lines[cur_line--]); return status; } @@ -260,8 +226,6 @@ static int gs_unbind(struct usb_composite_dev *cdev) for (i = 0; i < n_ports; i++) { usb_put_function(f_serial[i]); usb_put_function_instance(fi_serial[i]); - if (use_obex) - gserial_free_line(tty_lines[i]); } return 0; } From ecfd3f7bb3d5dceb8e7ad1c117303c774cb90234 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Wed, 27 Mar 2013 12:13:25 +0100 Subject: [PATCH 299/303] usb: gadget: f_obex: add configfs support f_obex learns about our new configfs-based interface, which will allow gadgets to be bound to controllers through userland. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- drivers/usb/gadget/f_obex.c | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 439b666120c2..29a348a2a294 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c @@ -456,6 +456,59 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num) #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; @@ -480,6 +533,8 @@ static struct usb_function_instance *obex_alloc_inst(void) kfree(opts); return ERR_PTR(ret); } + config_group_init_type_name(&opts->func_inst.group, "", + &obex_func_type); return &opts->func_inst; } From 88b1c78db32782041d9548e3c4ab405f9e9eab59 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 3 Apr 2013 16:02:25 +0200 Subject: [PATCH 300/303] usb: phy: ab8500-usb: check regulator_enable return value Since regulator_enable() is going to be marked as __must_check in the next merge window, always check regulator_enable() return value and print a warning if it fails. Cc: Linus Walleij Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-ab8500-usb.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 749614cf6e2b..4acef26a2ef5 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -167,7 +167,9 @@ static void ab8500_usb_regulator_enable(struct ab8500_usb *ab) { int ret, volt; - regulator_enable(ab->v_ape); + ret = regulator_enable(ab->v_ape); + if (ret) + dev_err(ab->dev, "Failed to enable v-ape\n"); if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { ab->saved_v_ulpi = regulator_get_voltage(ab->v_ulpi); @@ -185,7 +187,9 @@ static void ab8500_usb_regulator_enable(struct ab8500_usb *ab) ret); } - regulator_enable(ab->v_ulpi); + ret = regulator_enable(ab->v_ulpi); + if (ret) + dev_err(ab->dev, "Failed to enable vddulpivio18\n"); if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { volt = regulator_get_voltage(ab->v_ulpi); @@ -194,7 +198,9 @@ static void ab8500_usb_regulator_enable(struct ab8500_usb *ab) volt); } - regulator_enable(ab->v_musb); + ret = regulator_enable(ab->v_musb); + if (ret) + dev_err(ab->dev, "Failed to enable musb_1v8\n"); } static void ab8500_usb_regulator_disable(struct ab8500_usb *ab) From 9ec602ecb199653a16e1eb909551b7ba77d79922 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 3 Apr 2013 16:02:26 +0200 Subject: [PATCH 301/303] usb: phy: twl4030-usb: check regulator_enable return value Since regulator_enable() is going to be marked as __must_check in the next merge window, always check regulator_enable() return value and print a warning if it fails. Reviewed-by: Kalle Jokiniemi Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl4030-usb.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index 3f9858fbebc2..13e17ae5ecd9 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -384,9 +384,17 @@ static void __twl4030_phy_power(struct twl4030_usb *twl, int on) static void twl4030_phy_power(struct twl4030_usb *twl, int on) { + int ret; + if (on) { - regulator_enable(twl->usb3v1); - regulator_enable(twl->usb1v8); + ret = regulator_enable(twl->usb3v1); + if (ret) + dev_err(twl->dev, "Failed to enable usb3v1\n"); + + ret = regulator_enable(twl->usb1v8); + if (ret) + dev_err(twl->dev, "Failed to enable usb1v8\n"); + /* * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP * in twl4030) resets the VUSB_DEDICATED2 register. This reset @@ -395,7 +403,11 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) * is re-activated. This ensures that VUSB3V1 is really active. */ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); - regulator_enable(twl->usb1v5); + + ret = regulator_enable(twl->usb1v5); + if (ret) + dev_err(twl->dev, "Failed to enable usb1v5\n"); + __twl4030_phy_power(twl, 1); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | From bb54542cfaac0e7949925b774b04b7ea069b80d1 Mon Sep 17 00:00:00 2001 From: Fabio Baltieri Date: Wed, 3 Apr 2013 16:02:27 +0200 Subject: [PATCH 302/303] usb: phy: twl6030-usb: check regulator_enable return value Since regulator_enable() is going to be marked as __must_check in the next merge window, always check regulator_enable() return value and print a warning if it fails. Cc: Hema HK Signed-off-by: Fabio Baltieri Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-twl6030-usb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 8cd6cf49bdbd..e841474d07b8 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -211,6 +211,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) struct twl6030_usb *twl = _twl; enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; u8 vbus_state, hw_state; + int ret; hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); @@ -218,7 +219,10 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) CONTROLLER_STAT1); if (!(hw_state & STS_USB_ID)) { if (vbus_state & VBUS_DET) { - regulator_enable(twl->usb3v3); + ret = regulator_enable(twl->usb3v3); + if (ret) + dev_err(twl->dev, "Failed to enable usb3v3\n"); + twl->asleep = 1; status = OMAP_MUSB_VBUS_VALID; twl->linkstat = status; @@ -245,12 +249,15 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) struct twl6030_usb *twl = _twl; enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; u8 hw_state; + int ret; hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); if (hw_state & STS_USB_ID) { + ret = regulator_enable(twl->usb3v3); + if (ret) + dev_err(twl->dev, "Failed to enable usb3v3\n"); - regulator_enable(twl->usb3v3); twl->asleep = 1; twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); From 9b192de60b5a584ee4ed967fb6758773c75e4643 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 3 Apr 2013 21:01:44 +0300 Subject: [PATCH 303/303] usb: gadget: nokia: include f_ecm.c recent changes to gadget framework have exposed a flaw in nokia.c where it uses f_ecm.c but it wasn't including it like other gadget drivers. This is a temporary patch until all other function drivers are converted to new API where each function driver becomes a module and binding is done through configfs. Solves a linking error when building g_nokia.ko Signed-off-by: Felipe Balbi --- drivers/usb/gadget/nokia.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index eebdd0e0b1d6..3b344b41a167 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -38,6 +38,7 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #define USBF_OBEX_INCLUDED +#include "f_ecm.c" #include "f_obex.c" #include "f_phonet.c" #include "u_ether.c"