Skip to contentSkip to conversation

phy-sun4i-usb: Add OTG and newer SoC support

PATCH New Hans de Goede 4 participants 13 messages Jun 13, 2015 – Jul 31, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v5 cover phy-sun4i-usb: Add OTG and newer SoC support

Hi Kishon,

Here is a patch series with all my oustanding phy-sun4i-usb changes pending for merging into 4.3.

This includes the 5th iteration of the OTG support addition, now with the extcon provider support addition split-out into a new patch and ported to the extcon API changes which are queued up for 4.2 from :

http://git.kernel.org/cgit/linux/kernel/git/chanwoo/extcon.git/log/?h=extcon-next-v4.2

which already merged in GKH's char-misc branch for 4.2, this means that this series now depends on those changes.

Other than that this is a resend of some of the other feature addition patches I recently send rebased on top of v5 of the OTG support.

Please merge this series for 4.3.

Regards,

Hans

#1 lore raw

PATCH v5 1/7 phy-sun4i-usb: Add id and vbus detection support for the otg phy (phy0)

The usb0 phy is connected to an OTG controller, and as such needs some special handling:

1) It allows explicit control over the pullups, enable these on phy_init and disable them on phy_exit.

2) It has bits to signal id and vbus detect to the musb-core, add support for for monitoring id and vbus detect gpio-s for use in dual role mode, and set these bits to the correct values for operating in host only mode when no gpios are specified in the devicetree.

While updating the devicetree binding documentation also add documentation for the sofar undocumented usage of regulators for vbus for all 3 phys.

---
Changes in v2:
-Removed the sunxi specific phy functions, instead the id / vbus gpio polling
has been moved to the phy-sun4i-usb driver and their status is exported through extcon for the sunxi-musb glue
Changes in v3:
-No changes
Changes in v4:
-Do not call regulator_disable in an unbalanced manner when an external vbus
is present
Changes in v5:
-Split the addition of the extcon handler out into a separate patch -Use sun4i_usb_phy_remove() to ensure the vbus/id detect workqueue is stopped
if sun4i_usb_phy_probe() fails after registering an irq handler

---
 .../devicetree/bindings/phy/sun4i-usb-phy.txt      |  18 +-
 drivers/phy/phy-sun4i-usb.c                        | 250 ++++++++++++++++++++-
 2 files changed, 256 insertions(+), 12 deletions(-)
Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +16 -2
index 16528b9..557fa99 100644
@@ -23,6 +23,13 @@ Required properties:
   * "usb1_reset"
   * "usb2_reset" for sun4i, sun6i or sun7i
 
+Optional properties:
+- usb0_id_det-gpios : gpio phandle for reading the otg id pin value
+- usb0_vbus_det-gpios : gpio phandle for detecting the presence of usb0 vbus
+- usb0_vbus-supply : regulator phandle for controller usb0 vbus
+- usb1_vbus-supply : regulator phandle for controller usb1 vbus
+- usb2_vbus-supply : regulator phandle for controller usb2 vbus
+
 Example:
 	usbphy: phy at 0x01c13400 {
 		#phy-cells = <1>;
@@ -32,6 +39,13 @@ Example:
 		reg-names = "phy_ctrl", "pmu1", "pmu2";
 		clocks = <&usb_clk 8>;
 		clock-names = "usb_phy";
-		resets = <&usb_clk 1>, <&usb_clk 2>;
-		reset-names = "usb1_reset", "usb2_reset";
+		resets = <&usb_clk 0>, <&usb_clk 1>, <&usb_clk 2>;
+		reset-names = "usb0_reset", "usb1_reset", "usb2_reset";
+		pinctrl-names = "default";
+		pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
+		usb0_id_det-gpios = <&pio 7 19 GPIO_ACTIVE_HIGH>; /* PH19 */
+		usb0_vbus_det-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */
+		usb0_vbus-supply = <&reg_usb0_vbus>;
+		usb1_vbus-supply = <&reg_usb1_vbus>;
+		usb2_vbus-supply = <&reg_usb2_vbus>;
 	};
