123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- From 132e23775779cc895c37f7883c33a60a1a8a7cdd Mon Sep 17 00:00:00 2001
- From: Hans de Goede <hdegoede@redhat.com>
- Date: Wed, 8 Jul 2015 16:41:39 +0200
- Subject: [PATCH] usb: musb: sunxi: Add support for musb controller in A31 SoC
- The A31 SoC uses the same musb controller as found in earlier SoCs, but it
- is hooked up slightly different. Its SRAM is private and no longer controlled
- through the SRAM controller, and its reset is controlled via a separate
- reset controller. This commit adds support for this setup.
- Signed-off-by: Hans de Goede <hdegoede@redhat.com>
- Signed-off-by: Felipe Balbi <balbi@ti.com>
- ---
- .../bindings/usb/allwinner,sun4i-a10-musb.txt | 3 +-
- drivers/usb/musb/sunxi.c | 50 +++++++++++++++++++---
- 2 files changed, 46 insertions(+), 7 deletions(-)
- --- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
- +++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
- @@ -2,9 +2,10 @@ Allwinner sun4i A10 musb DRC/OTG control
- -------------------------------------------
-
- Required properties:
- - - compatible : "allwinner,sun4i-a10-musb"
- + - compatible : "allwinner,sun4i-a10-musb" or "allwinner,sun6i-a31-musb"
- - reg : mmio address range of the musb controller
- - clocks : clock specifier for the musb controller ahb gate clock
- + - reset : reset specifier for the ahb reset (A31 and newer only)
- - interrupts : interrupt to which the musb controller is connected
- - interrupt-names : must be "mc"
- - phys : phy specifier for the otg phy
- --- a/drivers/usb/musb/sunxi.c
- +++ b/drivers/usb/musb/sunxi.c
- @@ -26,6 +26,7 @@
- #include <linux/of.h>
- #include <linux/phy/phy-sun4i-usb.h>
- #include <linux/platform_device.h>
- +#include <linux/reset.h>
- #include <linux/soc/sunxi/sunxi_sram.h>
- #include <linux/usb/musb.h>
- #include <linux/usb/of.h>
- @@ -70,6 +71,8 @@
- #define SUNXI_MUSB_FL_HOSTMODE_PEND 2
- #define SUNXI_MUSB_FL_VBUS_ON 3
- #define SUNXI_MUSB_FL_PHY_ON 4
- +#define SUNXI_MUSB_FL_HAS_SRAM 5
- +#define SUNXI_MUSB_FL_HAS_RESET 6
-
- /* Our read/write methods need access and do not get passed in a musb ref :| */
- static struct musb *sunxi_musb;
- @@ -78,6 +81,7 @@ struct sunxi_glue {
- struct device *dev;
- struct platform_device *musb;
- struct clk *clk;
- + struct reset_control *rst;
- struct phy *phy;
- struct platform_device *usb_phy;
- struct usb_phy *xceiv;
- @@ -229,14 +233,22 @@ static int sunxi_musb_init(struct musb *
- musb->phy = glue->phy;
- musb->xceiv = glue->xceiv;
-
- - ret = sunxi_sram_claim(musb->controller->parent);
- - if (ret)
- - return ret;
- + if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
- + ret = sunxi_sram_claim(musb->controller->parent);
- + if (ret)
- + return ret;
- + }
-
- ret = clk_prepare_enable(glue->clk);
- if (ret)
- goto error_sram_release;
-
- + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
- + ret = reset_control_deassert(glue->rst);
- + if (ret)
- + goto error_clk_disable;
- + }
- +
- writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
-
- /* Register notifier before calling phy_init() */
- @@ -244,7 +256,7 @@ static int sunxi_musb_init(struct musb *
- ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
- &glue->host_nb);
- if (ret)
- - goto error_clk_disable;
- + goto error_reset_assert;
- }
-
- ret = phy_init(glue->phy);
- @@ -273,10 +285,14 @@ error_unregister_notifier:
- if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
- extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
- &glue->host_nb);
- +error_reset_assert:
- + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
- + reset_control_assert(glue->rst);
- error_clk_disable:
- clk_disable_unprepare(glue->clk);
- error_sram_release:
- - sunxi_sram_release(musb->controller->parent);
- + if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
- + sunxi_sram_release(musb->controller->parent);
- return ret;
- }
-
- @@ -296,8 +312,12 @@ static int sunxi_musb_exit(struct musb *
- extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
- &glue->host_nb);
-
- + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
- + reset_control_assert(glue->rst);
- +
- clk_disable_unprepare(glue->clk);
- - sunxi_sram_release(musb->controller->parent);
- + if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
- + sunxi_sram_release(musb->controller->parent);
-
- return 0;
- }
- @@ -617,6 +637,12 @@ static int sunxi_musb_probe(struct platf
- INIT_WORK(&glue->work, sunxi_musb_work);
- glue->host_nb.notifier_call = sunxi_musb_host_notifier;
-
- + if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
- + set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
- +
- + if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
- + set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
- +
- glue->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(glue->clk)) {
- dev_err(&pdev->dev, "Error getting clock: %ld\n",
- @@ -624,6 +650,17 @@ static int sunxi_musb_probe(struct platf
- return PTR_ERR(glue->clk);
- }
-
- + if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
- + glue->rst = devm_reset_control_get(&pdev->dev, NULL);
- + if (IS_ERR(glue->rst)) {
- + if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
- + return -EPROBE_DEFER;
- + dev_err(&pdev->dev, "Error getting reset %ld\n",
- + PTR_ERR(glue->rst));
- + return PTR_ERR(glue->rst);
- + }
- + }
- +
- glue->phy = devm_phy_get(&pdev->dev, "usb");
- if (IS_ERR(glue->phy)) {
- if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
- @@ -685,6 +722,7 @@ static int sunxi_musb_remove(struct plat
-
- static const struct of_device_id sunxi_musb_match[] = {
- { .compatible = "allwinner,sun4i-a10-musb", },
- + { .compatible = "allwinner,sun6i-a31-musb", },
- {}
- };
-
|