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