drivers/phy/phy-sun4i-usb.c +240 -10

367 lines not on this page · raw message

Signature · 1 line
2.4.3
#2 lore raw

PATCH v5 2/7 phy-sun4i-usb: Add extcon support for the otg phy (phy0)

In reply to Hans de Goede

The sunxi musb glue needs to know if a host or normal usb cable is plugged in, add extcon support so that the musb glue can monitor the host status.

---
Changes in v5:
-Split out of the "Add id and vbus detection support" commit -Ported to the new extcon API queued for 4.2

---
 drivers/phy/Kconfig         |  1 +
 drivers/phy/phy-sun4i-usb.c | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 1 deletion(-)
drivers/phy/Kconfig +1 -0
index a53bd5b..9841780 100644
@@ -173,6 +173,7 @@ config PHY_SUN4I_USB
 	tristate "Allwinner sunxi SoC USB PHY driver"
 	depends on ARCH_SUNXI && HAS_IOMEM && OF
 	depends on RESET_CONTROLLER
+	depends on EXTCON
 	select GENERIC_PHY
 	help
 	  Enable this to support the transceiver that is part of Allwinner
drivers/phy/phy-sun4i-usb.c +31 -1
index bdf63ad..86d9ce1 100644
@@ -23,6 +23,7 @@
 
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/extcon.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -99,6 +100,7 @@ struct sun4i_usb_phy_data {
 		int index;
 	} phys[MAX_PHYS];
 	/* phy0 / otg related variables */
+	struct extcon_dev *extcon;
 	bool phy0_init;
 	bool phy0_poll;
 	struct gpio_desc *id_det_gpio;
@@ -343,7 +345,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 	struct sun4i_usb_phy_data *data =
 		container_of(work, struct sun4i_usb_phy_data, detect.work);
 	struct phy *phy0 = data->phys[0].phy;
-	int id_det, vbus_det;
+	int id_det, vbus_det, id_notify = 0, vbus_notify = 0;
 
 	id_det = gpiod_get_value_cansleep(data->id_det_gpio);
 	vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio);
@@ -358,15 +360,24 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 	if (id_det != data->id_det) {
 		sun4i_usb_phy0_set_id_detect(phy0, id_det);
 		data->id_det = id_det;
+		id_notify = 1;
 	}
 
 	if (vbus_det != data->vbus_det) {
 		sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det);
 		data->vbus_det = vbus_det;
+		vbus_notify = 1;
 	}
 
 	mutex_unlock(&phy0->mutex);
 
+	if (id_notify)
+		extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST,
+					!id_det);
+
+	if (vbus_notify)
+		extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
+
 	if (data->phy0_poll)
 		queue_delayed_work(system_wq, &data->detect, POLL_TIME);
 }
