Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1205243 > unrolled thread

[GIT PULL 00/19] phy: for 4.3

Started byKishon Vijay Abraham I <kishon@ti.com>
First post2015-08-11 18:00 +0200
Last post2015-08-15 02:00 +0200
Articles 9 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [GIT PULL 00/19] phy: for 4.3 Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-11 18:00 +0200
    [PATCH 09/19] phy-sun4i-usb: Add support for monitoring vbus via a power-supply Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-11 18:10 +0200
    [PATCH 11/19] phy: berlin: Do not use sata name in usb phy driver Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-11 18:10 +0200
    [PATCH 03/19] phy-sun4i-usb: Add id and vbus detection support for the otg phy (phy0) Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-11 18:10 +0200
    [PATCH 13/19] phy: Drop owner assignment from i2c_driver Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-11 18:10 +0200
    [PATCH 05/19] phy-sun4i-usb: Swap check for disconnect threshold Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-11 18:10 +0200
    [PATCH 01/19] phy: add lpc18xx usb otg phy driver Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-11 18:10 +0200
    [PATCH 07/19] phy-sun4i-usb: Add support for the usb-phys on the sun8i-a33 SoC Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-11 18:10 +0200
    Re: [GIT PULL 00/19] phy: for 4.3 Greg KH <gregkh@linuxfoundation.org> - 2015-08-15 02:00 +0200

#1205243 — [GIT PULL 00/19] phy: for 4.3

FromKishon Vijay Abraham I <kishon@ti.com>
Date2015-08-11 18:00 +0200
Subject[GIT PULL 00/19] phy: for 4.3
Message-ID<pWk82-1c5-3@gated-at.bofh.it>
Hi Greg,

Please find the pull request for 4.3 merge window below. This contains a new
NXP phy driver, extcon support and few fixes in phy-sun4i-usb driver and other
trivial code cleanups.

Let me know if I have to change something.

Thanks
Kishon

The following changes since commit d770e558e21961ad6cfdf0ff7df0eb5d7d4f0754:

  Linux 4.2-rc1 (2015-07-05 11:01:52 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git tags/phy-for-4.3

for you to fetch changes up to cfd093bbb5fe84ec8c7bb069fe618159a8b601f5:

  phy: lpc18xx-usb-otg: fix clock order in phy init (2015-08-10 20:11:58 +0530)

----------------------------------------------------------------
phy: for 4.3

*) Add new NXP USB OTG PHY driver
*) Add vbus/id detection, extcon support and fixes in phy-sun4i-usb
   driver
*) Add support to use phy-sun4i-usb driver for sun8i-a23 and sun8i-a33
   SoCs
*) Other trivial code cleanups, dropping .owner assignment and constify
   phy_ops

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

----------------------------------------------------------------
Axel Lin (2):
  phy: ulpi_phy: Add const qualifier to ops
  phy: Constify struct phy_ops variables

Hans de Goede (9):
  phy-sun4i-usb: Add id and vbus detection support for the otg phy
    (phy0)
  phy-sun4i-usb: Add extcon support for the otg phy (phy0)
  phy-sun4i-usb: Swap check for disconnect threshold
  phy-sun4i-usb: Add support for the usb-phys on the sun8i-a23 SoC
  phy-sun4i-usb: Add support for the usb-phys on the sun8i-a33 SoC
  phy-sun4i-usb: Add support for boards with broken Vusb-detection
  phy-sun4i-usb: Add support for monitoring vbus via a power-supply
  phy-sun4i-sub: Move vbus-detect helper functions up in the file
  phy-sun4i-usb: Only check vbus-det on power-on on boards with
    vbus-det

Joachim Eastwood (3):
  phy: add lpc18xx usb otg phy driver
  phy: dt bindings: add NXP LPC18xx/43xx USB OTG PHY bindings
  phy: lpc18xx-usb-otg: fix clock order in phy init

Krzysztof Kozlowski (2):
  phy: Drop owner assignment from i2c_driver
  phy: Drop owner assignment from platform_driver

