1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
20b56e9a7SVivek Gautam /*
30b56e9a7SVivek Gautam * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support
40b56e9a7SVivek Gautam *
50b56e9a7SVivek Gautam * Copyright (C) 2013 Samsung Electronics Co., Ltd.
60b56e9a7SVivek Gautam * Author: Kamil Debski <k.debski@samsung.com>
70b56e9a7SVivek Gautam */
80b56e9a7SVivek Gautam
90b56e9a7SVivek Gautam #include <linux/delay.h>
100b56e9a7SVivek Gautam #include <linux/io.h>
110b56e9a7SVivek Gautam #include <linux/phy/phy.h>
120b56e9a7SVivek Gautam #include <linux/regmap.h>
130b56e9a7SVivek Gautam #include "phy-samsung-usb2.h"
140b56e9a7SVivek Gautam
150b56e9a7SVivek Gautam /* Exynos USB PHY registers */
160b56e9a7SVivek Gautam #define EXYNOS_5250_REFCLKSEL_CRYSTAL 0x0
170b56e9a7SVivek Gautam #define EXYNOS_5250_REFCLKSEL_XO 0x1
180b56e9a7SVivek Gautam #define EXYNOS_5250_REFCLKSEL_CLKCORE 0x2
190b56e9a7SVivek Gautam
200b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_9MHZ6 0x0
210b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_10MHZ 0x1
220b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_12MHZ 0x2
230b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_19MHZ2 0x3
240b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_20MHZ 0x4
250b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_24MHZ 0x5
260b56e9a7SVivek Gautam #define EXYNOS_5250_FSEL_50MHZ 0x7
270b56e9a7SVivek Gautam
280b56e9a7SVivek Gautam /* Normal host */
290b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0 0x0
300b56e9a7SVivek Gautam
310b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL BIT(31)
320b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT 19
330b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK \
340b56e9a7SVivek Gautam (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT)
350b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT 16
360b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \
370b56e9a7SVivek Gautam (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT)
380b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN BIT(11)
390b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE BIT(10)
400b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N BIT(9)
410b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK (0x3 << 7)
420b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL (0x0 << 7)
430b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0 (0x1 << 7)
440b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST (0x2 << 7)
450b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ BIT(6)
460b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP BIT(5)
470b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND BIT(4)
480b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE BIT(3)
490b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST BIT(2)
500b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST BIT(1)
510b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST BIT(0)
520b56e9a7SVivek Gautam
530b56e9a7SVivek Gautam /* HSIC0 & HSIC1 */
540b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRL1 0x10
550b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRL2 0x20
560b56e9a7SVivek Gautam
570b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK (0x3 << 23)
580b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT (0x2 << 23)
590b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK (0x7f << 16)
600b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 (0x24 << 16)
610b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15 (0x1c << 16)
620b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16 (0x1a << 16)
630b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2 (0x15 << 16)
640b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20 (0x14 << 16)
650b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_SIDDQ BIT(6)
660b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP BIT(5)
670b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND BIT(4)
680b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE BIT(3)
690b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST BIT(2)
700b56e9a7SVivek Gautam #define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST BIT(0)
710b56e9a7SVivek Gautam
720b56e9a7SVivek Gautam /* EHCI control */
730b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL 0x30
740b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN BIT(29)
750b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 BIT(28)
760b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 BIT(27)
770b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16 BIT(26)
780b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN BIT(25)
790b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT 19
800b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
810b56e9a7SVivek Gautam (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
820b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT 13
830b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK \
840b56e9a7SVivek Gautam (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT)
850b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT 7
860b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
870b56e9a7SVivek Gautam (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
880b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT 1
890b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \
900b56e9a7SVivek Gautam (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT)
910b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE BIT(0)
920b56e9a7SVivek Gautam
930b56e9a7SVivek Gautam /* OHCI control */
940b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTOHCICTRL 0x34
950b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT 1
960b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \
970b56e9a7SVivek Gautam (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT)
980b56e9a7SVivek Gautam #define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN BIT(0)
990b56e9a7SVivek Gautam
1000b56e9a7SVivek Gautam /* USBOTG */
1010b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS 0x38
1020b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET BIT(14)
1030b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG BIT(13)
1040b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_PHY_SW_RST BIT(12)
1050b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT 9
1060b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \
1070b56e9a7SVivek Gautam (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT)
1080b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_ID_PULLUP BIT(8)
1090b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_COMMON_ON BIT(7)
1100b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT 4
1110b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_FSEL_MASK \
1120b56e9a7SVivek Gautam (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT)
1130b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP BIT(3)
1140b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_OTGDISABLE BIT(2)
1150b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG BIT(1)
1160b56e9a7SVivek Gautam #define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND BIT(0)
1170b56e9a7SVivek Gautam
1180b56e9a7SVivek Gautam /* Isolation, configured in the power management unit */
1190b56e9a7SVivek Gautam #define EXYNOS_5250_USB_ISOL_OTG_OFFSET 0x704
1200b56e9a7SVivek Gautam #define EXYNOS_5250_USB_ISOL_HOST_OFFSET 0x708
121*81b534f7SMarek Szyprowski #define EXYNOS_5420_USB_ISOL_HOST_OFFSET 0x70C
122*81b534f7SMarek Szyprowski #define EXYNOS_5250_USB_ISOL_ENABLE BIT(0)
1230b56e9a7SVivek Gautam
1240b56e9a7SVivek Gautam /* Mode swtich register */
1250b56e9a7SVivek Gautam #define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230
1260b56e9a7SVivek Gautam #define EXYNOS_5250_MODE_SWITCH_MASK 1
1270b56e9a7SVivek Gautam #define EXYNOS_5250_MODE_SWITCH_DEVICE 0
1280b56e9a7SVivek Gautam #define EXYNOS_5250_MODE_SWITCH_HOST 1
1290b56e9a7SVivek Gautam
1300b56e9a7SVivek Gautam enum exynos4x12_phy_id {
1310b56e9a7SVivek Gautam EXYNOS5250_DEVICE,
1320b56e9a7SVivek Gautam EXYNOS5250_HOST,
1330b56e9a7SVivek Gautam EXYNOS5250_HSIC0,
1340b56e9a7SVivek Gautam EXYNOS5250_HSIC1,
1350b56e9a7SVivek Gautam };
1360b56e9a7SVivek Gautam
1370b56e9a7SVivek Gautam /*
1380b56e9a7SVivek Gautam * exynos5250_rate_to_clk() converts the supplied clock rate to the value that
1390b56e9a7SVivek Gautam * can be written to the phy register.
1400b56e9a7SVivek Gautam */
exynos5250_rate_to_clk(unsigned long rate,u32 * reg)1410b56e9a7SVivek Gautam static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg)
1420b56e9a7SVivek Gautam {
1430b56e9a7SVivek Gautam /* EXYNOS_5250_FSEL_MASK */
1440b56e9a7SVivek Gautam
1450b56e9a7SVivek Gautam switch (rate) {
1460b56e9a7SVivek Gautam case 9600 * KHZ:
1470b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_9MHZ6;
1480b56e9a7SVivek Gautam break;
1490b56e9a7SVivek Gautam case 10 * MHZ:
1500b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_10MHZ;
1510b56e9a7SVivek Gautam break;
1520b56e9a7SVivek Gautam case 12 * MHZ:
1530b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_12MHZ;
1540b56e9a7SVivek Gautam break;
1550b56e9a7SVivek Gautam case 19200 * KHZ:
1560b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_19MHZ2;
1570b56e9a7SVivek Gautam break;
1580b56e9a7SVivek Gautam case 20 * MHZ:
1590b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_20MHZ;
1600b56e9a7SVivek Gautam break;
1610b56e9a7SVivek Gautam case 24 * MHZ:
1620b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_24MHZ;
1630b56e9a7SVivek Gautam break;
1640b56e9a7SVivek Gautam case 50 * MHZ:
1650b56e9a7SVivek Gautam *reg = EXYNOS_5250_FSEL_50MHZ;
1660b56e9a7SVivek Gautam break;
1670b56e9a7SVivek Gautam default:
1680b56e9a7SVivek Gautam return -EINVAL;
1690b56e9a7SVivek Gautam }
1700b56e9a7SVivek Gautam
1710b56e9a7SVivek Gautam return 0;
1720b56e9a7SVivek Gautam }
1730b56e9a7SVivek Gautam
exynos5250_isol(struct samsung_usb2_phy_instance * inst,bool on)1740b56e9a7SVivek Gautam static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
1750b56e9a7SVivek Gautam {
1760b56e9a7SVivek Gautam struct samsung_usb2_phy_driver *drv = inst->drv;
1770b56e9a7SVivek Gautam u32 offset;
178*81b534f7SMarek Szyprowski u32 mask = EXYNOS_5250_USB_ISOL_ENABLE;
1790b56e9a7SVivek Gautam
180*81b534f7SMarek Szyprowski if (drv->cfg == &exynos5250_usb2_phy_config &&
181*81b534f7SMarek Szyprowski inst->cfg->id == EXYNOS5250_DEVICE)
1820b56e9a7SVivek Gautam offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
183*81b534f7SMarek Szyprowski else if (drv->cfg == &exynos5250_usb2_phy_config &&
184*81b534f7SMarek Szyprowski inst->cfg->id == EXYNOS5250_HOST)
1850b56e9a7SVivek Gautam offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
186*81b534f7SMarek Szyprowski else if (drv->cfg == &exynos5420_usb2_phy_config &&
187*81b534f7SMarek Szyprowski inst->cfg->id == EXYNOS5250_HOST)
188*81b534f7SMarek Szyprowski offset = EXYNOS_5420_USB_ISOL_HOST_OFFSET;
189*81b534f7SMarek Szyprowski else
1900b56e9a7SVivek Gautam return;
1910b56e9a7SVivek Gautam
1920b56e9a7SVivek Gautam regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
1930b56e9a7SVivek Gautam }
1940b56e9a7SVivek Gautam
exynos5250_power_on(struct samsung_usb2_phy_instance * inst)1950b56e9a7SVivek Gautam static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
1960b56e9a7SVivek Gautam {
1970b56e9a7SVivek Gautam struct samsung_usb2_phy_driver *drv = inst->drv;
1980b56e9a7SVivek Gautam u32 ctrl0;
1990b56e9a7SVivek Gautam u32 otg;
2000b56e9a7SVivek Gautam u32 ehci;
2010b56e9a7SVivek Gautam u32 ohci;
2020b56e9a7SVivek Gautam u32 hsic;
2030b56e9a7SVivek Gautam
2040b56e9a7SVivek Gautam switch (inst->cfg->id) {
2050b56e9a7SVivek Gautam case EXYNOS5250_DEVICE:
2060b56e9a7SVivek Gautam regmap_update_bits(drv->reg_sys,
2070b56e9a7SVivek Gautam EXYNOS_5250_MODE_SWITCH_OFFSET,
2080b56e9a7SVivek Gautam EXYNOS_5250_MODE_SWITCH_MASK,
2090b56e9a7SVivek Gautam EXYNOS_5250_MODE_SWITCH_DEVICE);
2100b56e9a7SVivek Gautam
2110b56e9a7SVivek Gautam /* OTG configuration */
2120b56e9a7SVivek Gautam otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
2130b56e9a7SVivek Gautam /* The clock */
2140b56e9a7SVivek Gautam otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
2150b56e9a7SVivek Gautam otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
2160b56e9a7SVivek Gautam /* Reset */
2170b56e9a7SVivek Gautam otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
2180b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
2190b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
2200b56e9a7SVivek Gautam otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
2210b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
2220b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
2230b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_OTGDISABLE;
2240b56e9a7SVivek Gautam /* Ref clock */
2250b56e9a7SVivek Gautam otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
2260b56e9a7SVivek Gautam otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<
2270b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
2280b56e9a7SVivek Gautam writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
2290b56e9a7SVivek Gautam udelay(100);
2300b56e9a7SVivek Gautam otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
2310b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
2320b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
2330b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_OTGDISABLE);
2340b56e9a7SVivek Gautam writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
2350b56e9a7SVivek Gautam
2360b56e9a7SVivek Gautam
2370b56e9a7SVivek Gautam break;
2380b56e9a7SVivek Gautam case EXYNOS5250_HOST:
2390b56e9a7SVivek Gautam case EXYNOS5250_HSIC0:
2400b56e9a7SVivek Gautam case EXYNOS5250_HSIC1:
2410b56e9a7SVivek Gautam /* Host registers configuration */
2420b56e9a7SVivek Gautam ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
2430b56e9a7SVivek Gautam /* The clock */
2440b56e9a7SVivek Gautam ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK;
2450b56e9a7SVivek Gautam ctrl0 |= drv->ref_reg_val <<
2460b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT;
2470b56e9a7SVivek Gautam
2480b56e9a7SVivek Gautam /* Reset */
2490b56e9a7SVivek Gautam ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
2500b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL |
2510b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
2520b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
2530b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP);
2540b56e9a7SVivek Gautam ctrl0 |= EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
2550b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST |
2560b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N;
2570b56e9a7SVivek Gautam writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
2580b56e9a7SVivek Gautam udelay(10);
2590b56e9a7SVivek Gautam ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
2600b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST);
2610b56e9a7SVivek Gautam writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
2620b56e9a7SVivek Gautam
2630b56e9a7SVivek Gautam /* OTG configuration */
2640b56e9a7SVivek Gautam otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
2650b56e9a7SVivek Gautam /* The clock */
2660b56e9a7SVivek Gautam otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
2670b56e9a7SVivek Gautam otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
2680b56e9a7SVivek Gautam /* Reset */
2690b56e9a7SVivek Gautam otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
2700b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
2710b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
2720b56e9a7SVivek Gautam otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
2730b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
2740b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
2750b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_OTGDISABLE;
2760b56e9a7SVivek Gautam /* Ref clock */
2770b56e9a7SVivek Gautam otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
2780b56e9a7SVivek Gautam otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<
2790b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
2800b56e9a7SVivek Gautam writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
2810b56e9a7SVivek Gautam udelay(10);
2820b56e9a7SVivek Gautam otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
2830b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
2840b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET);
2850b56e9a7SVivek Gautam
2860b56e9a7SVivek Gautam /* HSIC phy configuration */
2870b56e9a7SVivek Gautam hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
2880b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
2890b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_PHYSWRST);
2900b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
2910b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
2920b56e9a7SVivek Gautam udelay(10);
2930b56e9a7SVivek Gautam hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST;
2940b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
2950b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
2960b56e9a7SVivek Gautam /* The following delay is necessary for the reset sequence to be
2970b56e9a7SVivek Gautam * completed */
2980b56e9a7SVivek Gautam udelay(80);
2990b56e9a7SVivek Gautam
3000b56e9a7SVivek Gautam /* Enable EHCI DMA burst */
3010b56e9a7SVivek Gautam ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
3020b56e9a7SVivek Gautam ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN |
3030b56e9a7SVivek Gautam EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 |
3040b56e9a7SVivek Gautam EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 |
3050b56e9a7SVivek Gautam EXYNOS_5250_HOSTEHCICTRL_ENAINCR16;
3060b56e9a7SVivek Gautam writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
3070b56e9a7SVivek Gautam
3080b56e9a7SVivek Gautam /* OHCI settings */
3090b56e9a7SVivek Gautam ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
3100b56e9a7SVivek Gautam /* Following code is based on the old driver */
3110b56e9a7SVivek Gautam ohci |= 0x1 << 3;
3120b56e9a7SVivek Gautam writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
3130b56e9a7SVivek Gautam
3140b56e9a7SVivek Gautam break;
3150b56e9a7SVivek Gautam }
3160b56e9a7SVivek Gautam exynos5250_isol(inst, 0);
3170b56e9a7SVivek Gautam
3180b56e9a7SVivek Gautam return 0;
3190b56e9a7SVivek Gautam }
3200b56e9a7SVivek Gautam
exynos5250_power_off(struct samsung_usb2_phy_instance * inst)3210b56e9a7SVivek Gautam static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
3220b56e9a7SVivek Gautam {
3230b56e9a7SVivek Gautam struct samsung_usb2_phy_driver *drv = inst->drv;
3240b56e9a7SVivek Gautam u32 ctrl0;
3250b56e9a7SVivek Gautam u32 otg;
3260b56e9a7SVivek Gautam u32 hsic;
3270b56e9a7SVivek Gautam
3280b56e9a7SVivek Gautam exynos5250_isol(inst, 1);
3290b56e9a7SVivek Gautam
3300b56e9a7SVivek Gautam switch (inst->cfg->id) {
3310b56e9a7SVivek Gautam case EXYNOS5250_DEVICE:
3320b56e9a7SVivek Gautam otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
3330b56e9a7SVivek Gautam otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
3340b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG |
3350b56e9a7SVivek Gautam EXYNOS_5250_USBOTGSYS_FORCE_SLEEP);
3360b56e9a7SVivek Gautam writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
3370b56e9a7SVivek Gautam break;
3380b56e9a7SVivek Gautam case EXYNOS5250_HOST:
3390b56e9a7SVivek Gautam ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
3400b56e9a7SVivek Gautam ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
3410b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
3420b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP |
3430b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
3440b56e9a7SVivek Gautam EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL);
3450b56e9a7SVivek Gautam writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
3460b56e9a7SVivek Gautam break;
3470b56e9a7SVivek Gautam case EXYNOS5250_HSIC0:
3480b56e9a7SVivek Gautam case EXYNOS5250_HSIC1:
3490b56e9a7SVivek Gautam hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
3500b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
3510b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_SIDDQ |
3520b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP |
3530b56e9a7SVivek Gautam EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND
3540b56e9a7SVivek Gautam );
3550b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
3560b56e9a7SVivek Gautam writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
3570b56e9a7SVivek Gautam break;
3580b56e9a7SVivek Gautam }
3590b56e9a7SVivek Gautam
3600b56e9a7SVivek Gautam return 0;
3610b56e9a7SVivek Gautam }
3620b56e9a7SVivek Gautam
3630b56e9a7SVivek Gautam
3640b56e9a7SVivek Gautam static const struct samsung_usb2_common_phy exynos5250_phys[] = {
3650b56e9a7SVivek Gautam {
3660b56e9a7SVivek Gautam .label = "device",
3670b56e9a7SVivek Gautam .id = EXYNOS5250_DEVICE,
3680b56e9a7SVivek Gautam .power_on = exynos5250_power_on,
3690b56e9a7SVivek Gautam .power_off = exynos5250_power_off,
3700b56e9a7SVivek Gautam },
3710b56e9a7SVivek Gautam {
3720b56e9a7SVivek Gautam .label = "host",
3730b56e9a7SVivek Gautam .id = EXYNOS5250_HOST,
3740b56e9a7SVivek Gautam .power_on = exynos5250_power_on,
3750b56e9a7SVivek Gautam .power_off = exynos5250_power_off,
3760b56e9a7SVivek Gautam },
3770b56e9a7SVivek Gautam {
3780b56e9a7SVivek Gautam .label = "hsic0",
3790b56e9a7SVivek Gautam .id = EXYNOS5250_HSIC0,
3800b56e9a7SVivek Gautam .power_on = exynos5250_power_on,
3810b56e9a7SVivek Gautam .power_off = exynos5250_power_off,
3820b56e9a7SVivek Gautam },
3830b56e9a7SVivek Gautam {
3840b56e9a7SVivek Gautam .label = "hsic1",
3850b56e9a7SVivek Gautam .id = EXYNOS5250_HSIC1,
3860b56e9a7SVivek Gautam .power_on = exynos5250_power_on,
3870b56e9a7SVivek Gautam .power_off = exynos5250_power_off,
3880b56e9a7SVivek Gautam },
3890b56e9a7SVivek Gautam };
3900b56e9a7SVivek Gautam
391*81b534f7SMarek Szyprowski static const struct samsung_usb2_common_phy exynos5420_phys[] = {
392*81b534f7SMarek Szyprowski {
393*81b534f7SMarek Szyprowski .label = "host",
394*81b534f7SMarek Szyprowski .id = EXYNOS5250_HOST,
395*81b534f7SMarek Szyprowski .power_on = exynos5250_power_on,
396*81b534f7SMarek Szyprowski .power_off = exynos5250_power_off,
397*81b534f7SMarek Szyprowski },
398*81b534f7SMarek Szyprowski {
399*81b534f7SMarek Szyprowski .label = "hsic",
400*81b534f7SMarek Szyprowski .id = EXYNOS5250_HSIC0,
401*81b534f7SMarek Szyprowski .power_on = exynos5250_power_on,
402*81b534f7SMarek Szyprowski .power_off = exynos5250_power_off,
403*81b534f7SMarek Szyprowski },
404*81b534f7SMarek Szyprowski };
405*81b534f7SMarek Szyprowski
4060b56e9a7SVivek Gautam const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {
4070b56e9a7SVivek Gautam .has_mode_switch = 1,
408*81b534f7SMarek Szyprowski .num_phys = ARRAY_SIZE(exynos5250_phys),
4090b56e9a7SVivek Gautam .phys = exynos5250_phys,
4100b56e9a7SVivek Gautam .rate_to_clk = exynos5250_rate_to_clk,
4110b56e9a7SVivek Gautam };
412*81b534f7SMarek Szyprowski
413*81b534f7SMarek Szyprowski const struct samsung_usb2_phy_config exynos5420_usb2_phy_config = {
414*81b534f7SMarek Szyprowski .has_mode_switch = 1,
415*81b534f7SMarek Szyprowski .num_phys = ARRAY_SIZE(exynos5420_phys),
416*81b534f7SMarek Szyprowski .phys = exynos5420_phys,
417*81b534f7SMarek Szyprowski .rate_to_clk = exynos5250_rate_to_clk,
418*81b534f7SMarek Szyprowski };
419