brintos

brintos / linux-shallow public Read only

0
0
Text · 53.2 KiB · c421b49 Raw
1811 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Samsung Exynos5 SoC series USB DRD PHY driver4 *5 * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series6 *7 * Copyright (C) 2014 Samsung Electronics Co., Ltd.8 * Author: Vivek Gautam <gautam.vivek@samsung.com>9 */10 11#include <linux/bitfield.h>12#include <linux/clk.h>13#include <linux/delay.h>14#include <linux/io.h>15#include <linux/kernel.h>16#include <linux/module.h>17#include <linux/of.h>18#include <linux/iopoll.h>19#include <linux/phy/phy.h>20#include <linux/platform_device.h>21#include <linux/mutex.h>22#include <linux/mfd/syscon.h>23#include <linux/regmap.h>24#include <linux/regulator/consumer.h>25#include <linux/soc/samsung/exynos-regs-pmu.h>26 27/* Exynos USB PHY registers */28#define EXYNOS5_FSEL_9MHZ6		0x029#define EXYNOS5_FSEL_10MHZ		0x130#define EXYNOS5_FSEL_12MHZ		0x231#define EXYNOS5_FSEL_19MHZ2		0x332#define EXYNOS5_FSEL_20MHZ		0x433#define EXYNOS5_FSEL_24MHZ		0x534#define EXYNOS5_FSEL_26MHZ		0x635#define EXYNOS5_FSEL_50MHZ		0x736 37/* Exynos5: USB 3.0 DRD PHY registers */38#define EXYNOS5_DRD_LINKSYSTEM			0x0439#define LINKSYSTEM_XHCI_VERSION_CONTROL		BIT(27)40#define LINKSYSTEM_FLADJ_MASK			(0x3f << 1)41#define LINKSYSTEM_FLADJ(_x)			((_x) << 1)42 43#define EXYNOS5_DRD_PHYUTMI			0x0844#define PHYUTMI_OTGDISABLE			BIT(6)45#define PHYUTMI_FORCESUSPEND			BIT(1)46#define PHYUTMI_FORCESLEEP			BIT(0)47 48#define EXYNOS5_DRD_PHYPIPE			0x0c49 50#define EXYNOS5_DRD_PHYCLKRST			0x1051#define PHYCLKRST_EN_UTMISUSPEND		BIT(31)52#define PHYCLKRST_SSC_REFCLKSEL_MASK		(0xff << 23)53#define PHYCLKRST_SSC_REFCLKSEL(_x)		((_x) << 23)54#define PHYCLKRST_SSC_RANGE_MASK		(0x03 << 21)55#define PHYCLKRST_SSC_RANGE(_x)			((_x) << 21)56#define PHYCLKRST_SSC_EN			BIT(20)57#define PHYCLKRST_REF_SSP_EN			BIT(19)58#define PHYCLKRST_REF_CLKDIV2			BIT(18)59#define PHYCLKRST_MPLL_MULTIPLIER_MASK		(0x7f << 11)60#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF	(0x19 << 11)61#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF	(0x32 << 11)62#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF	(0x68 << 11)63#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF	(0x7d << 11)64#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF	(0x02 << 11)65#define PHYCLKRST_FSEL_PIPE_MASK		(0x7 << 8)66#define PHYCLKRST_FSEL_UTMI_MASK		(0x7 << 5)67#define PHYCLKRST_FSEL(_x)			((_x) << 5)68#define PHYCLKRST_FSEL_PAD_100MHZ		(0x27 << 5)69#define PHYCLKRST_FSEL_PAD_24MHZ		(0x2a << 5)70#define PHYCLKRST_FSEL_PAD_20MHZ		(0x31 << 5)71#define PHYCLKRST_FSEL_PAD_19_2MHZ		(0x38 << 5)72#define PHYCLKRST_RETENABLEN			BIT(4)73#define PHYCLKRST_REFCLKSEL_MASK		(0x03 << 2)74#define PHYCLKRST_REFCLKSEL_PAD_REFCLK		(0x2 << 2)75#define PHYCLKRST_REFCLKSEL_EXT_REFCLK		(0x3 << 2)76#define PHYCLKRST_PORTRESET			BIT(1)77#define PHYCLKRST_COMMONONN			BIT(0)78 79#define EXYNOS5_DRD_PHYREG0			0x1480#define PHYREG0_SSC_REF_CLK_SEL			BIT(21)81#define PHYREG0_SSC_RANGE			BIT(20)82#define PHYREG0_CR_WRITE			BIT(19)83#define PHYREG0_CR_READ				BIT(18)84#define PHYREG0_CR_DATA_IN(_x)			((_x) << 2)85#define PHYREG0_CR_CAP_DATA			BIT(1)86#define PHYREG0_CR_CAP_ADDR			BIT(0)87 88#define EXYNOS5_DRD_PHYREG1			0x1889#define PHYREG1_CR_DATA_OUT(_x)			((_x) << 1)90#define PHYREG1_CR_ACK				BIT(0)91 92#define EXYNOS5_DRD_PHYPARAM0			0x1c93#define PHYPARAM0_REF_USE_PAD			BIT(31)94#define PHYPARAM0_REF_LOSLEVEL_MASK		(0x1f << 26)95#define PHYPARAM0_REF_LOSLEVEL			(0x9 << 26)96 97#define EXYNOS5_DRD_PHYPARAM1			0x2098#define PHYPARAM1_PCS_TXDEEMPH_MASK		(0x1f << 0)99#define PHYPARAM1_PCS_TXDEEMPH			(0x1c)100 101#define EXYNOS5_DRD_PHYTERM			0x24102 103#define EXYNOS5_DRD_PHYTEST			0x28104#define PHYTEST_POWERDOWN_SSP			BIT(3)105#define PHYTEST_POWERDOWN_HSP			BIT(2)106 107#define EXYNOS5_DRD_PHYADP			0x2c108 109#define EXYNOS5_DRD_PHYUTMICLKSEL		0x30110#define PHYUTMICLKSEL_UTMI_CLKSEL		BIT(2)111 112#define EXYNOS5_DRD_PHYRESUME			0x34113 114#define EXYNOS5_DRD_LINKPORT			0x44115 116/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */117#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN		(0x15)118#define LOSLEVEL_OVRD_IN_LOS_BIAS_5420			(0x5 << 13)119#define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT		(0x0 << 13)120#define LOSLEVEL_OVRD_IN_EN				(0x1 << 10)121#define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT		(0x9 << 0)122 123#define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN	(0x12)124#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420		(0x5 << 13)125#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT		(0x4 << 13)126 127#define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG		(0x1010)128#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M		(0x4 << 4)129#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M		(0x8 << 4)130#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M		(0x8 << 4)131#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M	(0x20 << 4)132#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5		(0x20 << 4)133#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M		(0x40 << 4)134 135/* Exynos850: USB DRD PHY registers */136#define EXYNOS850_DRD_LINKCTRL			0x04137#define LINKCTRL_FORCE_RXELECIDLE		BIT(18)138#define LINKCTRL_FORCE_PHYSTATUS		BIT(17)139#define LINKCTRL_FORCE_PIPE_EN			BIT(16)140#define LINKCTRL_FORCE_QACT			BIT(8)141#define LINKCTRL_BUS_FILTER_BYPASS(_x)		((_x) << 4)142 143#define EXYNOS850_DRD_LINKPORT			0x08144#define LINKPORT_HOST_NUM_U3			GENMASK(19, 16)145#define LINKPORT_HOST_NUM_U2			GENMASK(15, 12)146 147#define EXYNOS850_DRD_CLKRST			0x20148/*149 * On versions without SS ports (like E850), bit 3 is for the 2.0 phy (HS),150 * while on versions with (like gs101), bits 2 and 3 are for the 3.0 phy (SS)151 * and bits 12 & 13 for the 2.0 phy.152 */153#define CLKRST_PHY20_SW_POR			BIT(13)154#define CLKRST_PHY20_SW_POR_SEL			BIT(12)155#define CLKRST_LINK_PCLK_SEL			BIT(7)156#define CLKRST_PHY_SW_RST			BIT(3)157#define CLKRST_PHY_RESET_SEL			BIT(2)158#define CLKRST_PORT_RST				BIT(1)159#define CLKRST_LINK_SW_RST			BIT(0)160 161#define EXYNOS850_DRD_SSPPLLCTL			0x30162#define SSPPLLCTL_FSEL				GENMASK(2, 0)163 164#define EXYNOS850_DRD_UTMI			0x50165#define UTMI_FORCE_VBUSVALID			BIT(5)166#define UTMI_FORCE_BVALID			BIT(4)167#define UTMI_DP_PULLDOWN			BIT(3)168#define UTMI_DM_PULLDOWN			BIT(2)169#define UTMI_FORCE_SUSPEND			BIT(1)170#define UTMI_FORCE_SLEEP			BIT(0)171 172#define EXYNOS850_DRD_HSP			0x54173#define HSP_FSV_OUT_EN				BIT(24)174#define HSP_VBUSVLDEXTSEL			BIT(13)175#define HSP_VBUSVLDEXT				BIT(12)176#define HSP_EN_UTMISUSPEND			BIT(9)177#define HSP_COMMONONN				BIT(8)178 179#define EXYNOS850_DRD_HSPPARACON		0x58180#define HSPPARACON_TXVREF			GENMASK(31, 28)181#define HSPPARACON_TXRISE			GENMASK(25, 24)182#define HSPPARACON_TXRES			GENMASK(22, 21)183#define HSPPARACON_TXPREEMPPULSE		BIT(20)184#define HSPPARACON_TXPREEMPAMP			GENMASK(19, 18)185#define HSPPARACON_TXHSXV			GENMASK(17, 16)186#define HSPPARACON_TXFSLS			GENMASK(15, 12)187#define HSPPARACON_SQRX				GENMASK(10, 8)188#define HSPPARACON_OTG				GENMASK(6, 4)189#define HSPPARACON_COMPDIS			GENMASK(2, 0)190 191#define EXYNOS850_DRD_HSP_TEST			0x5c192#define HSP_TEST_SIDDQ				BIT(24)193 194/* Exynos9 - GS101 */195#define EXYNOS850_DRD_SECPMACTL			0x48196#define SECPMACTL_PMA_ROPLL_REF_CLK_SEL		GENMASK(13, 12)197#define SECPMACTL_PMA_LCPLL_REF_CLK_SEL		GENMASK(11, 10)198#define SECPMACTL_PMA_REF_FREQ_SEL		GENMASK(9, 8)199#define SECPMACTL_PMA_LOW_PWR			BIT(4)200#define SECPMACTL_PMA_TRSV_SW_RST		BIT(3)201#define SECPMACTL_PMA_CMN_SW_RST		BIT(2)202#define SECPMACTL_PMA_INIT_SW_RST		BIT(1)203#define SECPMACTL_PMA_APB_SW_RST		BIT(0)204 205/* PMA registers */206#define EXYNOS9_PMA_USBDP_CMN_REG0008		0x0020207#define CMN_REG0008_OVRD_AUX_EN			BIT(3)208#define CMN_REG0008_AUX_EN			BIT(2)209 210#define EXYNOS9_PMA_USBDP_CMN_REG00B8		0x02e0211#define CMN_REG00B8_LANE_MUX_SEL_DP		GENMASK(3, 0)212 213#define EXYNOS9_PMA_USBDP_CMN_REG01C0		0x0700214#define CMN_REG01C0_ANA_LCPLL_LOCK_DONE		BIT(7)215#define CMN_REG01C0_ANA_LCPLL_AFC_DONE		BIT(6)216 217/* these have similar register layout, for lanes 0 and 2 */218#define EXYNOS9_PMA_USBDP_TRSV_REG03C3			0x0f0c219#define EXYNOS9_PMA_USBDP_TRSV_REG07C3			0x1f0c220#define TRSV_REG03C3_LN0_MON_RX_CDR_AFC_DONE		BIT(3)221#define TRSV_REG03C3_LN0_MON_RX_CDR_CAL_DONE		BIT(2)222#define TRSV_REG03C3_LN0_MON_RX_CDR_FLD_PLL_MODE_DONE	BIT(1)223#define TRSV_REG03C3_LN0_MON_RX_CDR_LOCK_DONE		BIT(0)224 225/* TRSV_REG0413 and TRSV_REG0813 have similar register layout */226#define EXYNOS9_PMA_USBDP_TRSV_REG0413		0x104c227#define TRSV_REG0413_OVRD_LN1_TX_RXD_COMP_EN	BIT(7)228#define TRSV_REG0413_OVRD_LN1_TX_RXD_EN		BIT(5)229 230#define EXYNOS9_PMA_USBDP_TRSV_REG0813		0x204c231#define TRSV_REG0813_OVRD_LN3_TX_RXD_COMP_EN	BIT(7)232#define TRSV_REG0813_OVRD_LN3_TX_RXD_EN		BIT(5)233 234/* PCS registers */235#define EXYNOS9_PCS_NS_VEC_PS1_N1		0x010c236#define EXYNOS9_PCS_NS_VEC_PS2_N0		0x0110237#define EXYNOS9_PCS_NS_VEC_PS3_N0		0x0118238#define NS_VEC_NS_REQ				GENMASK(31, 24)239#define NS_VEC_ENABLE_TIMER			BIT(22)240#define NS_VEC_SEL_TIMEOUT			GENMASK(21, 20)241#define NS_VEC_INV_MASK				GENMASK(19, 16)242#define NS_VEC_COND_MASK			GENMASK(11, 8)243#define NS_VEC_EXP_COND				GENMASK(3, 0)244 245#define EXYNOS9_PCS_OUT_VEC_2			0x014c246#define EXYNOS9_PCS_OUT_VEC_3			0x0150247#define PCS_OUT_VEC_B9_DYNAMIC			BIT(19)248#define PCS_OUT_VEC_B9_SEL_OUT			BIT(18)249#define PCS_OUT_VEC_B8_DYNAMIC			BIT(17)250#define PCS_OUT_VEC_B8_SEL_OUT			BIT(16)251#define PCS_OUT_VEC_B7_DYNAMIC			BIT(15)252#define PCS_OUT_VEC_B7_SEL_OUT			BIT(14)253#define PCS_OUT_VEC_B6_DYNAMIC			BIT(13)254#define PCS_OUT_VEC_B6_SEL_OUT			BIT(12)255#define PCS_OUT_VEC_B5_DYNAMIC			BIT(11)256#define PCS_OUT_VEC_B5_SEL_OUT			BIT(10)257#define PCS_OUT_VEC_B4_DYNAMIC			BIT(9)258#define PCS_OUT_VEC_B4_SEL_OUT			BIT(8)259#define PCS_OUT_VEC_B3_DYNAMIC			BIT(7)260#define PCS_OUT_VEC_B3_SEL_OUT			BIT(6)261#define PCS_OUT_VEC_B2_DYNAMIC			BIT(5)262#define PCS_OUT_VEC_B2_SEL_OUT			BIT(4)263#define PCS_OUT_VEC_B1_DYNAMIC			BIT(3)264#define PCS_OUT_VEC_B1_SEL_OUT			BIT(2)265#define PCS_OUT_VEC_B0_DYNAMIC			BIT(1)266#define PCS_OUT_VEC_B0_SEL_OUT			BIT(0)267 268#define EXYNOS9_PCS_TIMEOUT_0			0x0170269 270#define EXYNOS9_PCS_TIMEOUT_3			0x017c271 272#define EXYNOS9_PCS_EBUF_PARAM			0x0304273#define EBUF_PARAM_SKP_REMOVE_TH_EMPTY_MODE	GENMASK(29, 24)274 275#define EXYNOS9_PCS_BACK_END_MODE_VEC		0x030c276#define BACK_END_MODE_VEC_FORCE_EBUF_EMPTY_MODE	BIT(1)277#define BACK_END_MODE_VEC_DISABLE_DATA_MASK	BIT(0)278 279#define EXYNOS9_PCS_RX_CONTROL			0x03f0280#define RX_CONTROL_EN_BLOCK_ALIGNER_TYPE_B	BIT(22)281 282#define EXYNOS9_PCS_RX_CONTROL_DEBUG		0x03f4283#define RX_CONTROL_DEBUG_EN_TS_CHECK		BIT(5)284#define RX_CONTROL_DEBUG_NUM_COM_FOUND		GENMASK(3, 0)285 286#define EXYNOS9_PCS_LOCAL_COEF			0x040c287#define LOCAL_COEF_PMA_CENTER_COEF		GENMASK(21, 16)288#define LOCAL_COEF_LF				GENMASK(13, 8)289#define LOCAL_COEF_FS				GENMASK(5, 0)290 291#define EXYNOS9_PCS_HS_TX_COEF_MAP_0		0x0410292#define HS_TX_COEF_MAP_0_SSTX_DEEMP		GENMASK(17, 12)293#define HS_TX_COEF_MAP_0_SSTX_LEVEL		GENMASK(11, 6)294#define HS_TX_COEF_MAP_0_SSTX_PRE_SHOOT		GENMASK(5, 0)295 296 297#define KHZ	1000298#define MHZ	(KHZ * KHZ)299 300#define PHY_TUNING_ENTRY_PHY(o, m, v) {	\301		.off = (o),		\302		.mask = (m),		\303		.val = (v),		\304		.region = PTR_PHY	\305	}306 307#define PHY_TUNING_ENTRY_PCS(o, m, v) {	\308		.off = (o),		\309		.mask = (m),		\310		.val = (v),		\311		.region = PTR_PCS	\312	}313 314#define PHY_TUNING_ENTRY_PMA(o, m, v) {	\315		.off = (o),		\316		.mask = (m),		\317		.val = (v),		\318		.region = PTR_PMA,	\319	}320 321#define PHY_TUNING_ENTRY_LAST { .region = PTR_INVALID }322 323#define for_each_phy_tune(tune) \324	for (; (tune)->region != PTR_INVALID; ++(tune))325 326struct exynos5_usbdrd_phy_tuning {327	u32 off;328	u32 mask;329	u32 val;330	char region;331#define PTR_INVALID	0332#define PTR_PHY		1333#define PTR_PCS		2334#define PTR_PMA		3335};336 337enum exynos5_usbdrd_phy_tuning_state {338	PTS_UTMI_POSTINIT,339	PTS_PIPE3_PREINIT,340	PTS_PIPE3_INIT,341	PTS_PIPE3_POSTINIT,342	PTS_PIPE3_POSTLOCK,343	PTS_MAX,344};345 346enum exynos5_usbdrd_phy_id {347	EXYNOS5_DRDPHY_UTMI,348	EXYNOS5_DRDPHY_PIPE3,349	EXYNOS5_DRDPHYS_NUM,350};351 352struct phy_usb_instance;353struct exynos5_usbdrd_phy;354 355struct exynos5_usbdrd_phy_config {356	u32 id;357	void (*phy_isol)(struct phy_usb_instance *inst, bool isolate);358	void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);359	unsigned int (*set_refclk)(struct phy_usb_instance *inst);360};361 362struct exynos5_usbdrd_phy_drvdata {363	const struct exynos5_usbdrd_phy_config *phy_cfg;364	const struct exynos5_usbdrd_phy_tuning **phy_tunes;365	const struct phy_ops *phy_ops;366	const char * const *clk_names;367	int n_clks;368	const char * const *core_clk_names;369	int n_core_clks;370	const char * const *regulator_names;371	int n_regulators;372	u32 pmu_offset_usbdrd0_phy;373	u32 pmu_offset_usbdrd0_phy_ss;374	u32 pmu_offset_usbdrd1_phy;375};376 377/**378 * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY379 * @dev: pointer to device instance of this platform device380 * @reg_phy: usb phy controller register memory base381 * @reg_pcs: usb phy physical coding sublayer register memory base382 * @reg_pma: usb phy physical media attachment register memory base383 * @clks: clocks for register access384 * @core_clks: core clocks for phy (ref, pipe3, utmi+, ITP, etc. as required)385 * @drv_data: pointer to SoC level driver data structure386 * @phys: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY387 *	    instances each with its 'phy' and 'phy_cfg'.388 * @extrefclk: frequency select settings when using 'separate389 *	       reference clocks' for SS and HS operations390 * @regulators: regulators for phy391 */392struct exynos5_usbdrd_phy {393	struct device *dev;394	void __iomem *reg_phy;395	void __iomem *reg_pcs;396	void __iomem *reg_pma;397	struct clk_bulk_data *clks;398	struct clk_bulk_data *core_clks;399	const struct exynos5_usbdrd_phy_drvdata *drv_data;400	struct phy_usb_instance {401		struct phy *phy;402		u32 index;403		struct regmap *reg_pmu;404		u32 pmu_offset;405		const struct exynos5_usbdrd_phy_config *phy_cfg;406	} phys[EXYNOS5_DRDPHYS_NUM];407	u32 extrefclk;408	struct regulator_bulk_data *regulators;409};410 411static inline412struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)413{414	return container_of((inst), struct exynos5_usbdrd_phy,415			    phys[(inst)->index]);416}417 418/*419 * exynos5_rate_to_clk() converts the supplied clock rate to the value that420 * can be written to the phy register.421 */422static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)423{424	/* EXYNOS5_FSEL_MASK */425 426	switch (rate) {427	case 9600 * KHZ:428		*reg = EXYNOS5_FSEL_9MHZ6;429		break;430	case 10 * MHZ:431		*reg = EXYNOS5_FSEL_10MHZ;432		break;433	case 12 * MHZ:434		*reg = EXYNOS5_FSEL_12MHZ;435		break;436	case 19200 * KHZ:437		*reg = EXYNOS5_FSEL_19MHZ2;438		break;439	case 20 * MHZ:440		*reg = EXYNOS5_FSEL_20MHZ;441		break;442	case 24 * MHZ:443		*reg = EXYNOS5_FSEL_24MHZ;444		break;445	case 26 * MHZ:446		*reg = EXYNOS5_FSEL_26MHZ;447		break;448	case 50 * MHZ:449		*reg = EXYNOS5_FSEL_50MHZ;450		break;451	default:452		return -EINVAL;453	}454 455	return 0;456}457 458static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,459				    bool isolate)460{461	unsigned int val;462 463	if (!inst->reg_pmu)464		return;465 466	val = isolate ? 0 : EXYNOS4_PHY_ENABLE;467 468	regmap_update_bits(inst->reg_pmu, inst->pmu_offset,469			   EXYNOS4_PHY_ENABLE, val);470}471 472/*473 * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock474 * from clock core. Further sets multiplier values and spread spectrum475 * clock settings for SuperSpeed operations.476 */477static unsigned int478exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)479{480	u32 reg;481	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);482 483	/* restore any previous reference clock settings */484	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);485 486	/* Use EXTREFCLK as ref clock */487	reg &= ~PHYCLKRST_REFCLKSEL_MASK;488	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;489 490	/* FSEL settings corresponding to reference clock */491	reg &= ~PHYCLKRST_FSEL_PIPE_MASK |492		PHYCLKRST_MPLL_MULTIPLIER_MASK |493		PHYCLKRST_SSC_REFCLKSEL_MASK;494	switch (phy_drd->extrefclk) {495	case EXYNOS5_FSEL_50MHZ:496		reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |497			PHYCLKRST_SSC_REFCLKSEL(0x00));498		break;499	case EXYNOS5_FSEL_24MHZ:500		reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |501			PHYCLKRST_SSC_REFCLKSEL(0x88));502		break;503	case EXYNOS5_FSEL_20MHZ:504		reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |505			PHYCLKRST_SSC_REFCLKSEL(0x00));506		break;507	case EXYNOS5_FSEL_19MHZ2:508		reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |509			PHYCLKRST_SSC_REFCLKSEL(0x88));510		break;511	default:512		dev_dbg(phy_drd->dev, "unsupported ref clk\n");513		break;514	}515 516	return reg;517}518 519/*520 * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock521 * from clock core. Further sets the FSEL values for HighSpeed operations.522 */523static unsigned int524exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)525{526	u32 reg;527	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);528 529	/* restore any previous reference clock settings */530	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);531 532	reg &= ~PHYCLKRST_REFCLKSEL_MASK;533	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;534 535	reg &= ~PHYCLKRST_FSEL_UTMI_MASK |536		PHYCLKRST_MPLL_MULTIPLIER_MASK |537		PHYCLKRST_SSC_REFCLKSEL_MASK;538	reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);539 540	return reg;541}542 543static void544exynos5_usbdrd_apply_phy_tunes(struct exynos5_usbdrd_phy *phy_drd,545			       enum exynos5_usbdrd_phy_tuning_state state)546{547	const struct exynos5_usbdrd_phy_tuning *tune;548 549	tune = phy_drd->drv_data->phy_tunes[state];550	if (!tune)551		return;552 553	for_each_phy_tune(tune) {554		void __iomem *reg_base;555		u32 reg = 0;556 557		switch (tune->region) {558		case PTR_PHY:559			reg_base = phy_drd->reg_phy;560			break;561		case PTR_PCS:562			reg_base = phy_drd->reg_pcs;563			break;564		case PTR_PMA:565			reg_base = phy_drd->reg_pma;566			break;567		default:568			dev_warn_once(phy_drd->dev,569				      "unknown phy region %d\n", tune->region);570			continue;571		}572 573		if (~tune->mask) {574			reg = readl(reg_base + tune->off);575			reg &= ~tune->mask;576		}577		reg |= tune->val;578		writel(reg, reg_base + tune->off);579	}580}581 582static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)583{584	u32 reg;585 586	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);587	/* Set Tx De-Emphasis level */588	reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;589	reg |=	PHYPARAM1_PCS_TXDEEMPH;590	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);591 592	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);593	reg &= ~PHYTEST_POWERDOWN_SSP;594	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);595}596 597static void598exynos5_usbdrd_usbdp_g2_v4_ctrl_pma_ready(struct exynos5_usbdrd_phy *phy_drd)599{600	void __iomem *regs_base = phy_drd->reg_phy;601	u32 reg;602 603	/* link pipe_clock selection to pclk of PMA */604	reg = readl(regs_base + EXYNOS850_DRD_CLKRST);605	reg |= CLKRST_LINK_PCLK_SEL;606	writel(reg, regs_base + EXYNOS850_DRD_CLKRST);607 608	reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);609	reg &= ~SECPMACTL_PMA_REF_FREQ_SEL;610	reg |= FIELD_PREP(SECPMACTL_PMA_REF_FREQ_SEL, 1);611	/* SFR reset */612	reg |= (SECPMACTL_PMA_LOW_PWR | SECPMACTL_PMA_APB_SW_RST);613	reg &= ~(SECPMACTL_PMA_ROPLL_REF_CLK_SEL |614		 SECPMACTL_PMA_LCPLL_REF_CLK_SEL);615	/* PMA power off */616	reg |= (SECPMACTL_PMA_TRSV_SW_RST | SECPMACTL_PMA_CMN_SW_RST |617		SECPMACTL_PMA_INIT_SW_RST);618	writel(reg, regs_base + EXYNOS850_DRD_SECPMACTL);619 620	udelay(1);621 622	reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);623	reg &= ~SECPMACTL_PMA_LOW_PWR;624	writel(reg, regs_base + EXYNOS850_DRD_SECPMACTL);625 626	udelay(1);627 628	/* release override */629	reg = readl(regs_base + EXYNOS850_DRD_LINKCTRL);630	reg &= ~LINKCTRL_FORCE_PIPE_EN;631	writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);632 633	udelay(1);634 635	/* APB enable */636	reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);637	reg &= ~SECPMACTL_PMA_APB_SW_RST;638	writel(reg, regs_base + EXYNOS850_DRD_SECPMACTL);639}640 641static void642exynos5_usbdrd_usbdp_g2_v4_pma_lane_mux_sel(struct exynos5_usbdrd_phy *phy_drd)643{644	void __iomem *regs_base = phy_drd->reg_pma;645	u32 reg;646 647	/* lane configuration: USB on all lanes */648	reg = readl(regs_base + EXYNOS9_PMA_USBDP_CMN_REG00B8);649	reg &= ~CMN_REG00B8_LANE_MUX_SEL_DP;650	writel(reg, regs_base + EXYNOS9_PMA_USBDP_CMN_REG00B8);651 652	/*653	 * FIXME: below code supports one connector orientation only. It needs654	 * updating once we can receive connector events.655	 */656	/* override of TX receiver detector and comparator: lane 1 */657	reg = readl(regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0413);658	reg &= ~TRSV_REG0413_OVRD_LN1_TX_RXD_COMP_EN;659	reg &= ~TRSV_REG0413_OVRD_LN1_TX_RXD_EN;660	writel(reg, regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0413);661 662	/* lane 3 */663	reg = readl(regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0813);664	reg |= TRSV_REG0813_OVRD_LN3_TX_RXD_COMP_EN;665	reg |= TRSV_REG0813_OVRD_LN3_TX_RXD_EN;666	writel(reg, regs_base + EXYNOS9_PMA_USBDP_TRSV_REG0813);667}668 669static int670exynos5_usbdrd_usbdp_g2_v4_pma_check_pll_lock(struct exynos5_usbdrd_phy *phy_drd)671{672	static const unsigned int timeout_us = 40000;673	static const unsigned int sleep_us = 40;674	static const u32 locked = (CMN_REG01C0_ANA_LCPLL_LOCK_DONE |675				   CMN_REG01C0_ANA_LCPLL_AFC_DONE);676	u32 reg;677	int err;678 679	err = readl_poll_timeout(680			phy_drd->reg_pma + EXYNOS9_PMA_USBDP_CMN_REG01C0,681			reg, (reg & locked) == locked, sleep_us, timeout_us);682	if (err)683		dev_err(phy_drd->dev,684			"timed out waiting for PLL lock: %#.8x\n", reg);685 686	return err;687}688 689static void690exynos5_usbdrd_usbdp_g2_v4_pma_check_cdr_lock(struct exynos5_usbdrd_phy *phy_drd)691{692	static const unsigned int timeout_us = 40000;693	static const unsigned int sleep_us = 40;694	static const u32 locked =695		(TRSV_REG03C3_LN0_MON_RX_CDR_AFC_DONE696		 | TRSV_REG03C3_LN0_MON_RX_CDR_CAL_DONE697		 | TRSV_REG03C3_LN0_MON_RX_CDR_FLD_PLL_MODE_DONE698		 | TRSV_REG03C3_LN0_MON_RX_CDR_LOCK_DONE);699	u32 reg;700	int err;701 702	err = readl_poll_timeout(703			phy_drd->reg_pma + EXYNOS9_PMA_USBDP_TRSV_REG03C3,704			reg, (reg & locked) == locked, sleep_us, timeout_us);705	if (!err)706		return;707 708	dev_err(phy_drd->dev,709		"timed out waiting for CDR lock (l0): %#.8x, retrying\n", reg);710 711	/* based on cable orientation, this might be on the other phy port */712	err = readl_poll_timeout(713			phy_drd->reg_pma + EXYNOS9_PMA_USBDP_TRSV_REG07C3,714			reg, (reg & locked) == locked, sleep_us, timeout_us);715	if (err)716		dev_err(phy_drd->dev,717			"timed out waiting for CDR lock (l2): %#.8x\n", reg);718}719 720static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)721{722	u32 reg;723 724	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);725	/* Set Loss-of-Signal Detector sensitivity */726	reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;727	reg |=	PHYPARAM0_REF_LOSLEVEL;728	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);729 730	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);731	/* Set Tx De-Emphasis level */732	reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;733	reg |=	PHYPARAM1_PCS_TXDEEMPH;734	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);735 736	/* UTMI Power Control */737	writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);738 739	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);740	reg &= ~PHYTEST_POWERDOWN_HSP;741	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);742}743 744static int exynos5_usbdrd_phy_init(struct phy *phy)745{746	int ret;747	u32 reg;748	struct phy_usb_instance *inst = phy_get_drvdata(phy);749	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);750 751	ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);752	if (ret)753		return ret;754 755	/* Reset USB 3.0 PHY */756	writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);757	writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);758 759	/*760	 * Setting the Frame length Adj value[6:1] to default 0x20761	 * See xHCI 1.0 spec, 5.2.4762	 */763	reg =	LINKSYSTEM_XHCI_VERSION_CONTROL |764		LINKSYSTEM_FLADJ(0x20);765	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);766 767	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);768	/* Select PHY CLK source */769	reg &= ~PHYPARAM0_REF_USE_PAD;770	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);771 772	/* This bit must be set for both HS and SS operations */773	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);774	reg |= PHYUTMICLKSEL_UTMI_CLKSEL;775	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);776 777	/* UTMI or PIPE3 specific init */778	inst->phy_cfg->phy_init(phy_drd);779 780	/* reference clock settings */781	reg = inst->phy_cfg->set_refclk(inst);782 783		/* Digital power supply in normal operating mode */784	reg |=	PHYCLKRST_RETENABLEN |785		/* Enable ref clock for SS function */786		PHYCLKRST_REF_SSP_EN |787		/* Enable spread spectrum */788		PHYCLKRST_SSC_EN |789		/* Power down HS Bias and PLL blocks in suspend mode */790		PHYCLKRST_COMMONONN |791		/* Reset the port */792		PHYCLKRST_PORTRESET;793 794	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);795 796	fsleep(10);797 798	reg &= ~PHYCLKRST_PORTRESET;799	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);800 801	clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);802 803	return 0;804}805 806static int exynos5_usbdrd_phy_exit(struct phy *phy)807{808	int ret;809	u32 reg;810	struct phy_usb_instance *inst = phy_get_drvdata(phy);811	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);812 813	ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);814	if (ret)815		return ret;816 817	reg =	PHYUTMI_OTGDISABLE |818		PHYUTMI_FORCESUSPEND |819		PHYUTMI_FORCESLEEP;820	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);821 822	/* Resetting the PHYCLKRST enable bits to reduce leakage current */823	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);824	reg &= ~(PHYCLKRST_REF_SSP_EN |825		 PHYCLKRST_SSC_EN |826		 PHYCLKRST_COMMONONN);827	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);828 829	/* Control PHYTEST to remove leakage current */830	reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);831	reg |=	PHYTEST_POWERDOWN_SSP |832		PHYTEST_POWERDOWN_HSP;833	writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);834 835	clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);836 837	return 0;838}839 840static int exynos5_usbdrd_phy_power_on(struct phy *phy)841{842	int ret;843	struct phy_usb_instance *inst = phy_get_drvdata(phy);844	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);845 846	dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");847 848	ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_core_clks,849				      phy_drd->core_clks);850	if (ret)851		return ret;852 853	/* Enable VBUS supply */854	ret = regulator_bulk_enable(phy_drd->drv_data->n_regulators,855				    phy_drd->regulators);856	if (ret) {857		dev_err(phy_drd->dev, "Failed to enable PHY regulator(s)\n");858		goto fail_vbus;859	}860 861	/* Power-on PHY */862	inst->phy_cfg->phy_isol(inst, false);863 864	return 0;865 866fail_vbus:867	clk_bulk_disable_unprepare(phy_drd->drv_data->n_core_clks,868				   phy_drd->core_clks);869 870	return ret;871}872 873static int exynos5_usbdrd_phy_power_off(struct phy *phy)874{875	struct phy_usb_instance *inst = phy_get_drvdata(phy);876	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);877 878	dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");879 880	/* Power-off the PHY */881	inst->phy_cfg->phy_isol(inst, true);882 883	/* Disable VBUS supply */884	regulator_bulk_disable(phy_drd->drv_data->n_regulators,885			       phy_drd->regulators);886 887	clk_bulk_disable_unprepare(phy_drd->drv_data->n_core_clks,888				   phy_drd->core_clks);889 890	return 0;891}892 893static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd,894			    u32 val, u32 cmd)895{896	unsigned int result;897	int err;898 899	writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);900 901	err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,902				 result, (result & PHYREG1_CR_ACK), 1, 100);903	if (err == -ETIMEDOUT) {904		dev_err(phy_drd->dev, "CRPORT handshake timeout1 (0x%08x)\n", val);905		return err;906	}907 908	writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);909 910	err = readl_poll_timeout(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1,911				 result, !(result & PHYREG1_CR_ACK), 1, 100);912	if (err == -ETIMEDOUT) {913		dev_err(phy_drd->dev, "CRPORT handshake timeout2 (0x%08x)\n", val);914		return err;915	}916 917	return 0;918}919 920static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,921			     u32 addr, u32 data)922{923	int ret;924 925	/* Write Address */926	writel(PHYREG0_CR_DATA_IN(addr),927	       phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);928	ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr),929			       PHYREG0_CR_CAP_ADDR);930	if (ret)931		return ret;932 933	/* Write Data */934	writel(PHYREG0_CR_DATA_IN(data),935	       phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);936	ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),937			       PHYREG0_CR_CAP_DATA);938	if (ret)939		return ret;940 941	ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),942			       PHYREG0_CR_WRITE);943 944	return ret;945}946 947/*948 * Calibrate few PHY parameters using CR_PORT register to meet949 * SuperSpeed requirements on Exynos5420 and Exynos5800 systems,950 * which have 28nm USB 3.0 DRD PHY.951 */952static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)953{954	unsigned int temp;955	int ret = 0;956 957	/*958	 * Change los_bias to (0x5) for 28nm PHY from a959	 * default value (0x0); los_level is set as default960	 * (0x9) as also reflected in los_level[30:26] bits961	 * of PHYPARAM0 register.962	 */963	temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |964		LOSLEVEL_OVRD_IN_EN |965		LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;966	ret = crport_ctrl_write(phy_drd,967				EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,968				temp);969	if (ret) {970		dev_err(phy_drd->dev,971			"Failed setting Loss-of-Signal level for SuperSpeed\n");972		return ret;973	}974 975	/*976	 * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,977	 * to raise Tx signal level from its default value of (0x4)978	 */979	temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;980	ret = crport_ctrl_write(phy_drd,981				EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,982				temp);983	if (ret) {984		dev_err(phy_drd->dev,985			"Failed setting Tx-Vboost-Level for SuperSpeed\n");986		return ret;987	}988 989	/*990	 * Set proper time to wait for RxDetect measurement, for991	 * desired reference clock of PHY, by tuning the CR_PORT992	 * register LANE0.TX_DEBUG which is internal to PHY.993	 * This fixes issue with few USB 3.0 devices, which are994	 * not detected (not even generate interrupts on the bus995	 * on insertion) without this change.996	 * e.g. Samsung SUM-TSB16S 3.0 USB drive.997	 */998	switch (phy_drd->extrefclk) {999	case EXYNOS5_FSEL_50MHZ:1000		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;1001		break;1002	case EXYNOS5_FSEL_20MHZ:1003	case EXYNOS5_FSEL_19MHZ2:1004		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;1005		break;1006	case EXYNOS5_FSEL_24MHZ:1007	default:1008		temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;1009		break;1010	}1011 1012	ret = crport_ctrl_write(phy_drd,1013				EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,1014				temp);1015	if (ret)1016		dev_err(phy_drd->dev,1017			"Fail to set RxDet measurement time for SuperSpeed\n");1018 1019	return ret;1020}1021 1022static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,1023					const struct of_phandle_args *args)1024{1025	struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);1026 1027	if (WARN_ON(args->args[0] >= EXYNOS5_DRDPHYS_NUM))1028		return ERR_PTR(-ENODEV);1029 1030	return phy_drd->phys[args->args[0]].phy;1031}1032 1033static int exynos5_usbdrd_phy_calibrate(struct phy *phy)1034{1035	struct phy_usb_instance *inst = phy_get_drvdata(phy);1036	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);1037 1038	if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI)1039		return exynos5420_usbdrd_phy_calibrate(phy_drd);1040	return 0;1041}1042 1043static const struct phy_ops exynos5_usbdrd_phy_ops = {1044	.init		= exynos5_usbdrd_phy_init,1045	.exit		= exynos5_usbdrd_phy_exit,1046	.power_on	= exynos5_usbdrd_phy_power_on,1047	.power_off	= exynos5_usbdrd_phy_power_off,1048	.calibrate	= exynos5_usbdrd_phy_calibrate,1049	.owner		= THIS_MODULE,1050};1051 1052static void1053exynos5_usbdrd_usb_v3p1_pipe_override(struct exynos5_usbdrd_phy *phy_drd)1054{1055	void __iomem *regs_base = phy_drd->reg_phy;1056	u32 reg;1057 1058	/* force pipe3 signal for link */1059	reg = readl(regs_base + EXYNOS850_DRD_LINKCTRL);1060	reg &= ~LINKCTRL_FORCE_PHYSTATUS;1061	reg |= LINKCTRL_FORCE_PIPE_EN | LINKCTRL_FORCE_RXELECIDLE;1062	writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);1063 1064	/* PMA disable */1065	reg = readl(regs_base + EXYNOS850_DRD_SECPMACTL);1066	reg |= SECPMACTL_PMA_LOW_PWR;1067	writel(reg, regs_base + EXYNOS850_DRD_SECPMACTL);1068}1069 1070static void exynos850_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)1071{1072	void __iomem *regs_base = phy_drd->reg_phy;1073	u32 reg;1074	u32 ss_ports;1075 1076	/*1077	 * Disable HWACG (hardware auto clock gating control). This will force1078	 * QACTIVE signal in Q-Channel interface to HIGH level, to make sure1079	 * the PHY clock is not gated by the hardware.1080	 */1081	reg = readl(regs_base + EXYNOS850_DRD_LINKCTRL);1082	reg |= LINKCTRL_FORCE_QACT;1083	writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);1084 1085	reg = readl(regs_base + EXYNOS850_DRD_LINKPORT);1086	ss_ports = FIELD_GET(LINKPORT_HOST_NUM_U3, reg);1087 1088	/* Start PHY Reset (POR=high) */1089	reg = readl(regs_base + EXYNOS850_DRD_CLKRST);1090	if (ss_ports) {1091		reg |= CLKRST_PHY20_SW_POR;1092		reg |= CLKRST_PHY20_SW_POR_SEL;1093		reg |= CLKRST_PHY_RESET_SEL;1094	}1095	reg |= CLKRST_PHY_SW_RST;1096	writel(reg, regs_base + EXYNOS850_DRD_CLKRST);1097 1098	/* Enable UTMI+ */1099	reg = readl(regs_base + EXYNOS850_DRD_UTMI);1100	reg &= ~(UTMI_FORCE_SUSPEND | UTMI_FORCE_SLEEP | UTMI_DP_PULLDOWN |1101		 UTMI_DM_PULLDOWN);1102	writel(reg, regs_base + EXYNOS850_DRD_UTMI);1103 1104	/* Set PHY clock and control HS PHY */1105	reg = readl(regs_base + EXYNOS850_DRD_HSP);1106	reg |= HSP_EN_UTMISUSPEND | HSP_COMMONONN;1107	writel(reg, regs_base + EXYNOS850_DRD_HSP);1108 1109	/* Set VBUS Valid and D+ pull-up control by VBUS pad usage */1110	reg = readl(regs_base + EXYNOS850_DRD_LINKCTRL);1111	reg |= LINKCTRL_BUS_FILTER_BYPASS(0xf);1112	writel(reg, regs_base + EXYNOS850_DRD_LINKCTRL);1113 1114	reg = readl(regs_base + EXYNOS850_DRD_UTMI);1115	reg |= UTMI_FORCE_BVALID | UTMI_FORCE_VBUSVALID;1116	writel(reg, regs_base + EXYNOS850_DRD_UTMI);1117 1118	reg = readl(regs_base + EXYNOS850_DRD_HSP);1119	reg |= HSP_VBUSVLDEXT | HSP_VBUSVLDEXTSEL;1120	writel(reg, regs_base + EXYNOS850_DRD_HSP);1121 1122	reg = readl(regs_base + EXYNOS850_DRD_SSPPLLCTL);1123	reg &= ~SSPPLLCTL_FSEL;1124	switch (phy_drd->extrefclk) {1125	case EXYNOS5_FSEL_50MHZ:1126		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 7);1127		break;1128	case EXYNOS5_FSEL_26MHZ:1129		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 6);1130		break;1131	case EXYNOS5_FSEL_24MHZ:1132		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 2);1133		break;1134	case EXYNOS5_FSEL_20MHZ:1135		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 1);1136		break;1137	case EXYNOS5_FSEL_19MHZ2:1138		reg |= FIELD_PREP(SSPPLLCTL_FSEL, 0);1139		break;1140	default:1141		dev_warn(phy_drd->dev, "unsupported ref clk: %#.2x\n",1142			 phy_drd->extrefclk);1143		break;1144	}1145	writel(reg, regs_base + EXYNOS850_DRD_SSPPLLCTL);1146 1147	if (phy_drd->drv_data->phy_tunes)1148		exynos5_usbdrd_apply_phy_tunes(phy_drd,1149					       PTS_UTMI_POSTINIT);1150 1151	/* Power up PHY analog blocks */1152	reg = readl(regs_base + EXYNOS850_DRD_HSP_TEST);1153	reg &= ~HSP_TEST_SIDDQ;1154	writel(reg, regs_base + EXYNOS850_DRD_HSP_TEST);1155 1156	/* Finish PHY reset (POR=low) */1157	fsleep(10); /* required before doing POR=low */1158	reg = readl(regs_base + EXYNOS850_DRD_CLKRST);1159	if (ss_ports) {1160		reg |= CLKRST_PHY20_SW_POR_SEL;1161		reg &= ~CLKRST_PHY20_SW_POR;1162	}1163	reg &= ~(CLKRST_PHY_SW_RST | CLKRST_PORT_RST);1164	writel(reg, regs_base + EXYNOS850_DRD_CLKRST);1165	fsleep(75); /* required after POR=low for guaranteed PHY clock */1166 1167	/* Disable single ended signal out */1168	reg = readl(regs_base + EXYNOS850_DRD_HSP);1169	reg &= ~HSP_FSV_OUT_EN;1170	writel(reg, regs_base + EXYNOS850_DRD_HSP);1171 1172	if (ss_ports)1173		exynos5_usbdrd_usb_v3p1_pipe_override(phy_drd);1174}1175 1176static int exynos850_usbdrd_phy_init(struct phy *phy)1177{1178	struct phy_usb_instance *inst = phy_get_drvdata(phy);1179	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);1180	int ret;1181 1182	ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);1183	if (ret)1184		return ret;1185 1186	/* UTMI or PIPE3 specific init */1187	inst->phy_cfg->phy_init(phy_drd);1188 1189	clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);1190 1191	return 0;1192}1193 1194static int exynos850_usbdrd_phy_exit(struct phy *phy)1195{1196	struct phy_usb_instance *inst = phy_get_drvdata(phy);1197	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);1198	void __iomem *regs_base = phy_drd->reg_phy;1199	u32 reg;1200	int ret;1201 1202	ret = clk_bulk_prepare_enable(phy_drd->drv_data->n_clks, phy_drd->clks);1203	if (ret)1204		return ret;1205 1206	/* Set PHY clock and control HS PHY */1207	reg = readl(regs_base + EXYNOS850_DRD_UTMI);1208	reg &= ~(UTMI_DP_PULLDOWN | UTMI_DM_PULLDOWN);1209	reg |= UTMI_FORCE_SUSPEND | UTMI_FORCE_SLEEP;1210	writel(reg, regs_base + EXYNOS850_DRD_UTMI);1211 1212	/* Power down PHY analog blocks */1213	reg = readl(regs_base + EXYNOS850_DRD_HSP_TEST);1214	reg |= HSP_TEST_SIDDQ;1215	writel(reg, regs_base + EXYNOS850_DRD_HSP_TEST);1216 1217	/* Link reset */1218	reg = readl(regs_base + EXYNOS850_DRD_CLKRST);1219	reg |= CLKRST_LINK_SW_RST;1220	writel(reg, regs_base + EXYNOS850_DRD_CLKRST);1221	fsleep(10); /* required before doing POR=low */1222	reg &= ~CLKRST_LINK_SW_RST;1223	writel(reg, regs_base + EXYNOS850_DRD_CLKRST);1224 1225	clk_bulk_disable_unprepare(phy_drd->drv_data->n_clks, phy_drd->clks);1226 1227	return 0;1228}1229 1230static const struct phy_ops exynos850_usbdrd_phy_ops = {1231	.init		= exynos850_usbdrd_phy_init,1232	.exit		= exynos850_usbdrd_phy_exit,1233	.power_on	= exynos5_usbdrd_phy_power_on,1234	.power_off	= exynos5_usbdrd_phy_power_off,1235	.owner		= THIS_MODULE,1236};1237 1238static void exynos5_usbdrd_gs101_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)1239{1240	void __iomem *regs_pma = phy_drd->reg_pma;1241	void __iomem *regs_phy = phy_drd->reg_phy;1242	u32 reg;1243 1244	exynos5_usbdrd_usbdp_g2_v4_ctrl_pma_ready(phy_drd);1245 1246	/* force aux off */1247	reg = readl(regs_pma + EXYNOS9_PMA_USBDP_CMN_REG0008);1248	reg &= ~CMN_REG0008_AUX_EN;1249	reg |= CMN_REG0008_OVRD_AUX_EN;1250	writel(reg, regs_pma + EXYNOS9_PMA_USBDP_CMN_REG0008);1251 1252	exynos5_usbdrd_apply_phy_tunes(phy_drd, PTS_PIPE3_PREINIT);1253	exynos5_usbdrd_apply_phy_tunes(phy_drd, PTS_PIPE3_INIT);1254	exynos5_usbdrd_apply_phy_tunes(phy_drd, PTS_PIPE3_POSTINIT);1255 1256	exynos5_usbdrd_usbdp_g2_v4_pma_lane_mux_sel(phy_drd);1257 1258	/* reset release from port */1259	reg = readl(regs_phy + EXYNOS850_DRD_SECPMACTL);1260	reg &= ~(SECPMACTL_PMA_TRSV_SW_RST | SECPMACTL_PMA_CMN_SW_RST |1261		 SECPMACTL_PMA_INIT_SW_RST);1262	writel(reg, regs_phy + EXYNOS850_DRD_SECPMACTL);1263 1264	if (!exynos5_usbdrd_usbdp_g2_v4_pma_check_pll_lock(phy_drd))1265		exynos5_usbdrd_usbdp_g2_v4_pma_check_cdr_lock(phy_drd);1266}1267 1268static int exynos5_usbdrd_gs101_phy_init(struct phy *phy)1269{1270	struct phy_usb_instance *inst = phy_get_drvdata(phy);1271	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);1272	int ret;1273 1274	if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI) {1275		/* Power-on PHY ... */1276		ret = regulator_bulk_enable(phy_drd->drv_data->n_regulators,1277					    phy_drd->regulators);1278		if (ret) {1279			dev_err(phy_drd->dev,1280				"Failed to enable PHY regulator(s)\n");1281			return ret;1282		}1283	}1284	/*1285	 * ... and ungate power via PMU. Without this here, we get an SError1286	 * trying to access PMA registers1287	 */1288	exynos5_usbdrd_phy_isol(inst, false);1289 1290	return exynos850_usbdrd_phy_init(phy);1291}1292 1293static int exynos5_usbdrd_gs101_phy_exit(struct phy *phy)1294{1295	struct phy_usb_instance *inst = phy_get_drvdata(phy);1296	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);1297	int ret;1298 1299	if (inst->phy_cfg->id != EXYNOS5_DRDPHY_UTMI)1300		return 0;1301 1302	ret = exynos850_usbdrd_phy_exit(phy);1303	if (ret)1304		return ret;1305 1306	exynos5_usbdrd_phy_isol(inst, true);1307	return regulator_bulk_disable(phy_drd->drv_data->n_regulators,1308				      phy_drd->regulators);1309}1310 1311static const struct phy_ops gs101_usbdrd_phy_ops = {1312	.init		= exynos5_usbdrd_gs101_phy_init,1313	.exit		= exynos5_usbdrd_gs101_phy_exit,1314	.owner		= THIS_MODULE,1315};1316 1317static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)1318{1319	int ret;1320	struct clk *ref_clk;1321	unsigned long ref_rate;1322 1323	phy_drd->clks = devm_kcalloc(phy_drd->dev, phy_drd->drv_data->n_clks,1324				     sizeof(*phy_drd->clks), GFP_KERNEL);1325	if (!phy_drd->clks)1326		return -ENOMEM;1327 1328	for (int i = 0; i < phy_drd->drv_data->n_clks; ++i)1329		phy_drd->clks[i].id = phy_drd->drv_data->clk_names[i];1330 1331	ret = devm_clk_bulk_get(phy_drd->dev, phy_drd->drv_data->n_clks,1332				phy_drd->clks);1333	if (ret)1334		return dev_err_probe(phy_drd->dev, ret,1335				     "failed to get phy clock(s)\n");1336 1337	phy_drd->core_clks = devm_kcalloc(phy_drd->dev,1338					  phy_drd->drv_data->n_core_clks,1339					  sizeof(*phy_drd->core_clks),1340					  GFP_KERNEL);1341	if (!phy_drd->core_clks)1342		return -ENOMEM;1343 1344	for (int i = 0; i < phy_drd->drv_data->n_core_clks; ++i)1345		phy_drd->core_clks[i].id = phy_drd->drv_data->core_clk_names[i];1346 1347	ret = devm_clk_bulk_get(phy_drd->dev, phy_drd->drv_data->n_core_clks,1348				phy_drd->core_clks);1349	if (ret)1350		return dev_err_probe(phy_drd->dev, ret,1351				     "failed to get phy core clock(s)\n");1352 1353	ref_clk = NULL;1354	for (int i = 0; i < phy_drd->drv_data->n_core_clks; ++i) {1355		if (!strcmp(phy_drd->core_clks[i].id, "ref")) {1356			ref_clk = phy_drd->core_clks[i].clk;1357			break;1358		}1359	}1360	if (!ref_clk)1361		return dev_err_probe(phy_drd->dev, -ENODEV,1362				     "failed to find phy reference clock\n");1363 1364	ref_rate = clk_get_rate(ref_clk);1365	ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);1366	if (ret)1367		return dev_err_probe(phy_drd->dev, ret,1368				     "clock rate (%ld) not supported\n",1369				     ref_rate);1370 1371	return 0;1372}1373 1374static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {1375	{1376		.id		= EXYNOS5_DRDPHY_UTMI,1377		.phy_isol	= exynos5_usbdrd_phy_isol,1378		.phy_init	= exynos5_usbdrd_utmi_init,1379		.set_refclk	= exynos5_usbdrd_utmi_set_refclk,1380	},1381	{1382		.id		= EXYNOS5_DRDPHY_PIPE3,1383		.phy_isol	= exynos5_usbdrd_phy_isol,1384		.phy_init	= exynos5_usbdrd_pipe3_init,1385		.set_refclk	= exynos5_usbdrd_pipe3_set_refclk,1386	},1387};1388 1389static const struct exynos5_usbdrd_phy_config phy_cfg_exynos850[] = {1390	{1391		.id		= EXYNOS5_DRDPHY_UTMI,1392		.phy_isol	= exynos5_usbdrd_phy_isol,1393		.phy_init	= exynos850_usbdrd_utmi_init,1394	},1395};1396 1397static const char * const exynos5_clk_names[] = {1398	"phy",1399};1400 1401static const char * const exynos5_core_clk_names[] = {1402	"ref",1403};1404 1405static const char * const exynos5433_core_clk_names[] = {1406	"ref", "phy_pipe", "phy_utmi", "itp",1407};1408 1409static const char * const exynos5_regulator_names[] = {1410	"vbus", "vbus-boost",1411};1412 1413static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {1414	.phy_cfg		= phy_cfg_exynos5,1415	.phy_ops		= &exynos5_usbdrd_phy_ops,1416	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,1417	.pmu_offset_usbdrd1_phy	= EXYNOS5420_USBDRD1_PHY_CONTROL,1418	.clk_names		= exynos5_clk_names,1419	.n_clks			= ARRAY_SIZE(exynos5_clk_names),1420	.core_clk_names		= exynos5_core_clk_names,1421	.n_core_clks		= ARRAY_SIZE(exynos5_core_clk_names),1422	.regulator_names	= exynos5_regulator_names,1423	.n_regulators		= ARRAY_SIZE(exynos5_regulator_names),1424};1425 1426static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {1427	.phy_cfg		= phy_cfg_exynos5,1428	.phy_ops		= &exynos5_usbdrd_phy_ops,1429	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,1430	.clk_names		= exynos5_clk_names,1431	.n_clks			= ARRAY_SIZE(exynos5_clk_names),1432	.core_clk_names		= exynos5_core_clk_names,1433	.n_core_clks		= ARRAY_SIZE(exynos5_core_clk_names),1434	.regulator_names	= exynos5_regulator_names,1435	.n_regulators		= ARRAY_SIZE(exynos5_regulator_names),1436};1437 1438static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {1439	.phy_cfg		= phy_cfg_exynos5,1440	.phy_ops		= &exynos5_usbdrd_phy_ops,1441	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,1442	.pmu_offset_usbdrd1_phy	= EXYNOS5433_USBHOST30_PHY_CONTROL,1443	.clk_names		= exynos5_clk_names,1444	.n_clks			= ARRAY_SIZE(exynos5_clk_names),1445	.core_clk_names		= exynos5433_core_clk_names,1446	.n_core_clks		= ARRAY_SIZE(exynos5433_core_clk_names),1447	.regulator_names	= exynos5_regulator_names,1448	.n_regulators		= ARRAY_SIZE(exynos5_regulator_names),1449};1450 1451static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {1452	.phy_cfg		= phy_cfg_exynos5,1453	.phy_ops		= &exynos5_usbdrd_phy_ops,1454	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,1455	.clk_names		= exynos5_clk_names,1456	.n_clks			= ARRAY_SIZE(exynos5_clk_names),1457	.core_clk_names		= exynos5433_core_clk_names,1458	.n_core_clks		= ARRAY_SIZE(exynos5433_core_clk_names),1459	.regulator_names	= exynos5_regulator_names,1460	.n_regulators		= ARRAY_SIZE(exynos5_regulator_names),1461};1462 1463static const struct exynos5_usbdrd_phy_drvdata exynos850_usbdrd_phy = {1464	.phy_cfg		= phy_cfg_exynos850,1465	.phy_ops		= &exynos850_usbdrd_phy_ops,1466	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,1467	.clk_names		= exynos5_clk_names,1468	.n_clks			= ARRAY_SIZE(exynos5_clk_names),1469	.core_clk_names		= exynos5_core_clk_names,1470	.n_core_clks		= ARRAY_SIZE(exynos5_core_clk_names),1471	.regulator_names	= exynos5_regulator_names,1472	.n_regulators		= ARRAY_SIZE(exynos5_regulator_names),1473};1474 1475static const struct exynos5_usbdrd_phy_config phy_cfg_gs101[] = {1476	{1477		.id		= EXYNOS5_DRDPHY_UTMI,1478		.phy_isol	= exynos5_usbdrd_phy_isol,1479		.phy_init	= exynos850_usbdrd_utmi_init,1480	},1481	{1482		.id		= EXYNOS5_DRDPHY_PIPE3,1483		.phy_isol	= exynos5_usbdrd_phy_isol,1484		.phy_init	= exynos5_usbdrd_gs101_pipe3_init,1485	},1486};1487 1488static const struct exynos5_usbdrd_phy_tuning gs101_tunes_utmi_postinit[] = {1489	PHY_TUNING_ENTRY_PHY(EXYNOS850_DRD_HSPPARACON,1490			     (HSPPARACON_TXVREF | HSPPARACON_TXRES |1491			      HSPPARACON_TXPREEMPAMP | HSPPARACON_SQRX |1492			      HSPPARACON_COMPDIS),1493			     (FIELD_PREP_CONST(HSPPARACON_TXVREF, 6) |1494			      FIELD_PREP_CONST(HSPPARACON_TXRES, 1) |1495			      FIELD_PREP_CONST(HSPPARACON_TXPREEMPAMP, 3) |1496			      FIELD_PREP_CONST(HSPPARACON_SQRX, 5) |1497			      FIELD_PREP_CONST(HSPPARACON_COMPDIS, 7))),1498	PHY_TUNING_ENTRY_LAST1499};1500 1501static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_preinit[] = {1502	/* preinit */1503	/* CDR data mode exit GEN1 ON / GEN2 OFF */1504	PHY_TUNING_ENTRY_PMA(0x0c8c, -1, 0xff),1505	PHY_TUNING_ENTRY_PMA(0x1c8c, -1, 0xff),1506	PHY_TUNING_ENTRY_PMA(0x0c9c, -1, 0x7d),1507	PHY_TUNING_ENTRY_PMA(0x1c9c, -1, 0x7d),1508	/* improve EDS distribution */1509	PHY_TUNING_ENTRY_PMA(0x0e7c, -1, 0x06),1510	PHY_TUNING_ENTRY_PMA(0x09e0, -1, 0x00),1511	PHY_TUNING_ENTRY_PMA(0x09e4, -1, 0x36),1512	PHY_TUNING_ENTRY_PMA(0x1e7c, -1, 0x06),1513	PHY_TUNING_ENTRY_PMA(0x1e90, -1, 0x00),1514	PHY_TUNING_ENTRY_PMA(0x1e94, -1, 0x36),1515	/* improve LVCC */1516	PHY_TUNING_ENTRY_PMA(0x08f0, -1, 0x30),1517	PHY_TUNING_ENTRY_PMA(0x18f0, -1, 0x30),1518	/* LFPS RX VIH shmoo hole */1519	PHY_TUNING_ENTRY_PMA(0x0a08, -1, 0x0c),1520	PHY_TUNING_ENTRY_PMA(0x1a08, -1, 0x0c),1521	/* remove unrelated option for v4 phy */1522	PHY_TUNING_ENTRY_PMA(0x0a0c, -1, 0x05),1523	PHY_TUNING_ENTRY_PMA(0x1a0c, -1, 0x05),1524	/* improve Gen2 LVCC */1525	PHY_TUNING_ENTRY_PMA(0x00f8, -1, 0x1c),1526	PHY_TUNING_ENTRY_PMA(0x00fc, -1, 0x54),1527	/* Change Vth of RCV_DET because of TD 7.40 Polling Retry Test */1528	PHY_TUNING_ENTRY_PMA(0x104c, -1, 0x07),1529	PHY_TUNING_ENTRY_PMA(0x204c, -1, 0x07),1530	/* reduce Ux Exit time, assuming 26MHz clock */1531	/* Gen1 */1532	PHY_TUNING_ENTRY_PMA(0x0ca8, -1, 0x00),1533	PHY_TUNING_ENTRY_PMA(0x0cac, -1, 0x04),1534	PHY_TUNING_ENTRY_PMA(0x1ca8, -1, 0x00),1535	PHY_TUNING_ENTRY_PMA(0x1cac, -1, 0x04),1536	/* Gen2 */1537	PHY_TUNING_ENTRY_PMA(0x0cb8, -1, 0x00),1538	PHY_TUNING_ENTRY_PMA(0x0cbc, -1, 0x04),1539	PHY_TUNING_ENTRY_PMA(0x1cb8, -1, 0x00),1540	PHY_TUNING_ENTRY_PMA(0x1cbc, -1, 0x04),1541	/* RX impedance setting */1542	PHY_TUNING_ENTRY_PMA(0x0bb0, 0x03, 0x01),1543	PHY_TUNING_ENTRY_PMA(0x0bb4, 0xf0, 0xa0),1544	PHY_TUNING_ENTRY_PMA(0x1bb0, 0x03, 0x01),1545	PHY_TUNING_ENTRY_PMA(0x1bb4, 0xf0, 0xa0),1546 1547	PHY_TUNING_ENTRY_LAST1548};1549 1550static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_init[] = {1551	/* init */1552	/* abnormal common pattern mask */1553	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_BACK_END_MODE_VEC,1554			     BACK_END_MODE_VEC_DISABLE_DATA_MASK, 0),1555	/* de-serializer enabled when U2 */1556	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_OUT_VEC_2, PCS_OUT_VEC_B4_DYNAMIC,1557			     PCS_OUT_VEC_B4_SEL_OUT),1558	/* TX Keeper Disable, Squelch on when U3 */1559	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_OUT_VEC_3, PCS_OUT_VEC_B7_DYNAMIC,1560			     PCS_OUT_VEC_B7_SEL_OUT | PCS_OUT_VEC_B2_SEL_OUT),1561	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_NS_VEC_PS1_N1, -1,1562			     (FIELD_PREP_CONST(NS_VEC_NS_REQ, 5) |1563			      NS_VEC_ENABLE_TIMER |1564			      FIELD_PREP_CONST(NS_VEC_SEL_TIMEOUT, 3))),1565	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_NS_VEC_PS2_N0, -1,1566			     (FIELD_PREP_CONST(NS_VEC_NS_REQ, 1) |1567			      NS_VEC_ENABLE_TIMER |1568			      FIELD_PREP_CONST(NS_VEC_SEL_TIMEOUT, 3) |1569			      FIELD_PREP_CONST(NS_VEC_COND_MASK, 2) |1570			      FIELD_PREP_CONST(NS_VEC_EXP_COND, 2))),1571	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_NS_VEC_PS3_N0, -1,1572			     (FIELD_PREP_CONST(NS_VEC_NS_REQ, 1) |1573			      NS_VEC_ENABLE_TIMER |1574			      FIELD_PREP_CONST(NS_VEC_SEL_TIMEOUT, 3) |1575			      FIELD_PREP_CONST(NS_VEC_COND_MASK, 7) |1576			      FIELD_PREP_CONST(NS_VEC_EXP_COND, 7))),1577	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_TIMEOUT_0, -1, 112),1578	/* Block Aligner Type B */1579	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_RX_CONTROL, 0,1580			     RX_CONTROL_EN_BLOCK_ALIGNER_TYPE_B),1581	/* Block align at TS1/TS2 for Gen2 stability (Gen2 only) */1582	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_RX_CONTROL_DEBUG,1583		RX_CONTROL_DEBUG_NUM_COM_FOUND,1584		(RX_CONTROL_DEBUG_EN_TS_CHECK |1585		 /*1586		  * increase pcs ts1 adding packet-cnt 1 --> 41587		  * lnx_rx_valid_rstn_delay_rise_sp/ssp :1588		  * 19.6us(0x200) -> 15.3us(0x4)1589		  */1590		 FIELD_PREP_CONST(RX_CONTROL_DEBUG_NUM_COM_FOUND, 4))),1591	/* Gen1 Tx DRIVER pre-shoot, de-emphasis, level ctrl */1592	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_HS_TX_COEF_MAP_0,1593		(HS_TX_COEF_MAP_0_SSTX_DEEMP | HS_TX_COEF_MAP_0_SSTX_LEVEL |1594		 HS_TX_COEF_MAP_0_SSTX_PRE_SHOOT),1595		(FIELD_PREP_CONST(HS_TX_COEF_MAP_0_SSTX_DEEMP, 8) |1596		 FIELD_PREP_CONST(HS_TX_COEF_MAP_0_SSTX_LEVEL, 0xb) |1597		 FIELD_PREP_CONST(HS_TX_COEF_MAP_0_SSTX_PRE_SHOOT, 0))),1598	/* Gen2 Tx DRIVER level ctrl */1599	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_LOCAL_COEF,1600		LOCAL_COEF_PMA_CENTER_COEF,1601		FIELD_PREP_CONST(LOCAL_COEF_PMA_CENTER_COEF, 0xb)),1602	/* Gen2 U1 exit LFPS duration : 900ns ~ 1.2us */1603	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_TIMEOUT_3, -1, 4096),1604	/* set skp_remove_th 0x2 -> 0x7 for avoiding retry problem. */1605	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_EBUF_PARAM,1606		EBUF_PARAM_SKP_REMOVE_TH_EMPTY_MODE,1607		FIELD_PREP_CONST(EBUF_PARAM_SKP_REMOVE_TH_EMPTY_MODE, 0x7)),1608 1609	PHY_TUNING_ENTRY_LAST1610};1611 1612static const struct exynos5_usbdrd_phy_tuning gs101_tunes_pipe3_postlock[] = {1613	/* Squelch off when U3 */1614	PHY_TUNING_ENTRY_PCS(EXYNOS9_PCS_OUT_VEC_3, PCS_OUT_VEC_B2_SEL_OUT, 0),1615 1616	PHY_TUNING_ENTRY_LAST1617};1618 1619static const struct exynos5_usbdrd_phy_tuning *gs101_tunes[PTS_MAX] = {1620	[PTS_UTMI_POSTINIT] = gs101_tunes_utmi_postinit,1621	[PTS_PIPE3_PREINIT] = gs101_tunes_pipe3_preinit,1622	[PTS_PIPE3_INIT] = gs101_tunes_pipe3_init,1623	[PTS_PIPE3_POSTLOCK] = gs101_tunes_pipe3_postlock,1624};1625 1626static const char * const gs101_clk_names[] = {1627	"phy", "ctrl_aclk", "ctrl_pclk", "scl_pclk",1628};1629 1630static const char * const gs101_regulator_names[] = {1631	"pll",1632	"dvdd-usb20", "vddh-usb20", "vdd33-usb20",1633	"vdda-usbdp", "vddh-usbdp",1634};1635 1636static const struct exynos5_usbdrd_phy_drvdata gs101_usbd31rd_phy = {1637	.phy_cfg			= phy_cfg_gs101,1638	.phy_tunes			= gs101_tunes,1639	.phy_ops			= &gs101_usbdrd_phy_ops,1640	.pmu_offset_usbdrd0_phy		= GS101_PHY_CTRL_USB20,1641	.pmu_offset_usbdrd0_phy_ss	= GS101_PHY_CTRL_USBDP,1642	.clk_names			= gs101_clk_names,1643	.n_clks				= ARRAY_SIZE(gs101_clk_names),1644	.core_clk_names			= exynos5_core_clk_names,1645	.n_core_clks			= ARRAY_SIZE(exynos5_core_clk_names),1646	.regulator_names		= gs101_regulator_names,1647	.n_regulators			= ARRAY_SIZE(gs101_regulator_names),1648};1649 1650static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {1651	{1652		.compatible = "google,gs101-usb31drd-phy",1653		.data = &gs101_usbd31rd_phy1654	}, {1655		.compatible = "samsung,exynos5250-usbdrd-phy",1656		.data = &exynos5250_usbdrd_phy1657	}, {1658		.compatible = "samsung,exynos5420-usbdrd-phy",1659		.data = &exynos5420_usbdrd_phy1660	}, {1661		.compatible = "samsung,exynos5433-usbdrd-phy",1662		.data = &exynos5433_usbdrd_phy1663	}, {1664		.compatible = "samsung,exynos7-usbdrd-phy",1665		.data = &exynos7_usbdrd_phy1666	}, {1667		.compatible = "samsung,exynos850-usbdrd-phy",1668		.data = &exynos850_usbdrd_phy1669	},1670	{ },1671};1672MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);1673 1674static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)1675{1676	struct device *dev = &pdev->dev;1677	struct device_node *node = dev->of_node;1678	struct exynos5_usbdrd_phy *phy_drd;1679	struct phy_provider *phy_provider;1680	const struct exynos5_usbdrd_phy_drvdata *drv_data;1681	struct regmap *reg_pmu;1682	u32 pmu_offset;1683	int i, ret;1684	int channel;1685 1686	phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);1687	if (!phy_drd)1688		return -ENOMEM;1689 1690	dev_set_drvdata(dev, phy_drd);1691	phy_drd->dev = dev;1692 1693	drv_data = of_device_get_match_data(dev);1694	if (!drv_data)1695		return -EINVAL;1696	phy_drd->drv_data = drv_data;1697 1698	if (of_property_present(dev->of_node, "reg-names")) {1699		void __iomem *reg;1700 1701		reg = devm_platform_ioremap_resource_byname(pdev, "phy");1702		if (IS_ERR(reg))1703			return PTR_ERR(reg);1704		phy_drd->reg_phy = reg;1705 1706		reg = devm_platform_ioremap_resource_byname(pdev, "pcs");1707		if (IS_ERR(reg))1708			return PTR_ERR(reg);1709		phy_drd->reg_pcs = reg;1710 1711		reg = devm_platform_ioremap_resource_byname(pdev, "pma");1712		if (IS_ERR(reg))1713			return PTR_ERR(reg);1714		phy_drd->reg_pma = reg;1715	} else {1716		/* DTB with just a single region */1717		phy_drd->reg_phy = devm_platform_ioremap_resource(pdev, 0);1718		if (IS_ERR(phy_drd->reg_phy))1719			return PTR_ERR(phy_drd->reg_phy);1720	}1721 1722	ret = exynos5_usbdrd_phy_clk_handle(phy_drd);1723	if (ret)1724		return ret;1725 1726	reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,1727						   "samsung,pmu-syscon");1728	if (IS_ERR(reg_pmu)) {1729		dev_err(dev, "Failed to lookup PMU regmap\n");1730		return PTR_ERR(reg_pmu);1731	}1732 1733	/*1734	 * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with1735	 * each having separate power control registers.1736	 * 'channel' facilitates to set such registers.1737	 */1738	channel = of_alias_get_id(node, "usbdrdphy");1739	if (channel < 0)1740		dev_dbg(dev, "Not a multi-controller usbdrd phy\n");1741 1742	/* Get regulators */1743	phy_drd->regulators = devm_kcalloc(dev,1744					   drv_data->n_regulators,1745					   sizeof(*phy_drd->regulators),1746					   GFP_KERNEL);1747	if (!phy_drd->regulators)1748		return -ENOMEM;1749	regulator_bulk_set_supply_names(phy_drd->regulators,1750					drv_data->regulator_names,1751					drv_data->n_regulators);1752	ret = devm_regulator_bulk_get(dev, drv_data->n_regulators,1753				      phy_drd->regulators);1754	if (ret)1755		return dev_err_probe(dev, ret, "failed to get regulators\n");1756 1757	dev_vdbg(dev, "Creating usbdrd_phy phy\n");1758 1759	for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {1760		struct phy *phy = devm_phy_create(dev, NULL, drv_data->phy_ops);1761 1762		if (IS_ERR(phy)) {1763			dev_err(dev, "Failed to create usbdrd_phy phy\n");1764			return PTR_ERR(phy);1765		}1766 1767		phy_drd->phys[i].phy = phy;1768		phy_drd->phys[i].index = i;1769		phy_drd->phys[i].reg_pmu = reg_pmu;1770		switch (channel) {1771		case 1:1772			pmu_offset = drv_data->pmu_offset_usbdrd1_phy;1773			break;1774		case 0:1775		default:1776			pmu_offset = drv_data->pmu_offset_usbdrd0_phy;1777			if (i == EXYNOS5_DRDPHY_PIPE3 && drv_data1778						->pmu_offset_usbdrd0_phy_ss)1779				pmu_offset = drv_data->pmu_offset_usbdrd0_phy_ss;1780			break;1781		}1782		phy_drd->phys[i].pmu_offset = pmu_offset;1783		phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];1784		phy_set_drvdata(phy, &phy_drd->phys[i]);1785	}1786 1787	phy_provider = devm_of_phy_provider_register(dev,1788						     exynos5_usbdrd_phy_xlate);1789	if (IS_ERR(phy_provider)) {1790		dev_err(phy_drd->dev, "Failed to register phy provider\n");1791		return PTR_ERR(phy_provider);1792	}1793 1794	return 0;1795}1796 1797static struct platform_driver exynos5_usb3drd_phy = {1798	.probe	= exynos5_usbdrd_phy_probe,1799	.driver = {1800		.of_match_table	= exynos5_usbdrd_phy_of_match,1801		.name		= "exynos5_usb3drd_phy",1802		.suppress_bind_attrs = true,1803	}1804};1805 1806module_platform_driver(exynos5_usb3drd_phy);1807MODULE_DESCRIPTION("Samsung Exynos5 SoCs USB 3.0 DRD controller PHY driver");1808MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");1809MODULE_LICENSE("GPL v2");1810MODULE_ALIAS("platform:exynos5_usb3drd_phy");1811