@@ -407,6 +418,12 @@ static int sun4i_usb_phy_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const unsigned int sun4i_usb_phy0_cable[] = {
+	EXTCON_USB,
+	EXTCON_USB_HOST,
+	EXTCON_NONE,
+};
+
 static int sun4i_usb_phy_probe(struct platform_device *pdev)
 {
 	struct sun4i_usb_phy_data *data;
@@ -466,6 +483,19 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	if (data->id_det_gpio) {
+		data->extcon = devm_extcon_dev_allocate(dev,
+							sun4i_usb_phy0_cable);
+		if (IS_ERR(data->extcon))
+			return PTR_ERR(data->extcon);
+
+		ret = devm_extcon_dev_register(dev, data->extcon);
+		if (ret) {
+			dev_err(dev, "failed to register extcon: %d\n", ret);
+			return ret;
+		}
+	}
+
 	for (i = 0; i < data->num_phys; i++) {
 		struct sun4i_usb_phy *phy = data->phys + i;
 		char name[16];
Signature · 1 line
2.4.3
#3 lore raw

PATCH v5 2/7 phy-sun4i-usb: Add extcon support for the otg phy (phy0)

Hi Hans,

Quoted 102 lines · Hans de Goede

The sunxi musb glue needs to know if a host or normal usb cable is plugged in, add extcon support so that the musb glue can monitor the host status.

---
Changes in v5:

(quoted diff) +0 -3
-Split out of the "Add id and vbus detection support" commit
-Ported to the new extcon API queued for 4.2
---
 drivers/phy/Kconfig         |  1 +
 drivers/phy/phy-sun4i-usb.c | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 32 insertions(+), 1 deletion(-)
drivers/phy/Kconfig +1 -0
index a53bd5b..9841780 100644
@@ -173,6 +173,7 @@ config PHY_SUN4I_USB
        tristate "Allwinner sunxi SoC USB PHY driver"
        depends on ARCH_SUNXI && HAS_IOMEM && OF
        depends on RESET_CONTROLLER
+       depends on EXTCON
        select GENERIC_PHY
        help
          Enable this to support the transceiver that is part of Allwinner
drivers/phy/phy-sun4i-usb.c +24 -1
index bdf63ad..86d9ce1 100644
@@ -23,6 +23,7 @@
 
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/extcon.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -99,6 +100,7 @@ struct sun4i_usb_phy_data {
                int index;
        } phys[MAX_PHYS];
        /* phy0 / otg related variables */
+       struct extcon_dev *extcon;
        bool phy0_init;
        bool phy0_poll;
        struct gpio_desc *id_det_gpio;
@@ -343,7 +345,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
        struct sun4i_usb_phy_data *data =
                container_of(work, struct sun4i_usb_phy_data, detect.work);
        struct phy *phy0 = data->phys[0].phy;
-       int id_det, vbus_det;
+       int id_det, vbus_det, id_notify = 0, vbus_notify = 0;
 
        id_det = gpiod_get_value_cansleep(data->id_det_gpio);
        vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio);
@@ -358,15 +360,24 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
        if (id_det != data->id_det) {
                sun4i_usb_phy0_set_id_detect(phy0, id_det);
                data->id_det = id_det;
+               id_notify = 1;
        }
 
        if (vbus_det != data->vbus_det) {
                sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det);
                data->vbus_det = vbus_det;
+               vbus_notify = 1;
        }
 
        mutex_unlock(&phy0->mutex);
 
+       if (id_notify)
+               extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST,
+                                       !id_det);
+
+       if (vbus_notify)
+               extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
+
        if (data->phy0_poll)
                queue_delayed_work(system_wq, &data->detect, POLL_TIME);
 }
