linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround
@ 2016-06-29 18:14 Hans de Goede
  2016-06-29 18:14 ` [PATCH v5 resend 1/2] phy-sun4i-usb: Add support for peripheral-only mode Hans de Goede
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Hans de Goede @ 2016-06-29 18:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kishon,

The "USB: Fix of_usb_get_dr_mode_by_phy with a shared phy block"
patch on which this series depends is in usb-next now:

https://git.kernel.org/cgit/linux/kernel/git/gregkh/usb.git/commit/?h=usb-next&id=ce15ed4c5dfb3f7757e6611902aed5db253af977

Can you please merge this series?

Regards,

Hans

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v5 resend 1/2] phy-sun4i-usb: Add support for peripheral-only mode
  2016-06-29 18:14 [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround Hans de Goede
@ 2016-06-29 18:14 ` Hans de Goede
  2016-06-29 18:14 ` [PATCH v5 resend 2/2] phy-sun4i-usb: Add workaround for missing Vbus det interrupts on A31 Hans de Goede
  2016-06-30  5:47 ` [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround Kishon Vijay Abraham I
  2 siblings, 0 replies; 6+ messages in thread
From: Hans de Goede @ 2016-06-29 18:14 UTC (permalink / raw)
  To: linux-arm-kernel

Use the new of_usb_get_dr_mode_by_phy() function to get the dr_mode
from the musb controller node instead of assuming that having an id_det
gpio means otg mode, and not having one means host mode.

Implement peripheral-only mode by adding a sun4i_usb_phy0_get_id_det
helper which looks at the dr_mode, always registering our extcon and
always monitoring vbus.

If dr_mode is not specified in the dts, do not register phy0 as we then
do not know how to treat it. This is actually a good thing as this means
we will not be registering phy0 on devices where the otg controller is
not enabled in the devicetree.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
---
Changes in v2:
-Adjust for of_usb_get_dr_mode_by_phy now taking an args0 parameter
Changes in v3:
-Only toggle the phy vbus-det bit on id-change on systems without vbus-det
 when in otg mode
Changes in v4:
-No changes
Changes in v5:
-Added Kishon's Acked-by
---
 drivers/phy/phy-sun4i-usb.c | 68 ++++++++++++++++++++++++++++++---------------
 1 file changed, 46 insertions(+), 22 deletions(-)

diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index de3101f..f4d1178 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -40,6 +40,7 @@
 #include <linux/power_supply.h>
 #include <linux/regulator/consumer.h>
 #include <linux/reset.h>
+#include <linux/usb/of.h>
 #include <linux/workqueue.h>
 
 #define REG_ISCR			0x00
@@ -109,6 +110,7 @@ struct sun4i_usb_phy_cfg {
 struct sun4i_usb_phy_data {
 	void __iomem *base;
 	const struct sun4i_usb_phy_cfg *cfg;
+	enum usb_dr_mode dr_mode;
 	struct mutex mutex;
 	struct sun4i_usb_phy {
 		struct phy *phy;
@@ -119,6 +121,7 @@ struct sun4i_usb_phy_data {
 		bool regulator_on;
 		int index;
 	} phys[MAX_PHYS];
+	int first_phy;
 	/* phy0 / otg related variables */
 	struct extcon_dev *extcon;
 	bool phy0_init;
@@ -285,16 +288,10 @@ static int sun4i_usb_phy_init(struct phy *_phy)
 		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);
-		}
+		/* Force ISCR and cable state updates */
+		data->id_det = -1;
+		data->vbus_det = -1;
+		queue_delayed_work(system_wq, &data->detect, 0);
 	}
 
 	return 0;
@@ -319,6 +316,19 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
 	return 0;
 }
 
