2013-04-03 08:45:32

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 00/12] second set of musb-ux500 and ab8500-usb updates

Hello Felipe,

This is the second series of usb updates for Ux500 drivers, covering
almost only ab8500-usb phy.

Patches includes various fixes and errata workarounds, API updates (the
devm_ stuff), and integration with modern subsystems (regulator and
pinctrl).

The whole series has been developed and tested on top of your "next"
branch.

I have to warn you that a couple of patches (regulator and pinctrl) have
run-time dependencies on other frameworks's patches that are currently
being reviewed... Either way, none of that is required for vital
functionalities, and all you get are a couple of printk warnings, so I
don't think is worth to go through tree dependency pain as everything
should come together nicely in linux-next.

Thanks,
Fabio


Fabio Baltieri (6):
usb: musb: ux500_dma: drop references to U5500
usb: phy: ab8500-usb: convert to devm_kzalloc
usb: phy: ab8500-usb: add regulator support
usb: phy: ab8500-usb: split ab8500_usb_phy_ctrl
usb: phy: ab8500-usb: enable/disable regulator on phy events
usb: phy: ab8500-usb: fix last notifier arguments

Mian Yousaf Kaukab (1):
usb: phy: ab8500-usb: fix unbalanced clock and regulator disable
warnings

Patrice Chotard (1):
usb: phy: ab8500-usb: adopt pinctrl support

Sakethram Bommisetti (4):
usb: phy: ab8500-usb: set phy tuning values
usb: phy: ab8500-usb: fix eye diagram for ab8500 v2.0
usb: phy: ab8500-usb: drop link status delayed work
usb: phy: ab8500-usb: call phy_dis_work only when necessary

drivers/usb/musb/ux500.c | 1 -
drivers/usb/musb/ux500_dma.c | 2 +-
drivers/usb/phy/phy-ab8500-usb.c | 366 +++++++++++++++++++++++++++++----------
3 files changed, 276 insertions(+), 93 deletions(-)

--
1.8.1.3


2013-04-03 08:46:28

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 01/12] usb: musb: ux500_dma: drop references to U5500

Drop references to deprecated U5500 platform in driver comments.

Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/musb/ux500_dma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c
index f417b7e..3381206 100644
--- a/drivers/usb/musb/ux500_dma.c
+++ b/drivers/usb/musb/ux500_dma.c
@@ -1,7 +1,7 @@
/*
* drivers/usb/musb/ux500_dma.c
*
- * U8500 and U5500 DMA support code
+ * U8500 DMA support code
*
* Copyright (C) 2009 STMicroelectronics
* Copyright (C) 2011 ST-Ericsson SA
--
1.8.1.3

2013-04-03 08:46:45

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 02/12] usb: phy: ab8500-usb: convert to devm_kzalloc

Convert local data allocation to devm_kzalloc and drop unnecessary fail
path code.

Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 351b036..ab6dd07 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -628,15 +628,13 @@ static int ab8500_usb_probe(struct platform_device *pdev)
return -ENODEV;
}

- ab = kzalloc(sizeof *ab, GFP_KERNEL);
+ ab = devm_kzalloc(&pdev->dev, sizeof(*ab), GFP_KERNEL);
if (!ab)
return -ENOMEM;

- otg = kzalloc(sizeof *otg, GFP_KERNEL);
- if (!otg) {
- kfree(ab);
+ otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+ if (!otg)
return -ENOMEM;
- }

ab->dev = &pdev->dev;
ab->ab8500 = ab8500;
@@ -665,12 +663,12 @@ static int ab8500_usb_probe(struct platform_device *pdev)

err = ab8500_usb_irq_setup(pdev, ab);
if (err < 0)
- goto fail;
+ return err;

err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
if (err) {
dev_err(&pdev->dev, "Can't register transceiver\n");
- goto fail;
+ return err;
}

/* Needed to enable ID detection. */
@@ -679,10 +677,6 @@ static int ab8500_usb_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev);

return 0;
-fail:
- kfree(otg);
- kfree(ab);
- return err;
}

static int ab8500_usb_remove(struct platform_device *pdev)
@@ -700,9 +694,6 @@ static int ab8500_usb_remove(struct platform_device *pdev)

platform_set_drvdata(pdev, NULL);

- kfree(ab->phy.otg);
- kfree(ab);
-
return 0;
}

--
1.8.1.3

2013-04-03 08:47:25

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 05/12] usb: phy: ab8500-usb: add regulator support