Michal Simek (3):
  phy: berlin: .owner field is setup by core
  phy: berlin: Do not use sata name in usb phy driver
  phy: berlin: Trivial coding style cleanup

 .../bindings/phy/phy-lpc18xx-usb-otg.txt           |   26 ++
 .../devicetree/bindings/phy/sun4i-usb-phy.txt      |   22 +-
 drivers/phy/Kconfig                                |   13 +
 drivers/phy/Makefile                               |    1 +
 drivers/phy/phy-armada375-usb2.c                   |    3 +-
 drivers/phy/phy-bcm-kona-usb2.c                    |    2 +-
 drivers/phy/phy-berlin-sata.c                      |    2 +-
 drivers/phy/phy-berlin-usb.c                       |   13 +-
 drivers/phy/phy-brcmstb-sata.c                     |    2 +-
 drivers/phy/phy-dm816x-usb.c                       |    2 +-
 drivers/phy/phy-exynos-dp-video.c                  |    2 +-
 drivers/phy/phy-exynos-mipi-video.c                |    2 +-
 drivers/phy/phy-exynos5-usbdrd.c                   |    2 +-
 drivers/phy/phy-exynos5250-sata.c                  |    2 +-
 drivers/phy/phy-hix5hd2-sata.c                     |    2 +-
 drivers/phy/phy-lpc18xx-usb-otg.c                  |  143 +++++++
 drivers/phy/phy-miphy28lp.c                        |    3 +-
 drivers/phy/phy-miphy365x.c                        |    2 +-
 drivers/phy/phy-mvebu-sata.c                       |    2 +-
 drivers/phy/phy-omap-usb2.c                        |    2 +-
 drivers/phy/phy-qcom-apq8064-sata.c                |    2 +-
 drivers/phy/phy-qcom-ipq806x-sata.c                |    2 +-
 drivers/phy/phy-qcom-ufs-i.h                       |    2 +-
 drivers/phy/phy-qcom-ufs-qmp-14nm.c                |    3 +-
 drivers/phy/phy-qcom-ufs-qmp-20nm.c                |    3 +-
 drivers/phy/phy-qcom-ufs.c                         |    2 +-
 drivers/phy/phy-rcar-gen2.c                        |    2 +-
 drivers/phy/phy-rockchip-usb.c                     |    3 +-
 drivers/phy/phy-samsung-usb2.c                     |    2 +-
 drivers/phy/phy-spear1310-miphy.c                  |    2 +-
 drivers/phy/phy-spear1340-miphy.c                  |    2 +-
 drivers/phy/phy-stih41x-usb.c                      |    2 +-
 drivers/phy/phy-sun4i-usb.c                        |  423 ++++++++++++++++++--
 drivers/phy/phy-sun9i-usb.c                        |    2 +-
 drivers/phy/phy-ti-pipe3.c                         |    2 +-
 drivers/phy/phy-tusb1210.c                         |    2 +-
 drivers/phy/ulpi_phy.h                             |    2 +-
 37 files changed, 636 insertions(+), 70 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt
 create mode 100644 drivers/phy/phy-lpc18xx-usb-otg.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1205244 — [PATCH 09/19] phy-sun4i-usb: Add support for monitoring vbus via a power-supply

FromKishon Vijay Abraham I <kishon@ti.com>
Date2015-08-11 18:10 +0200
Subject[PATCH 09/19] phy-sun4i-usb: Add support for monitoring vbus via a power-supply
Message-ID<pWkhH-1Fq-1@gated-at.bofh.it>
In reply to#1205243
From: Hans de Goede <hdegoede@redhat.com>

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.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../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(-)

diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
index 5f48979..0cebf74 100644
--- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
@@ -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
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index c0c1ad2..0fe9bff 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -209,6 +209,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
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 4ba9856..5138843 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -36,6 +36,7 @@
 #include <linux/phy/phy.h>
 #include <linux/phy/phy-sun4i-usb.h>
 #include <linux/platform_device.h>
+#include <linux/power_supply.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 #include <linux/workqueue.h>
@@ -108,6 +109,9 @@ struct sun4i_usb_phy_data {
 	bool phy0_poll;
 	struct gpio_desc *id_det_gpio;
 	struct gpio_desc *vbus_det_gpio;
+	struct power_supply *vbus_power_supply;
+	struct notifier_block vbus_power_nb;
+	bool vbus_power_nb_registered;
 	int id_det_irq;
 	int vbus_det_irq;
 	int id_det;
@@ -352,6 +356,30 @@ static struct phy_ops sun4i_usb_phy_ops = {
 	.owner		= THIS_MODULE,
 };
 
+static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data)
+{
+	if (data->vbus_det_gpio)
+		return gpiod_get_value_cansleep(data->vbus_det_gpio);
+
+	if (data->vbus_power_supply) {
+		union power_supply_propval val;
+		int r;
+
+		r = power_supply_get_property(data->vbus_power_supply,
+					      POWER_SUPPLY_PROP_PRESENT, &val);
+		if (r == 0)
+			return val.intval;
+	}
+
+	/* Fallback: report vbus as high */
+	return 1;
+}
+
+static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
+{
+	return data->vbus_det_gpio || data->vbus_power_supply;
+}
+
 static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 {
 	struct sun4i_usb_phy_data *data =
@@ -360,10 +388,7 @@ 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);
-	if (data->vbus_det_gpio)
-		vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio);
-	else
-		vbus_det = 1; /* Report vbus as high */
+	vbus_det = sun4i_usb_phy0_get_vbus_det(data);
 
 	mutex_lock(&phy0->mutex);
 