@@ -407,6 +418,12 @@ static int sun4i_usb_phy_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const unsigned int sun4i_usb_phy0_cable[] = {
+       EXTCON_USB,
+       EXTCON_USB_HOST,
+       EXTCON_NONE,
+};
+
 static int sun4i_usb_phy_probe(struct platform_device *pdev)
 {
        struct sun4i_usb_phy_data *data;
@@ -466,6 +483,19 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       if (data->id_det_gpio) {
+               data->extcon = devm_extcon_dev_allocate(dev,
+                                                       sun4i_usb_phy0_cable);
+               if (IS_ERR(data->extcon))
+                       return PTR_ERR(data->extcon);
+

drivers/phy/phy-sun4i-usb.c static int sun4i_usb_phy_probe(struct platform_device *pdev) · line 501

Quoted 10 lines
drivers/phy/phy-sun4i-usb.c +7 -0
+               ret = devm_extcon_dev_register(dev, data->extcon);
+               if (ret) {
+                       dev_err(dev, "failed to register extcon: %d\n", ret);
+                       return ret;
+               }
+       }
+
        for (i = 0; i < data->num_phys; i++) {
                struct sun4i_usb_phy *phy = data->phys + i;
                char name[16];

Looks good to me about or extcon part.

Thanks,
Chanwoo Choi

#4 lore raw

PATCH v5 2/7 phy-sun4i-usb: Add extcon support for the otg phy (phy0)

In reply to Hans de Goede

Hi Hans,

Quoted 19 lines · Hans de Goede

The sunxi musb glue needs to know if a host or normal usb cable is plugged in, add extcon support so that the musb glue can monitor the host status.

---
Changes in v5:

(quoted diff) +0 -3
-Split out of the "Add id and vbus detection support" commit
-Ported to the new extcon API queued for 4.2
---
  drivers/phy/Kconfig         |  1 +
  drivers/phy/phy-sun4i-usb.c | 32 +++++++++++++++++++++++++++++++-
  2 files changed, 32 insertions(+), 1 deletion(-)
drivers/phy/Kconfig +0 -0
index a53bd5b..9841780 100644

drivers/phy/Kconfig config PHY_SUN4I_USB · line 179

Quoted 7 lines
drivers/phy/Kconfig +1 -0
@@ -173,6 +173,7 @@ config PHY_SUN4I_USB
  	tristate "Allwinner sunxi SoC USB PHY driver"
  	depends on ARCH_SUNXI && HAS_IOMEM && OF
  	depends on RESET_CONTROLLER
+	depends on EXTCON
  	select GENERIC_PHY
  	help
  	  Enable this to support the transceiver that is part of Allwinner

Should probably add CONFIG_EXTCON=y to arch/arm/configs/sunxi_defconfig so that CONFIG_PHY_SUN4I_USB=y works out of the box.

Regards,
Jonathan

#5 lore raw

PATCH v5 2/7 phy-sun4i-usb: Add extcon support for the otg phy (phy0)

Hi,

Quoted 16 lines · Jonathan Liu

Hi Hans,

Quoted 13 lines · Hans de Goede

The sunxi musb glue needs to know if a host or normal usb cable is plugged in, add extcon support so that the musb glue can monitor the host status.

---
Changes in v5:

(quoted diff) +0 -3
-Split out of the "Add id and vbus detection support" commit
-Ported to the new extcon API queued for 4.2
---
  drivers/phy/Kconfig         |  1 +
  drivers/phy/phy-sun4i-usb.c | 32 +++++++++++++++++++++++++++++++-
  2 files changed, 32 insertions(+), 1 deletion(-)
Quoted 14 lines

drivers/phy/Kconfig config PHY_SUN4I_USB · line 179

Quoted 13 lines
drivers/phy/Kconfig +1 -0
index a53bd5b..9841780 100644
@@ -173,6 +173,7 @@ config PHY_SUN4I_USB
      tristate "Allwinner sunxi SoC USB PHY driver"
      depends on ARCH_SUNXI && HAS_IOMEM && OF
      depends on RESET_CONTROLLER
+    depends on EXTCON
      select GENERIC_PHY
      help
        Enable this to support the transceiver that is part of Allwinner

Should probably add CONFIG_EXTCON=y to arch/arm/configs/sunxi_defconfig so that CONFIG_PHY_SUN4I_USB=y works out of the box.

Right, ChenYu just send out 2 defconfig patches fixing this.

Thanks for the heads up.

Regards,

Hans

#6 lore raw

PATCH v5 3/7 phy-sun4i-usb: Swap check for disconnect threshold

In reply to Hans de Goede

Before this commit the code for determining the disconnect threshold was checking for "allwinner,sun4i-a10-usb-phy" or "allwinner,sun6i-a31-usb-phy" assuming that those where the exception and then newer SoCs would use a disconnect threshold of 2 like sun7i does. But it turns out that newer SoCs use a disconnect threshold of 3 and sun5i and sun7i are the exceptions, so check for those instead.

Here are the settings from the various Allwinner SDK sources:
sun4i-a10: USBC_Phy_Write(usbc_no, 0x2a, 3, 2);
sun5i-a13: USBC_Phy_Write(usbc_no, 0x2a, 2, 2);
sun6i-a31: USBC_Phy_Write(usbc_no, 0x2a, 3, 2);
sun7i-a20: USBC_Phy_Write(usbc_no, 0x2a, 2, 2);
sun8i-a23: USBC_Phy_Write(usbc_no, 0x2a, 3, 2);
sun8i-h3: USBC_Phy_Write(usbc_no, 0x2a, 3, 2);
sun9i-a80: USBC_Phy_Write(usbc_no, 0x2a, 3, 2);

Note this commit makes no functional changes as currently we only support sun4i - sun7i.

---
 drivers/phy/phy-sun4i-usb.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/phy/phy-sun4i-usb.c +4 -4
index 86d9ce1..d78a071 100644
@@ -447,11 +447,11 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 	else
 		data->num_phys = 3;
 
-	if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy") ||
-	    of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
-		data->disc_thresh = 3;
-	else
+	if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") ||
+	    of_device_is_compatible(np, "allwinner,sun7i-a20-usb-phy"))
 		data->disc_thresh = 2;
+	else
+		data->disc_thresh = 3;
 
 	if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
 		dedicated_clocks = true;
Signature · 1 line
2.4.3
#7 lore raw

PATCH v5 4/7 phy-sun4i-usb: Add support for the usb-phys on the sun8i-a23 SoC

In reply to Hans de Goede

The usb-phys on the sun8i-a23 SoC have the same setup wrt clocks as on the sun6i-a31 SoC, but there are only 2 instead of 3 like on the sun5i-a13 SoC.

---
 Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt | 2 ++
 drivers/phy/phy-sun4i-usb.c                             | 7 +++++--
 2 files changed, 7 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +2 -0
index 557fa99..f0c640a 100644
@@ -7,6 +7,7 @@ Required properties:
   * allwinner,sun5i-a13-usb-phy
   * allwinner,sun6i-a31-usb-phy
   * allwinner,sun7i-a20-usb-phy
+  * allwinner,sun8i-a23-usb-phy
 - reg : a list of offset + length pairs
 - reg-names :
   * "phy_ctrl"
@@ -17,6 +18,7 @@ Required properties:
 - clock-names :
   * "usb_phy" for sun4i, sun5i or sun7i
   * "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i
+  * "usb0_phy", "usb1_phy" for sun8i
 - resets : a list of phandle + reset specifier pairs
 - reset-names :
   * "usb0_reset"
drivers/phy/phy-sun4i-usb.c +5 -2
index d78a071..6850fcd 100644
@@ -442,7 +442,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 	INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan);
 	dev_set_drvdata(dev, data);
 