Add initial regulator support to ab8500-usb by introducing necessary
devm_regulator_get().

Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 1fd0780..4caa820 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -32,6 +32,7 @@
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/usb/musb-ux500.h>
+#include <linux/regulator/consumer.h>

/* Bank AB8500_SYS_CTRL2_BLOCK */
#define AB8500_MAIN_WD_CTRL_REG 0x01
@@ -126,6 +127,9 @@ struct ab8500_usb {
struct work_struct phy_dis_work;
unsigned long link_status_wait;
enum ab8500_usb_mode mode;
+ struct regulator *v_ape;
+ struct regulator *v_musb;
+ struct regulator *v_ulpi;
int previous_link_status_state;
};

@@ -589,6 +593,34 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
return 0;
}

+static int ab8500_usb_regulator_get(struct ab8500_usb *ab)
+{
+ int err;
+
+ ab->v_ape = devm_regulator_get(ab->dev, "v-ape");
+ if (IS_ERR(ab->v_ape)) {
+ dev_err(ab->dev, "Could not get v-ape supply\n");
+ err = PTR_ERR(ab->v_ape);
+ return err;
+ }
+
+ ab->v_ulpi = devm_regulator_get(ab->dev, "vddulpivio18");
+ if (IS_ERR(ab->v_ulpi)) {
+ dev_err(ab->dev, "Could not get vddulpivio18 supply\n");
+ err = PTR_ERR(ab->v_ulpi);
+ return err;
+ }
+
+ ab->v_musb = devm_regulator_get(ab->dev, "musb_1v8");
+ if (IS_ERR(ab->v_musb)) {
+ dev_err(ab->dev, "Could not get musb_1v8 supply\n");
+ err = PTR_ERR(ab->v_musb);
+ return err;
+ }
+
+ return 0;
+}
+
static int ab8500_usb_irq_setup(struct platform_device *pdev,
struct ab8500_usb *ab)
{
@@ -686,6 +718,10 @@ static int ab8500_usb_probe(struct platform_device *pdev)
/* all: Disable phy when called from set_host and set_peripheral */
INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);

+ err = ab8500_usb_regulator_get(ab);
+ if (err)
+ return err;
+
err = ab8500_usb_irq_setup(pdev, ab);
if (err < 0)
return err;
--
1.8.1.3

2013-04-03 08:47:38

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 06/12] usb: phy: ab8500-usb: split ab8500_usb_phy_ctrl

Split ab8500_usb_phy_ctrl into separate enable/disable functions to make
the code more linear and readable.

Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 55 +++++++++++++++++++---------------------
1 file changed, 26 insertions(+), 29 deletions(-)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 4caa820..1c6eec9 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -172,40 +172,37 @@ static void ab8500_usb_wd_linkstatus(struct ab8500_usb *ab, u8 bit)
}
}

-static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host,
- bool enable)
+static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host)
{
- u8 ctrl_reg;
- abx500_get_register_interruptible(ab->dev,
- AB8500_USB,
- AB8500_USB_PHY_CTRL_REG,
- &ctrl_reg);
- if (sel_host) {
- if (enable)
- ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN;
- else
- ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN;
- } else {
- if (enable)
- ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN;
- else
- ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN;
- }
+ u8 bit;
+ bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
+ AB8500_BIT_PHY_CTRL_DEVICE_EN;

- abx500_set_register_interruptible(ab->dev,
- AB8500_USB,
- AB8500_USB_PHY_CTRL_REG,
- ctrl_reg);
+ abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+ bit, bit);
+}

- /* Needed to enable the phy.*/
- if (enable)
- ab8500_usb_wd_workaround(ab);
+static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host)
+{
+ u8 bit;
+ bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
+ AB8500_BIT_PHY_CTRL_DEVICE_EN;
+
+ ab8500_usb_wd_linkstatus(ab, bit);
+
+ abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+ bit, 0);
+
+ /* Needed to disable the phy.*/
+ ab8500_usb_wd_workaround(ab);
}

-#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_ctrl(ab, true, true)
-#define ab8500_usb_host_phy_dis(ab) ab8500_usb_phy_ctrl(ab, true, false)
-#define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_ctrl(ab, false, true)
-#define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_ctrl(ab, false, false)
+#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_enable(ab, true)
+#define ab8500_usb_host_phy_dis(ab) ab8500_usb_phy_disable(ab, true)
+#define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_enable(ab, false)
+#define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_disable(ab, false)

