Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Samsung Exynos5 SoC series USB DRD PHY driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Copyright (C) 2014 Samsung Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Author: Vivek Gautam <gautam.vivek@samsung.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/iopoll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/phy/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/regulator/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/soc/samsung/exynos-regs-pmu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) /* Exynos USB PHY registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define EXYNOS5_FSEL_9MHZ6		0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define EXYNOS5_FSEL_10MHZ		0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define EXYNOS5_FSEL_12MHZ		0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define EXYNOS5_FSEL_19MHZ2		0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define EXYNOS5_FSEL_20MHZ		0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define EXYNOS5_FSEL_24MHZ		0x5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define EXYNOS5_FSEL_50MHZ		0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) /* Exynos5: USB 3.0 DRD PHY registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define EXYNOS5_DRD_LINKSYSTEM			0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define LINKSYSTEM_FLADJ_MASK			(0x3f << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define LINKSYSTEM_FLADJ(_x)			((_x) << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define LINKSYSTEM_XHCI_VERSION_CONTROL		BIT(27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define EXYNOS5_DRD_PHYUTMI			0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define PHYUTMI_OTGDISABLE			BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define PHYUTMI_FORCESUSPEND			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define PHYUTMI_FORCESLEEP			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #define EXYNOS5_DRD_PHYPIPE			0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define EXYNOS5_DRD_PHYCLKRST			0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) #define PHYCLKRST_EN_UTMISUSPEND		BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #define PHYCLKRST_SSC_REFCLKSEL_MASK		(0xff << 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) #define PHYCLKRST_SSC_REFCLKSEL(_x)		((_x) << 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) #define PHYCLKRST_SSC_RANGE_MASK		(0x03 << 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) #define PHYCLKRST_SSC_RANGE(_x)			((_x) << 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) #define PHYCLKRST_SSC_EN			BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) #define PHYCLKRST_REF_SSP_EN			BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) #define PHYCLKRST_REF_CLKDIV2			BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) #define PHYCLKRST_MPLL_MULTIPLIER_MASK		(0x7f << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) #define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF	(0x19 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) #define PHYCLKRST_MPLL_MULTIPLIER_50M_REF	(0x32 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) #define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF	(0x68 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) #define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF	(0x7d << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) #define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF	(0x02 << 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) #define PHYCLKRST_FSEL_UTMI_MASK		(0x7 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) #define PHYCLKRST_FSEL_PIPE_MASK		(0x7 << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) #define PHYCLKRST_FSEL(_x)			((_x) << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #define PHYCLKRST_FSEL_PAD_100MHZ		(0x27 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) #define PHYCLKRST_FSEL_PAD_24MHZ		(0x2a << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) #define PHYCLKRST_FSEL_PAD_20MHZ		(0x31 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) #define PHYCLKRST_FSEL_PAD_19_2MHZ		(0x38 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) #define PHYCLKRST_RETENABLEN			BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) #define PHYCLKRST_REFCLKSEL_MASK		(0x03 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) #define PHYCLKRST_REFCLKSEL_PAD_REFCLK		(0x2 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) #define PHYCLKRST_REFCLKSEL_EXT_REFCLK		(0x3 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) #define PHYCLKRST_PORTRESET			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) #define PHYCLKRST_COMMONONN			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) #define EXYNOS5_DRD_PHYREG0			0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) #define PHYREG0_SSC_REF_CLK_SEL			BIT(21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) #define PHYREG0_SSC_RANGE			BIT(20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) #define PHYREG0_CR_WRITE			BIT(19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) #define PHYREG0_CR_READ				BIT(18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) #define PHYREG0_CR_DATA_IN(_x)			((_x) << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) #define PHYREG0_CR_CAP_DATA			BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) #define PHYREG0_CR_CAP_ADDR			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) #define EXYNOS5_DRD_PHYREG1			0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define PHYREG1_CR_DATA_OUT(_x)			((_x) << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define PHYREG1_CR_ACK				BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define EXYNOS5_DRD_PHYPARAM0			0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define PHYPARAM0_REF_USE_PAD			BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define PHYPARAM0_REF_LOSLEVEL_MASK		(0x1f << 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define PHYPARAM0_REF_LOSLEVEL			(0x9 << 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define EXYNOS5_DRD_PHYPARAM1			0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define PHYPARAM1_PCS_TXDEEMPH_MASK		(0x1f << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #define PHYPARAM1_PCS_TXDEEMPH			(0x1c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #define EXYNOS5_DRD_PHYTERM			0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #define EXYNOS5_DRD_PHYTEST			0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define PHYTEST_POWERDOWN_SSP			BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define PHYTEST_POWERDOWN_HSP			BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define EXYNOS5_DRD_PHYADP			0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define EXYNOS5_DRD_PHYUTMICLKSEL		0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define PHYUTMICLKSEL_UTMI_CLKSEL		BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #define EXYNOS5_DRD_PHYRESUME			0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define EXYNOS5_DRD_LINKPORT			0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN		(0x15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define LOSLEVEL_OVRD_IN_LOS_BIAS_5420			(0x5 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT		(0x0 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define LOSLEVEL_OVRD_IN_EN				(0x1 << 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT		(0x9 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN	(0x12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420		(0x5 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT		(0x4 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG		(0x1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M		(0x4 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M		(0x8 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M		(0x8 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M	(0x20 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5		(0x20 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M		(0x40 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define KHZ	1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) #define MHZ	(KHZ * KHZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) enum exynos5_usbdrd_phy_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	EXYNOS5_DRDPHY_UTMI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	EXYNOS5_DRDPHY_PIPE3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	EXYNOS5_DRDPHYS_NUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct phy_usb_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct exynos5_usbdrd_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct exynos5_usbdrd_phy_config {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	u32 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	unsigned int (*set_refclk)(struct phy_usb_instance *inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct exynos5_usbdrd_phy_drvdata {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	const struct exynos5_usbdrd_phy_config *phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	u32 pmu_offset_usbdrd0_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	u32 pmu_offset_usbdrd1_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	bool has_common_clk_gate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)  * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)  * @dev: pointer to device instance of this platform device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)  * @reg_phy: usb phy controller register memory base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)  * @clk: phy clock for register access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  * @pipeclk: clock for pipe3 phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)  * @utmiclk: clock for utmi+ phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)  * @itpclk: clock for ITP generation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)  * @drv_data: pointer to SoC level driver data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * @phys: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  *	    instances each with its 'phy' and 'phy_cfg'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * @extrefclk: frequency select settings when using 'separate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  *	       reference clocks' for SS and HS operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  * @ref_clk: reference clock to PHY block from which PHY's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  *	     operational clocks are derived
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)  * @vbus: VBUS regulator for phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)  * @vbus_boost: Boost regulator for VBUS present on few Exynos boards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct exynos5_usbdrd_phy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	void __iomem *reg_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	struct clk *pipeclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	struct clk *utmiclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	struct clk *itpclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	const struct exynos5_usbdrd_phy_drvdata *drv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	struct phy_usb_instance {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		struct phy *phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		u32 index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		struct regmap *reg_pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		u32 pmu_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		const struct exynos5_usbdrd_phy_config *phy_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	} phys[EXYNOS5_DRDPHYS_NUM];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	u32 extrefclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	struct clk *ref_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	struct regulator *vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	struct regulator *vbus_boost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	return container_of((inst), struct exynos5_usbdrd_phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			    phys[(inst)->index]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  * exynos5_rate_to_clk() converts the supplied clock rate to the value that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  * can be written to the phy register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	/* EXYNOS5_FSEL_MASK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	case 9600 * KHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		*reg = EXYNOS5_FSEL_9MHZ6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	case 10 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		*reg = EXYNOS5_FSEL_10MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	case 12 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		*reg = EXYNOS5_FSEL_12MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	case 19200 * KHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		*reg = EXYNOS5_FSEL_19MHZ2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	case 20 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 		*reg = EXYNOS5_FSEL_20MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	case 24 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		*reg = EXYNOS5_FSEL_24MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	case 50 * MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		*reg = EXYNOS5_FSEL_50MHZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 						unsigned int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	if (!inst->reg_pmu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	val = on ? 0 : EXYNOS4_PHY_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			   EXYNOS4_PHY_ENABLE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)  * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)  * from clock core. Further sets multiplier values and spread spectrum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)  * clock settings for SuperSpeed operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	/* restore any previous reference clock settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	/* Use EXTREFCLK as ref clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	reg &= ~PHYCLKRST_REFCLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	/* FSEL settings corresponding to reference clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		PHYCLKRST_MPLL_MULTIPLIER_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		PHYCLKRST_SSC_REFCLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	switch (phy_drd->extrefclk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	case EXYNOS5_FSEL_50MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 			PHYCLKRST_SSC_REFCLKSEL(0x00));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	case EXYNOS5_FSEL_24MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 			PHYCLKRST_SSC_REFCLKSEL(0x88));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	case EXYNOS5_FSEL_20MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 			PHYCLKRST_SSC_REFCLKSEL(0x00));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	case EXYNOS5_FSEL_19MHZ2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 			PHYCLKRST_SSC_REFCLKSEL(0x88));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		dev_dbg(phy_drd->dev, "unsupported ref clk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)  * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)  * from clock core. Further sets the FSEL values for HighSpeed operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	/* restore any previous reference clock settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	reg &= ~PHYCLKRST_REFCLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		PHYCLKRST_MPLL_MULTIPLIER_MASK |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		PHYCLKRST_SSC_REFCLKSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	/* Set Tx De-Emphasis level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	reg |=	PHYPARAM1_PCS_TXDEEMPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	reg &= ~PHYTEST_POWERDOWN_SSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	/* Set Loss-of-Signal Detector sensitivity */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	reg |=	PHYPARAM0_REF_LOSLEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	/* Set Tx De-Emphasis level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	reg |=	PHYPARAM1_PCS_TXDEEMPH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	/* UTMI Power Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	reg &= ~PHYTEST_POWERDOWN_HSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static int exynos5_usbdrd_phy_init(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	ret = clk_prepare_enable(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	/* Reset USB 3.0 PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	 * Setting the Frame length Adj value[6:1] to default 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	 * See xHCI 1.0 spec, 5.2.4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	reg =	LINKSYSTEM_XHCI_VERSION_CONTROL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 		LINKSYSTEM_FLADJ(0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	/* Select PHY CLK source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	reg &= ~PHYPARAM0_REF_USE_PAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	/* This bit must be set for both HS and SS operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	reg |= PHYUTMICLKSEL_UTMI_CLKSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	/* UTMI or PIPE3 specific init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	inst->phy_cfg->phy_init(phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	/* reference clock settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	reg = inst->phy_cfg->set_refclk(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 		/* Digital power supply in normal operating mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	reg |=	PHYCLKRST_RETENABLEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 		/* Enable ref clock for SS function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 		PHYCLKRST_REF_SSP_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 		/* Enable spread spectrum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		PHYCLKRST_SSC_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		/* Power down HS Bias and PLL blocks in suspend mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 		PHYCLKRST_COMMONONN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		/* Reset the port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		PHYCLKRST_PORTRESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	reg &= ~PHYCLKRST_PORTRESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	clk_disable_unprepare(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) static int exynos5_usbdrd_phy_exit(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	ret = clk_prepare_enable(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	reg =	PHYUTMI_OTGDISABLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 		PHYUTMI_FORCESUSPEND |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 		PHYUTMI_FORCESLEEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	/* Resetting the PHYCLKRST enable bits to reduce leakage current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	reg &= ~(PHYCLKRST_REF_SSP_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		 PHYCLKRST_SSC_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 		 PHYCLKRST_COMMONONN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	/* Control PHYTEST to remove leakage current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	reg |=	PHYTEST_POWERDOWN_SSP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		PHYTEST_POWERDOWN_HSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 	clk_disable_unprepare(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static int exynos5_usbdrd_phy_power_on(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 	clk_prepare_enable(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	if (!phy_drd->drv_data->has_common_clk_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		clk_prepare_enable(phy_drd->pipeclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		clk_prepare_enable(phy_drd->utmiclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		clk_prepare_enable(phy_drd->itpclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	/* Enable VBUS supply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	if (phy_drd->vbus_boost) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		ret = regulator_enable(phy_drd->vbus_boost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 			dev_err(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 				"Failed to enable VBUS boost supply\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 			goto fail_vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	if (phy_drd->vbus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		ret = regulator_enable(phy_drd->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 			dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 			goto fail_vbus_boost;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	/* Power-on PHY*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	inst->phy_cfg->phy_isol(inst, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) fail_vbus_boost:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 	if (phy_drd->vbus_boost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		regulator_disable(phy_drd->vbus_boost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) fail_vbus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	clk_disable_unprepare(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	if (!phy_drd->drv_data->has_common_clk_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 		clk_disable_unprepare(phy_drd->itpclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		clk_disable_unprepare(phy_drd->utmiclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		clk_disable_unprepare(phy_drd->pipeclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) static int exynos5_usbdrd_phy_power_off(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	/* Power-off the PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	inst->phy_cfg->phy_isol(inst, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	/* Disable VBUS supply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 	if (phy_drd->vbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		regulator_disable(phy_drd->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	if (phy_drd->vbus_boost)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		regulator_disable(phy_drd->vbus_boost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	clk_disable_unprepare(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	if (!phy_drd->drv_data->has_common_clk_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		clk_disable_unprepare(phy_drd->itpclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		clk_disable_unprepare(phy_drd->pipeclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		clk_disable_unprepare(phy_drd->utmiclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 			    u32 val, u32 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	unsigned int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 				 result, (result & PHYREG1_CR_ACK), 1, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	if (err == -ETIMEDOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 		dev_err(phy_drd->dev, "CRPORT handshake timeout1 (0x%08x)\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 				 result, !(result & PHYREG1_CR_ACK), 1, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	if (err == -ETIMEDOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 		dev_err(phy_drd->dev, "CRPORT handshake timeout2 (0x%08x)\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 			     u32 addr, u32 data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	/* Write Address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 	writel(PHYREG0_CR_DATA_IN(addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	       phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 			       PHYREG0_CR_CAP_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	/* Write Data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	writel(PHYREG0_CR_DATA_IN(data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 	       phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 			       PHYREG0_CR_CAP_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 			       PHYREG0_CR_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)  * Calibrate few PHY parameters using CR_PORT register to meet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)  * SuperSpeed requirements on Exynos5420 and Exynos5800 systems,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)  * which have 28nm USB 3.0 DRD PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	unsigned int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	 * Change los_bias to (0x5) for 28nm PHY from a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	 * default value (0x0); los_level is set as default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	 * (0x9) as also reflected in los_level[30:26] bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	 * of PHYPARAM0 register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 		LOSLEVEL_OVRD_IN_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 		LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	ret = crport_ctrl_write(phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 				EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 				temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		dev_err(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 			"Failed setting Loss-of-Signal level for SuperSpeed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	 * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	 * to raise Tx signal level from its default value of (0x4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	ret = crport_ctrl_write(phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 				EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 				temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 		dev_err(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 			"Failed setting Tx-Vboost-Level for SuperSpeed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	 * Set proper time to wait for RxDetect measurement, for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	 * desired reference clock of PHY, by tuning the CR_PORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	 * register LANE0.TX_DEBUG which is internal to PHY.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	 * This fixes issue with few USB 3.0 devices, which are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	 * not detected (not even generate interrupts on the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	 * on insertion) without this change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	 * e.g. Samsung SUM-TSB16S 3.0 USB drive.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	switch (phy_drd->extrefclk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	case EXYNOS5_FSEL_50MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 	case EXYNOS5_FSEL_20MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 	case EXYNOS5_FSEL_19MHZ2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	case EXYNOS5_FSEL_24MHZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	ret = crport_ctrl_write(phy_drd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 				EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 				temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		dev_err(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 			"Fail to set RxDet measurement time for SuperSpeed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 					struct of_phandle_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 		return ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	return phy_drd->phys[args->args[0]].phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 		return exynos5420_usbdrd_phy_calibrate(phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) static const struct phy_ops exynos5_usbdrd_phy_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	.init		= exynos5_usbdrd_phy_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	.exit		= exynos5_usbdrd_phy_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	.power_on	= exynos5_usbdrd_phy_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	.power_off	= exynos5_usbdrd_phy_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	.calibrate	= exynos5_usbdrd_phy_calibrate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	.owner		= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	unsigned long ref_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 	if (IS_ERR(phy_drd->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 		dev_err(phy_drd->dev, "Failed to get phy clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 		return PTR_ERR(phy_drd->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	if (IS_ERR(phy_drd->ref_clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 		return PTR_ERR(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	ref_rate = clk_get_rate(phy_drd->ref_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 	ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 		dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 			ref_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 	if (!phy_drd->drv_data->has_common_clk_gate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 		phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 		if (IS_ERR(phy_drd->pipeclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 			dev_info(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 				 "PIPE3 phy operational clock not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 			phy_drd->pipeclk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 		phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		if (IS_ERR(phy_drd->utmiclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 			dev_info(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 				 "UTMI phy operational clock not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 			phy_drd->utmiclk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 		phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 		if (IS_ERR(phy_drd->itpclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 			dev_info(phy_drd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 				 "ITP clock from main OSC not specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 			phy_drd->itpclk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 		.id		= EXYNOS5_DRDPHY_UTMI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 		.phy_isol	= exynos5_usbdrd_phy_isol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 		.phy_init	= exynos5_usbdrd_utmi_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 		.set_refclk	= exynos5_usbdrd_utmi_set_refclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 		.id		= EXYNOS5_DRDPHY_PIPE3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 		.phy_isol	= exynos5_usbdrd_phy_isol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 		.phy_init	= exynos5_usbdrd_pipe3_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 		.set_refclk	= exynos5_usbdrd_pipe3_set_refclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 	.phy_cfg		= phy_cfg_exynos5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 	.pmu_offset_usbdrd1_phy	= EXYNOS5420_USBDRD1_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 	.has_common_clk_gate	= true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	.phy_cfg		= phy_cfg_exynos5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 	.has_common_clk_gate	= true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 	.phy_cfg		= phy_cfg_exynos5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	.pmu_offset_usbdrd1_phy	= EXYNOS5433_USBHOST30_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 	.has_common_clk_gate	= false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 	.phy_cfg		= phy_cfg_exynos5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 	.has_common_clk_gate	= false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 		.compatible = "samsung,exynos5250-usbdrd-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 		.data = &exynos5250_usbdrd_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 		.compatible = "samsung,exynos5420-usbdrd-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 		.data = &exynos5420_usbdrd_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 		.compatible = "samsung,exynos5433-usbdrd-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 		.data = &exynos5433_usbdrd_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	}, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 		.compatible = "samsung,exynos7-usbdrd-phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 		.data = &exynos7_usbdrd_phy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 	{ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 	struct device_node *node = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 	struct exynos5_usbdrd_phy *phy_drd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 	struct phy_provider *phy_provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 	struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	const struct exynos5_usbdrd_phy_drvdata *drv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	struct regmap *reg_pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 	u32 pmu_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 	int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 	int channel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 	phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	if (!phy_drd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 	dev_set_drvdata(dev, phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 	phy_drd->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 	phy_drd->reg_phy = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	if (IS_ERR(phy_drd->reg_phy))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 		return PTR_ERR(phy_drd->reg_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 	drv_data = of_device_get_match_data(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 	if (!drv_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	phy_drd->drv_data = drv_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 	ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 		dev_err(dev, "Failed to initialize clocks\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 	reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 						   "samsung,pmu-syscon");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 	if (IS_ERR(reg_pmu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 		dev_err(dev, "Failed to lookup PMU regmap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 		return PTR_ERR(reg_pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	 * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 	 * each having separate power control registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 	 * 'channel' facilitates to set such registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 	channel = of_alias_get_id(node, "usbdrdphy");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 	if (channel < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 		dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 	switch (channel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 		pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 	case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 		pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) 	/* Get Vbus regulators */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) 	phy_drd->vbus = devm_regulator_get(dev, "vbus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) 	if (IS_ERR(phy_drd->vbus)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) 		ret = PTR_ERR(phy_drd->vbus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) 		if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 		dev_warn(dev, "Failed to get VBUS supply regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) 		phy_drd->vbus = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) 	phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 	if (IS_ERR(phy_drd->vbus_boost)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) 		ret = PTR_ERR(phy_drd->vbus_boost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 		if (ret == -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 		dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 		phy_drd->vbus_boost = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) 	dev_vdbg(dev, "Creating usbdrd_phy phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 	for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) 		struct phy *phy = devm_phy_create(dev, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) 						  &exynos5_usbdrd_phy_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 		if (IS_ERR(phy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) 			dev_err(dev, "Failed to create usbdrd_phy phy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) 			return PTR_ERR(phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) 		phy_drd->phys[i].phy = phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 		phy_drd->phys[i].index = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 		phy_drd->phys[i].reg_pmu = reg_pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 		phy_drd->phys[i].pmu_offset = pmu_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) 		phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 		phy_set_drvdata(phy, &phy_drd->phys[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) 	phy_provider = devm_of_phy_provider_register(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 						     exynos5_usbdrd_phy_xlate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 	if (IS_ERR(phy_provider)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 		dev_err(phy_drd->dev, "Failed to register phy provider\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 		return PTR_ERR(phy_provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static struct platform_driver exynos5_usb3drd_phy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) 	.probe	= exynos5_usbdrd_phy_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) 		.of_match_table	= exynos5_usbdrd_phy_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) 		.name		= "exynos5_usb3drd_phy",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) 		.suppress_bind_attrs = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) module_platform_driver(exynos5_usb3drd_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) MODULE_DESCRIPTION("Samsung Exynos5 SoCs USB 3.0 DRD controller PHY driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) MODULE_ALIAS("platform:exynos5_usb3drd_phy");