-	if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy"))
+	if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") ||
+	    of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy"))
 		data->num_phys = 2;
 	else
 		data->num_phys = 3;
@@ -453,7 +454,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 	else
 		data->disc_thresh = 3;
 
-	if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
+	if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") ||
+	    of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy"))
 		dedicated_clocks = true;
 	else
 		dedicated_clocks = false;
@@ -588,6 +590,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
 	{ .compatible = "allwinner,sun5i-a13-usb-phy" },
 	{ .compatible = "allwinner,sun6i-a31-usb-phy" },
 	{ .compatible = "allwinner,sun7i-a20-usb-phy" },
+	{ .compatible = "allwinner,sun8i-a23-usb-phy" },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
Signature · 1 line
2.4.3
#8 lore raw

PATCH v5 5/7 phy-sun4i-usb: Add support for the usb-phys on the sun8i-a33 SoC

In reply to Hans de Goede

The usb-phys on the sun8i-a33 SoC are mostly the same as sun8i-a23 but for some reason (hw bug?) the phyctl register was moved to a different address and is not initialized to 0 on reset.

---
 .../devicetree/bindings/phy/sun4i-usb-phy.txt      |  1 +
 drivers/phy/phy-sun4i-usb.c                        | 39 ++++++++++++++++------
 2 files changed, 29 insertions(+), 11 deletions(-)
Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +1 -0
index f0c640a..5f48979 100644
@@ -8,6 +8,7 @@ Required properties:
   * allwinner,sun6i-a31-usb-phy
   * allwinner,sun7i-a20-usb-phy
   * allwinner,sun8i-a23-usb-phy
+  * allwinner,sun8i-a33-usb-phy
 - reg : a list of offset + length pairs
 - reg-names :
   * "phy_ctrl"