static int ab8505_usb_link_status_update(struct ab8500_usb *ab,
enum ab8505_usb_link_status lsts)
--
1.8.1.3

2013-04-03 08:47:51

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 07/12] usb: phy: ab8500-usb: enable/disable regulator on phy events

Add ab8500_usb_regulator_{enable,disable} functions to control USB phy
regulators on corresponding ab8500_usb_phy_{enable,disable} events.

This contains some workaround and optimization for specific AB8500
versions.

Signed-off-by: Mian Yousaf Kaukab <[email protected]>
Signed-off-by: Sakethram Bommisetti <[email protected]>
Signed-off-by: Praveena Nadahally <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 68 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 66 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 1c6eec9..803ad93 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -130,6 +130,7 @@ struct ab8500_usb {
struct regulator *v_ape;
struct regulator *v_musb;
struct regulator *v_ulpi;
+ int saved_v_ulpi;
int previous_link_status_state;
};

@@ -161,6 +162,67 @@ static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
0);
}

+static void ab8500_usb_regulator_enable(struct ab8500_usb *ab)
+{
+ int ret, volt;
+
+ regulator_enable(ab->v_ape);
+
+ if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+ ab->saved_v_ulpi = regulator_get_voltage(ab->v_ulpi);
+ if (ab->saved_v_ulpi < 0)
+ dev_err(ab->dev, "Failed to get v_ulpi voltage\n");
+
+ ret = regulator_set_voltage(ab->v_ulpi, 1300000, 1350000);
+ if (ret < 0)
+ dev_err(ab->dev, "Failed to set the Vintcore to 1.3V, ret=%d\n",
+ ret);
+
+ ret = regulator_set_optimum_mode(ab->v_ulpi, 28000);
+ if (ret < 0)
+ dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
+ ret);
+ }
+
+ regulator_enable(ab->v_ulpi);
+
+ if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+ volt = regulator_get_voltage(ab->v_ulpi);
+ if ((volt != 1300000) && (volt != 1350000))
+ dev_err(ab->dev, "Vintcore is not set to 1.3V volt=%d\n",
+ volt);
+ }
+
+ regulator_enable(ab->v_musb);
+}
+
+static void ab8500_usb_regulator_disable(struct ab8500_usb *ab)
+{
+ int ret;
+
+ regulator_disable(ab->v_musb);
+
+ regulator_disable(ab->v_ulpi);
+
+ /* USB is not the only consumer of Vintcore, restore old settings */
+ if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+ if (ab->saved_v_ulpi > 0) {
+ ret = regulator_set_voltage(ab->v_ulpi,
+ ab->saved_v_ulpi, ab->saved_v_ulpi);
+ if (ret < 0)
+ dev_err(ab->dev, "Failed to set the Vintcore to %duV, ret=%d\n",
+ ab->saved_v_ulpi, ret);
+ }
+
+ ret = regulator_set_optimum_mode(ab->v_ulpi, 0);
+ if (ret < 0)
+ dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
+ ret);
+ }
+
+ regulator_disable(ab->v_ape);
+}
+
static void ab8500_usb_wd_linkstatus(struct ab8500_usb *ab, u8 bit)
{
/* Workaround for v2.0 bug # 31952 */
@@ -178,6 +240,8 @@ static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host)
bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
AB8500_BIT_PHY_CTRL_DEVICE_EN;

+ ab8500_usb_regulator_enable(ab);
+
abx500_mask_and_set_register_interruptible(ab->dev,
AB8500_USB, AB8500_USB_PHY_CTRL_REG,
bit, bit);
@@ -197,6 +261,8 @@ static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host)

/* Needed to disable the phy.*/
ab8500_usb_wd_workaround(ab);
+
+ ab8500_usb_regulator_disable(ab);
}