@@ -378,7 +403,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 		 * 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) {
+		if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 0) {
 			sun4i_usb_phy0_set_vbus_detect(phy0, 0);
 			msleep(200);
 			sun4i_usb_phy0_set_vbus_detect(phy0, 1);
@@ -404,7 +429,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 		 * 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) {
+		if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 1) {
 			mutex_lock(&phy0->mutex);
 			sun4i_usb_phy0_set_vbus_detect(phy0, 0);
 			msleep(1000);
@@ -430,6 +455,20 @@ static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb,
+				      unsigned long val, void *v)
+{
+	struct sun4i_usb_phy_data *data =
+		container_of(nb, struct sun4i_usb_phy_data, vbus_power_nb);
+	struct power_supply *psy = v;
+
+	/* Properties on the vbus_power_supply changed, scan vbus_det */
+	if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply)
+		mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+	return NOTIFY_OK;
+}
+
 static struct phy *sun4i_usb_phy_xlate(struct device *dev,
 					struct of_phandle_args *args)
 {
@@ -446,6 +485,8 @@ static int sun4i_usb_phy_remove(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
 
+	if (data->vbus_power_nb_registered)
+		power_supply_unreg_notifier(&data->vbus_power_nb);
 	if (data->id_det_irq >= 0)
 		devm_free_irq(dev, data->id_det_irq, data);
 	if (data->vbus_det_irq >= 0)
@@ -522,8 +563,18 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 		data->vbus_det_gpio = NULL;
 	}
 
+	if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
+		data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
+						     "usb0_vbus_power-supply");
+		if (IS_ERR(data->vbus_power_supply))
+			return PTR_ERR(data->vbus_power_supply);
+
+		if (!data->vbus_power_supply)
+			return -EPROBE_DEFER;
+	}
+
 	/* vbus_det without id_det makes no sense, and is not supported */
-	if (data->vbus_det_gpio && !data->id_det_gpio) {
+	if (sun4i_usb_phy0_have_vbus_det(data) && !data->id_det_gpio) {
 		dev_err(dev, "usb0_id_det missing or invalid\n");
 		return -ENODEV;
 	}
@@ -620,6 +671,17 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 		}
 	}
 