drivers/phy/phy-sun4i-usb.c +28 -11
index 6850fcd..5060257 100644
@@ -40,9 +40,10 @@
 #include <linux/workqueue.h>
 
 #define REG_ISCR			0x00
-#define REG_PHYCTL			0x04
+#define REG_PHYCTL_A10			0x04
 #define REG_PHYBIST			0x08
 #define REG_PHYTUNE			0x0c
+#define REG_PHYCTL_A33			0x10
 
 #define PHYCTL_DATA			BIT(7)
 
@@ -90,6 +91,7 @@ struct sun4i_usb_phy_data {
 	struct mutex mutex;
 	int num_phys;
 	u32 disc_thresh;
+	bool has_a33_phyctl;
 	struct sun4i_usb_phy {
 		struct phy *phy;
 		void __iomem *pmu;
@@ -152,37 +154,46 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
 {
 	struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
 	u32 temp, usbc_bit = BIT(phy->index * 2);
+	void *phyctl;
 	int i;
 
 	mutex_lock(&phy_data->mutex);
 
+	if (phy_data->has_a33_phyctl) {
+		phyctl = phy_data->base + REG_PHYCTL_A33;
+		/* A33 needs us to set phyctl to 0 explictly */
+		writel(0, phyctl);
+	} else {
+		phyctl = phy_data->base + REG_PHYCTL_A10;
+	}
+
 	for (i = 0; i < len; i++) {
-		temp = readl(phy_data->base + REG_PHYCTL);
+		temp = readl(phyctl);
 
 		/* clear the address portion */
 		temp &= ~(0xff << 8);
 
 		/* set the address */
 		temp |= ((addr + i) << 8);
-		writel(temp, phy_data->base + REG_PHYCTL);
+		writel(temp, phyctl);
 
 		/* set the data bit and clear usbc bit*/
-		temp = readb(phy_data->base + REG_PHYCTL);
+		temp = readb(phyctl);
 		if (data & 0x1)
 			temp |= PHYCTL_DATA;
 		else
 			temp &= ~PHYCTL_DATA;
 		temp &= ~usbc_bit;
-		writeb(temp, phy_data->base + REG_PHYCTL);
+		writeb(temp, phyctl);
 
 		/* pulse usbc_bit */
-		temp = readb(phy_data->base + REG_PHYCTL);
+		temp = readb(phyctl);
 		temp |= usbc_bit;
-		writeb(temp, phy_data->base + REG_PHYCTL);
+		writeb(temp, phyctl);
 
-		temp = readb(phy_data->base + REG_PHYCTL);
+		temp = readb(phyctl);
 		temp &= ~usbc_bit;
-		writeb(temp, phy_data->base + REG_PHYCTL);
+		writeb(temp, phyctl);
 
 		data >>= 1;
 	}
@@ -443,7 +454,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 	dev_set_drvdata(dev, data);
 
 	if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") ||
-	    of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy"))
+	    of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") ||
+	    of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
 		data->num_phys = 2;
 	else
 		data->num_phys = 3;
@@ -455,11 +467,15 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 		data->disc_thresh = 3;
 
 	if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") ||
-	    of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy"))
+	    of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") ||
+	    of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
 		dedicated_clocks = true;
 	else
 		dedicated_clocks = false;
 
+	if (of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
+		data->has_a33_phyctl = true;
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
 	data->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(data->base))
@@ -591,6 +607,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
 	{ .compatible = "allwinner,sun6i-a31-usb-phy" },
 	{ .compatible = "allwinner,sun7i-a20-usb-phy" },
 	{ .compatible = "allwinner,sun8i-a23-usb-phy" },
+	{ .compatible = "allwinner,sun8i-a33-usb-phy" },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
Signature · 1 line
2.4.3
#9 lore raw

PATCH v5 6/7 phy-sun4i-usb: Add support for boards with broken Vusb-detection

In reply to Hans de Goede

On some boards we cannot detect the presence of an external Vusb, because e.g. the 5V of the otg connector is directly connected to the 5V of the board, and thus is always high.

This commit adds support for using such boards by only looking at the id-detection pin.

---
 drivers/phy/phy-sun4i-usb.c | 44 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 36 insertions(+), 8 deletions(-)
drivers/phy/phy-sun4i-usb.c +36 -8
index 5060257..0681641 100644
@@ -22,6 +22,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/extcon.h>
 #include <linux/io.h>
@@ -309,7 +310,7 @@ static int sun4i_usb_phy_power_on(struct phy *_phy)
 	phy->regulator_on = true;
 
 	/* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
-	if (phy->index == 0 && data->phy0_poll)
+	if (phy->index == 0 && data->vbus_det_gpio && data->phy0_poll)
 		mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
 
 	return 0;
@@ -330,7 +331,7 @@ static int sun4i_usb_phy_power_off(struct phy *_phy)
 	 * phy0 vbus typically slowly discharges, sometimes this causes the
 	 * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
 	 */
-	if (phy->index == 0 && !data->phy0_poll)
+	if (phy->index == 0 && data->vbus_det_gpio && !data->phy0_poll)
 		mod_delayed_work(system_wq, &data->detect, POLL_TIME);
 
 	return 0;
@@ -359,7 +360,10 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 	int id_det, vbus_det, id_notify = 0, vbus_notify = 0;
 
 	id_det = gpiod_get_value_cansleep(data->id_det_gpio);
-	vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio);
+	if (data->vbus_det_gpio)
+		vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio);
+	else
+		vbus_det = 1; /* Report vbus as high */
 
 	mutex_lock(&phy0->mutex);
 
@@ -369,6 +373,16 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 	}
 
 	if (id_det != data->id_det) {
+		/*
+		 * When a host cable (id == 0) gets plugged in on systems
+		 * without vbus detection report vbus low for long enough for
+		 * the musb-ip to end the current device session.
+		 */
+		if (!data->vbus_det_gpio && id_det == 0) {
+			sun4i_usb_phy0_set_vbus_detect(phy0, 0);
+			msleep(200);
+			sun4i_usb_phy0_set_vbus_detect(phy0, 1);
+		}
 		sun4i_usb_phy0_set_id_detect(phy0, id_det);
 		data->id_det = id_det;
 		id_notify = 1;
@@ -382,9 +396,22 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 
 	mutex_unlock(&phy0->mutex);
 
-	if (id_notify)
+	if (id_notify) {
 		extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST,
 					!id_det);
+		/*
+		 * When a host cable gets unplugged (id == 1) on systems
+		 * without vbus detection report vbus low for long enough to
+		 * the musb-ip to end the current host session.
+		 */
+		if (!data->vbus_det_gpio && id_det == 1) {
+			mutex_lock(&phy0->mutex);
+			sun4i_usb_phy0_set_vbus_detect(phy0, 0);
+			msleep(1000);
+			sun4i_usb_phy0_set_vbus_detect(phy0, 1);
+			mutex_unlock(&phy0->mutex);
+		}
+	}
 
 	if (vbus_notify)
 		extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