#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_enable(ab, true)
@@ -543,7 +609,6 @@ static int ab8500_usb_set_peripheral(struct usb_otg *otg,
*/

if (!gadget) {
- /* TODO: Disable regulators. */
otg->gadget = NULL;
schedule_work(&ab->phy_dis_work);
} else {
@@ -575,7 +640,6 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
*/

if (!host) {
- /* TODO: Disable regulators. */
otg->host = NULL;
schedule_work(&ab->phy_dis_work);
} else {
--
1.8.1.3

2013-04-03 08:48:03

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 08/12] usb: phy: ab8500-usb: fix unbalanced clock and regulator disable warnings

From: Mian Yousaf Kaukab <[email protected]>

To prevent clock and regulator frameworks from complaining, only disable
the host or peripheral phy if they were enabled.

Reported-by: Sakethram Bommisetti <[email protected]>
Signed-off-by: Mian Yousaf Kaukab <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 803ad93..b7f6639 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -887,8 +887,10 @@ static int ab8500_usb_remove(struct platform_device *pdev)

usb_remove_phy(&ab->phy);

- ab8500_usb_host_phy_dis(ab);
- ab8500_usb_peri_phy_dis(ab);
+ if (ab->mode == USB_HOST)
+ ab8500_usb_host_phy_dis(ab);
+ else if (ab->mode == USB_PERIPHERAL)
+ ab8500_usb_peri_phy_dis(ab);

platform_set_drvdata(pdev, NULL);

--
1.8.1.3

2013-04-03 08:48:09

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 09/12] usb: phy: ab8500-usb: fix last notifier arguments

Fix last ab->phy.notifier call to use vbus_draw as notifier argument, as
that's used in ab8500_charger to control charging current.

Also drop a related TODO comment, and the additional
ux500_musb_set_vbus(musb, 0), as with this patch it was causing an
erratic behaviour of gadget ep0 state machine.

Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/musb/ux500.c | 1 -
drivers/usb/phy/phy-ab8500-usb.c | 10 +++-------
2 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index 88795f5..2c80004 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -114,7 +114,6 @@ static int musb_otg_notifications(struct notifier_block *nb,
break;
case UX500_MUSB_VBUS:
dev_dbg(musb->controller, "VBUS Connect\n");
- ux500_musb_set_vbus(musb, 0);
break;
case UX500_MUSB_NONE:
dev_dbg(musb->controller, "VBUS Disconnect\n");
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index b7f6639..ff27058 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -577,16 +577,12 @@ static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)

ab->vbus_draw = mA;

- if (mA)
- atomic_notifier_call_chain(&ab->phy.notifier,
- UX500_MUSB_ENUMERATED, ab->phy.otg->gadget);
+ atomic_notifier_call_chain(&ab->phy.notifier,
+ UX500_MUSB_VBUS, &ab->vbus_draw);
+
return 0;
}

-/* TODO: Implement some way for charging or other drivers to read
- * ab->vbus_draw.
- */
-
static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend)
{
/* TODO */
--
1.8.1.3

2013-04-03 08:48:25

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 10/12] usb: phy: ab8500-usb: adopt pinctrl support

From: Patrice Chotard <[email protected]>

Amend the ab8500-usb driver to optionally take a pin control handle and
set the state of the pins to "default" on ab8500_usb_phy_enable and to
"sleep" on ab8500_usb_phy_disable.

The pinctrl handle is released on ab8500_usb_phy_disable because USB
pins are shared with ab8505_micro_usb_iddet driver.

Signed-off-by: Patrice Chotard <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index ff27058..0875e2b 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -33,6 +33,7 @@
#include <linux/mfd/abx500/ab8500.h>
#include <linux/usb/musb-ux500.h>
#include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>

/* Bank AB8500_SYS_CTRL2_BLOCK */
#define AB8500_MAIN_WD_CTRL_REG 0x01
@@ -132,6 +133,8 @@ struct ab8500_usb {
struct regulator *v_ulpi;
int saved_v_ulpi;
int previous_link_status_state;
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_sleep;
};

static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x)
@@ -240,6 +243,11 @@ static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host)
bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
AB8500_BIT_PHY_CTRL_DEVICE_EN;

+ /* mux and configure USB pins to DEFAULT state */
+ ab->pinctrl = pinctrl_get_select(ab->dev, PINCTRL_STATE_DEFAULT);
+ if (IS_ERR(ab->pinctrl))
+ dev_err(ab->dev, "could not get/set default pinstate\n");
+
ab8500_usb_regulator_enable(ab);

abx500_mask_and_set_register_interruptible(ab->dev,
@@ -263,6 +271,22 @@ static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host)
ab8500_usb_wd_workaround(ab);

