summaryrefslogtreecommitdiff
path: root/drivers/phy/phy-exynos4x12-usb2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/phy/phy-exynos4x12-usb2.c')
-rw-r--r--drivers/phy/phy-exynos4x12-usb2.c48
1 files changed, 34 insertions, 14 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;