+	if (data->vbus_power_supply) {
+		data->vbus_power_nb.notifier_call = sun4i_usb_phy0_vbus_notify;
+		data->vbus_power_nb.priority = 0;
+		ret = power_supply_reg_notifier(&data->vbus_power_nb);
+		if (ret) {
+			sun4i_usb_phy_remove(pdev); /* Stop detect work */
+			return ret;
+		}
+		data->vbus_power_nb_registered = true;
+	}
+
 	phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
 	if (IS_ERR(phy_provider)) {
 		sun4i_usb_phy_remove(pdev); /* Stop detect work */
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1205246 — [PATCH 11/19] phy: berlin: Do not use sata name in usb phy driver

FromKishon Vijay Abraham I <kishon@ti.com>
Date2015-08-11 18:10 +0200
Subject[PATCH 11/19] phy: berlin: Do not use sata name in usb phy driver
Message-ID<pWkhH-1Fq-11@gated-at.bofh.it>
In reply to#1205243
From: Michal Simek <michal.simek@xilinx.com>

copy and paste error from berlin sata phy driver.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Acked-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-berlin-usb.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c
index d7431f6..762f0fb 100644
--- a/drivers/phy/phy-berlin-usb.c
+++ b/drivers/phy/phy-berlin-usb.c
@@ -152,7 +152,7 @@ static struct phy_ops phy_berlin_usb_ops = {
 	.owner		= THIS_MODULE,
 };
 
-static const struct of_device_id phy_berlin_sata_of_match[] = {
+static const struct of_device_id phy_berlin_usb_of_match[] = {
 	{
 		.compatible = "marvell,berlin2-usb-phy",
 		.data = &phy_berlin_pll_dividers[0],
@@ -163,12 +163,12 @@ static const struct of_device_id phy_berlin_sata_of_match[] = {
 	},
 	{ },
 };
-MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
+MODULE_DEVICE_TABLE(of, phy_berlin_usb_of_match);
 
 static int phy_berlin_usb_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match =
-		of_match_device(phy_berlin_sata_of_match, &pdev->dev);
+		of_match_device(phy_berlin_usb_of_match, &pdev->dev);
 	struct phy_berlin_usb_priv *priv;
 	struct resource *res;
 	struct phy *phy;
@@ -207,7 +207,7 @@ static struct platform_driver phy_berlin_usb_driver = {
 	.probe	= phy_berlin_usb_probe,
 	.driver	= {
 		.name		= "phy-berlin-usb",
-		.of_match_table	= phy_berlin_sata_of_match,
+		.of_match_table	= phy_berlin_usb_of_match,
 	 },
 };
 module_platform_driver(phy_berlin_usb_driver);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1205247 — [PATCH 03/19] phy-sun4i-usb: Add id and vbus detection support for the otg phy (phy0)

FromKishon Vijay Abraham I <kishon@ti.com>
Date2015-08-11 18:10 +0200
Subject[PATCH 03/19] phy-sun4i-usb: Add id and vbus detection support for the otg phy (phy0)
Message-ID<pWkhI-1Fq-15@gated-at.bofh.it>
In reply to#1205243
From: Hans de Goede <hdegoede@redhat.com>

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.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/sun4i-usb-phy.txt      |   18 +-
 drivers/phy/phy-sun4i-usb.c                        |  250 +++++++++++++++++++-
 2 files changed, 256 insertions(+), 12 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
index 16528b9..557fa99 100644
--- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
@@ -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@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>;
 	};
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index e17c539..37f52f7 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -1,7 +1,7 @@
 /*
  * Allwinner sun4i USB phy driver
  *
- * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (C) 2014-2015 Hans de Goede <hdegoede@redhat.com>
  *
  * Based on code from
  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
@@ -24,16 +24,19 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/phy/phy.h>
 #include <linux/phy/phy-sun4i-usb.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
+#include <linux/workqueue.h>
 
 #define REG_ISCR			0x00
 #define REG_PHYCTL			0x04
@@ -47,6 +50,17 @@
 #define SUNXI_AHB_INCRX_ALIGN_EN	BIT(8)
 #define SUNXI_ULPI_BYPASS_EN		BIT(0)
 
+/* ISCR, Interface Status and Control bits */
+#define ISCR_ID_PULLUP_EN		(1 << 17)
+#define ISCR_DPDM_PULLUP_EN	(1 << 16)
+/* sunxi has the phy id/vbus pins not connected, so we use the force bits */
+#define ISCR_FORCE_ID_MASK	(3 << 14)
+#define ISCR_FORCE_ID_LOW		(2 << 14)
+#define ISCR_FORCE_ID_HIGH	(3 << 14)
+#define ISCR_FORCE_VBUS_MASK	(3 << 12)
+#define ISCR_FORCE_VBUS_LOW	(2 << 12)
+#define ISCR_FORCE_VBUS_HIGH	(3 << 12)
+
 /* Common Control Bits for Both PHYs */
 #define PHY_PLL_BW			0x03
 #define PHY_RES45_CAL_EN		0x0c
@@ -63,6 +77,13 @@
 
 #define MAX_PHYS			3
 
+/*
+ * Note do not raise the debounce time, we must report Vusb high within 100ms
+ * otherwise we get Vbus errors
+ */
+#define DEBOUNCE_TIME			msecs_to_jiffies(50)
+#define POLL_TIME			msecs_to_jiffies(250)
+
 struct sun4i_usb_phy_data {
 	void __iomem *base;
 	struct mutex mutex;
@@ -74,13 +95,56 @@ struct sun4i_usb_phy_data {
 		struct regulator *vbus;
 		struct reset_control *reset;
 		struct clk *clk;
+		bool regulator_on;
 		int index;
 	} phys[MAX_PHYS];
+	/* phy0 / otg related variables */
+	bool phy0_init;
+	bool phy0_poll;
+	struct gpio_desc *id_det_gpio;
+	struct gpio_desc *vbus_det_gpio;
+	int id_det_irq;
+	int vbus_det_irq;
+	int id_det;
+	int vbus_det;
+	struct delayed_work detect;
 };
 
 #define to_sun4i_usb_phy_data(phy) \
 	container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
 
+static void sun4i_usb_phy0_update_iscr(struct phy *_phy, u32 clr, u32 set)
+{
+	struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+	struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+	u32 iscr;
+
+	iscr = readl(data->base + REG_ISCR);
+	iscr &= ~clr;
+	iscr |= set;
+	writel(iscr, data->base + REG_ISCR);
+}
+
+static void sun4i_usb_phy0_set_id_detect(struct phy *phy, u32 val)
+{
+	if (val)
+		val = ISCR_FORCE_ID_HIGH;
+	else
+		val = ISCR_FORCE_ID_LOW;
+
+	sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_ID_MASK, val);
+}
+
+static void sun4i_usb_phy0_set_vbus_detect(struct phy *phy, u32 val)
+{
+	if (val)
+		val = ISCR_FORCE_VBUS_HIGH;
+	else
+		val = ISCR_FORCE_VBUS_LOW;
+
+	sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_VBUS_MASK, val);
+}
+
 static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
 				int len)
 {
@@ -171,12 +235,39 @@ static int sun4i_usb_phy_init(struct phy *_phy)
 
 	sun4i_usb_phy_passby(phy, 1);
 
+	if (phy->index == 0) {
+		data->phy0_init = true;
+
+		/* Enable pull-ups */
+		sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_DPDM_PULLUP_EN);
+		sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_ID_PULLUP_EN);
+
+		if (data->id_det_gpio) {
+			/* OTG mode, force ISCR and cable state updates */
+			data->id_det = -1;
+			data->vbus_det = -1;
+			queue_delayed_work(system_wq, &data->detect, 0);
+		} else {
+			/* Host only mode */
+			sun4i_usb_phy0_set_id_detect(_phy, 0);
+			sun4i_usb_phy0_set_vbus_detect(_phy, 1);
+		}
+	}
+
 	return 0;
 }
 
 static int sun4i_usb_phy_exit(struct phy *_phy)
 {
 	struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+	struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+	if (phy->index == 0) {
+		/* Disable pull-ups */
+		sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
+		sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
+		data->phy0_init = false;
+	}
 
 	sun4i_usb_phy_passby(phy, 0);
 	reset_control_assert(phy->reset);
@@ -188,20 +279,46 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
 static int sun4i_usb_phy_power_on(struct phy *_phy)
 {
 	struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
-	int ret = 0;
+	struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+	int ret;
+
+	if (!phy->vbus || phy->regulator_on)
+		return 0;
+
+	/* For phy0 only turn on Vbus if we don't have an ext. Vbus */
+	if (phy->index == 0 && data->vbus_det)
+		return 0;
 
-	if (phy->vbus)
-		ret = regulator_enable(phy->vbus);
+	ret = regulator_enable(phy->vbus);
+	if (ret)
+		return ret;
 
-	return ret;
+	phy->regulator_on = true;
+
+	/* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
+	if (phy->index == 0 && data->phy0_poll)
+		mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+	return 0;
 }
 
 static int sun4i_usb_phy_power_off(struct phy *_phy)
 {
 	struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+	struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+	if (!phy->vbus || !phy->regulator_on)
+		return 0;
 
-	if (phy->vbus)
-		regulator_disable(phy->vbus);
+	regulator_disable(phy->vbus);
+	phy->regulator_on = false;
+
+	/*
+	 * 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)
+		mod_delayed_work(system_wq, &data->detect, POLL_TIME);
 
 	return 0;
 }
@@ -221,6 +338,49 @@ static struct phy_ops sun4i_usb_phy_ops = {
 	.owner		= THIS_MODULE,
 };
 
+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;
+
+	id_det = gpiod_get_value_cansleep(data->id_det_gpio);
+	vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio);
+
+	mutex_lock(&phy0->mutex);
+
+	if (!data->phy0_init) {
+		mutex_unlock(&phy0->mutex);
+		return;
+	}
+
+	if (id_det != data->id_det) {
+		sun4i_usb_phy0_set_id_detect(phy0, id_det);
+		data->id_det = id_det;
+	}
+
+	if (vbus_det != data->vbus_det) {
+		sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det);
+		data->vbus_det = vbus_det;
+	}
+
+	mutex_unlock(&phy0->mutex);
+
+	if (data->phy0_poll)
+		queue_delayed_work(system_wq, &data->detect, POLL_TIME);
+}
+
+static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
+{
+	struct sun4i_usb_phy_data *data = dev_id;
+
+	/* vbus or id changed, let the pins settle and then scan them */
+	mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+	return IRQ_HANDLED;
+}
+
 static struct phy *sun4i_usb_phy_xlate(struct device *dev,
 					struct of_phandle_args *args)
 {
@@ -232,6 +392,21 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev,
 	return data->phys[args->args[0]].phy;
 }
 
+static int sun4i_usb_phy_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
+
+	if (data->id_det_irq >= 0)
+		devm_free_irq(dev, data->id_det_irq, data);
+	if (data->vbus_det_irq >= 0)
+		devm_free_irq(dev, data->vbus_det_irq, data);
+
+	cancel_delayed_work_sync(&data->detect);
+
+	return 0;
+}
+
 static int sun4i_usb_phy_probe(struct platform_device *pdev)
 {
 	struct sun4i_usb_phy_data *data;
@@ -240,13 +415,15 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 	struct phy_provider *phy_provider;
 	bool dedicated_clocks;
 	struct resource *res;
-	int i;
+	int i, ret;
 
 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
 	mutex_init(&data->mutex);
+	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"))
 		data->num_phys = 2;
@@ -269,6 +446,26 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 	if (IS_ERR(data->base))
 		return PTR_ERR(data->base);
 
+	data->id_det_gpio = devm_gpiod_get(dev, "usb0_id_det", GPIOD_IN);
+	if (IS_ERR(data->id_det_gpio)) {
+		if (PTR_ERR(data->id_det_gpio) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		data->id_det_gpio = NULL;
+	}
+
+	data->vbus_det_gpio = devm_gpiod_get(dev, "usb0_vbus_det", GPIOD_IN);
+	if (IS_ERR(data->vbus_det_gpio)) {
+		if (PTR_ERR(data->vbus_det_gpio) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		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");
+		return -ENODEV;
+	}
+
 	for (i = 0; i < data->num_phys; i++) {
 		struct sun4i_usb_phy *phy = data->phys + i;
 		char name[16];
@@ -318,10 +515,42 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 		phy_set_drvdata(phy->phy, &data->phys[i]);
 	}
 
-	dev_set_drvdata(dev, data);
+	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)
+		data->phy0_poll = true;
+
+	if (data->id_det_irq >= 0) {
+		ret = devm_request_irq(dev, data->id_det_irq,
+				sun4i_usb_phy0_id_vbus_det_irq,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				"usb0-id-det", data);
+		if (ret) {
+			dev_err(dev, "Err requesting id-det-irq: %d\n", ret);
+			return ret;
+		}
+	}
+
+	if (data->vbus_det_irq >= 0) {
+		ret = devm_request_irq(dev, data->vbus_det_irq,
+				sun4i_usb_phy0_id_vbus_det_irq,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				"usb0-vbus-det", data);
+		if (ret) {
+			dev_err(dev, "Err requesting vbus-det-irq: %d\n", ret);
+			data->vbus_det_irq = -1;
+			sun4i_usb_phy_remove(pdev); /* Stop detect work */
+			return ret;
+		}
+	}
+
 	phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
+	if (IS_ERR(phy_provider)) {
+		sun4i_usb_phy_remove(pdev); /* Stop detect work */
+		return PTR_ERR(phy_provider);
+	}
 
-	return PTR_ERR_OR_ZERO(phy_provider);
+	return 0;
 }
 
 static const struct of_device_id sun4i_usb_phy_of_match[] = {
@@ -335,6 +564,7 @@ MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
 
 static struct platform_driver sun4i_usb_phy_driver = {
 	.probe	= sun4i_usb_phy_probe,
+	.remove	= sun4i_usb_phy_remove,
 	.driver = {
 		.of_match_table	= sun4i_usb_phy_of_match,
 		.name  = "sun4i-usb-phy",
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1205249 — [PATCH 13/19] phy: Drop owner assignment from i2c_driver

FromKishon Vijay Abraham I <kishon@ti.com>
Date2015-08-11 18:10 +0200
Subject[PATCH 13/19] phy: Drop owner assignment from i2c_driver
Message-ID<pWkhI-1Fq-23@gated-at.bofh.it>
In reply to#1205243
From: Krzysztof Kozlowski <k.kozlowski@samsung.com>

i2c_driver does not need to set an owner because i2c_register_driver()
will set it.

Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-armada375-usb2.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/phy-armada375-usb2.c
index 8ccc395..39c7d21 100644
--- a/drivers/phy/phy-armada375-usb2.c
+++ b/drivers/phy/phy-armada375-usb2.c
@@ -149,7 +149,6 @@ static struct platform_driver armada375_usb_phy_driver = {
 	.driver = {
 		.of_match_table	= of_usb_cluster_table,
 		.name  = "armada-375-usb-cluster",
-		.owner = THIS_MODULE,
 	}
 };
 module_platform_driver(armada375_usb_phy_driver);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1205250 — [PATCH 05/19] phy-sun4i-usb: Swap check for disconnect threshold

FromKishon Vijay Abraham I <kishon@ti.com>
Date2015-08-11 18:10 +0200
Subject[PATCH 05/19] phy-sun4i-usb: Swap check for disconnect threshold
Message-ID<pWkhI-1Fq-29@gated-at.bofh.it>
In reply to#1205243
From: Hans de Goede <hdegoede@redhat.com>

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.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-sun4i-usb.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index a6ea2e6..50ecab9 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -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;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1205252 — [PATCH 01/19] phy: add lpc18xx usb otg phy driver

FromKishon Vijay Abraham I <kishon@ti.com>
Date2015-08-11 18:10 +0200
Subject[PATCH 01/19] phy: add lpc18xx usb otg phy driver
Message-ID<pWkhJ-1Fq-41@gated-at.bofh.it>
In reply to#1205243
From: Joachim Eastwood <manabian@gmail.com>

Add PHY driver for the internal USB OTG PHY found on NXP
LPC18xx and LPC43xx devices. This driver takes care of
enabling the PHY in CREG (syscon) and setting the required
clock frequency.

Signed-off-by: Joachim Eastwood <manabian@gmail.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig               |   11 +++
 drivers/phy/Makefile              |    1 +
 drivers/phy/phy-lpc18xx-usb-otg.c |  143 +++++++++++++++++++++++++++++++++++++
 3 files changed, 155 insertions(+)
 create mode 100644 drivers/phy/phy-lpc18xx-usb-otg.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index c0e6ede..e2f2a4d 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -54,6 +54,17 @@ config PHY_EXYNOS_MIPI_VIDEO
 	  Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
 	  and EXYNOS SoCs.
 
+config PHY_LPC18XX_USB_OTG
+	tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
+	depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
+	depends on MFD_SYSCON
+	select GENERIC_PHY
+	help
+	  Enable this to support NXP LPC18xx/43xx internal USB OTG PHY.
+
+	  This driver is need for USB0 support on LPC18xx/43xx and takes
+	  care of enabling and clock setup.
+
 config PHY_PXA_28NM_HSIC
 	tristate "Marvell USB HSIC 28nm PHY Driver"
 	select GENERIC_PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index f344e1b..a5b18c1 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY)	+= phy-armada375-usb2.o
 obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
+obj-$(CONFIG_PHY_LPC18XX_USB_OTG)	+= phy-lpc18xx-usb-otg.o
 obj-$(CONFIG_PHY_PXA_28NM_USB2)		+= phy-pxa-28nm-usb2.o
 obj-$(CONFIG_PHY_PXA_28NM_HSIC)		+= phy-pxa-28nm-hsic.o
 obj-$(CONFIG_PHY_MVEBU_SATA)		+= phy-mvebu-sata.o
diff --git a/drivers/phy/phy-lpc18xx-usb-otg.c b/drivers/phy/phy-lpc18xx-usb-otg.c
new file mode 100644
index 0000000..3aa8e4d
--- /dev/null
+++ b/drivers/phy/phy-lpc18xx-usb-otg.c
@@ -0,0 +1,143 @@
+/*
+ * PHY driver for NXP LPC18xx/43xx internal USB OTG PHY
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* USB OTG PHY register offset and bit in CREG */
+#define LPC18XX_CREG_CREG0		0x004
+#define LPC18XX_CREG_CREG0_USB0PHY	BIT(5)
+
+struct lpc18xx_usb_otg_phy {
+	struct phy *phy;
+	struct clk *clk;
+	struct regmap *reg;
+};
+
+static int lpc18xx_usb_otg_phy_init(struct phy *phy)
+{
+	struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+	int ret;
+
+	ret = clk_prepare(lpc->clk);
+	if (ret)
+		return ret;
+
+	/* The PHY must be clocked at 480 MHz */
+	return clk_set_rate(lpc->clk, 480000000);
+}
+
+static int lpc18xx_usb_otg_phy_exit(struct phy *phy)
+{
+	struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+
+	clk_unprepare(lpc->clk);
+
+	return 0;
+}
+
+static int lpc18xx_usb_otg_phy_power_on(struct phy *phy)
+{
+	struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+	int ret;
+
+	ret = clk_enable(lpc->clk);
+	if (ret)
+		return ret;
+
+	/* The bit in CREG is cleared to enable the PHY */
+	return regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0,
+				  LPC18XX_CREG_CREG0_USB0PHY, 0);
+}
+
+static int lpc18xx_usb_otg_phy_power_off(struct phy *phy)
+{
+	struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+	int ret;
+
+	ret = regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0,
+				 LPC18XX_CREG_CREG0_USB0PHY,
+				 LPC18XX_CREG_CREG0_USB0PHY);
+	if (ret)
+		return ret;
+
+	clk_disable(lpc->clk);
+
+	return 0;
+}
+
+static const struct phy_ops lpc18xx_usb_otg_phy_ops = {
+	.init		= lpc18xx_usb_otg_phy_init,
+	.exit		= lpc18xx_usb_otg_phy_exit,
+	.power_on	= lpc18xx_usb_otg_phy_power_on,
+	.power_off	= lpc18xx_usb_otg_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int lpc18xx_usb_otg_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct lpc18xx_usb_otg_phy *lpc;
+
+	lpc = devm_kzalloc(&pdev->dev, sizeof(*lpc), GFP_KERNEL);
+	if (!lpc)
+		return -ENOMEM;
+
+	lpc->reg = syscon_node_to_regmap(pdev->dev.of_node->parent);
+	if (IS_ERR(lpc->reg)) {
+		dev_err(&pdev->dev, "failed to get syscon\n");
+		return PTR_ERR(lpc->reg);
+	}
+
+	lpc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(lpc->clk)) {
+		dev_err(&pdev->dev, "failed to get clock\n");
+		return PTR_ERR(lpc->clk);
+	}
+
+	lpc->phy = devm_phy_create(&pdev->dev, NULL, &lpc18xx_usb_otg_phy_ops);
+	if (IS_ERR(lpc->phy)) {
+		dev_err(&pdev->dev, "failed to create PHY\n");
+		return PTR_ERR(lpc->phy);
+	}
+
+	phy_set_drvdata(lpc->phy, lpc);
+
+	phy_provider = devm_of_phy_provider_register(&pdev->dev,
+						     of_phy_simple_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id lpc18xx_usb_otg_phy_match[] = {
+	{ .compatible = "nxp,lpc1850-usb-otg-phy" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_usb_otg_phy_match);
+
+static struct platform_driver lpc18xx_usb_otg_phy_driver = {
+	.probe		= lpc18xx_usb_otg_phy_probe,
+	.driver		= {
+		.name	= "lpc18xx-usb-otg-phy",
+		.of_match_table = lpc18xx_usb_otg_phy_match,
+	},
+};
+module_platform_driver(lpc18xx_usb_otg_phy_driver);
+
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_DESCRIPTION("NXP LPC18xx/43xx USB OTG PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1205253 — [PATCH 07/19] phy-sun4i-usb: Add support for the usb-phys on the sun8i-a33 SoC

FromKishon Vijay Abraham I <kishon@ti.com>
Date2015-08-11 18:10 +0200
Subject[PATCH 07/19] phy-sun4i-usb: Add support for the usb-phys on the sun8i-a33 SoC
Message-ID<pWkhK-1Fq-51@gated-at.bofh.it>
In reply to#1205243
From: Hans de Goede <hdegoede@redhat.com>

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.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/sun4i-usb-phy.txt      |    1 +
 drivers/phy/phy-sun4i-usb.c                        |   39 ++++++++++++++------
 2 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
index f0c640a..5f48979 100644
--- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
@@ -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"
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 00424dd..ddc3995 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -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 explicitly */
+		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);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1207946

FromGreg KH <gregkh@linuxfoundation.org>
Date2015-08-15 02:00 +0200
Message-ID<pXx3c-rb-1@gated-at.bofh.it>
In reply to#1205243
On Tue, Aug 11, 2015 at 09:26:59PM +0530, Kishon Vijay Abraham I wrote:
> Hi Greg,
> 
> Please find the pull request for 4.3 merge window below. This contains a new
> NXP phy driver, extcon support and few fixes in phy-sun4i-usb driver and other
> trivial code cleanups.
> 
> Let me know if I have to change something.
> 
> Thanks
> Kishon
> 
> The following changes since commit d770e558e21961ad6cfdf0ff7df0eb5d7d4f0754:
> 
>   Linux 4.2-rc1 (2015-07-05 11:01:52 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git tags/phy-for-4.3

Pulled and pushed out, thanks.

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web