ab8500_usb_regulator_disable(ab);
+
+ if (!IS_ERR(ab->pinctrl)) {
+ /* configure USB pins to SLEEP state */
+ ab->pins_sleep = pinctrl_lookup_state(ab->pinctrl,
+ PINCTRL_STATE_SLEEP);
+
+ if (IS_ERR(ab->pins_sleep))
+ dev_dbg(ab->dev, "could not get sleep pinstate\n");
+ else if (pinctrl_select_state(ab->pinctrl, ab->pins_sleep))
+ dev_err(ab->dev, "could not set pins to sleep state\n");
+
+ /* as USB pins are shared with idddet, release them to allow
+ * iddet to request them
+ */
+ pinctrl_put(ab->pinctrl);
+ }
}

#define ab8500_usb_host_phy_en(ab) ab8500_usb_phy_enable(ab, true)
--
1.8.1.3

2013-04-03 08:48:35

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 11/12] usb: phy: ab8500-usb: drop link status delayed work

From: Sakethram Bommisetti <[email protected]>

ab8500_usb_delayed_work was implemented as a workaroud for the internal
only and now unsupported v1.0 version of AB850. This patch removes the
delayed work and just leave a link status update call at probe time.

Signed-off-by: Sakethram Bommisetti <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 30 ++----------------------------
1 file changed, 2 insertions(+), 28 deletions(-)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 0875e2b..30adfee 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -124,9 +124,7 @@ struct ab8500_usb {
struct device *dev;
struct ab8500 *ab8500;
unsigned vbus_draw;
- struct delayed_work dwork;
struct work_struct phy_dis_work;
- unsigned long link_status_wait;
enum ab8500_usb_mode mode;
struct regulator *v_ape;
struct regulator *v_musb;
@@ -556,14 +554,6 @@ static irqreturn_t ab8500_usb_link_status_irq(int irq, void *data)
return IRQ_HANDLED;
}

-static void ab8500_usb_delayed_work(struct work_struct *work)
-{
- struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
- dwork.work);
-
- abx500_usb_link_status_update(ab);
-}
-
static void ab8500_usb_phy_disable_work(struct work_struct *work)
{
struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
@@ -634,12 +624,6 @@ static int ab8500_usb_set_peripheral(struct usb_otg *otg,
} else {
otg->gadget = gadget;
otg->phy->state = OTG_STATE_B_IDLE;
-
- /* Phy will not be enabled if cable is already
- * plugged-in. Schedule to enable phy.
- * Use same delay to avoid any race condition.
- */
- schedule_delayed_work(&ab->dwork, ab->link_status_wait);
}

return 0;
@@ -664,11 +648,6 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
schedule_work(&ab->phy_dis_work);
} else {
otg->host = host;
- /* Phy will not be enabled if cable is already
- * plugged-in. Schedule to enable phy.
- * Use same delay to avoid any race condition.
- */
- schedule_delayed_work(&ab->dwork, ab->link_status_wait);
}

return 0;
@@ -791,11 +770,6 @@ static int ab8500_usb_probe(struct platform_device *pdev)

ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);

- /* v1: Wait for link status to become stable.
- * all: Updates form set_host and set_peripheral as they are atomic.
- */
- INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work);
-
/* all: Disable phy when called from set_host and set_peripheral */
INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);

@@ -892,6 +866,8 @@ static int ab8500_usb_probe(struct platform_device *pdev)
/* Needed to enable ID detection. */
ab8500_usb_wd_workaround(ab);

+ abx500_usb_link_status_update(ab);
+
dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev);

return 0;
@@ -901,8 +877,6 @@ static int ab8500_usb_remove(struct platform_device *pdev)
{
struct ab8500_usb *ab = platform_get_drvdata(pdev);

- cancel_delayed_work_sync(&ab->dwork);
-
cancel_work_sync(&ab->phy_dis_work);

usb_remove_phy(&ab->phy);
--
1.8.1.3

2013-04-03 08:48:47

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 12/12] usb: phy: ab8500-usb: call phy_dis_work only when necessary

From: Sakethram Bommisetti <[email protected]>

Modify ab8500_usb_set_peripheral() and ab8500_usb_set_host() code to
schedule phy_dis_work only when necessary in order to prevent regulator
count mismatch during reboot/shutdown.