+static int sun4i_usb_phy0_get_id_det(struct sun4i_usb_phy_data *data)
+{
+	switch (data->dr_mode) {
+	case USB_DR_MODE_OTG:
+		return gpiod_get_value_cansleep(data->id_det_gpio);
+	case USB_DR_MODE_HOST:
+		return 0;
+	case USB_DR_MODE_PERIPHERAL:
+	default:
+		return 1;
+	}
+}
+
 static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data)
 {
 	if (data->vbus_det_gpio)
@@ -414,7 +424,10 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 	struct phy *phy0 = data->phys[0].phy;
 	int id_det, vbus_det, id_notify = 0, vbus_notify = 0;
 
-	id_det = gpiod_get_value_cansleep(data->id_det_gpio);
+	if (phy0 == NULL)
+		return;
+
+	id_det = sun4i_usb_phy0_get_id_det(data);
 	vbus_det = sun4i_usb_phy0_get_vbus_det(data);
 
 	mutex_lock(&phy0->mutex);
@@ -430,7 +443,8 @@ 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 (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 0) {
+		if (data->dr_mode == USB_DR_MODE_OTG &&
+		    !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);
@@ -456,7 +470,8 @@ 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 (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 1) {
+		if (data->dr_mode == USB_DR_MODE_OTG &&
+		    !sun4i_usb_phy0_have_vbus_det(data) && id_det == 1) {
 			mutex_lock(&phy0->mutex);
 			sun4i_usb_phy0_set_vbus_detect(phy0, 0);
 			msleep(1000);
@@ -501,7 +516,8 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev,
 {
 	struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
 
-	if (args->args[0] >= data->cfg->num_phys)
+	if (args->args[0] < data->first_phy ||
+	    args->args[0] >= data->cfg->num_phys)
 		return ERR_PTR(-ENODEV);
 
 	return data->phys[args->args[0]].phy;
@@ -575,13 +591,17 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 			return -EPROBE_DEFER;
 	}
 
-	/* vbus_det without id_det makes no sense, and is not supported */
-	if (sun4i_usb_phy0_have_vbus_det(data) && !data->id_det_gpio) {
-		dev_err(dev, "usb0_id_det missing or invalid\n");
-		return -ENODEV;
-	}
-
-	if (data->id_det_gpio) {
+	data->dr_mode = of_usb_get_dr_mode_by_phy(np, 0);
+	switch (data->dr_mode) {
+	case USB_DR_MODE_OTG:
+		/* otg without id_det makes no sense, and is not supported */
+		if (!data->id_det_gpio) {
+			dev_err(dev, "usb0_id_det missing or invalid\n");
+			return -ENODEV;
+		}
+		/* fall through */
+	case USB_DR_MODE_HOST:
+	case USB_DR_MODE_PERIPHERAL:
 		data->extcon = devm_extcon_dev_allocate(dev,
 							sun4i_usb_phy0_cable);
 		if (IS_ERR(data->extcon))
@@ -592,9 +612,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 			dev_err(dev, "failed to register extcon: %d\n", ret);
 			return ret;
 		}
+		break;
+	default:
+		dev_info(dev, "dr_mode unknown, not registering usb phy0\n");
+		data->first_phy = 1;
 	}
 
-	for (i = 0; i < data->cfg->num_phys; i++) {
+	for (i = data->first_phy; i < data->cfg->num_phys; i++) {
 		struct sun4i_usb_phy *phy = data->phys + i;
 		char name[16];
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v5 resend 2/2] phy-sun4i-usb: Add workaround for missing Vbus det interrupts on A31
  2016-06-29 18:14 [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround Hans de Goede
  2016-06-29 18:14 ` [PATCH v5 resend 1/2] phy-sun4i-usb: Add support for peripheral-only mode Hans de Goede
@ 2016-06-29 18:14 ` Hans de Goede
  2016-06-30  5:47 ` [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround Kishon Vijay Abraham I
  2 siblings, 0 replies; 6+ messages in thread
From: Hans de Goede @ 2016-06-29 18:14 UTC (permalink / raw)
  To: linux-arm-kernel

The A31 companion pmic (axp221) does not generate vbus change interrupts
when the board is driving vbus, so we must poll when using the pmic for
vbus-det _and_ we're driving vbus.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
---
Changes in v2:
-No changes
Changes in v3:
-No changes
Changes in v4:
-No changes
Changes in v5:
-Rebase on top of latest linux-phy/fixes
-Added Kishon's Acked-by
---
 drivers/phy/phy-sun4i-usb.c | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index f4d1178..8c7eb33 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -95,6 +95,7 @@
 
 enum sun4i_usb_phy_type {
 	sun4i_a10_phy,
+	sun6i_a31_phy,
 	sun8i_a33_phy,
 	sun8i_h3_phy,
 };
@@ -125,7 +126,6 @@ struct sun4i_usb_phy_data {
 	/* phy0 / otg related variables */
 	struct extcon_dev *extcon;
 	bool phy0_init;
-	bool phy0_poll;
 	struct gpio_desc *id_det_gpio;
 	struct gpio_desc *vbus_det_gpio;
 	struct power_supply *vbus_power_supply;
@@ -353,6 +353,24 @@ static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
 	return data->vbus_det_gpio || data->vbus_power_supply;
 }
 
+static bool sun4i_usb_phy0_poll(struct sun4i_usb_phy_data *data)
+{
+	if ((data->id_det_gpio && data->id_det_irq <= 0) ||
+	    (data->vbus_det_gpio && data->vbus_det_irq <= 0))
+		return true;
+
+	/*
+	 * The A31 companion pmic (axp221) does not generate vbus change
+	 * interrupts when the board is driving vbus, so we must poll
+	 * when using the pmic for vbus-det _and_ we're driving vbus.
+	 */
+	if (data->cfg->type == sun6i_a31_phy &&
+	    data->vbus_power_supply && data->phys[0].regulator_on)
+		return true;
+
+	return false;
+}
+
 static int sun4i_usb_phy_power_on(struct phy *_phy)
 {
 	struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
@@ -374,7 +392,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->vbus_det_gpio && data->phy0_poll)
+	if (phy->index == 0 && sun4i_usb_phy0_poll(data))
 		mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
 
 	return 0;
@@ -395,7 +413,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->vbus_det_gpio && !data->phy0_poll)
+	if (phy->index == 0 && !sun4i_usb_phy0_poll(data))
 		mod_delayed_work(system_wq, &data->detect, POLL_TIME);
 
 	return 0;
@@ -483,7 +501,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
 	if (vbus_notify)
 		extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
 
-	if (data->phy0_poll)
+	if (sun4i_usb_phy0_poll(data))
 		queue_delayed_work(system_wq, &data->detect, POLL_TIME);
 }
 
@@ -668,11 +686,6 @@ 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_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) {
 		ret = devm_request_irq(dev, data->id_det_irq,
 				sun4i_usb_phy0_id_vbus_det_irq,
@@ -684,6 +697,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 		}
 	}
 
+	data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
 	if (data->vbus_det_irq > 0) {
 		ret = devm_request_irq(dev, data->vbus_det_irq,
 				sun4i_usb_phy0_id_vbus_det_irq,
@@ -735,7 +749,7 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
 
 static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
 	.num_phys = 3,
-	.type = sun4i_a10_phy,
+	.type = sun6i_a31_phy,
 	.disc_thresh = 3,
 	.phyctl_offset = REG_PHYCTL_A10,
 	.dedicated_clocks = true,
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround
  2016-06-29 18:14 [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround Hans de Goede
  2016-06-29 18:14 ` [PATCH v5 resend 1/2] phy-sun4i-usb: Add support for peripheral-only mode Hans de Goede
  2016-06-29 18:14 ` [PATCH v5 resend 2/2] phy-sun4i-usb: Add workaround for missing Vbus det interrupts on A31 Hans de Goede
@ 2016-06-30  5:47 ` Kishon Vijay Abraham I
  2016-07-02 20:08   ` Hans de Goede
  2 siblings, 1 reply; 6+ messages in thread
From: Kishon Vijay Abraham I @ 2016-06-30  5:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Wednesday 29 June 2016 11:44 PM, Hans de Goede wrote:
> Hi Kishon,
> 
> The "USB: Fix of_usb_get_dr_mode_by_phy with a shared phy block"
> patch on which this series depends is in usb-next now:
> 
> https://git.kernel.org/cgit/linux/kernel/git/gregkh/usb.git/commit/?h=usb-next&id=ce15ed4c5dfb3f7757e6611902aed5db253af977
> 
> Can you please merge this series?

This is not applying cleanly against linux-phy -next. Can you rebase and send?

Thanks
Kishon

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround
  2016-06-30  5:47 ` [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround Kishon Vijay Abraham I
@ 2016-07-02 20:08   ` Hans de Goede
  2016-07-04  7:50     ` Kishon Vijay Abraham I
  0 siblings, 1 reply; 6+ messages in thread
From: Hans de Goede @ 2016-07-02 20:08 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 30-06-16 07:47, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Wednesday 29 June 2016 11:44 PM, Hans de Goede wrote:
>> Hi Kishon,
>>
>> The "USB: Fix of_usb_get_dr_mode_by_phy with a shared phy block"
>> patch on which this series depends is in usb-next now:
>>
>> https://git.kernel.org/cgit/linux/kernel/git/gregkh/usb.git/commit/?h=usb-next&id=ce15ed4c5dfb3f7757e6611902aed5db253af977
>>
>> Can you please merge this series?
>
> This is not applying cleanly against linux-phy -next. Can you rebase and send?

I just tried to rebase, the problem is that your -next branch does not
contain the fixes from your -fixes branch, specifically it is missing
this commit:

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/drivers/phy?id=5cf700ac9d50353dc5b8194a57c6f40bf1fc4424

Which is causing the conflict you're seeing when trying to merge
the patches I send. I can send you fixed patches which apply
cleanly to your linux-phy/next but those then will not merge
properly with linus' tree.

So it is probably better to at least cherry-pick the commit
I've linked to above into your -next, to avoid future merge
problems. If you cherry-pick that commit then the patches
I've send you should apply cleanly.

Regards,

Hans

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround
  2016-07-02 20:08   ` Hans de Goede
@ 2016-07-04  7:50     ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 6+ messages in thread
From: Kishon Vijay Abraham I @ 2016-07-04  7:50 UTC (permalink / raw)
  To: linux-arm-kernel



On Sunday 03 July 2016 01:38 AM, Hans de Goede wrote:
> Hi,
> 
> On 30-06-16 07:47, Kishon Vijay Abraham I wrote:
>> Hi,
>>
>> On Wednesday 29 June 2016 11:44 PM, Hans de Goede wrote:
>>> Hi Kishon,
>>>
>>> The "USB: Fix of_usb_get_dr_mode_by_phy with a shared phy block"
>>> patch on which this series depends is in usb-next now:
>>>
>>> https://git.kernel.org/cgit/linux/kernel/git/gregkh/usb.git/commit/?h=usb-next&id=ce15ed4c5dfb3f7757e6611902aed5db253af977
>>>
>>>
>>> Can you please merge this series?
>>
>> This is not applying cleanly against linux-phy -next. Can you rebase and send?
> 
> I just tried to rebase, the problem is that your -next branch does not
> contain the fixes from your -fixes branch, specifically it is missing
> this commit:
> 
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/drivers/phy?id=5cf700ac9d50353dc5b8194a57c6f40bf1fc4424
> 
> 
> Which is causing the conflict you're seeing when trying to merge
> the patches I send. I can send you fixed patches which apply
> cleanly to your linux-phy/next but those then will not merge
> properly with linus' tree.
> 
> So it is probably better to at least cherry-pick the commit
> I've linked to above into your -next, to avoid future merge
> problems. If you cherry-pick that commit then the patches
> I've send you should apply cleanly.

Ah okay.. I'll rebase my next onto my fixes. Thanks for letting me know this.

Thanks
Kishon

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-07-04  7:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-29 18:14 [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround Hans de Goede
2016-06-29 18:14 ` [PATCH v5 resend 1/2] phy-sun4i-usb: Add support for peripheral-only mode Hans de Goede
2016-06-29 18:14 ` [PATCH v5 resend 2/2] phy-sun4i-usb: Add workaround for missing Vbus det interrupts on A31 Hans de Goede
2016-06-30  5:47 ` [PATCH v5 resend 0/2] phy-sun4i-usb: peripheral-mode + a31 otg workaround Kishon Vijay Abraham I
2016-07-02 20:08   ` Hans de Goede
2016-07-04  7:50     ` Kishon Vijay Abraham I

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).