diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 13:23:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-26 13:23:47 -0400 |
commit | 9fc377799bc9bfd8d5cb35d0d1ea2e2458cbdbb3 (patch) | |
tree | fe93603b4e33dd50ff5f95ff769a0748b230cdf9 /drivers/usb/otg | |
parent | 5e23ae49960d05f578a73ecd19749c45af682c2b (diff) | |
parent | e387ef5c47ddeaeaa3cbdc54424cdb7a28dae2c0 (diff) |
Merge tag 'usb-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB patches from Greg Kroah-Hartman:
"Here's the big USB patch set for the 3.6-rc1 merge window.
Lots of little changes in here, primarily for gadget controllers and
drivers. There's some scsi changes that I think also went in through
the scsi tree, but they merge just fine. All of these patches have
been in the linux-next tree for a while now.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
Fix up trivial conflicts in include/scsi/scsi_device.h (same libata
conflict that Jeff had already encountered)
* tag 'usb-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (207 commits)
usb: Add USB_QUIRK_RESET_RESUME for all Logitech UVC webcams
usb: Add quirk detection based on interface information
usb: s3c-hsotg: Add header file protection macros in s3c-hsotg.h
USB: ehci-s5p: Add vbus setup function to the s5p ehci glue layer
USB: add USB_VENDOR_AND_INTERFACE_INFO() macro
USB: notify phy when root hub port connect change
USB: remove 8 bytes of padding from usb_host_interface on 64 bit builds
USB: option: add ZTE MF821D
USB: sierra: QMI mode MC7710 moved to qcserial
USB: qcserial: adding Sierra Wireless devices
USB: qcserial: support generic Qualcomm serial ports
USB: qcserial: make probe more flexible
USB: qcserial: centralize probe exit path
USB: qcserial: consolidate usb_set_interface calls
USB: ehci-s5p: Add support for device tree
USB: ohci-exynos: Add support for device tree
USB: ehci-omap: fix compile failure(v1)
usb: host: tegra: pass correct pointer in ehci_setup()
USB: ehci-fsl: Update ifdef check to work on 64-bit ppc
USB: serial: keyspan: Removed unrequired parentheses.
...
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r-- | drivers/usb/otg/Kconfig | 10 | ||||
-rw-r--r-- | drivers/usb/otg/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/otg/ab8500-usb.c | 4 | ||||
-rw-r--r-- | drivers/usb/otg/fsl_otg.c | 6 | ||||
-rw-r--r-- | drivers/usb/otg/gpio_vbus.c | 4 | ||||
-rw-r--r-- | drivers/usb/otg/isp1301_omap.c | 19 | ||||
-rw-r--r-- | drivers/usb/otg/msm_otg.c | 6 | ||||
-rw-r--r-- | drivers/usb/otg/mv_otg.c | 6 | ||||
-rw-r--r-- | drivers/usb/otg/mxs-phy.c | 186 | ||||
-rw-r--r-- | drivers/usb/otg/nop-usb-xceiv.c | 4 | ||||
-rw-r--r-- | drivers/usb/otg/otg.c | 181 | ||||
-rw-r--r-- | drivers/usb/otg/twl4030-usb.c | 73 | ||||
-rw-r--r-- | drivers/usb/otg/twl6030-usb.c | 71 |
13 files changed, 433 insertions, 138 deletions
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 5c87db06b59..13fd1ddf742 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -116,6 +116,16 @@ config FSL_USB2_OTG | |||
116 | help | 116 | help |
117 | Enable this to support Freescale USB OTG transceiver. | 117 | Enable this to support Freescale USB OTG transceiver. |
118 | 118 | ||
119 | config USB_MXS_PHY | ||
120 | tristate "Freescale MXS USB PHY support" | ||
121 | depends on ARCH_MXC || ARCH_MXS | ||
122 | select STMP_DEVICE | ||
123 | select USB_OTG_UTILS | ||
124 | help | ||
125 | Enable this to support the Freescale MXS USB PHY. | ||
126 | |||
127 | MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x. | ||
128 | |||
119 | config USB_MV_OTG | 129 | config USB_MV_OTG |
120 | tristate "Marvell USB OTG support" | 130 | tristate "Marvell USB OTG support" |
121 | depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND | 131 | depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND |
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 41aa5098b13..a844b8d35d1 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile | |||
@@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o | |||
20 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o | 20 | obj-$(CONFIG_AB8500_USB) += ab8500-usb.o |
21 | fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o | 21 | fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o |
22 | obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o | 22 | obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o |
23 | obj-$(CONFIG_USB_MXS_PHY) += mxs-phy.o | ||
23 | obj-$(CONFIG_USB_MV_OTG) += mv_otg.o | 24 | obj-$(CONFIG_USB_MV_OTG) += mv_otg.o |
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c index a84af677dc5..ae8ad561f08 100644 --- a/drivers/usb/otg/ab8500-usb.c +++ b/drivers/usb/otg/ab8500-usb.c | |||
@@ -529,7 +529,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) | |||
529 | if (err < 0) | 529 | if (err < 0) |
530 | goto fail0; | 530 | goto fail0; |
531 | 531 | ||
532 | err = usb_set_transceiver(&ab->phy); | 532 | err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2); |
533 | if (err) { | 533 | if (err) { |
534 | dev_err(&pdev->dev, "Can't register transceiver\n"); | 534 | dev_err(&pdev->dev, "Can't register transceiver\n"); |
535 | goto fail1; | 535 | goto fail1; |
@@ -556,7 +556,7 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev) | |||
556 | 556 | ||
557 | cancel_work_sync(&ab->phy_dis_work); | 557 | cancel_work_sync(&ab->phy_dis_work); |
558 | 558 | ||
559 | usb_set_transceiver(NULL); | 559 | usb_remove_phy(&ab->phy); |
560 | 560 | ||
561 | ab8500_usb_host_phy_dis(ab); | 561 | ab8500_usb_host_phy_dis(ab); |
562 | ab8500_usb_peri_phy_dis(ab); | 562 | ab8500_usb_peri_phy_dis(ab); |
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index be4a63e8302..23c798cb2d7 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c | |||
@@ -806,7 +806,7 @@ static int fsl_otg_conf(struct platform_device *pdev) | |||
806 | fsl_otg_dev = fsl_otg_tc; | 806 | fsl_otg_dev = fsl_otg_tc; |
807 | 807 | ||
808 | /* Store the otg transceiver */ | 808 | /* Store the otg transceiver */ |
809 | status = usb_set_transceiver(&fsl_otg_tc->phy); | 809 | status = usb_add_phy(&fsl_otg_tc->phy, USB_PHY_TYPE_USB2); |
810 | if (status) { | 810 | if (status) { |
811 | pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); | 811 | pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); |
812 | goto err; | 812 | goto err; |
@@ -824,7 +824,7 @@ err: | |||
824 | int usb_otg_start(struct platform_device *pdev) | 824 | int usb_otg_start(struct platform_device *pdev) |
825 | { | 825 | { |
826 | struct fsl_otg *p_otg; | 826 | struct fsl_otg *p_otg; |
827 | struct usb_phy *otg_trans = usb_get_transceiver(); | 827 | struct usb_phy *otg_trans = usb_get_phy(USB_PHY_TYPE_USB2); |
828 | struct otg_fsm *fsm; | 828 | struct otg_fsm *fsm; |
829 | int status; | 829 | int status; |
830 | struct resource *res; | 830 | struct resource *res; |
@@ -1134,7 +1134,7 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev) | |||
1134 | { | 1134 | { |
1135 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; | 1135 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
1136 | 1136 | ||
1137 | usb_set_transceiver(NULL); | 1137 | usb_remove_phy(&fsl_otg_dev->phy); |
1138 | free_irq(fsl_otg_dev->irq, fsl_otg_dev); | 1138 | free_irq(fsl_otg_dev->irq, fsl_otg_dev); |
1139 | 1139 | ||
1140 | iounmap((void *)usb_dr_regs); | 1140 | iounmap((void *)usb_dr_regs); |
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index bde6298a969..a67ffe22179 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c | |||
@@ -320,7 +320,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) | |||
320 | } | 320 | } |
321 | 321 | ||
322 | /* only active when a gadget is registered */ | 322 | /* only active when a gadget is registered */ |
323 | err = usb_set_transceiver(&gpio_vbus->phy); | 323 | err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2); |
324 | if (err) { | 324 | if (err) { |
325 | dev_err(&pdev->dev, "can't register transceiver, err: %d\n", | 325 | dev_err(&pdev->dev, "can't register transceiver, err: %d\n", |
326 | err); | 326 | err); |
@@ -354,7 +354,7 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev) | |||
354 | cancel_delayed_work_sync(&gpio_vbus->work); | 354 | cancel_delayed_work_sync(&gpio_vbus->work); |
355 | regulator_put(gpio_vbus->vbus_draw); | 355 | regulator_put(gpio_vbus->vbus_draw); |
356 | 356 | ||
357 | usb_set_transceiver(NULL); | 357 | usb_remove_phy(&gpio_vbus->phy); |
358 | 358 | ||
359 | free_irq(gpio_vbus->irq, pdev); | 359 | free_irq(gpio_vbus->irq, pdev); |
360 | if (gpio_is_valid(pdata->gpio_pullup)) | 360 | if (gpio_is_valid(pdata->gpio_pullup)) |
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index e0558dfcfaf..575fc815c93 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c | |||
@@ -1336,9 +1336,6 @@ static int | |||
1336 | isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) | 1336 | isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) |
1337 | { | 1337 | { |
1338 | struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); | 1338 | struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); |
1339 | #ifndef CONFIG_USB_OTG | ||
1340 | u32 l; | ||
1341 | #endif | ||
1342 | 1339 | ||
1343 | if (!otg || isp != the_transceiver) | 1340 | if (!otg || isp != the_transceiver) |
1344 | return -ENODEV; | 1341 | return -ENODEV; |
@@ -1365,10 +1362,14 @@ isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) | |||
1365 | otg->gadget = gadget; | 1362 | otg->gadget = gadget; |
1366 | // FIXME update its refcount | 1363 | // FIXME update its refcount |
1367 | 1364 | ||
1368 | l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; | 1365 | { |
1369 | l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS); | 1366 | u32 l; |
1370 | l |= OTG_ID; | 1367 | |
1371 | omap_writel(l, OTG_CTRL); | 1368 | l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; |
1369 | l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS); | ||
1370 | l |= OTG_ID; | ||
1371 | omap_writel(l, OTG_CTRL); | ||
1372 | } | ||
1372 | 1373 | ||
1373 | power_up(isp); | 1374 | power_up(isp); |
1374 | isp->phy.state = OTG_STATE_B_IDLE; | 1375 | isp->phy.state = OTG_STATE_B_IDLE; |
@@ -1610,7 +1611,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | |||
1610 | dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); | 1611 | dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); |
1611 | #endif | 1612 | #endif |
1612 | 1613 | ||
1613 | status = usb_set_transceiver(&isp->phy); | 1614 | status = usb_add_phy(&isp->phy, USB_PHY_TYPE_USB2); |
1614 | if (status < 0) | 1615 | if (status < 0) |
1615 | dev_err(&i2c->dev, "can't register transceiver, %d\n", | 1616 | dev_err(&i2c->dev, "can't register transceiver, %d\n", |
1616 | status); | 1617 | status); |
@@ -1649,7 +1650,7 @@ subsys_initcall(isp_init); | |||
1649 | static void __exit isp_exit(void) | 1650 | static void __exit isp_exit(void) |
1650 | { | 1651 | { |
1651 | if (the_transceiver) | 1652 | if (the_transceiver) |
1652 | usb_set_transceiver(NULL); | 1653 | usb_remove_phy(&the_transceiver->phy); |
1653 | i2c_del_driver(&isp1301_driver); | 1654 | i2c_del_driver(&isp1301_driver); |
1654 | } | 1655 | } |
1655 | module_exit(isp_exit); | 1656 | module_exit(isp_exit); |
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index 1d0347c247d..9f5fc906041 100644 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c | |||
@@ -1555,9 +1555,9 @@ static int __init msm_otg_probe(struct platform_device *pdev) | |||
1555 | phy->otg->set_host = msm_otg_set_host; | 1555 | phy->otg->set_host = msm_otg_set_host; |
1556 | phy->otg->set_peripheral = msm_otg_set_peripheral; | 1556 | phy->otg->set_peripheral = msm_otg_set_peripheral; |
1557 | 1557 | ||
1558 | ret = usb_set_transceiver(&motg->phy); | 1558 | ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2); |
1559 | if (ret) { | 1559 | if (ret) { |
1560 | dev_err(&pdev->dev, "usb_set_transceiver failed\n"); | 1560 | dev_err(&pdev->dev, "usb_add_phy failed\n"); |
1561 | goto free_irq; | 1561 | goto free_irq; |
1562 | } | 1562 | } |
1563 | 1563 | ||
@@ -1624,7 +1624,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) | |||
1624 | device_init_wakeup(&pdev->dev, 0); | 1624 | device_init_wakeup(&pdev->dev, 0); |
1625 | pm_runtime_disable(&pdev->dev); | 1625 | pm_runtime_disable(&pdev->dev); |
1626 | 1626 | ||
1627 | usb_set_transceiver(NULL); | 1627 | usb_remove_phy(phy); |
1628 | free_irq(motg->irq, motg); | 1628 | free_irq(motg->irq, motg); |
1629 | 1629 | ||
1630 | /* | 1630 | /* |
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index 6cc6c3ffbb8..3f124e8f579 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c | |||
@@ -690,7 +690,7 @@ int mv_otg_remove(struct platform_device *pdev) | |||
690 | for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++) | 690 | for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++) |
691 | clk_put(mvotg->clk[clk_i]); | 691 | clk_put(mvotg->clk[clk_i]); |
692 | 692 | ||
693 | usb_set_transceiver(NULL); | 693 | usb_remove_phy(&mvotg->phy); |
694 | platform_set_drvdata(pdev, NULL); | 694 | platform_set_drvdata(pdev, NULL); |
695 | 695 | ||
696 | kfree(mvotg->phy.otg); | 696 | kfree(mvotg->phy.otg); |
@@ -853,7 +853,7 @@ static int mv_otg_probe(struct platform_device *pdev) | |||
853 | goto err_disable_clk; | 853 | goto err_disable_clk; |
854 | } | 854 | } |
855 | 855 | ||
856 | retval = usb_set_transceiver(&mvotg->phy); | 856 | retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2); |
857 | if (retval < 0) { | 857 | if (retval < 0) { |
858 | dev_err(&pdev->dev, "can't register transceiver, %d\n", | 858 | dev_err(&pdev->dev, "can't register transceiver, %d\n", |
859 | retval); | 859 | retval); |
@@ -880,7 +880,7 @@ static int mv_otg_probe(struct platform_device *pdev) | |||
880 | return 0; | 880 | return 0; |
881 | 881 | ||
882 | err_set_transceiver: | 882 | err_set_transceiver: |
883 | usb_set_transceiver(NULL); | 883 | usb_remove_phy(&mvotg->phy); |
884 | err_free_irq: | 884 | err_free_irq: |
885 | free_irq(mvotg->irq, mvotg); | 885 | free_irq(mvotg->irq, mvotg); |
886 | err_disable_clk: | 886 | err_disable_clk: |
diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c new file mode 100644 index 00000000000..c1a67cb8e24 --- /dev/null +++ b/drivers/usb/otg/mxs-phy.c | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * Copyright (C) 2012 Marek Vasut <marex@denx.de> | ||
4 | * on behalf of DENX Software Engineering GmbH | ||
5 | * | ||
6 | * The code contained herein is licensed under the GNU General Public | ||
7 | * License. You may obtain a copy of the GNU General Public License | ||
8 | * Version 2 or later at the following locations: | ||
9 | * | ||
10 | * http://www.opensource.org/licenses/gpl-license.html | ||
11 | * http://www.gnu.org/copyleft/gpl.html | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/usb/otg.h> | ||
19 | #include <linux/stmp_device.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/io.h> | ||
23 | |||
24 | #define DRIVER_NAME "mxs_phy" | ||
25 | |||
26 | #define HW_USBPHY_PWD 0x00 | ||
27 | #define HW_USBPHY_CTRL 0x30 | ||
28 | #define HW_USBPHY_CTRL_SET 0x34 | ||
29 | #define HW_USBPHY_CTRL_CLR 0x38 | ||
30 | |||
31 | #define BM_USBPHY_CTRL_SFTRST BIT(31) | ||
32 | #define BM_USBPHY_CTRL_CLKGATE BIT(30) | ||
33 | #define BM_USBPHY_CTRL_ENUTMILEVEL3 BIT(15) | ||
34 | #define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14) | ||
35 | #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1) | ||
36 | |||
37 | struct mxs_phy { | ||
38 | struct usb_phy phy; | ||
39 | struct clk *clk; | ||
40 | }; | ||
41 | |||
42 | #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) | ||
43 | |||
44 | static void mxs_phy_hw_init(struct mxs_phy *mxs_phy) | ||
45 | { | ||
46 | void __iomem *base = mxs_phy->phy.io_priv; | ||
47 | |||
48 | stmp_reset_block(base + HW_USBPHY_CTRL); | ||
49 | |||
50 | /* Power up the PHY */ | ||
51 | writel_relaxed(0, base + HW_USBPHY_PWD); | ||
52 | |||
53 | /* enable FS/LS device */ | ||
54 | writel_relaxed(BM_USBPHY_CTRL_ENUTMILEVEL2 | | ||
55 | BM_USBPHY_CTRL_ENUTMILEVEL3, | ||
56 | base + HW_USBPHY_CTRL_SET); | ||
57 | } | ||
58 | |||
59 | static int mxs_phy_init(struct usb_phy *phy) | ||
60 | { | ||
61 | struct mxs_phy *mxs_phy = to_mxs_phy(phy); | ||
62 | |||
63 | clk_prepare_enable(mxs_phy->clk); | ||
64 | mxs_phy_hw_init(mxs_phy); | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static void mxs_phy_shutdown(struct usb_phy *phy) | ||
70 | { | ||
71 | struct mxs_phy *mxs_phy = to_mxs_phy(phy); | ||
72 | |||
73 | writel_relaxed(BM_USBPHY_CTRL_CLKGATE, | ||
74 | phy->io_priv + HW_USBPHY_CTRL_SET); | ||
75 | |||
76 | clk_disable_unprepare(mxs_phy->clk); | ||
77 | } | ||
78 | |||
79 | static int mxs_phy_on_connect(struct usb_phy *phy, int port) | ||
80 | { | ||
81 | dev_dbg(phy->dev, "Connect on port %d\n", port); | ||
82 | |||
83 | mxs_phy_hw_init(to_mxs_phy(phy)); | ||
84 | writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, | ||
85 | phy->io_priv + HW_USBPHY_CTRL_SET); | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int mxs_phy_on_disconnect(struct usb_phy *phy, int port) | ||
91 | { | ||
92 | dev_dbg(phy->dev, "Disconnect on port %d\n", port); | ||
93 | |||
94 | writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, | ||
95 | phy->io_priv + HW_USBPHY_CTRL_CLR); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static int mxs_phy_probe(struct platform_device *pdev) | ||
101 | { | ||
102 | struct resource *res; | ||
103 | void __iomem *base; | ||
104 | struct clk *clk; | ||
105 | struct mxs_phy *mxs_phy; | ||
106 | |||
107 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
108 | if (!res) { | ||
109 | dev_err(&pdev->dev, "can't get device resources\n"); | ||
110 | return -ENOENT; | ||
111 | } | ||
112 | |||
113 | base = devm_request_and_ioremap(&pdev->dev, res); | ||
114 | if (!base) | ||
115 | return -EBUSY; | ||
116 | |||
117 | clk = devm_clk_get(&pdev->dev, NULL); | ||
118 | if (IS_ERR(clk)) { | ||
119 | dev_err(&pdev->dev, | ||
120 | "can't get the clock, err=%ld", PTR_ERR(clk)); | ||
121 | return PTR_ERR(clk); | ||
122 | } | ||
123 | |||
124 | mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL); | ||
125 | if (!mxs_phy) { | ||
126 | dev_err(&pdev->dev, "Failed to allocate USB PHY structure!\n"); | ||
127 | return -ENOMEM; | ||
128 | } | ||
129 | |||
130 | mxs_phy->phy.io_priv = base; | ||
131 | mxs_phy->phy.dev = &pdev->dev; | ||
132 | mxs_phy->phy.label = DRIVER_NAME; | ||
133 | mxs_phy->phy.init = mxs_phy_init; | ||
134 | mxs_phy->phy.shutdown = mxs_phy_shutdown; | ||
135 | mxs_phy->phy.notify_connect = mxs_phy_on_connect; | ||
136 | mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect; | ||
137 | |||
138 | ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier); | ||
139 | |||
140 | mxs_phy->clk = clk; | ||
141 | |||
142 | platform_set_drvdata(pdev, &mxs_phy->phy); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int __devexit mxs_phy_remove(struct platform_device *pdev) | ||
148 | { | ||
149 | platform_set_drvdata(pdev, NULL); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static const struct of_device_id mxs_phy_dt_ids[] = { | ||
155 | { .compatible = "fsl,imx23-usbphy", }, | ||
156 | { /* sentinel */ } | ||
157 | }; | ||
158 | MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids); | ||
159 | |||
160 | static struct platform_driver mxs_phy_driver = { | ||
161 | .probe = mxs_phy_probe, | ||
162 | .remove = __devexit_p(mxs_phy_remove), | ||
163 | .driver = { | ||
164 | .name = DRIVER_NAME, | ||
165 | .owner = THIS_MODULE, | ||
166 | .of_match_table = mxs_phy_dt_ids, | ||
167 | }, | ||
168 | }; | ||
169 | |||
170 | static int __init mxs_phy_module_init(void) | ||
171 | { | ||
172 | return platform_driver_register(&mxs_phy_driver); | ||
173 | } | ||
174 | postcore_initcall(mxs_phy_module_init); | ||
175 | |||
176 | static void __exit mxs_phy_module_exit(void) | ||
177 | { | ||
178 | platform_driver_unregister(&mxs_phy_driver); | ||
179 | } | ||
180 | module_exit(mxs_phy_module_exit); | ||
181 | |||
182 | MODULE_ALIAS("platform:mxs-usb-phy"); | ||
183 | MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | ||
184 | MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); | ||
185 | MODULE_DESCRIPTION("Freescale MXS USB PHY driver"); | ||
186 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index 58b26df6afd..803f958f413 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c | |||
@@ -117,7 +117,7 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) | |||
117 | nop->phy.otg->set_host = nop_set_host; | 117 | nop->phy.otg->set_host = nop_set_host; |
118 | nop->phy.otg->set_peripheral = nop_set_peripheral; | 118 | nop->phy.otg->set_peripheral = nop_set_peripheral; |
119 | 119 | ||
120 | err = usb_set_transceiver(&nop->phy); | 120 | err = usb_add_phy(&nop->phy, USB_PHY_TYPE_USB2); |
121 | if (err) { | 121 | if (err) { |
122 | dev_err(&pdev->dev, "can't register transceiver, err: %d\n", | 122 | dev_err(&pdev->dev, "can't register transceiver, err: %d\n", |
123 | err); | 123 | err); |
@@ -139,7 +139,7 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) | |||
139 | { | 139 | { |
140 | struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); | 140 | struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); |
141 | 141 | ||
142 | usb_set_transceiver(NULL); | 142 | usb_remove_phy(&nop->phy); |
143 | 143 | ||
144 | platform_set_drvdata(pdev, NULL); | 144 | platform_set_drvdata(pdev, NULL); |
145 | kfree(nop->phy.otg); | 145 | kfree(nop->phy.otg); |
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index 801e597a154..1bf60a22595 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c | |||
@@ -11,60 +11,195 @@ | |||
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/export.h> | 13 | #include <linux/export.h> |
14 | #include <linux/err.h> | ||
14 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/slab.h> | ||
15 | 17 | ||
16 | #include <linux/usb/otg.h> | 18 | #include <linux/usb/otg.h> |
17 | 19 | ||
18 | static struct usb_phy *phy; | 20 | static LIST_HEAD(phy_list); |
21 | static DEFINE_SPINLOCK(phy_lock); | ||
22 | |||
23 | static struct usb_phy *__usb_find_phy(struct list_head *list, | ||
24 | enum usb_phy_type type) | ||
25 | { | ||
26 | struct usb_phy *phy = NULL; | ||
27 | |||
28 | list_for_each_entry(phy, list, head) { | ||
29 | if (phy->type != type) | ||
30 | continue; | ||
31 | |||
32 | return phy; | ||
33 | } | ||
34 | |||
35 | return ERR_PTR(-ENODEV); | ||
36 | } | ||
37 | |||
38 | static void devm_usb_phy_release(struct device *dev, void *res) | ||
39 | { | ||
40 | struct usb_phy *phy = *(struct usb_phy **)res; | ||
41 | |||
42 | usb_put_phy(phy); | ||
43 | } | ||
44 | |||
45 | static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) | ||
46 | { | ||
47 | return res == match_data; | ||
48 | } | ||
19 | 49 | ||
20 | /** | 50 | /** |
21 | * usb_get_transceiver - find the (single) USB transceiver | 51 | * devm_usb_get_phy - find the USB PHY |
52 | * @dev - device that requests this phy | ||
53 | * @type - the type of the phy the controller requires | ||
22 | * | 54 | * |
23 | * Returns the transceiver driver, after getting a refcount to it; or | 55 | * Gets the phy using usb_get_phy(), and associates a device with it using |
24 | * null if there is no such transceiver. The caller is responsible for | 56 | * devres. On driver detach, release function is invoked on the devres data, |
25 | * calling usb_put_transceiver() to release that count. | 57 | * then, devres data is freed. |
26 | * | 58 | * |
27 | * For use by USB host and peripheral drivers. | 59 | * For use by USB host and peripheral drivers. |
28 | */ | 60 | */ |
29 | struct usb_phy *usb_get_transceiver(void) | 61 | struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type) |
30 | { | 62 | { |
31 | if (phy) | 63 | struct usb_phy **ptr, *phy; |
32 | get_device(phy->dev); | 64 | |
65 | ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); | ||
66 | if (!ptr) | ||
67 | return NULL; | ||
68 | |||
69 | phy = usb_get_phy(type); | ||
70 | if (!IS_ERR(phy)) { | ||
71 | *ptr = phy; | ||
72 | devres_add(dev, ptr); | ||
73 | } else | ||
74 | devres_free(ptr); | ||
75 | |||
76 | return phy; | ||
77 | } | ||
78 | EXPORT_SYMBOL(devm_usb_get_phy); | ||
79 | |||
80 | /** | ||
81 | * usb_get_phy - find the USB PHY | ||
82 | * @type - the type of the phy the controller requires | ||
83 | * | ||
84 | * Returns the phy driver, after getting a refcount to it; or | ||
85 | * -ENODEV if there is no such phy. The caller is responsible for | ||
86 | * calling usb_put_phy() to release that count. | ||
87 | * | ||
88 | * For use by USB host and peripheral drivers. | ||
89 | */ | ||
90 | struct usb_phy *usb_get_phy(enum usb_phy_type type) | ||
91 | { | ||
92 | struct usb_phy *phy = NULL; | ||
93 | unsigned long flags; | ||
94 | |||
95 | spin_lock_irqsave(&phy_lock, flags); | ||
96 | |||
97 | phy = __usb_find_phy(&phy_list, type); | ||
98 | if (IS_ERR(phy)) { | ||
99 | pr_err("unable to find transceiver of type %s\n", | ||
100 | usb_phy_type_string(type)); | ||
101 | goto err0; | ||
102 | } | ||
103 | |||
104 | get_device(phy->dev); | ||
105 | |||
106 | err0: | ||
107 | spin_unlock_irqrestore(&phy_lock, flags); | ||
108 | |||
33 | return phy; | 109 | return phy; |
34 | } | 110 | } |
35 | EXPORT_SYMBOL(usb_get_transceiver); | 111 | EXPORT_SYMBOL(usb_get_phy); |
112 | |||
113 | /** | ||
114 | * devm_usb_put_phy - release the USB PHY | ||
115 | * @dev - device that wants to release this phy | ||
116 | * @phy - the phy returned by devm_usb_get_phy() | ||
117 | * | ||
118 | * destroys the devres associated with this phy and invokes usb_put_phy | ||
119 | * to release the phy. | ||
120 | * | ||
121 | * For use by USB host and peripheral drivers. | ||
122 | */ | ||
123 | void devm_usb_put_phy(struct device *dev, struct usb_phy *phy) | ||
124 | { | ||
125 | int r; | ||
126 | |||
127 | r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy); | ||
128 | dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n"); | ||
129 | } | ||
130 | EXPORT_SYMBOL(devm_usb_put_phy); | ||
36 | 131 | ||
37 | /** | 132 | /** |
38 | * usb_put_transceiver - release the (single) USB transceiver | 133 | * usb_put_phy - release the USB PHY |
39 | * @x: the transceiver returned by usb_get_transceiver() | 134 | * @x: the phy returned by usb_get_phy() |
40 | * | 135 | * |
41 | * Releases a refcount the caller received from usb_get_transceiver(). | 136 | * Releases a refcount the caller received from usb_get_phy(). |
42 | * | 137 | * |
43 | * For use by USB host and peripheral drivers. | 138 | * For use by USB host and peripheral drivers. |
44 | */ | 139 | */ |
45 | void usb_put_transceiver(struct usb_phy *x) | 140 | void usb_put_phy(struct usb_phy *x) |
46 | { | 141 | { |
47 | if (x) | 142 | if (x) |
48 | put_device(x->dev); | 143 | put_device(x->dev); |
49 | } | 144 | } |
50 | EXPORT_SYMBOL(usb_put_transceiver); | 145 | EXPORT_SYMBOL(usb_put_phy); |
51 | 146 | ||
52 | /** | 147 | /** |
53 | * usb_set_transceiver - declare the (single) USB transceiver | 148 | * usb_add_phy - declare the USB PHY |
54 | * @x: the USB transceiver to be used; or NULL | 149 | * @x: the USB phy to be used; or NULL |
150 | * @type - the type of this PHY | ||
55 | * | 151 | * |
56 | * This call is exclusively for use by transceiver drivers, which | 152 | * This call is exclusively for use by phy drivers, which |
57 | * coordinate the activities of drivers for host and peripheral | 153 | * coordinate the activities of drivers for host and peripheral |
58 | * controllers, and in some cases for VBUS current regulation. | 154 | * controllers, and in some cases for VBUS current regulation. |
59 | */ | 155 | */ |
60 | int usb_set_transceiver(struct usb_phy *x) | 156 | int usb_add_phy(struct usb_phy *x, enum usb_phy_type type) |
157 | { | ||
158 | int ret = 0; | ||
159 | unsigned long flags; | ||
160 | struct usb_phy *phy; | ||
161 | |||
162 | if (x && x->type != USB_PHY_TYPE_UNDEFINED) { | ||
163 | dev_err(x->dev, "not accepting initialized PHY %s\n", x->label); | ||
164 | return -EINVAL; | ||
165 | } | ||
166 | |||
167 | spin_lock_irqsave(&phy_lock, flags); | ||
168 | |||
169 | list_for_each_entry(phy, &phy_list, head) { | ||
170 | if (phy->type == type) { | ||
171 | ret = -EBUSY; | ||
172 | dev_err(x->dev, "transceiver type %s already exists\n", | ||
173 | usb_phy_type_string(type)); | ||
174 | goto out; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | x->type = type; | ||
179 | list_add_tail(&x->head, &phy_list); | ||
180 | |||
181 | out: | ||
182 | spin_unlock_irqrestore(&phy_lock, flags); | ||
183 | return ret; | ||
184 | } | ||
185 | EXPORT_SYMBOL(usb_add_phy); | ||
186 | |||
187 | /** | ||
188 | * usb_remove_phy - remove the OTG PHY | ||
189 | * @x: the USB OTG PHY to be removed; | ||
190 | * | ||
191 | * This reverts the effects of usb_add_phy | ||
192 | */ | ||
193 | void usb_remove_phy(struct usb_phy *x) | ||
61 | { | 194 | { |
62 | if (phy && x) | 195 | unsigned long flags; |
63 | return -EBUSY; | 196 | |
64 | phy = x; | 197 | spin_lock_irqsave(&phy_lock, flags); |
65 | return 0; | 198 | if (x) |
199 | list_del(&x->head); | ||
200 | spin_unlock_irqrestore(&phy_lock, flags); | ||
66 | } | 201 | } |
67 | EXPORT_SYMBOL(usb_set_transceiver); | 202 | EXPORT_SYMBOL(usb_remove_phy); |
68 | 203 | ||
69 | const char *otg_state_string(enum usb_otg_state state) | 204 | const char *otg_state_string(enum usb_otg_state state) |
70 | { | 205 | { |
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index c4a86da858e..523cad5bfea 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c | |||
@@ -33,11 +33,11 @@ | |||
33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/usb/otg.h> | 35 | #include <linux/usb/otg.h> |
36 | #include <linux/usb/musb-omap.h> | ||
36 | #include <linux/usb/ulpi.h> | 37 | #include <linux/usb/ulpi.h> |
37 | #include <linux/i2c/twl.h> | 38 | #include <linux/i2c/twl.h> |
38 | #include <linux/regulator/consumer.h> | 39 | #include <linux/regulator/consumer.h> |
39 | #include <linux/err.h> | 40 | #include <linux/err.h> |
40 | #include <linux/notifier.h> | ||
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | 42 | ||
43 | /* Register defines */ | 43 | /* Register defines */ |
@@ -159,7 +159,7 @@ struct twl4030_usb { | |||
159 | enum twl4030_usb_mode usb_mode; | 159 | enum twl4030_usb_mode usb_mode; |
160 | 160 | ||
161 | int irq; | 161 | int irq; |
162 | u8 linkstat; | 162 | enum omap_musb_vbus_id_status linkstat; |
163 | bool vbus_supplied; | 163 | bool vbus_supplied; |
164 | u8 asleep; | 164 | u8 asleep; |
165 | bool irq_enabled; | 165 | bool irq_enabled; |
@@ -246,11 +246,11 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) | |||
246 | 246 | ||
247 | /*-------------------------------------------------------------------------*/ | 247 | /*-------------------------------------------------------------------------*/ |
248 | 248 | ||
249 | static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) | 249 | static enum omap_musb_vbus_id_status |
250 | twl4030_usb_linkstat(struct twl4030_usb *twl) | ||
250 | { | 251 | { |
251 | int status; | 252 | int status; |
252 | int linkstat = USB_EVENT_NONE; | 253 | enum omap_musb_vbus_id_status linkstat = OMAP_MUSB_UNKNOWN; |
253 | struct usb_otg *otg = twl->phy.otg; | ||
254 | 254 | ||
255 | twl->vbus_supplied = false; | 255 | twl->vbus_supplied = false; |
256 | 256 | ||
@@ -273,30 +273,23 @@ static enum usb_phy_events twl4030_usb_linkstat(struct twl4030_usb *twl) | |||
273 | twl->vbus_supplied = true; | 273 | twl->vbus_supplied = true; |
274 | 274 | ||
275 | if (status & BIT(2)) | 275 | if (status & BIT(2)) |
276 | linkstat = USB_EVENT_ID; | 276 | linkstat = OMAP_MUSB_ID_GROUND; |
277 | else | 277 | else |
278 | linkstat = USB_EVENT_VBUS; | 278 | linkstat = OMAP_MUSB_VBUS_VALID; |
279 | } else | 279 | } else { |
280 | linkstat = USB_EVENT_NONE; | 280 | if (twl->linkstat != OMAP_MUSB_UNKNOWN) |
281 | linkstat = OMAP_MUSB_VBUS_OFF; | ||
282 | } | ||
281 | 283 | ||
282 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", | 284 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", |
283 | status, status, linkstat); | 285 | status, status, linkstat); |
284 | 286 | ||
285 | twl->phy.last_event = linkstat; | ||
286 | |||
287 | /* REVISIT this assumes host and peripheral controllers | 287 | /* REVISIT this assumes host and peripheral controllers |
288 | * are registered, and that both are active... | 288 | * are registered, and that both are active... |
289 | */ | 289 | */ |
290 | 290 | ||
291 | spin_lock_irq(&twl->lock); | 291 | spin_lock_irq(&twl->lock); |
292 | twl->linkstat = linkstat; | 292 | twl->linkstat = linkstat; |
293 | if (linkstat == USB_EVENT_ID) { | ||
294 | otg->default_a = true; | ||
295 | twl->phy.state = OTG_STATE_A_IDLE; | ||
296 | } else { | ||
297 | otg->default_a = false; | ||
298 | twl->phy.state = OTG_STATE_B_IDLE; | ||
299 | } | ||
300 | spin_unlock_irq(&twl->lock); | 293 | spin_unlock_irq(&twl->lock); |
301 | 294 | ||
302 | return linkstat; | 295 | return linkstat; |
@@ -501,10 +494,10 @@ static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL); | |||
501 | static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | 494 | static irqreturn_t twl4030_usb_irq(int irq, void *_twl) |
502 | { | 495 | { |
503 | struct twl4030_usb *twl = _twl; | 496 | struct twl4030_usb *twl = _twl; |
504 | int status; | 497 | enum omap_musb_vbus_id_status status; |
505 | 498 | ||
506 | status = twl4030_usb_linkstat(twl); | 499 | status = twl4030_usb_linkstat(twl); |
507 | if (status >= 0) { | 500 | if (status > 0) { |
508 | /* FIXME add a set_power() method so that B-devices can | 501 | /* FIXME add a set_power() method so that B-devices can |
509 | * configure the charger appropriately. It's not always | 502 | * configure the charger appropriately. It's not always |
510 | * correct to consume VBUS power, and how much current to | 503 | * correct to consume VBUS power, and how much current to |
@@ -516,13 +509,13 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
516 | * USB_LINK_VBUS state. musb_hdrc won't care until it | 509 | * USB_LINK_VBUS state. musb_hdrc won't care until it |
517 | * starts to handle softconnect right. | 510 | * starts to handle softconnect right. |
518 | */ | 511 | */ |
519 | if (status == USB_EVENT_NONE) | 512 | if (status == OMAP_MUSB_VBUS_OFF || |
513 | status == OMAP_MUSB_ID_FLOAT) | ||
520 | twl4030_phy_suspend(twl, 0); | 514 | twl4030_phy_suspend(twl, 0); |
521 | else | 515 | else |
522 | twl4030_phy_resume(twl); | 516 | twl4030_phy_resume(twl); |
523 | 517 | ||
524 | atomic_notifier_call_chain(&twl->phy.notifier, status, | 518 | omap_musb_mailbox(twl->linkstat); |
525 | twl->phy.otg->gadget); | ||
526 | } | 519 | } |
527 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | 520 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); |
528 | 521 | ||
@@ -531,11 +524,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
531 | 524 | ||
532 | static void twl4030_usb_phy_init(struct twl4030_usb *twl) | 525 | static void twl4030_usb_phy_init(struct twl4030_usb *twl) |
533 | { | 526 | { |
534 | int status; | 527 | enum omap_musb_vbus_id_status status; |
535 | 528 | ||
536 | status = twl4030_usb_linkstat(twl); | 529 | status = twl4030_usb_linkstat(twl); |
537 | if (status >= 0) { | 530 | if (status > 0) { |
538 | if (status == USB_EVENT_NONE) { | 531 | if (status == OMAP_MUSB_VBUS_OFF || |
532 | status == OMAP_MUSB_ID_FLOAT) { | ||
539 | __twl4030_phy_power(twl, 0); | 533 | __twl4030_phy_power(twl, 0); |
540 | twl->asleep = 1; | 534 | twl->asleep = 1; |
541 | } else { | 535 | } else { |
@@ -543,8 +537,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl) | |||
543 | twl->asleep = 0; | 537 | twl->asleep = 0; |
544 | } | 538 | } |
545 | 539 | ||
546 | atomic_notifier_call_chain(&twl->phy.notifier, status, | 540 | omap_musb_mailbox(twl->linkstat); |
547 | twl->phy.otg->gadget); | ||
548 | } | 541 | } |
549 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | 542 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); |
550 | } | 543 | } |
@@ -598,21 +591,20 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) | |||
598 | return -EINVAL; | 591 | return -EINVAL; |
599 | } | 592 | } |
600 | 593 | ||
601 | twl = kzalloc(sizeof *twl, GFP_KERNEL); | 594 | twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL); |
602 | if (!twl) | 595 | if (!twl) |
603 | return -ENOMEM; | 596 | return -ENOMEM; |
604 | 597 | ||
605 | otg = kzalloc(sizeof *otg, GFP_KERNEL); | 598 | otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL); |
606 | if (!otg) { | 599 | if (!otg) |
607 | kfree(twl); | ||
608 | return -ENOMEM; | 600 | return -ENOMEM; |
609 | } | ||
610 | 601 | ||
611 | twl->dev = &pdev->dev; | 602 | twl->dev = &pdev->dev; |
612 | twl->irq = platform_get_irq(pdev, 0); | 603 | twl->irq = platform_get_irq(pdev, 0); |
613 | twl->usb_mode = pdata->usb_mode; | 604 | twl->usb_mode = pdata->usb_mode; |
614 | twl->vbus_supplied = false; | 605 | twl->vbus_supplied = false; |
615 | twl->asleep = 1; | 606 | twl->asleep = 1; |
607 | twl->linkstat = OMAP_MUSB_UNKNOWN; | ||
616 | 608 | ||
617 | twl->phy.dev = twl->dev; | 609 | twl->phy.dev = twl->dev; |
618 | twl->phy.label = "twl4030"; | 610 | twl->phy.label = "twl4030"; |
@@ -629,18 +621,14 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) | |||
629 | err = twl4030_usb_ldo_init(twl); | 621 | err = twl4030_usb_ldo_init(twl); |
630 | if (err) { | 622 | if (err) { |
631 | dev_err(&pdev->dev, "ldo init failed\n"); | 623 | dev_err(&pdev->dev, "ldo init failed\n"); |
632 | kfree(otg); | ||
633 | kfree(twl); | ||
634 | return err; | 624 | return err; |
635 | } | 625 | } |
636 | usb_set_transceiver(&twl->phy); | 626 | usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2); |
637 | 627 | ||
638 | platform_set_drvdata(pdev, twl); | 628 | platform_set_drvdata(pdev, twl); |
639 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | 629 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
640 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 630 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
641 | 631 | ||
642 | ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); | ||
643 | |||
644 | /* Our job is to use irqs and status from the power module | 632 | /* Our job is to use irqs and status from the power module |
645 | * to keep the transceiver disabled when nothing's connected. | 633 | * to keep the transceiver disabled when nothing's connected. |
646 | * | 634 | * |
@@ -651,13 +639,11 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) | |||
651 | */ | 639 | */ |
652 | twl->irq_enabled = true; | 640 | twl->irq_enabled = true; |
653 | status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq, | 641 | status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq, |
654 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 642 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | |
655 | "twl4030_usb", twl); | 643 | IRQF_ONESHOT, "twl4030_usb", twl); |
656 | if (status < 0) { | 644 | if (status < 0) { |
657 | dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", | 645 | dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", |
658 | twl->irq, status); | 646 | twl->irq, status); |
659 | kfree(otg); | ||
660 | kfree(twl); | ||
661 | return status; | 647 | return status; |
662 | } | 648 | } |
663 | 649 | ||
@@ -701,9 +687,6 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) | |||
701 | regulator_put(twl->usb1v8); | 687 | regulator_put(twl->usb1v8); |
702 | regulator_put(twl->usb3v1); | 688 | regulator_put(twl->usb3v1); |
703 | 689 | ||
704 | kfree(twl->phy.otg); | ||
705 | kfree(twl); | ||
706 | |||
707 | return 0; | 690 | return 0; |
708 | } | 691 | } |
709 | 692 | ||
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index 0eabb049b6a..6907d8df7a2 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c | |||
@@ -26,10 +26,10 @@ | |||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/usb/otg.h> | 28 | #include <linux/usb/otg.h> |
29 | #include <linux/usb/musb-omap.h> | ||
29 | #include <linux/i2c/twl.h> | 30 | #include <linux/i2c/twl.h> |
30 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
31 | #include <linux/err.h> | 32 | #include <linux/err.h> |
32 | #include <linux/notifier.h> | ||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | 35 | ||
@@ -100,7 +100,7 @@ struct twl6030_usb { | |||
100 | 100 | ||
101 | int irq1; | 101 | int irq1; |
102 | int irq2; | 102 | int irq2; |
103 | u8 linkstat; | 103 | enum omap_musb_vbus_id_status linkstat; |
104 | u8 asleep; | 104 | u8 asleep; |
105 | bool irq_enabled; | 105 | bool irq_enabled; |
106 | bool vbus_enable; | 106 | bool vbus_enable; |
@@ -147,7 +147,7 @@ static int twl6030_phy_init(struct usb_phy *x) | |||
147 | dev = twl->dev; | 147 | dev = twl->dev; |
148 | pdata = dev->platform_data; | 148 | pdata = dev->platform_data; |
149 | 149 | ||
150 | if (twl->linkstat == USB_EVENT_ID) | 150 | if (twl->linkstat == OMAP_MUSB_ID_GROUND) |
151 | pdata->phy_power(twl->dev, 1, 1); | 151 | pdata->phy_power(twl->dev, 1, 1); |
152 | else | 152 | else |
153 | pdata->phy_power(twl->dev, 0, 1); | 153 | pdata->phy_power(twl->dev, 0, 1); |
@@ -235,13 +235,13 @@ static ssize_t twl6030_usb_vbus_show(struct device *dev, | |||
235 | spin_lock_irqsave(&twl->lock, flags); | 235 | spin_lock_irqsave(&twl->lock, flags); |
236 | 236 | ||
237 | switch (twl->linkstat) { | 237 | switch (twl->linkstat) { |
238 | case USB_EVENT_VBUS: | 238 | case OMAP_MUSB_VBUS_VALID: |
239 | ret = snprintf(buf, PAGE_SIZE, "vbus\n"); | 239 | ret = snprintf(buf, PAGE_SIZE, "vbus\n"); |
240 | break; | 240 | break; |
241 | case USB_EVENT_ID: | 241 | case OMAP_MUSB_ID_GROUND: |
242 | ret = snprintf(buf, PAGE_SIZE, "id\n"); | 242 | ret = snprintf(buf, PAGE_SIZE, "id\n"); |
243 | break; | 243 | break; |
244 | case USB_EVENT_NONE: | 244 | case OMAP_MUSB_VBUS_OFF: |
245 | ret = snprintf(buf, PAGE_SIZE, "none\n"); | 245 | ret = snprintf(buf, PAGE_SIZE, "none\n"); |
246 | break; | 246 | break; |
247 | default: | 247 | default: |
@@ -256,8 +256,7 @@ static DEVICE_ATTR(vbus, 0444, twl6030_usb_vbus_show, NULL); | |||
256 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | 256 | static irqreturn_t twl6030_usb_irq(int irq, void *_twl) |
257 | { | 257 | { |
258 | struct twl6030_usb *twl = _twl; | 258 | struct twl6030_usb *twl = _twl; |
259 | struct usb_otg *otg = twl->phy.otg; | 259 | enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; |
260 | int status; | ||
261 | u8 vbus_state, hw_state; | 260 | u8 vbus_state, hw_state; |
262 | 261 | ||
263 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | 262 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); |
@@ -268,22 +267,18 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | |||
268 | if (vbus_state & VBUS_DET) { | 267 | if (vbus_state & VBUS_DET) { |
269 | regulator_enable(twl->usb3v3); | 268 | regulator_enable(twl->usb3v3); |
270 | twl->asleep = 1; | 269 | twl->asleep = 1; |
271 | status = USB_EVENT_VBUS; | 270 | status = OMAP_MUSB_VBUS_VALID; |
272 | otg->default_a = false; | ||
273 | twl->phy.state = OTG_STATE_B_IDLE; | ||
274 | twl->linkstat = status; | 271 | twl->linkstat = status; |
275 | twl->phy.last_event = status; | 272 | omap_musb_mailbox(status); |
276 | atomic_notifier_call_chain(&twl->phy.notifier, | ||
277 | status, otg->gadget); | ||
278 | } else { | 273 | } else { |
279 | status = USB_EVENT_NONE; | 274 | if (twl->linkstat != OMAP_MUSB_UNKNOWN) { |
280 | twl->linkstat = status; | 275 | status = OMAP_MUSB_VBUS_OFF; |
281 | twl->phy.last_event = status; | 276 | twl->linkstat = status; |
282 | atomic_notifier_call_chain(&twl->phy.notifier, | 277 | omap_musb_mailbox(status); |
283 | status, otg->gadget); | 278 | if (twl->asleep) { |
284 | if (twl->asleep) { | 279 | regulator_disable(twl->usb3v3); |
285 | regulator_disable(twl->usb3v3); | 280 | twl->asleep = 0; |
286 | twl->asleep = 0; | 281 | } |
287 | } | 282 | } |
288 | } | 283 | } |
289 | } | 284 | } |
@@ -295,8 +290,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) | |||
295 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | 290 | static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) |
296 | { | 291 | { |
297 | struct twl6030_usb *twl = _twl; | 292 | struct twl6030_usb *twl = _twl; |
298 | struct usb_otg *otg = twl->phy.otg; | 293 | enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN; |
299 | int status = USB_EVENT_NONE; | ||
300 | u8 hw_state; | 294 | u8 hw_state; |
301 | 295 | ||
302 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); | 296 | hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS); |
@@ -307,13 +301,9 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) | |||
307 | twl->asleep = 1; | 301 | twl->asleep = 1; |
308 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); | 302 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR); |
309 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); | 303 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); |
310 | status = USB_EVENT_ID; | 304 | status = OMAP_MUSB_ID_GROUND; |
311 | otg->default_a = true; | ||
312 | twl->phy.state = OTG_STATE_A_IDLE; | ||
313 | twl->linkstat = status; | 305 | twl->linkstat = status; |
314 | twl->phy.last_event = status; | 306 | omap_musb_mailbox(status); |
315 | atomic_notifier_call_chain(&twl->phy.notifier, status, | ||
316 | otg->gadget); | ||
317 | } else { | 307 | } else { |
318 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); | 308 | twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); |
319 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); | 309 | twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); |
@@ -402,20 +392,19 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
402 | struct device *dev = &pdev->dev; | 392 | struct device *dev = &pdev->dev; |
403 | pdata = dev->platform_data; | 393 | pdata = dev->platform_data; |
404 | 394 | ||
405 | twl = kzalloc(sizeof *twl, GFP_KERNEL); | 395 | twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL); |
406 | if (!twl) | 396 | if (!twl) |
407 | return -ENOMEM; | 397 | return -ENOMEM; |
408 | 398 | ||
409 | otg = kzalloc(sizeof *otg, GFP_KERNEL); | 399 | otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL); |
410 | if (!otg) { | 400 | if (!otg) |
411 | kfree(twl); | ||
412 | return -ENOMEM; | 401 | return -ENOMEM; |
413 | } | ||
414 | 402 | ||
415 | twl->dev = &pdev->dev; | 403 | twl->dev = &pdev->dev; |
416 | twl->irq1 = platform_get_irq(pdev, 0); | 404 | twl->irq1 = platform_get_irq(pdev, 0); |
417 | twl->irq2 = platform_get_irq(pdev, 1); | 405 | twl->irq2 = platform_get_irq(pdev, 1); |
418 | twl->features = pdata->features; | 406 | twl->features = pdata->features; |
407 | twl->linkstat = OMAP_MUSB_UNKNOWN; | ||
419 | 408 | ||
420 | twl->phy.dev = twl->dev; | 409 | twl->phy.dev = twl->dev; |
421 | twl->phy.label = "twl6030"; | 410 | twl->phy.label = "twl6030"; |
@@ -436,18 +425,14 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
436 | err = twl6030_usb_ldo_init(twl); | 425 | err = twl6030_usb_ldo_init(twl); |
437 | if (err) { | 426 | if (err) { |
438 | dev_err(&pdev->dev, "ldo init failed\n"); | 427 | dev_err(&pdev->dev, "ldo init failed\n"); |
439 | kfree(otg); | ||
440 | kfree(twl); | ||
441 | return err; | 428 | return err; |
442 | } | 429 | } |
443 | usb_set_transceiver(&twl->phy); | 430 | usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2); |
444 | 431 | ||
445 | platform_set_drvdata(pdev, twl); | 432 | platform_set_drvdata(pdev, twl); |
446 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | 433 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) |
447 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | 434 | dev_warn(&pdev->dev, "could not create sysfs file\n"); |
448 | 435 | ||
449 | ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier); | ||
450 | |||
451 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); | 436 | INIT_WORK(&twl->set_vbus_work, otg_set_vbus_work); |
452 | 437 | ||
453 | twl->irq_enabled = true; | 438 | twl->irq_enabled = true; |
@@ -458,8 +443,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
458 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 443 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
459 | twl->irq1, status); | 444 | twl->irq1, status); |
460 | device_remove_file(twl->dev, &dev_attr_vbus); | 445 | device_remove_file(twl->dev, &dev_attr_vbus); |
461 | kfree(otg); | ||
462 | kfree(twl); | ||
463 | return status; | 446 | return status; |
464 | } | 447 | } |
465 | 448 | ||
@@ -471,8 +454,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) | |||
471 | twl->irq2, status); | 454 | twl->irq2, status); |
472 | free_irq(twl->irq1, twl); | 455 | free_irq(twl->irq1, twl); |
473 | device_remove_file(twl->dev, &dev_attr_vbus); | 456 | device_remove_file(twl->dev, &dev_attr_vbus); |
474 | kfree(otg); | ||
475 | kfree(twl); | ||
476 | return status; | 457 | return status; |
477 | } | 458 | } |
478 | 459 | ||
@@ -503,8 +484,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) | |||
503 | pdata->phy_exit(twl->dev); | 484 | pdata->phy_exit(twl->dev); |
504 | device_remove_file(twl->dev, &dev_attr_vbus); | 485 | device_remove_file(twl->dev, &dev_attr_vbus); |
505 | cancel_work_sync(&twl->set_vbus_work); | 486 | cancel_work_sync(&twl->set_vbus_work); |
506 | kfree(twl->phy.otg); | ||
507 | kfree(twl); | ||
508 | 487 | ||
509 | return 0; | 488 | return 0; |
510 | } | 489 | } |