Signed-off-by: Sakethram Bommisetti <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 30adfee..81d1a5a 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -613,17 +613,16 @@ static int ab8500_usb_set_peripheral(struct usb_otg *otg,

ab = phy_to_ab(otg->phy);

+ ab->phy.otg->gadget = gadget;
+
/* Some drivers call this function in atomic context.
* Do not update ab8500 registers directly till this
* is fixed.
*/

- if (!gadget) {
- otg->gadget = NULL;
+ if ((ab->mode != USB_IDLE) && (!gadget)) {
+ ab->mode = USB_IDLE;
schedule_work(&ab->phy_dis_work);
- } else {
- otg->gadget = gadget;
- otg->phy->state = OTG_STATE_B_IDLE;
}

return 0;
@@ -638,16 +637,16 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)

ab = phy_to_ab(otg->phy);

+ ab->phy.otg->host = host;
+
/* Some drivers call this function in atomic context.
* Do not update ab8500 registers directly till this
* is fixed.
*/

- if (!host) {
- otg->host = NULL;
+ if ((ab->mode != USB_IDLE) && (!host)) {
+ ab->mode = USB_IDLE;
schedule_work(&ab->phy_dis_work);
- } else {
- otg->host = host;
}

return 0;
--
1.8.1.3

2013-04-03 08:51:06

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 04/12] usb: phy: ab8500-usb: fix eye diagram for ab8500 v2.0

From: Sakethram Bommisetti <[email protected]>

AB8500 v2.0 has eye diagram issues when drawing more than 100mA from
VBUS. Force charging current to 100mA in case of standard host.

Signed-off-by: Sakethram Bommisetti <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 5b92a59..1fd0780 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -485,6 +485,18 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work)
ab8500_usb_peri_phy_dis(ab);
}

+static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA)
+{
+ /* AB8500 V2 has eye diagram issues when drawing more than 100mA from
+ * VBUS. Set charging current to 100mA in case of standard host
+ */
+ if (is_ab8500_2p0_or_earlier(ab->ab8500))
+ if (mA > 100)
+ mA = 100;
+
+ return mA;
+}
+
static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)
{
struct ab8500_usb *ab;
@@ -494,6 +506,8 @@ static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)

ab = phy_to_ab(phy);

+ mA = ab8500_eyediagram_workaroud(ab, mA);
+
ab->vbus_draw = mA;

if (mA)
--
1.8.1.3

2013-04-03 08:47:04

by Fabio Baltieri

[permalink] [raw]
Subject: [PATCH 03/12] usb: phy: ab8500-usb: set phy tuning values

From: Sakethram Bommisetti <[email protected]>

Set phy tuning values proposed by the hardware teams for AB8500 and
AB8505 to improve USB eye diagram performances.

Signed-off-by: Sakethram Bommisetti <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Signed-off-by: Fabio Baltieri <[email protected]>
---
drivers/usb/phy/phy-ab8500-usb.c | 87 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)

diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index ab6dd07..5b92a59 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -33,11 +33,22 @@
#include <linux/mfd/abx500/ab8500.h>
#include <linux/usb/musb-ux500.h>

+/* Bank AB8500_SYS_CTRL2_BLOCK */
#define AB8500_MAIN_WD_CTRL_REG 0x01
+
+/* Bank AB8500_USB */
#define AB8500_USB_LINE_STAT_REG 0x80
#define AB8505_USB_LINE_STAT_REG 0x94
#define AB8500_USB_PHY_CTRL_REG 0x8A

+/* Bank AB8500_DEVELOPMENT */
+#define AB8500_BANK12_ACCESS 0x00
+
+/* Bank AB8500_DEBUG */
+#define AB8500_USB_PHY_TUNE1 0x05
+#define AB8500_USB_PHY_TUNE2 0x06
+#define AB8500_USB_PHY_TUNE3 0x07
+
#define AB8500_BIT_OTG_STAT_ID (1 << 0)
#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
@@ -671,6 +682,82 @@ static int ab8500_usb_probe(struct platform_device *pdev)
return err;
}

+ /* Phy tuning values for AB8500 */
+ if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+ /* Enable the PBT/Bank 0x12 access */
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to enable bank12 access err=%d\n",
+ err);
+
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n",
+ err);
+
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x00);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n",
+ err);
+
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+ err);
+
+ /* Switch to normal mode/disable Bank 0x12 access */
+ err = abx500_set_register_interruptible(ab->dev,
+ AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x00);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to switch bank12 access err=%d\n",
+ err);
+ }
+
+ /* Phy tuning values for AB8505 */
+ if (is_ab8505(ab->ab8500)) {
+ /* Enable the PBT/Bank 0x12 access */
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS,
+ 0x01, 0x01);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to enable bank12 access err=%d\n",
+ err);
+
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE1,
+ 0xC8, 0xC8);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n",
+ err);
+
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE2,
+ 0x60, 0x60);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n",
+ err);
+
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEBUG, AB8500_USB_PHY_TUNE3,
+ 0xFC, 0x80);
+
+ if (err < 0)
+ dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+ err);
+
+ /* Switch to normal mode/disable Bank 0x12 access */
+ err = abx500_mask_and_set_register_interruptible(ab->dev,
+ AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS,
+ 0x00, 0x00);
+ if (err < 0)
+ dev_err(ab->dev, "Failed to switch bank12 access err=%d\n",
+ err);
+ }
+
/* Needed to enable ID detection. */
ab8500_usb_wd_workaround(ab);

