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