summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2014-05-07 08:57:36 +0200
committerMarek Szyprowski <m.szyprowski@samsung.com>2014-05-13 05:53:32 -0700
commitd2f744a23357e447d1f1875354cc6f58bd10b35c (patch)
tree447be123906d62ea01ab996fed906f96c7796871 /drivers
parente07d31d38eaf0d716f0e37d2de1d22a638aa5d6c (diff)
downloadlinux-3.10-d2f744a23357e447d1f1875354cc6f58bd10b35c.tar.gz
linux-3.10-d2f744a23357e447d1f1875354cc6f58bd10b35c.tar.bz2
linux-3.10-d2f744a23357e447d1f1875354cc6f58bd10b35c.zip
drivers: phy: exynos4x12-phy: fix HSIC1 power on/off sequence
From experiments with real hardware, it seems that URSTCON bits for HSIC0 and HSIC1 seems to be swapped, so updated macro definitions for them. HSIC1 also requires enabling power to device phy to get properly enabled (similar hack is already implemented for HSIC0). Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Change-Id: Idcbe47f1a55d882394296837b9218e9f843e842c
Diffstat (limited to 'drivers')
-rw-r--r--drivers/phy/phy-exynos4x12-usb2.c48
-rw-r--r--drivers/phy/phy-samsung-usb2.h2
2 files changed, 35 insertions, 15 deletions
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c
index d92a7cc5698..431568b5cc6 100644
--- a/drivers/phy/phy-exynos4x12-usb2.c
+++ b/drivers/phy/phy-exynos4x12-usb2.c
@@ -87,8 +87,16 @@
#define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2)
#define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3)
#define EXYNOS_4x12_URSTCON_PHY1 BIT(4)
-#define EXYNOS_4x12_URSTCON_HSIC0 BIT(5)
-#define EXYNOS_4x12_URSTCON_HSIC1 BIT(6)
+/*
+ * According to Exynos 4x12 reference manual the values for
+ * EXYNOS_4x12_URSTCON_HSIC are:
+ * URSTCON_HSIC0 = BIT(5)
+ * URSTCON_HSIC1 = BIT(6)
+ * but from experiments with real hardware the above 2 bitfields
+ * seems to be swapped, so define them to match the actual
+ * hardware */
+#define EXYNOS_4x12_URSTCON_HSIC1 BIT(5)
+#define EXYNOS_4x12_URSTCON_HSIC0 BIT(6)
#define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7)
#define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(8)
#define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9)
@@ -216,14 +224,15 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
break;
case EXYNOS4x12_HSIC0:
phypwr = EXYNOS_4x12_UPHYPWR_HSIC0;
- rstbits = EXYNOS_4x12_URSTCON_HSIC1 |
+ rstbits = EXYNOS_4x12_URSTCON_HSIC0 |
EXYNOS_4x12_URSTCON_HOST_LINK_P0 |
EXYNOS_4x12_URSTCON_HOST_PHY;
break;
case EXYNOS4x12_HSIC1:
phypwr = EXYNOS_4x12_UPHYPWR_HSIC1;
rstbits = EXYNOS_4x12_URSTCON_HSIC1 |
- EXYNOS_4x12_URSTCON_HOST_LINK_P1;
+ EXYNOS_4x12_URSTCON_HOST_LINK_P1 |
+ EXYNOS_4x12_URSTCON_HOST_PHY;
break;
};
@@ -256,18 +265,22 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
{
struct samsung_usb2_phy_driver *drv = inst->drv;
+ struct samsung_usb2_phy_instance *device =
+ &drv->instances[EXYNOS4x12_DEVICE];
- inst->enabled = 1;
+ inst->enabled++;
exynos4x12_setup_clk(inst);
exynos4x12_phy_pwr(inst, 1);
exynos4x12_isol(inst, 0);
/* Power on the device, as it is necessary for HSIC to work */
- if (inst->cfg->id == EXYNOS4x12_HSIC0) {
- struct samsung_usb2_phy_instance *device =
- &drv->instances[EXYNOS4x12_DEVICE];
- exynos4x12_phy_pwr(device, 1);
- exynos4x12_isol(device, 0);
+ if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+ inst->cfg->id == EXYNOS4x12_HSIC1) {
+ if (!device->enabled) {
+ exynos4x12_phy_pwr(device, 1);
+ exynos4x12_isol(device, 0);
+ }
+ device->enabled++;
}
return 0;
@@ -279,13 +292,20 @@ static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
struct samsung_usb2_phy_instance *device =
&drv->instances[EXYNOS4x12_DEVICE];
- inst->enabled = 0;
+ inst->enabled--;
+ if (inst->enabled)
+ return 0;
+
exynos4x12_isol(inst, 1);
exynos4x12_phy_pwr(inst, 0);
- if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) {
- exynos4x12_isol(device, 1);
- exynos4x12_phy_pwr(device, 0);
+ if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+ inst->cfg->id == EXYNOS4x12_HSIC1) {
+ device->enabled--;
+ if (!device->enabled) {
+ exynos4x12_isol(device, 1);
+ exynos4x12_phy_pwr(device, 0);
+ }
}
return 0;
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 51a16016a21..848744ab8f3 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -29,7 +29,7 @@ struct samsung_usb2_phy_instance {
const struct samsung_usb2_common_phy *cfg;
struct phy *phy;
struct samsung_usb2_phy_driver *drv;
- bool enabled;
+ int enabled;
};
struct samsung_usb2_phy_driver {