--
1.8.1.3

2013-04-03 08:53:58

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 04/12] usb: phy: ab8500-usb: fix eye diagram for ab8500 v2.0

On Wed, Apr 03, 2013 at 10:45:05AM +0200, Fabio Baltieri wrote:
> From: Sakethram Bommisetti <[email protected]>
>
> AB8500 v2.0 has eye diagram issues when drawing more than 100mA from
> VBUS. Force charging current to 100mA in case of standard host.
>
> Signed-off-by: Sakethram Bommisetti <[email protected]>
> Acked-by: Linus Walleij <[email protected]>
> Signed-off-by: Fabio Baltieri <[email protected]>
> ---
> drivers/usb/phy/phy-ab8500-usb.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
> index 5b92a59..1fd0780 100644
> --- a/drivers/usb/phy/phy-ab8500-usb.c
> +++ b/drivers/usb/phy/phy-ab8500-usb.c
> @@ -485,6 +485,18 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work)
> ab8500_usb_peri_phy_dis(ab);
> }
>
> +static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA)
> +{
> + /* AB8500 V2 has eye diagram issues when drawing more than 100mA from

wrong comment style. Please run *all* patches through checkpatch.pl
--strict and sparse. I can wait 2 more hours before closing my tree for
v3.10.

--
balbi


Attachments:
(No filename) (1.19 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments

2013-04-03 08:59:17

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 04/12] usb: phy: ab8500-usb: fix eye diagram for ab8500 v2.0

On Wed, Apr 03, 2013 at 11:53:36AM +0300, Felipe Balbi wrote:
> On Wed, Apr 03, 2013 at 10:45:05AM +0200, Fabio Baltieri wrote:
> > From: Sakethram Bommisetti <[email protected]>
> >
> > AB8500 v2.0 has eye diagram issues when drawing more than 100mA from
> > VBUS. Force charging current to 100mA in case of standard host.
> >
> > Signed-off-by: Sakethram Bommisetti <[email protected]>
> > Acked-by: Linus Walleij <[email protected]>
> > Signed-off-by: Fabio Baltieri <[email protected]>
> > ---
> > drivers/usb/phy/phy-ab8500-usb.c | 14 ++++++++++++++
> > 1 file changed, 14 insertions(+)
> >
> > diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
> > index 5b92a59..1fd0780 100644
> > --- a/drivers/usb/phy/phy-ab8500-usb.c
> > +++ b/drivers/usb/phy/phy-ab8500-usb.c
> > @@ -485,6 +485,18 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work)
> > ab8500_usb_peri_phy_dis(ab);
> > }
> >
> > +static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA)
> > +{
> > + /* AB8500 V2 has eye diagram issues when drawing more than 100mA from
>
> wrong comment style. Please run *all* patches through checkpatch.pl
> --strict and sparse. I can wait 2 more hours before closing my tree for
> v3.10.

you know what ? this is simple enough, I'll fix it myself.

--
balbi


Attachments:
(No filename) (1.36 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments

2013-04-03 09:12:15

by Fabio Baltieri

[permalink] [raw]
Subject: Re: [PATCH 04/12] usb: phy: ab8500-usb: fix eye diagram for ab8500 v2.0

Hi Felipe,

On Wed, Apr 03, 2013 at 11:58:58AM +0300, Felipe Balbi wrote:
> On Wed, Apr 03, 2013 at 11:53:36AM +0300, Felipe Balbi wrote:
> > On Wed, Apr 03, 2013 at 10:45:05AM +0200, Fabio Baltieri wrote:
> > > From: Sakethram Bommisetti <[email protected]>
> > >
> > > AB8500 v2.0 has eye diagram issues when drawing more than 100mA from
> > > VBUS. Force charging current to 100mA in case of standard host.
> > >
> > > Signed-off-by: Sakethram Bommisetti <[email protected]>
> > > Acked-by: Linus Walleij <[email protected]>
> > > Signed-off-by: Fabio Baltieri <[email protected]>
> > > ---
> > > drivers/usb/phy/phy-ab8500-usb.c | 14 ++++++++++++++
> > > 1 file changed, 14 insertions(+)
> > >
> > > diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
> > > index 5b92a59..1fd0780 100644
> > > --- a/drivers/usb/phy/phy-ab8500-usb.c
> > > +++ b/drivers/usb/phy/phy-ab8500-usb.c
> > > @@ -485,6 +485,18 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work)
> > > ab8500_usb_peri_phy_dis(ab);
> > > }
> > >
> > > +static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA)
> > > +{
> > > + /* AB8500 V2 has eye diagram issues when drawing more than 100mA from
> >
> > wrong comment style. Please run *all* patches through checkpatch.pl
> > --strict and sparse. I can wait 2 more hours before closing my tree for
> > v3.10.
>
> you know what ? this is simple enough, I'll fix it myself.

Ok, I was rushing a rebase but you've been faster! :-)

Anyway, paches were already sparse and checkpatch checked, but I ignored
a warning for "mA" camelcase (as that's how it's commonly spelled for
regulator) and new line indentation (where I used two-tabs instead of
open parenthesis to be coherent with the rest of the source).

For comment style, checkpatch does not give me any warning for some
reson. The in-line open style is already used in the net/ subsystem so
I was assuming that it was accepted here too. If this is not the case
maybe checkpatch.pl has to be fixed somehow.

Thanks,
Fabio

--
Fabio Baltieri

2013-04-03 09:35:57

by Felipe Balbi

[permalink] [raw]
Subject: Re: [PATCH 04/12] usb: phy: ab8500-usb: fix eye diagram for ab8500 v2.0

On Wed, Apr 03, 2013 at 11:12:00AM +0200, Fabio Baltieri wrote:
> Hi Felipe,
>
> On Wed, Apr 03, 2013 at 11:58:58AM +0300, Felipe Balbi wrote:
> > On Wed, Apr 03, 2013 at 11:53:36AM +0300, Felipe Balbi wrote:
> > > On Wed, Apr 03, 2013 at 10:45:05AM +0200, Fabio Baltieri wrote:
> > > > From: Sakethram Bommisetti <[email protected]>
> > > >
> > > > AB8500 v2.0 has eye diagram issues when drawing more than 100mA from
> > > > VBUS. Force charging current to 100mA in case of standard host.
> > > >
> > > > Signed-off-by: Sakethram Bommisetti <[email protected]>
> > > > Acked-by: Linus Walleij <[email protected]>
> > > > Signed-off-by: Fabio Baltieri <[email protected]>
> > > > ---
> > > > drivers/usb/phy/phy-ab8500-usb.c | 14 ++++++++++++++
> > > > 1 file changed, 14 insertions(+)
> > > >
> > > > diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
> > > > index 5b92a59..1fd0780 100644
> > > > --- a/drivers/usb/phy/phy-ab8500-usb.c
> > > > +++ b/drivers/usb/phy/phy-ab8500-usb.c
> > > > @@ -485,6 +485,18 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work)
> > > > ab8500_usb_peri_phy_dis(ab);
> > > > }
> > > >
> > > > +static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA)
> > > > +{
> > > > + /* AB8500 V2 has eye diagram issues when drawing more than 100mA from
> > >
> > > wrong comment style. Please run *all* patches through checkpatch.pl
> > > --strict and sparse. I can wait 2 more hours before closing my tree for
> > > v3.10.
> >
> > you know what ? this is simple enough, I'll fix it myself.
>
> Ok, I was rushing a rebase but you've been faster! :-)
>
> Anyway, paches were already sparse and checkpatch checked, but I ignored
> a warning for "mA" camelcase (as that's how it's commonly spelled for
> regulator) and new line indentation (where I used two-tabs instead of
> open parenthesis to be coherent with the rest of the source).
>
> For comment style, checkpatch does not give me any warning for some
> reson. The in-line open style is already used in the net/ subsystem so
> I was assuming that it was accepted here too. If this is not the case
> maybe checkpatch.pl has to be fixed somehow.

right, only the net subsystem has this inline open style :-)

Nevermind, it was so minor that it didn't even hurt me :-p

cheers

--
balbi


Attachments:
(No filename) (2.35 kB)
signature.asc (836.00 B)
Digital signature
Download all attachments