@@ -495,9 +522,9 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 		data->vbus_det_gpio = NULL;
 	}
 
-	/* We either want both gpio pins or neither (when in host mode) */
-	if (!data->id_det_gpio != !data->vbus_det_gpio) {
-		dev_err(dev, "failed to get id or vbus detect pin\n");
+	/* vbus_det without id_det makes no sense, and is not supported */
+	if (data->vbus_det_gpio && !data->id_det_gpio) {
+		dev_err(dev, "usb0_id_det missing or invalid\n");
 		return -ENODEV;
 	}
 
@@ -565,7 +592,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 
 	data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
 	data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
-	if (data->id_det_irq  < 0 || data->vbus_det_irq < 0)
+	if ((data->id_det_gpio && data->id_det_irq < 0) ||
+	    (data->vbus_det_gpio && data->vbus_det_irq < 0))
 		data->phy0_poll = true;
 
 	if (data->id_det_irq >= 0) {
Signature · 1 line
2.4.3
#10 lore raw

PATCH v5 7/7 phy-sun4i-usb: Add support for monitoring vbus via a power-supply

In reply to Hans de Goede

On some boards there is no vbus_det gpio pin, instead vbus-detection for otg can be done via the pmic.

This commit adds support for monitoring vbus_det via the power_supply exported by the pmic, enabling support for otg on these boards.

---
 .../devicetree/bindings/phy/sun4i-usb-phy.txt      |  1 +
 drivers/phy/Kconfig                                |  1 +
 drivers/phy/phy-sun4i-usb.c                        | 76 ++++++++++++++++++++--
 3 files changed, 71 insertions(+), 7 deletions(-)
Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +1 -0
index 5f48979..0cebf74 100644
@@ -29,6 +29,7 @@ Required properties:
 Optional properties:
 - usb0_id_det-gpios : gpio phandle for reading the otg id pin value
 - usb0_vbus_det-gpios : gpio phandle for detecting the presence of usb0 vbus
+- usb0_vbus_power-supply: power-supply phandle for usb0 vbus presence detect
 - usb0_vbus-supply : regulator phandle for controller usb0 vbus
 - usb1_vbus-supply : regulator phandle for controller usb1 vbus
 - usb2_vbus-supply : regulator phandle for controller usb2 vbus
drivers/phy/Kconfig +1 -0
index 9841780..4e71765 100644
@@ -174,6 +174,7 @@ config PHY_SUN4I_USB
 	depends on ARCH_SUNXI && HAS_IOMEM && OF
 	depends on RESET_CONTROLLER
 	depends on EXTCON
+	depends on POWER_SUPPLY
 	select GENERIC_PHY
 	help
 	  Enable this to support the transceiver that is part of Allwinner
drivers/phy/phy-sun4i-usb.c +69 -7

137 lines not on this page · raw message

Signature · 1 line
2.4.3
#11 lore raw

v5 cover phy-sun4i-usb: Add OTG and newer SoC support

In reply to Hans de Goede

Hi,

Quoted 11 lines · Hans de Goede

Hi Kishon,

Here is a patch series with all my oustanding phy-sun4i-usb changes pending for merging into 4.3.

This includes the 5th iteration of the OTG support addition, now with the extcon provider support addition split-out into a new patch and ported to the extcon API changes which are queued up for 4.2 from :

http://git.kernel.org/cgit/linux/kernel/git/chanwoo/extcon.git/log/?h=extcon-next-v4.2

Quoted 7 lines

which already merged in GKH's char-misc branch for 4.2, this means that this series now depends on those changes.

Other than that this is a resend of some of the other feature addition patches I recently send rebased on top of v5 of the OTG support.

Please merge this series for 4.3.

sure, will queue once -rc1 is tagged.

Thanks
Kishon

#12 lore raw

v5 cover phy-sun4i-usb: Add OTG and newer SoC support

In reply to Hans de Goede

Hi,

Quoted 11 lines · Hans de Goede

Hi Kishon,

Here is a patch series with all my oustanding phy-sun4i-usb changes pending for merging into 4.3.

This includes the 5th iteration of the OTG support addition, now with the extcon provider support addition split-out into a new patch and ported to the extcon API changes which are queued up for 4.2 from :

http://git.kernel.org/cgit/linux/kernel/git/chanwoo/extcon.git/log/?h=extcon-next-v4.2

Quoted 7 lines

which already merged in GKH's char-misc branch for 4.2, this means that this series now depends on those changes.

Other than that this is a resend of some of the other feature addition patches I recently send rebased on top of v5 of the OTG support.

Please merge this series for 4.3.

Fixed a couple of checkpatch warnings and merged this to linux-phy tree

WARNING: 'explictly' may be misspelled - perhaps 'explicitly'? #113: FILE: drivers/phy/phy-sun4i-usb.c:164:
+ /* A33 needs us to set phyctl to 0 explictly */

ERROR: trailing whitespace
#556: FILE: drivers/phy/phy-sun4i-usb.c:461:
+^Istruct sun4i_usb_phy_data *data = $

Cheers
Kishon