19695375aSMiquel Raynal // SPDX-License-Identifier: GPL-2.0
29695375aSMiquel Raynal /*
39695375aSMiquel Raynal  * Copyright (C) 2018 Marvell
49695375aSMiquel Raynal  *
59695375aSMiquel Raynal  * Authors:
69695375aSMiquel Raynal  *   Evan Wang <xswang@marvell.com>
79695375aSMiquel Raynal  *   Miquèl Raynal <miquel.raynal@bootlin.com>
893433708SPali Rohár  *   Pali Rohár <pali@kernel.org>
993433708SPali Rohár  *   Marek Behún <kabel@kernel.org>
109695375aSMiquel Raynal  *
119695375aSMiquel Raynal  * Structure inspired from phy-mvebu-cp110-comphy.c written by Antoine Tenart.
1293433708SPali Rohár  * Comphy code from ARM Trusted Firmware ported by Pali Rohár <pali@kernel.org>
1393433708SPali Rohár  * and Marek Behún <kabel@kernel.org>.
149695375aSMiquel Raynal  */
159695375aSMiquel Raynal 
1693433708SPali Rohár #include <linux/bitfield.h>
1793433708SPali Rohár #include <linux/clk.h>
189695375aSMiquel Raynal #include <linux/io.h>
199695375aSMiquel Raynal #include <linux/iopoll.h>
209695375aSMiquel Raynal #include <linux/mfd/syscon.h>
219695375aSMiquel Raynal #include <linux/module.h>
229695375aSMiquel Raynal #include <linux/phy.h>
239695375aSMiquel Raynal #include <linux/phy/phy.h>
249695375aSMiquel Raynal #include <linux/platform_device.h>
2593433708SPali Rohár #include <linux/spinlock.h>
269695375aSMiquel Raynal 
2793433708SPali Rohár #define PLL_SET_DELAY_US		600
2893433708SPali Rohár #define COMPHY_PLL_SLEEP		1000
2993433708SPali Rohár #define COMPHY_PLL_TIMEOUT		150000
309695375aSMiquel Raynal 
3193433708SPali Rohár /* Comphy lane2 indirect access register offset */
3293433708SPali Rohár #define COMPHY_LANE2_INDIR_ADDR		0x0
3393433708SPali Rohár #define COMPHY_LANE2_INDIR_DATA		0x4
349695375aSMiquel Raynal 
3593433708SPali Rohár /* SATA and USB3 PHY offset compared to SATA PHY */
3693433708SPali Rohár #define COMPHY_LANE2_REGS_BASE		0x200
379695375aSMiquel Raynal 
3893433708SPali Rohár /*
3993433708SPali Rohár  * When accessing common PHY lane registers directly, we need to shift by 1,
4093433708SPali Rohár  * since the registers are 16-bit.
4193433708SPali Rohár  */
4293433708SPali Rohár #define COMPHY_LANE_REG_DIRECT(reg)	(((reg) & 0x7FF) << 1)
439695375aSMiquel Raynal 
4493433708SPali Rohár /* COMPHY registers */
4593433708SPali Rohár #define COMPHY_POWER_PLL_CTRL		0x01
4693433708SPali Rohár #define PU_IVREF_BIT			BIT(15)
4793433708SPali Rohár #define PU_PLL_BIT			BIT(14)
4893433708SPali Rohár #define PU_RX_BIT			BIT(13)
4993433708SPali Rohár #define PU_TX_BIT			BIT(12)
5093433708SPali Rohár #define PU_TX_INTP_BIT			BIT(11)
5193433708SPali Rohár #define PU_DFE_BIT			BIT(10)
5293433708SPali Rohár #define RESET_DTL_RX_BIT		BIT(9)
5393433708SPali Rohár #define PLL_LOCK_BIT			BIT(8)
5493433708SPali Rohár #define REF_FREF_SEL_MASK		GENMASK(4, 0)
5593433708SPali Rohár #define REF_FREF_SEL_SERDES_25MHZ	FIELD_PREP(REF_FREF_SEL_MASK, 0x1)
5693433708SPali Rohár #define REF_FREF_SEL_SERDES_40MHZ	FIELD_PREP(REF_FREF_SEL_MASK, 0x3)
5793433708SPali Rohár #define REF_FREF_SEL_SERDES_50MHZ	FIELD_PREP(REF_FREF_SEL_MASK, 0x4)
5893433708SPali Rohár #define REF_FREF_SEL_PCIE_USB3_25MHZ	FIELD_PREP(REF_FREF_SEL_MASK, 0x2)
5993433708SPali Rohár #define REF_FREF_SEL_PCIE_USB3_40MHZ	FIELD_PREP(REF_FREF_SEL_MASK, 0x3)
6093433708SPali Rohár #define COMPHY_MODE_MASK		GENMASK(7, 5)
6193433708SPali Rohár #define COMPHY_MODE_SATA		FIELD_PREP(COMPHY_MODE_MASK, 0x0)
6293433708SPali Rohár #define COMPHY_MODE_PCIE		FIELD_PREP(COMPHY_MODE_MASK, 0x3)
6393433708SPali Rohár #define COMPHY_MODE_SERDES		FIELD_PREP(COMPHY_MODE_MASK, 0x4)
6493433708SPali Rohár #define COMPHY_MODE_USB3		FIELD_PREP(COMPHY_MODE_MASK, 0x5)
6593433708SPali Rohár 
6693433708SPali Rohár #define COMPHY_KVCO_CAL_CTRL		0x02
6793433708SPali Rohár #define USE_MAX_PLL_RATE_BIT		BIT(12)
6893433708SPali Rohár #define SPEED_PLL_MASK			GENMASK(7, 2)
6993433708SPali Rohár #define SPEED_PLL_VALUE_16		FIELD_PREP(SPEED_PLL_MASK, 0x10)
7093433708SPali Rohár 
7193433708SPali Rohár #define COMPHY_DIG_LOOPBACK_EN		0x23
7293433708SPali Rohár #define SEL_DATA_WIDTH_MASK		GENMASK(11, 10)
7393433708SPali Rohár #define DATA_WIDTH_10BIT		FIELD_PREP(SEL_DATA_WIDTH_MASK, 0x0)
7493433708SPali Rohár #define DATA_WIDTH_20BIT		FIELD_PREP(SEL_DATA_WIDTH_MASK, 0x1)
7593433708SPali Rohár #define DATA_WIDTH_40BIT		FIELD_PREP(SEL_DATA_WIDTH_MASK, 0x2)
7693433708SPali Rohár #define PLL_READY_TX_BIT		BIT(4)
7793433708SPali Rohár 
7893433708SPali Rohár #define COMPHY_SYNC_PATTERN		0x24
7993433708SPali Rohár #define TXD_INVERT_BIT			BIT(10)
8093433708SPali Rohár #define RXD_INVERT_BIT			BIT(11)
8193433708SPali Rohár 
8293433708SPali Rohár #define COMPHY_SYNC_MASK_GEN		0x25
8393433708SPali Rohár #define PHY_GEN_MAX_MASK		GENMASK(11, 10)
8493433708SPali Rohár #define PHY_GEN_MAX_USB3_5G		FIELD_PREP(PHY_GEN_MAX_MASK, 0x1)
8593433708SPali Rohár 
8693433708SPali Rohár #define COMPHY_ISOLATION_CTRL		0x26
8793433708SPali Rohár #define PHY_ISOLATE_MODE		BIT(15)
8893433708SPali Rohár 
8993433708SPali Rohár #define COMPHY_GEN2_SET2		0x3e
9093433708SPali Rohár #define GS2_TX_SSC_AMP_MASK		GENMASK(15, 9)
9193433708SPali Rohár #define GS2_TX_SSC_AMP_4128		FIELD_PREP(GS2_TX_SSC_AMP_MASK, 0x20)
9293433708SPali Rohár #define GS2_VREG_RXTX_MAS_ISET_MASK	GENMASK(8, 7)
9393433708SPali Rohár #define GS2_VREG_RXTX_MAS_ISET_60U	FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\
9493433708SPali Rohár 						   0x0)
9593433708SPali Rohár #define GS2_VREG_RXTX_MAS_ISET_80U	FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\
9693433708SPali Rohár 						   0x1)
9793433708SPali Rohár #define GS2_VREG_RXTX_MAS_ISET_100U	FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\
9893433708SPali Rohár 						   0x2)
9993433708SPali Rohár #define GS2_VREG_RXTX_MAS_ISET_120U	FIELD_PREP(GS2_VREG_RXTX_MAS_ISET_MASK,\
10093433708SPali Rohár 						   0x3)
10193433708SPali Rohár #define GS2_RSVD_6_0_MASK		GENMASK(6, 0)
10293433708SPali Rohár 
10393433708SPali Rohár #define COMPHY_GEN3_SET2		0x3f
10493433708SPali Rohár 
10593433708SPali Rohár #define COMPHY_IDLE_SYNC_EN		0x48
10693433708SPali Rohár #define IDLE_SYNC_EN			BIT(12)
10793433708SPali Rohár 
10893433708SPali Rohár #define COMPHY_MISC_CTRL0		0x4F
10993433708SPali Rohár #define CLK100M_125M_EN			BIT(4)
11093433708SPali Rohár #define TXDCLK_2X_SEL			BIT(6)
11193433708SPali Rohár #define CLK500M_EN			BIT(7)
11293433708SPali Rohár #define PHY_REF_CLK_SEL			BIT(10)
11393433708SPali Rohár 
11493433708SPali Rohár #define COMPHY_SFT_RESET		0x52
11593433708SPali Rohár #define SFT_RST				BIT(9)
11693433708SPali Rohár #define SFT_RST_NO_REG			BIT(10)
11793433708SPali Rohár 
11893433708SPali Rohár #define COMPHY_MISC_CTRL1		0x73
11993433708SPali Rohár #define SEL_BITS_PCIE_FORCE		BIT(15)
12093433708SPali Rohár 
12193433708SPali Rohár #define COMPHY_GEN2_SET3		0x112
12293433708SPali Rohár #define GS3_FFE_CAP_SEL_MASK		GENMASK(3, 0)
12393433708SPali Rohár #define GS3_FFE_CAP_SEL_VALUE		FIELD_PREP(GS3_FFE_CAP_SEL_MASK, 0xF)
12493433708SPali Rohár 
12593433708SPali Rohár /* PIPE registers */
12693433708SPali Rohár #define COMPHY_PIPE_LANE_CFG0		0x180
12793433708SPali Rohár #define PRD_TXDEEMPH0_MASK		BIT(0)
12893433708SPali Rohár #define PRD_TXMARGIN_MASK		GENMASK(3, 1)
12993433708SPali Rohár #define PRD_TXSWING_MASK		BIT(4)
13093433708SPali Rohár #define CFG_TX_ALIGN_POS_MASK		GENMASK(8, 5)
13193433708SPali Rohár 
13293433708SPali Rohár #define COMPHY_PIPE_LANE_CFG1		0x181
13393433708SPali Rohár #define PRD_TXDEEMPH1_MASK		BIT(15)
13493433708SPali Rohár #define USE_MAX_PLL_RATE_EN		BIT(9)
13593433708SPali Rohár #define TX_DET_RX_MODE			BIT(6)
13693433708SPali Rohár #define GEN2_TX_DATA_DLY_MASK		GENMASK(4, 3)
13793433708SPali Rohár #define GEN2_TX_DATA_DLY_DEFT		FIELD_PREP(GEN2_TX_DATA_DLY_MASK, 2)
13893433708SPali Rohár #define TX_ELEC_IDLE_MODE_EN		BIT(0)
13993433708SPali Rohár 
14093433708SPali Rohár #define COMPHY_PIPE_LANE_STAT1		0x183
14193433708SPali Rohár #define TXDCLK_PCLK_EN			BIT(0)
14293433708SPali Rohár 
14393433708SPali Rohár #define COMPHY_PIPE_LANE_CFG4		0x188
14493433708SPali Rohár #define SPREAD_SPECTRUM_CLK_EN		BIT(7)
14593433708SPali Rohár 
14693433708SPali Rohár #define COMPHY_PIPE_RST_CLK_CTRL	0x1C1
14793433708SPali Rohár #define PIPE_SOFT_RESET			BIT(0)
14893433708SPali Rohár #define PIPE_REG_RESET			BIT(1)
14993433708SPali Rohár #define MODE_CORE_CLK_FREQ_SEL		BIT(9)
15093433708SPali Rohár #define MODE_PIPE_WIDTH_32		BIT(3)
15193433708SPali Rohár #define MODE_REFDIV_MASK		GENMASK(5, 4)
15293433708SPali Rohár #define MODE_REFDIV_BY_4		FIELD_PREP(MODE_REFDIV_MASK, 0x2)
15393433708SPali Rohár 
15493433708SPali Rohár #define COMPHY_PIPE_TEST_MODE_CTRL	0x1C2
15593433708SPali Rohár #define MODE_MARGIN_OVERRIDE		BIT(2)
15693433708SPali Rohár 
15793433708SPali Rohár #define COMPHY_PIPE_CLK_SRC_LO		0x1C3
15893433708SPali Rohár #define MODE_CLK_SRC			BIT(0)
15993433708SPali Rohár #define BUNDLE_PERIOD_SEL		BIT(1)
16093433708SPali Rohár #define BUNDLE_PERIOD_SCALE_MASK	GENMASK(3, 2)
16193433708SPali Rohár #define BUNDLE_SAMPLE_CTRL		BIT(4)
16293433708SPali Rohár #define PLL_READY_DLY_MASK		GENMASK(7, 5)
16393433708SPali Rohár #define CFG_SEL_20B			BIT(15)
16493433708SPali Rohár 
16593433708SPali Rohár #define COMPHY_PIPE_PWR_MGM_TIM1	0x1D0
16693433708SPali Rohár #define CFG_PM_OSCCLK_WAIT_MASK		GENMASK(15, 12)
16793433708SPali Rohár #define CFG_PM_RXDEN_WAIT_MASK		GENMASK(11, 8)
16893433708SPali Rohár #define CFG_PM_RXDEN_WAIT_1_UNIT	FIELD_PREP(CFG_PM_RXDEN_WAIT_MASK, 0x1)
16993433708SPali Rohár #define CFG_PM_RXDLOZ_WAIT_MASK		GENMASK(7, 0)
17093433708SPali Rohár #define CFG_PM_RXDLOZ_WAIT_7_UNIT	FIELD_PREP(CFG_PM_RXDLOZ_WAIT_MASK, 0x7)
17193433708SPali Rohár #define CFG_PM_RXDLOZ_WAIT_12_UNIT	FIELD_PREP(CFG_PM_RXDLOZ_WAIT_MASK, 0xC)
17293433708SPali Rohár 
17393433708SPali Rohár /*
17493433708SPali Rohár  * This register is not from PHY lane register space. It only exists in the
17593433708SPali Rohár  * indirect register space, before the actual PHY lane 2 registers. So the
17693433708SPali Rohár  * offset is absolute, not relative to COMPHY_LANE2_REGS_BASE.
17793433708SPali Rohár  * It is used only for SATA PHY initialization.
17893433708SPali Rohár  */
17993433708SPali Rohár #define COMPHY_RESERVED_REG		0x0E
18093433708SPali Rohár #define PHYCTRL_FRM_PIN_BIT		BIT(13)
18193433708SPali Rohár 
18293433708SPali Rohár /* South Bridge PHY Configuration Registers */
18393433708SPali Rohár #define COMPHY_PHY_REG(lane, reg)	(((1 - (lane)) * 0x28) + ((reg) & 0x3f))
18493433708SPali Rohár 
18593433708SPali Rohár /*
18693433708SPali Rohár  * lane0: USB3/GbE1 PHY Configuration 1
18793433708SPali Rohár  * lane1: PCIe/GbE0 PHY Configuration 1
18893433708SPali Rohár  * (used only by SGMII code)
18993433708SPali Rohár  */
19093433708SPali Rohár #define COMPHY_PHY_CFG1			0x0
19193433708SPali Rohár #define PIN_PU_IVREF_BIT		BIT(1)
19293433708SPali Rohár #define PIN_RESET_CORE_BIT		BIT(11)
19393433708SPali Rohár #define PIN_RESET_COMPHY_BIT		BIT(12)
19493433708SPali Rohár #define PIN_PU_PLL_BIT			BIT(16)
19593433708SPali Rohár #define PIN_PU_RX_BIT			BIT(17)
19693433708SPali Rohár #define PIN_PU_TX_BIT			BIT(18)
19793433708SPali Rohár #define PIN_TX_IDLE_BIT			BIT(19)
19893433708SPali Rohár #define GEN_RX_SEL_MASK			GENMASK(25, 22)
19993433708SPali Rohár #define GEN_RX_SEL_VALUE(val)		FIELD_PREP(GEN_RX_SEL_MASK, (val))
20093433708SPali Rohár #define GEN_TX_SEL_MASK			GENMASK(29, 26)
20193433708SPali Rohár #define GEN_TX_SEL_VALUE(val)		FIELD_PREP(GEN_TX_SEL_MASK, (val))
20293433708SPali Rohár #define SERDES_SPEED_1_25_G		0x6
20393433708SPali Rohár #define SERDES_SPEED_3_125_G		0x8
20493433708SPali Rohár #define PHY_RX_INIT_BIT			BIT(30)
20593433708SPali Rohár 
20693433708SPali Rohár /*
20793433708SPali Rohár  * lane0: USB3/GbE1 PHY Status 1
20893433708SPali Rohár  * lane1: PCIe/GbE0 PHY Status 1
20993433708SPali Rohár  * (used only by SGMII code)
21093433708SPali Rohár  */
21193433708SPali Rohár #define COMPHY_PHY_STAT1		0x18
21293433708SPali Rohár #define PHY_RX_INIT_DONE_BIT		BIT(0)
21393433708SPali Rohár #define PHY_PLL_READY_RX_BIT		BIT(2)
21493433708SPali Rohár #define PHY_PLL_READY_TX_BIT		BIT(3)
21593433708SPali Rohár 
21693433708SPali Rohár /* PHY Selector */
21793433708SPali Rohár #define COMPHY_SELECTOR_PHY_REG			0xFC
21893433708SPali Rohár /* bit0: 0: Lane1 is GbE0; 1: Lane1 is PCIe */
21993433708SPali Rohár #define COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT	BIT(0)
22093433708SPali Rohár /* bit4: 0: Lane0 is GbE1; 1: Lane0 is USB3 */
22193433708SPali Rohár #define COMPHY_SELECTOR_USB3_GBE1_SEL_BIT	BIT(4)
22293433708SPali Rohár /* bit8: 0: Lane0 is USB3 instead of GbE1, Lane2 is SATA; 1: Lane2 is USB3 */
22393433708SPali Rohár #define COMPHY_SELECTOR_USB3_PHY_SEL_BIT	BIT(8)
2249695375aSMiquel Raynal 
2259695375aSMiquel Raynal struct mvebu_a3700_comphy_conf {
2269695375aSMiquel Raynal 	unsigned int lane;
2279695375aSMiquel Raynal 	enum phy_mode mode;
2289695375aSMiquel Raynal 	int submode;
2299695375aSMiquel Raynal };
2309695375aSMiquel Raynal 
23193433708SPali Rohár #define MVEBU_A3700_COMPHY_CONF(_lane, _mode, _smode)			\
2329695375aSMiquel Raynal 	{								\
2339695375aSMiquel Raynal 		.lane = _lane,						\
2349695375aSMiquel Raynal 		.mode = _mode,						\
2359695375aSMiquel Raynal 		.submode = _smode,					\
2369695375aSMiquel Raynal 	}
2379695375aSMiquel Raynal 
23893433708SPali Rohár #define MVEBU_A3700_COMPHY_CONF_GEN(_lane, _mode) \
23993433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF(_lane, _mode, PHY_INTERFACE_MODE_NA)
2409695375aSMiquel Raynal 
24193433708SPali Rohár #define MVEBU_A3700_COMPHY_CONF_ETH(_lane, _smode) \
24293433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF(_lane, PHY_MODE_ETHERNET, _smode)
2439695375aSMiquel Raynal 
2449695375aSMiquel Raynal static const struct mvebu_a3700_comphy_conf mvebu_a3700_comphy_modes[] = {
2459695375aSMiquel Raynal 	/* lane 0 */
24693433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_GEN(0, PHY_MODE_USB_HOST_SS),
24793433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_SGMII),
24893433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_1000BASEX),
24993433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_ETH(0, PHY_INTERFACE_MODE_2500BASEX),
2509695375aSMiquel Raynal 	/* lane 1 */
25193433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_GEN(1, PHY_MODE_PCIE),
25293433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_SGMII),
25393433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_1000BASEX),
25493433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_ETH(1, PHY_INTERFACE_MODE_2500BASEX),
2559695375aSMiquel Raynal 	/* lane 2 */
25693433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_SATA),
25793433708SPali Rohár 	MVEBU_A3700_COMPHY_CONF_GEN(2, PHY_MODE_USB_HOST_SS),
25893433708SPali Rohár };
25993433708SPali Rohár 
26093433708SPali Rohár struct mvebu_a3700_comphy_priv {
26193433708SPali Rohár 	void __iomem *comphy_regs;
26293433708SPali Rohár 	void __iomem *lane0_phy_regs; /* USB3 and GbE1 */
26393433708SPali Rohár 	void __iomem *lane1_phy_regs; /* PCIe and GbE0 */
26493433708SPali Rohár 	void __iomem *lane2_phy_indirect; /* SATA and USB3 */
26593433708SPali Rohár 	spinlock_t lock; /* for PHY selector access */
26693433708SPali Rohár 	bool xtal_is_40m;
2679695375aSMiquel Raynal };
2689695375aSMiquel Raynal 
2699695375aSMiquel Raynal struct mvebu_a3700_comphy_lane {
27093433708SPali Rohár 	struct mvebu_a3700_comphy_priv *priv;
2719695375aSMiquel Raynal 	struct device *dev;
2729695375aSMiquel Raynal 	unsigned int id;
2739695375aSMiquel Raynal 	enum phy_mode mode;
2749695375aSMiquel Raynal 	int submode;
27593433708SPali Rohár 	bool invert_tx;
27693433708SPali Rohár 	bool invert_rx;
2779695375aSMiquel Raynal };
2789695375aSMiquel Raynal 
27993433708SPali Rohár struct gbe_phy_init_data_fix {
28093433708SPali Rohár 	u16 addr;
28193433708SPali Rohár 	u16 value;
28293433708SPali Rohár };
28393433708SPali Rohár 
28493433708SPali Rohár /* Changes to 40M1G25 mode data required for running 40M3G125 init mode */
28593433708SPali Rohár static struct gbe_phy_init_data_fix gbe_phy_init_fix[] = {
28693433708SPali Rohár 	{ 0x005, 0x07CC }, { 0x015, 0x0000 }, { 0x01B, 0x0000 },
28793433708SPali Rohár 	{ 0x01D, 0x0000 }, { 0x01E, 0x0000 }, { 0x01F, 0x0000 },
28893433708SPali Rohár 	{ 0x020, 0x0000 }, { 0x021, 0x0030 }, { 0x026, 0x0888 },
28993433708SPali Rohár 	{ 0x04D, 0x0152 }, { 0x04F, 0xA020 }, { 0x050, 0x07CC },
29093433708SPali Rohár 	{ 0x053, 0xE9CA }, { 0x055, 0xBD97 }, { 0x071, 0x3015 },
29193433708SPali Rohár 	{ 0x076, 0x03AA }, { 0x07C, 0x0FDF }, { 0x0C2, 0x3030 },
29293433708SPali Rohár 	{ 0x0C3, 0x8000 }, { 0x0E2, 0x5550 }, { 0x0E3, 0x12A4 },
29393433708SPali Rohár 	{ 0x0E4, 0x7D00 }, { 0x0E6, 0x0C83 }, { 0x101, 0xFCC0 },
29493433708SPali Rohár 	{ 0x104, 0x0C10 }
29593433708SPali Rohár };
29693433708SPali Rohár 
29793433708SPali Rohár /* 40M1G25 mode init data */
29893433708SPali Rohár static u16 gbe_phy_init[512] = {
29993433708SPali Rohár 	/* 0       1       2       3       4       5       6       7 */
30093433708SPali Rohár 	/*-----------------------------------------------------------*/
30193433708SPali Rohár 	/* 8       9       A       B       C       D       E       F */
30293433708SPali Rohár 	0x3110, 0xFD83, 0x6430, 0x412F, 0x82C0, 0x06FA, 0x4500, 0x6D26,	/* 00 */
30393433708SPali Rohár 	0xAFC0, 0x8000, 0xC000, 0x0000, 0x2000, 0x49CC, 0x0BC9, 0x2A52,	/* 08 */
30493433708SPali Rohár 	0x0BD2, 0x0CDE, 0x13D2, 0x0CE8, 0x1149, 0x10E0, 0x0000, 0x0000,	/* 10 */
30593433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x4134, 0x0D2D, 0xFFFF,	/* 18 */
30693433708SPali Rohár 	0xFFE0, 0x4030, 0x1016, 0x0030, 0x0000, 0x0800, 0x0866, 0x0000,	/* 20 */
30793433708SPali Rohár 	0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,	/* 28 */
30893433708SPali Rohár 	0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/* 30 */
30993433708SPali Rohár 	0x0000, 0x0000, 0x000F, 0x6A62, 0x1988, 0x3100, 0x3100, 0x3100,	/* 38 */
31093433708SPali Rohár 	0x3100, 0xA708, 0x2430, 0x0830, 0x1030, 0x4610, 0xFF00, 0xFF00,	/* 40 */
31193433708SPali Rohár 	0x0060, 0x1000, 0x0400, 0x0040, 0x00F0, 0x0155, 0x1100, 0xA02A,	/* 48 */
31293433708SPali Rohár 	0x06FA, 0x0080, 0xB008, 0xE3ED, 0x5002, 0xB592, 0x7A80, 0x0001,	/* 50 */
31393433708SPali Rohár 	0x020A, 0x8820, 0x6014, 0x8054, 0xACAA, 0xFC88, 0x2A02, 0x45CF,	/* 58 */
31493433708SPali Rohár 	0x000F, 0x1817, 0x2860, 0x064F, 0x0000, 0x0204, 0x1800, 0x6000,	/* 60 */
31593433708SPali Rohár 	0x810F, 0x4F23, 0x4000, 0x4498, 0x0850, 0x0000, 0x000E, 0x1002,	/* 68 */
31693433708SPali Rohár 	0x9D3A, 0x3009, 0xD066, 0x0491, 0x0001, 0x6AB0, 0x0399, 0x3780,	/* 70 */
31793433708SPali Rohár 	0x0040, 0x5AC0, 0x4A80, 0x0000, 0x01DF, 0x0000, 0x0007, 0x0000,	/* 78 */
31893433708SPali Rohár 	0x2D54, 0x00A1, 0x4000, 0x0100, 0xA20A, 0x0000, 0x0000, 0x0000,	/* 80 */
31993433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x7400, 0x0E81, 0x1000, 0x1242, 0x0210,	/* 88 */
32093433708SPali Rohár 	0x80DF, 0x0F1F, 0x2F3F, 0x4F5F, 0x6F7F, 0x0F1F, 0x2F3F, 0x4F5F,	/* 90 */
32193433708SPali Rohár 	0x6F7F, 0x4BAD, 0x0000, 0x0000, 0x0800, 0x0000, 0x2400, 0xB651,	/* 98 */
32293433708SPali Rohár 	0xC9E0, 0x4247, 0x0A24, 0x0000, 0xAF19, 0x1004, 0x0000, 0x0000,	/* A0 */
32393433708SPali Rohár 	0x0000, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/* A8 */
32493433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/* B0 */
32593433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0060, 0x0000, 0x0000, 0x0000, 0x0000,	/* B8 */
32693433708SPali Rohár 	0x0000, 0x0000, 0x3010, 0xFA00, 0x0000, 0x0000, 0x0000, 0x0003,	/* C0 */
32793433708SPali Rohár 	0x1618, 0x8200, 0x8000, 0x0400, 0x050F, 0x0000, 0x0000, 0x0000,	/* C8 */
32893433708SPali Rohár 	0x4C93, 0x0000, 0x1000, 0x1120, 0x0010, 0x1242, 0x1242, 0x1E00,	/* D0 */
32993433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x00F8, 0x0000, 0x0041, 0x0800, 0x0000,	/* D8 */
33093433708SPali Rohár 	0x82A0, 0x572E, 0x2490, 0x14A9, 0x4E00, 0x0000, 0x0803, 0x0541,	/* E0 */
33193433708SPali Rohár 	0x0C15, 0x0000, 0x0000, 0x0400, 0x2626, 0x0000, 0x0000, 0x4200,	/* E8 */
33293433708SPali Rohár 	0x0000, 0xAA55, 0x1020, 0x0000, 0x0000, 0x5010, 0x0000, 0x0000,	/* F0 */
33393433708SPali Rohár 	0x0000, 0x0000, 0x5000, 0x0000, 0x0000, 0x0000, 0x02F2, 0x0000,	/* F8 */
33493433708SPali Rohár 	0x101F, 0xFDC0, 0x4000, 0x8010, 0x0110, 0x0006, 0x0000, 0x0000,	/*100 */
33593433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*108 */
33693433708SPali Rohár 	0x04CF, 0x0000, 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04C6, 0x0000,	/*110 */
33793433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*118 */
33893433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*120 */
33993433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*128 */
34093433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*130 */
34193433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*138 */
34293433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*140 */
34393433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*148 */
34493433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*150 */
34593433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*158 */
34693433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*160 */
34793433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*168 */
34893433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*170 */
34993433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x00F0, 0x08A2, 0x3112, 0x0A14, 0x0000,	/*178 */
35093433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*180 */
35193433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*188 */
35293433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*190 */
35393433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*198 */
35493433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1A0 */
35593433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1A8 */
35693433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1B0 */
35793433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1B8 */
35893433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1C0 */
35993433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1C8 */
36093433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1D0 */
36193433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1D8 */
36293433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1E0 */
36393433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1E8 */
36493433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1F0 */
36593433708SPali Rohár 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000	/*1F8 */
36693433708SPali Rohár };
36793433708SPali Rohár 
36893433708SPali Rohár static inline void comphy_reg_set(void __iomem *addr, u32 data, u32 mask)
3699695375aSMiquel Raynal {
37093433708SPali Rohár 	u32 val;
3719695375aSMiquel Raynal 
37293433708SPali Rohár 	val = readl(addr);
37393433708SPali Rohár 	val = (val & ~mask) | (data & mask);
37493433708SPali Rohár 	writel(val, addr);
37593433708SPali Rohár }
3769695375aSMiquel Raynal 
37793433708SPali Rohár static inline void comphy_reg_set16(void __iomem *addr, u16 data, u16 mask)
37893433708SPali Rohár {
37993433708SPali Rohár 	u16 val;
38093433708SPali Rohár 
38193433708SPali Rohár 	val = readw(addr);
38293433708SPali Rohár 	val = (val & ~mask) | (data & mask);
38393433708SPali Rohár 	writew(val, addr);
38493433708SPali Rohár }
38593433708SPali Rohár 
38693433708SPali Rohár /* Used for accessing lane 2 registers (SATA/USB3 PHY) */
38793433708SPali Rohár static void comphy_set_indirect(struct mvebu_a3700_comphy_priv *priv,
38893433708SPali Rohár 				u32 offset, u16 data, u16 mask)
38993433708SPali Rohár {
39093433708SPali Rohár 	writel(offset,
39193433708SPali Rohár 	       priv->lane2_phy_indirect + COMPHY_LANE2_INDIR_ADDR);
39293433708SPali Rohár 	comphy_reg_set(priv->lane2_phy_indirect + COMPHY_LANE2_INDIR_DATA,
39393433708SPali Rohár 		       data, mask);
39493433708SPali Rohár }
39593433708SPali Rohár 
39693433708SPali Rohár static void comphy_lane_reg_set(struct mvebu_a3700_comphy_lane *lane,
39793433708SPali Rohár 				u16 reg, u16 data, u16 mask)
39893433708SPali Rohár {
39993433708SPali Rohár 	if (lane->id == 2) {
40093433708SPali Rohár 		/* lane 2 PHY registers are accessed indirectly */
40193433708SPali Rohár 		comphy_set_indirect(lane->priv,
40293433708SPali Rohár 				    reg + COMPHY_LANE2_REGS_BASE,
40393433708SPali Rohár 				    data, mask);
40493433708SPali Rohár 	} else {
40593433708SPali Rohár 		void __iomem *base = lane->id == 1 ?
40693433708SPali Rohár 				     lane->priv->lane1_phy_regs :
40793433708SPali Rohár 				     lane->priv->lane0_phy_regs;
40893433708SPali Rohár 
40993433708SPali Rohár 		comphy_reg_set16(base + COMPHY_LANE_REG_DIRECT(reg),
41093433708SPali Rohár 				 data, mask);
41193433708SPali Rohár 	}
41293433708SPali Rohár }
41393433708SPali Rohár 
41493433708SPali Rohár static int comphy_lane_reg_poll(struct mvebu_a3700_comphy_lane *lane,
41593433708SPali Rohár 				u16 reg, u16 bits,
41693433708SPali Rohár 				ulong sleep_us, ulong timeout_us)
41793433708SPali Rohár {
41893433708SPali Rohár 	int ret;
41993433708SPali Rohár 
42093433708SPali Rohár 	if (lane->id == 2) {
42193433708SPali Rohár 		u32 data;
42293433708SPali Rohár 
42393433708SPali Rohár 		/* lane 2 PHY registers are accessed indirectly */
42493433708SPali Rohár 		writel(reg + COMPHY_LANE2_REGS_BASE,
42593433708SPali Rohár 		       lane->priv->lane2_phy_indirect +
42693433708SPali Rohár 		       COMPHY_LANE2_INDIR_ADDR);
42793433708SPali Rohár 
42893433708SPali Rohár 		ret = readl_poll_timeout(lane->priv->lane2_phy_indirect +
42993433708SPali Rohár 					 COMPHY_LANE2_INDIR_DATA,
43093433708SPali Rohár 					 data, (data & bits) == bits,
43193433708SPali Rohár 					 sleep_us, timeout_us);
43293433708SPali Rohár 	} else {
43393433708SPali Rohár 		void __iomem *base = lane->id == 1 ?
43493433708SPali Rohár 				     lane->priv->lane1_phy_regs :
43593433708SPali Rohár 				     lane->priv->lane0_phy_regs;
43693433708SPali Rohár 		u16 data;
43793433708SPali Rohár 
43893433708SPali Rohár 		ret = readw_poll_timeout(base + COMPHY_LANE_REG_DIRECT(reg),
43993433708SPali Rohár 					 data, (data & bits) == bits,
44093433708SPali Rohár 					 sleep_us, timeout_us);
44193433708SPali Rohár 	}
44293433708SPali Rohár 
44393433708SPali Rohár 	return ret;
44493433708SPali Rohár }
44593433708SPali Rohár 
44693433708SPali Rohár static void comphy_periph_reg_set(struct mvebu_a3700_comphy_lane *lane,
44793433708SPali Rohár 				  u8 reg, u32 data, u32 mask)
44893433708SPali Rohár {
44993433708SPali Rohár 	comphy_reg_set(lane->priv->comphy_regs + COMPHY_PHY_REG(lane->id, reg),
45093433708SPali Rohár 		       data, mask);
45193433708SPali Rohár }
45293433708SPali Rohár 
45393433708SPali Rohár static int comphy_periph_reg_poll(struct mvebu_a3700_comphy_lane *lane,
45493433708SPali Rohár 				  u8 reg, u32 bits,
45593433708SPali Rohár 				  ulong sleep_us, ulong timeout_us)
45693433708SPali Rohár {
45793433708SPali Rohár 	u32 data;
45893433708SPali Rohár 
45993433708SPali Rohár 	return readl_poll_timeout(lane->priv->comphy_regs +
46093433708SPali Rohár 				  COMPHY_PHY_REG(lane->id, reg),
46193433708SPali Rohár 				  data, (data & bits) == bits,
46293433708SPali Rohár 				  sleep_us, timeout_us);
46393433708SPali Rohár }
46493433708SPali Rohár 
46593433708SPali Rohár /* PHY selector configures with corresponding modes */
46693433708SPali Rohár static int
46793433708SPali Rohár mvebu_a3700_comphy_set_phy_selector(struct mvebu_a3700_comphy_lane *lane)
46893433708SPali Rohár {
46993433708SPali Rohár 	u32 old, new, clr = 0, set = 0;
47093433708SPali Rohár 	unsigned long flags;
47193433708SPali Rohár 
47293433708SPali Rohár 	switch (lane->mode) {
47393433708SPali Rohár 	case PHY_MODE_SATA:
47493433708SPali Rohár 		/* SATA must be in Lane2 */
47593433708SPali Rohár 		if (lane->id == 2)
47693433708SPali Rohár 			clr = COMPHY_SELECTOR_USB3_PHY_SEL_BIT;
47793433708SPali Rohár 		else
47893433708SPali Rohár 			goto error;
47993433708SPali Rohár 		break;
48093433708SPali Rohár 
48193433708SPali Rohár 	case PHY_MODE_ETHERNET:
48293433708SPali Rohár 		if (lane->id == 0)
48393433708SPali Rohár 			clr = COMPHY_SELECTOR_USB3_GBE1_SEL_BIT;
48493433708SPali Rohár 		else if (lane->id == 1)
48593433708SPali Rohár 			clr = COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT;
48693433708SPali Rohár 		else
48793433708SPali Rohár 			goto error;
48893433708SPali Rohár 		break;
48993433708SPali Rohár 
49093433708SPali Rohár 	case PHY_MODE_USB_HOST_SS:
49193433708SPali Rohár 		if (lane->id == 2)
49293433708SPali Rohár 			set = COMPHY_SELECTOR_USB3_PHY_SEL_BIT;
49393433708SPali Rohár 		else if (lane->id == 0)
49493433708SPali Rohár 			set = COMPHY_SELECTOR_USB3_GBE1_SEL_BIT;
49593433708SPali Rohár 		else
49693433708SPali Rohár 			goto error;
49793433708SPali Rohár 		break;
49893433708SPali Rohár 
49993433708SPali Rohár 	case PHY_MODE_PCIE:
50093433708SPali Rohár 		/* PCIE must be in Lane1 */
50193433708SPali Rohár 		if (lane->id == 1)
50293433708SPali Rohár 			set = COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT;
50393433708SPali Rohár 		else
50493433708SPali Rohár 			goto error;
50593433708SPali Rohár 		break;
50693433708SPali Rohár 
507ea17a0f1SPali Rohár 	default:
50893433708SPali Rohár 		goto error;
50993433708SPali Rohár 	}
51093433708SPali Rohár 
51193433708SPali Rohár 	spin_lock_irqsave(&lane->priv->lock, flags);
51293433708SPali Rohár 
51393433708SPali Rohár 	old = readl(lane->priv->comphy_regs + COMPHY_SELECTOR_PHY_REG);
51493433708SPali Rohár 	new = (old & ~clr) | set;
51593433708SPali Rohár 	writel(new, lane->priv->comphy_regs + COMPHY_SELECTOR_PHY_REG);
51693433708SPali Rohár 
51793433708SPali Rohár 	spin_unlock_irqrestore(&lane->priv->lock, flags);
51893433708SPali Rohár 
51993433708SPali Rohár 	dev_dbg(lane->dev,
52093433708SPali Rohár 		"COMPHY[%d] mode[%d] changed PHY selector 0x%08x -> 0x%08x\n",
52193433708SPali Rohár 		lane->id, lane->mode, old, new);
52293433708SPali Rohár 
52393433708SPali Rohár 	return 0;
52493433708SPali Rohár error:
52593433708SPali Rohár 	dev_err(lane->dev, "COMPHY[%d] mode[%d] is invalid\n", lane->id,
52693433708SPali Rohár 		lane->mode);
527ea17a0f1SPali Rohár 	return -EINVAL;
528ea17a0f1SPali Rohár }
52993433708SPali Rohár 
53093433708SPali Rohár static int
53193433708SPali Rohár mvebu_a3700_comphy_sata_power_on(struct mvebu_a3700_comphy_lane *lane)
53293433708SPali Rohár {
53393433708SPali Rohár 	u32 mask, data, ref_clk;
53493433708SPali Rohár 	int ret;
53593433708SPali Rohár 
53693433708SPali Rohár 	/* Configure phy selector for SATA */
53793433708SPali Rohár 	ret = mvebu_a3700_comphy_set_phy_selector(lane);
53893433708SPali Rohár 	if (ret)
53993433708SPali Rohár 		return ret;
54093433708SPali Rohár 
54193433708SPali Rohár 	/* Clear phy isolation mode to make it work in normal mode */
54293433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_ISOLATION_CTRL,
54393433708SPali Rohár 			    0x0, PHY_ISOLATE_MODE);
54493433708SPali Rohár 
54593433708SPali Rohár 	/* 0. Check the Polarity invert bits */
54693433708SPali Rohár 	data = 0x0;
54793433708SPali Rohár 	if (lane->invert_tx)
54893433708SPali Rohár 		data |= TXD_INVERT_BIT;
54993433708SPali Rohár 	if (lane->invert_rx)
55093433708SPali Rohár 		data |= RXD_INVERT_BIT;
55193433708SPali Rohár 	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
55293433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask);
55393433708SPali Rohár 
55493433708SPali Rohár 	/* 1. Select 40-bit data width */
55593433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN,
55693433708SPali Rohár 			    DATA_WIDTH_40BIT, SEL_DATA_WIDTH_MASK);
55793433708SPali Rohár 
55893433708SPali Rohár 	/* 2. Select reference clock(25M) and PHY mode (SATA) */
55993433708SPali Rohár 	if (lane->priv->xtal_is_40m)
56093433708SPali Rohár 		ref_clk = REF_FREF_SEL_SERDES_40MHZ;
56193433708SPali Rohár 	else
56293433708SPali Rohár 		ref_clk = REF_FREF_SEL_SERDES_25MHZ;
56393433708SPali Rohár 
56493433708SPali Rohár 	data = ref_clk | COMPHY_MODE_SATA;
56593433708SPali Rohár 	mask = REF_FREF_SEL_MASK | COMPHY_MODE_MASK;
56693433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask);
56793433708SPali Rohár 
56893433708SPali Rohár 	/* 3. Use maximum PLL rate (no power save) */
56993433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL,
57093433708SPali Rohár 			    USE_MAX_PLL_RATE_BIT, USE_MAX_PLL_RATE_BIT);
57193433708SPali Rohár 
57293433708SPali Rohár 	/* 4. Reset reserved bit */
57393433708SPali Rohár 	comphy_set_indirect(lane->priv, COMPHY_RESERVED_REG,
57493433708SPali Rohár 			    0x0, PHYCTRL_FRM_PIN_BIT);
57593433708SPali Rohár 
57693433708SPali Rohár 	/* 5. Set vendor-specific configuration (It is done in sata driver) */
57793433708SPali Rohár 	/* XXX: in U-Boot below sequence was executed in this place, in Linux
57893433708SPali Rohár 	 * not.  Now it is done only in U-Boot before this comphy
57993433708SPali Rohár 	 * initialization - tests shows that it works ok, but in case of any
58093433708SPali Rohár 	 * future problem it is left for reference.
58193433708SPali Rohár 	 *   reg_set(MVEBU_REGS_BASE + 0xe00a0, 0, 0xffffffff);
58293433708SPali Rohár 	 *   reg_set(MVEBU_REGS_BASE + 0xe00a4, BIT(6), BIT(6));
58393433708SPali Rohár 	 */
58493433708SPali Rohár 
58593433708SPali Rohár 	/* Wait for > 55 us to allow PLL be enabled */
58693433708SPali Rohár 	udelay(PLL_SET_DELAY_US);
58793433708SPali Rohár 
58893433708SPali Rohár 	/* Polling status */
58993433708SPali Rohár 	ret = comphy_lane_reg_poll(lane, COMPHY_DIG_LOOPBACK_EN,
59093433708SPali Rohár 				   PLL_READY_TX_BIT, COMPHY_PLL_SLEEP,
59193433708SPali Rohár 				   COMPHY_PLL_TIMEOUT);
59293433708SPali Rohár 	if (ret)
59393433708SPali Rohár 		dev_err(lane->dev, "Failed to lock SATA PLL\n");
59493433708SPali Rohár 
59593433708SPali Rohár 	return ret;
5969695375aSMiquel Raynal }
5979695375aSMiquel Raynal 
59893433708SPali Rohár static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane,
59993433708SPali Rohár 				bool is_1gbps)
60093433708SPali Rohár {
60193433708SPali Rohár 	int addr, fix_idx;
60293433708SPali Rohár 	u16 val;
60393433708SPali Rohár 
60493433708SPali Rohár 	fix_idx = 0;
60593433708SPali Rohár 	for (addr = 0; addr < 512; addr++) {
60693433708SPali Rohár 		/*
60793433708SPali Rohár 		 * All PHY register values are defined in full for 3.125Gbps
60893433708SPali Rohár 		 * SERDES speed. The values required for 1.25 Gbps are almost
60993433708SPali Rohár 		 * the same and only few registers should be "fixed" in
61093433708SPali Rohár 		 * comparison to 3.125 Gbps values. These register values are
61193433708SPali Rohár 		 * stored in "gbe_phy_init_fix" array.
61293433708SPali Rohár 		 */
61393433708SPali Rohár 		if (!is_1gbps && gbe_phy_init_fix[fix_idx].addr == addr) {
61493433708SPali Rohár 			/* Use new value */
61593433708SPali Rohár 			val = gbe_phy_init_fix[fix_idx].value;
61693433708SPali Rohár 			if (fix_idx < ARRAY_SIZE(gbe_phy_init_fix))
61793433708SPali Rohár 				fix_idx++;
61893433708SPali Rohár 		} else {
61993433708SPali Rohár 			val = gbe_phy_init[addr];
62093433708SPali Rohár 		}
62193433708SPali Rohár 
62293433708SPali Rohár 		comphy_lane_reg_set(lane, addr, val, 0xFFFF);
62393433708SPali Rohár 	}
62493433708SPali Rohár }
62593433708SPali Rohár 
62693433708SPali Rohár static int
62793433708SPali Rohár mvebu_a3700_comphy_ethernet_power_on(struct mvebu_a3700_comphy_lane *lane)
62893433708SPali Rohár {
62993433708SPali Rohár 	u32 mask, data, speed_sel;
63093433708SPali Rohár 	int ret;
63193433708SPali Rohár 
63293433708SPali Rohár 	/* Set selector */
63393433708SPali Rohár 	ret = mvebu_a3700_comphy_set_phy_selector(lane);
63493433708SPali Rohár 	if (ret)
63593433708SPali Rohár 		return ret;
63693433708SPali Rohár 
63793433708SPali Rohár 	/*
63893433708SPali Rohár 	 * 1. Reset PHY by setting PHY input port PIN_RESET=1.
63993433708SPali Rohár 	 * 2. Set PHY input port PIN_TX_IDLE=1, PIN_PU_IVREF=1 to keep
64093433708SPali Rohár 	 *    PHY TXP/TXN output to idle state during PHY initialization
64193433708SPali Rohár 	 * 3. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0.
64293433708SPali Rohár 	 */
64393433708SPali Rohár 	data = PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT | PIN_RESET_COMPHY_BIT;
64493433708SPali Rohár 	mask = data | PIN_RESET_CORE_BIT | PIN_PU_PLL_BIT | PIN_PU_RX_BIT |
64593433708SPali Rohár 	       PIN_PU_TX_BIT | PHY_RX_INIT_BIT;
64693433708SPali Rohár 	comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
64793433708SPali Rohár 
64893433708SPali Rohár 	/* 4. Release reset to the PHY by setting PIN_RESET=0. */
64993433708SPali Rohár 	data = 0x0;
65093433708SPali Rohár 	mask = PIN_RESET_COMPHY_BIT;
65193433708SPali Rohár 	comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
65293433708SPali Rohár 
65393433708SPali Rohár 	/*
65493433708SPali Rohár 	 * 5. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide COMPHY
65593433708SPali Rohár 	 * bit rate
65693433708SPali Rohár 	 */
65793433708SPali Rohár 	switch (lane->submode) {
65893433708SPali Rohár 	case PHY_INTERFACE_MODE_SGMII:
65993433708SPali Rohár 	case PHY_INTERFACE_MODE_1000BASEX:
66093433708SPali Rohár 		/* SGMII 1G, SerDes speed 1.25G */
66193433708SPali Rohár 		speed_sel = SERDES_SPEED_1_25_G;
66293433708SPali Rohár 		break;
66393433708SPali Rohár 	case PHY_INTERFACE_MODE_2500BASEX:
66493433708SPali Rohár 		/* 2500Base-X, SerDes speed 3.125G */
66593433708SPali Rohár 		speed_sel = SERDES_SPEED_3_125_G;
66693433708SPali Rohár 		break;
66793433708SPali Rohár 	default:
66893433708SPali Rohár 		/* Other rates are not supported */
66993433708SPali Rohár 		dev_err(lane->dev,
67093433708SPali Rohár 			"unsupported phy speed %d on comphy lane%d\n",
67193433708SPali Rohár 			lane->submode, lane->id);
67293433708SPali Rohár 		return -EINVAL;
67393433708SPali Rohár 	}
67493433708SPali Rohár 	data = GEN_RX_SEL_VALUE(speed_sel) | GEN_TX_SEL_VALUE(speed_sel);
67593433708SPali Rohár 	mask = GEN_RX_SEL_MASK | GEN_TX_SEL_MASK;
67693433708SPali Rohár 	comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
67793433708SPali Rohár 
67893433708SPali Rohár 	/*
67993433708SPali Rohár 	 * 6. Wait 10mS for bandgap and reference clocks to stabilize; then
68093433708SPali Rohár 	 * start SW programming.
68193433708SPali Rohár 	 */
68293433708SPali Rohár 	mdelay(10);
68393433708SPali Rohár 
68493433708SPali Rohár 	/* 7. Program COMPHY register PHY_MODE */
68593433708SPali Rohár 	data = COMPHY_MODE_SERDES;
68693433708SPali Rohár 	mask = COMPHY_MODE_MASK;
68793433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask);
68893433708SPali Rohár 
68993433708SPali Rohár 	/*
69093433708SPali Rohár 	 * 8. Set COMPHY register REFCLK_SEL to select the correct REFCLK
69193433708SPali Rohár 	 * source
69293433708SPali Rohár 	 */
69393433708SPali Rohár 	data = 0x0;
69493433708SPali Rohár 	mask = PHY_REF_CLK_SEL;
69593433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, data, mask);
69693433708SPali Rohár 
69793433708SPali Rohár 	/*
69893433708SPali Rohár 	 * 9. Set correct reference clock frequency in COMPHY register
69993433708SPali Rohár 	 * REF_FREF_SEL.
70093433708SPali Rohár 	 */
70193433708SPali Rohár 	if (lane->priv->xtal_is_40m)
70293433708SPali Rohár 		data = REF_FREF_SEL_SERDES_50MHZ;
70393433708SPali Rohár 	else
70493433708SPali Rohár 		data = REF_FREF_SEL_SERDES_25MHZ;
70593433708SPali Rohár 
70693433708SPali Rohár 	mask = REF_FREF_SEL_MASK;
70793433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask);
70893433708SPali Rohár 
70993433708SPali Rohár 	/*
71093433708SPali Rohár 	 * 10. Program COMPHY register PHY_GEN_MAX[1:0]
71193433708SPali Rohár 	 * This step is mentioned in the flow received from verification team.
71293433708SPali Rohár 	 * However the PHY_GEN_MAX value is only meaningful for other interfaces
71393433708SPali Rohár 	 * (not SERDES). For instance, it selects SATA speed 1.5/3/6 Gbps or
71493433708SPali Rohár 	 * PCIe speed 2.5/5 Gbps
71593433708SPali Rohár 	 */
71693433708SPali Rohár 
71793433708SPali Rohár 	/*
71893433708SPali Rohár 	 * 11. Program COMPHY register SEL_BITS to set correct parallel data
71993433708SPali Rohár 	 * bus width
72093433708SPali Rohár 	 */
72193433708SPali Rohár 	data = DATA_WIDTH_10BIT;
72293433708SPali Rohár 	mask = SEL_DATA_WIDTH_MASK;
72393433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN, data, mask);
72493433708SPali Rohár 
72593433708SPali Rohár 	/*
72693433708SPali Rohár 	 * 12. As long as DFE function needs to be enabled in any mode,
72793433708SPali Rohár 	 * COMPHY register DFE_UPDATE_EN[5:0] shall be programmed to 0x3F
72893433708SPali Rohár 	 * for real chip during COMPHY power on.
72993433708SPali Rohár 	 * The value of the DFE_UPDATE_EN already is 0x3F, because it is the
73093433708SPali Rohár 	 * default value after reset of the PHY.
73193433708SPali Rohár 	 */
73293433708SPali Rohár 
73393433708SPali Rohár 	/*
73493433708SPali Rohár 	 * 13. Program COMPHY GEN registers.
73593433708SPali Rohár 	 * These registers should be programmed based on the lab testing result
73693433708SPali Rohár 	 * to achieve optimal performance. Please contact the CEA group to get
73793433708SPali Rohár 	 * the related GEN table during real chip bring-up. We only required to
73893433708SPali Rohár 	 * run though the entire registers programming flow defined by
73993433708SPali Rohár 	 * "comphy_gbe_phy_init" when the REF clock is 40 MHz. For REF clock
74093433708SPali Rohár 	 * 25 MHz the default values stored in PHY registers are OK.
74193433708SPali Rohár 	 */
74293433708SPali Rohár 	dev_dbg(lane->dev, "Running C-DPI phy init %s mode\n",
74393433708SPali Rohár 		lane->submode == PHY_INTERFACE_MODE_2500BASEX ? "2G5" : "1G");
74493433708SPali Rohár 	if (lane->priv->xtal_is_40m)
74593433708SPali Rohár 		comphy_gbe_phy_init(lane,
74693433708SPali Rohár 				    lane->submode != PHY_INTERFACE_MODE_2500BASEX);
74793433708SPali Rohár 
74893433708SPali Rohár 	/*
74993433708SPali Rohár 	 * 14. Check the PHY Polarity invert bit
75093433708SPali Rohár 	 */
75193433708SPali Rohár 	data = 0x0;
75293433708SPali Rohár 	if (lane->invert_tx)
75393433708SPali Rohár 		data |= TXD_INVERT_BIT;
75493433708SPali Rohár 	if (lane->invert_rx)
75593433708SPali Rohár 		data |= RXD_INVERT_BIT;
75693433708SPali Rohár 	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
75793433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask);
75893433708SPali Rohár 
75993433708SPali Rohár 	/*
76093433708SPali Rohár 	 * 15. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 to
76193433708SPali Rohár 	 * start PHY power up sequence. All the PHY register programming should
76293433708SPali Rohár 	 * be done before PIN_PU_PLL=1. There should be no register programming
76393433708SPali Rohár 	 * for normal PHY operation from this point.
76493433708SPali Rohár 	 */
76593433708SPali Rohár 	data = PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT;
76693433708SPali Rohár 	mask = data;
76793433708SPali Rohár 	comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
76893433708SPali Rohár 
76993433708SPali Rohár 	/*
77093433708SPali Rohár 	 * 16. Wait for PHY power up sequence to finish by checking output ports
77193433708SPali Rohár 	 * PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1.
77293433708SPali Rohár 	 */
77393433708SPali Rohár 	ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1,
77493433708SPali Rohár 				     PHY_PLL_READY_TX_BIT |
77593433708SPali Rohár 				     PHY_PLL_READY_RX_BIT,
77693433708SPali Rohár 				     COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT);
77793433708SPali Rohár 	if (ret) {
77893433708SPali Rohár 		dev_err(lane->dev, "Failed to lock PLL for SERDES PHY %d\n",
77993433708SPali Rohár 			lane->id);
78093433708SPali Rohár 		return ret;
78193433708SPali Rohár 	}
78293433708SPali Rohár 
78393433708SPali Rohár 	/*
78493433708SPali Rohár 	 * 17. Set COMPHY input port PIN_TX_IDLE=0
78593433708SPali Rohár 	 */
78693433708SPali Rohár 	comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, 0x0, PIN_TX_IDLE_BIT);
78793433708SPali Rohár 
78893433708SPali Rohár 	/*
78993433708SPali Rohár 	 * 18. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1. To
79093433708SPali Rohár 	 * start RX initialization. PIN_RX_INIT_DONE will be cleared to 0 by the
79193433708SPali Rohár 	 * PHY After RX initialization is done, PIN_RX_INIT_DONE will be set to
79293433708SPali Rohár 	 * 1 by COMPHY Set PIN_RX_INIT=0 after PIN_RX_INIT_DONE= 1. Please
79393433708SPali Rohár 	 * refer to RX initialization part for details.
79493433708SPali Rohár 	 */
79593433708SPali Rohár 	comphy_periph_reg_set(lane, COMPHY_PHY_CFG1,
79693433708SPali Rohár 			      PHY_RX_INIT_BIT, PHY_RX_INIT_BIT);
79793433708SPali Rohár 
79893433708SPali Rohár 	ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1,
79993433708SPali Rohár 				     PHY_PLL_READY_TX_BIT |
80093433708SPali Rohár 				     PHY_PLL_READY_RX_BIT,
80193433708SPali Rohár 				     COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT);
80293433708SPali Rohár 	if (ret) {
80393433708SPali Rohár 		dev_err(lane->dev, "Failed to lock PLL for SERDES PHY %d\n",
80493433708SPali Rohár 			lane->id);
80593433708SPali Rohár 		return ret;
80693433708SPali Rohár 	}
80793433708SPali Rohár 
80893433708SPali Rohár 	ret = comphy_periph_reg_poll(lane, COMPHY_PHY_STAT1,
80993433708SPali Rohár 				     PHY_RX_INIT_DONE_BIT,
81093433708SPali Rohár 				     COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT);
81193433708SPali Rohár 	if (ret)
81293433708SPali Rohár 		dev_err(lane->dev, "Failed to init RX of SERDES PHY %d\n",
81393433708SPali Rohár 			lane->id);
81493433708SPali Rohár 
81593433708SPali Rohár 	return ret;
81693433708SPali Rohár }
81793433708SPali Rohár 
81893433708SPali Rohár static int
81993433708SPali Rohár mvebu_a3700_comphy_usb3_power_on(struct mvebu_a3700_comphy_lane *lane)
82093433708SPali Rohár {
82193433708SPali Rohár 	u32 mask, data, cfg, ref_clk;
82293433708SPali Rohár 	int ret;
82393433708SPali Rohár 
82493433708SPali Rohár 	/* Set phy seclector */
82593433708SPali Rohár 	ret = mvebu_a3700_comphy_set_phy_selector(lane);
82693433708SPali Rohár 	if (ret)
82793433708SPali Rohár 		return ret;
82893433708SPali Rohár 
82993433708SPali Rohár 	/*
83093433708SPali Rohár 	 * 0. Set PHY OTG Control(0x5d034), bit 4, Power up OTG module The
83193433708SPali Rohár 	 * register belong to UTMI module, so it is set in UTMI phy driver.
83293433708SPali Rohár 	 */
83393433708SPali Rohár 
83493433708SPali Rohár 	/*
83593433708SPali Rohár 	 * 1. Set PRD_TXDEEMPH (3.5db de-emph)
83693433708SPali Rohár 	 */
83793433708SPali Rohár 	data = PRD_TXDEEMPH0_MASK;
83893433708SPali Rohár 	mask = PRD_TXDEEMPH0_MASK | PRD_TXMARGIN_MASK | PRD_TXSWING_MASK |
83993433708SPali Rohár 	       CFG_TX_ALIGN_POS_MASK;
84093433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG0, data, mask);
84193433708SPali Rohár 
84293433708SPali Rohár 	/*
84393433708SPali Rohár 	 * 2. Set BIT0: enable transmitter in high impedance mode
84493433708SPali Rohár 	 *    Set BIT[3:4]: delay 2 clock cycles for HiZ off latency
84593433708SPali Rohár 	 *    Set BIT6: Tx detect Rx at HiZ mode
84693433708SPali Rohár 	 *    Unset BIT15: set to 0 to set USB3 De-emphasize level to -3.5db
84793433708SPali Rohár 	 *            together with bit 0 of COMPHY_PIPE_LANE_CFG0 register
84893433708SPali Rohár 	 */
84993433708SPali Rohár 	data = TX_DET_RX_MODE | GEN2_TX_DATA_DLY_DEFT | TX_ELEC_IDLE_MODE_EN;
85093433708SPali Rohár 	mask = PRD_TXDEEMPH1_MASK | TX_DET_RX_MODE | GEN2_TX_DATA_DLY_MASK |
85193433708SPali Rohár 	       TX_ELEC_IDLE_MODE_EN;
85293433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG1, data, mask);
85393433708SPali Rohár 
85493433708SPali Rohár 	/*
85593433708SPali Rohár 	 * 3. Set Spread Spectrum Clock Enabled
85693433708SPali Rohár 	 */
85793433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG4,
85893433708SPali Rohár 			    SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN);
85993433708SPali Rohár 
86093433708SPali Rohár 	/*
86193433708SPali Rohár 	 * 4. Set Override Margining Controls From the MAC:
86293433708SPali Rohár 	 *    Use margining signals from lane configuration
86393433708SPali Rohár 	 */
86493433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_TEST_MODE_CTRL,
86593433708SPali Rohár 			    MODE_MARGIN_OVERRIDE, 0xFFFF);
86693433708SPali Rohár 
86793433708SPali Rohár 	/*
86893433708SPali Rohár 	 * 5. Set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles
86993433708SPali Rohár 	 *    set Mode Clock Source = PCLK is generated from REFCLK
87093433708SPali Rohár 	 */
87193433708SPali Rohár 	data = 0x0;
87293433708SPali Rohár 	mask = MODE_CLK_SRC | BUNDLE_PERIOD_SEL | BUNDLE_PERIOD_SCALE_MASK |
87393433708SPali Rohár 	       BUNDLE_SAMPLE_CTRL | PLL_READY_DLY_MASK;
87493433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_CLK_SRC_LO, data, mask);
87593433708SPali Rohár 
87693433708SPali Rohár 	/*
87793433708SPali Rohár 	 * 6. Set G2 Spread Spectrum Clock Amplitude at 4K
87893433708SPali Rohár 	 */
87993433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_GEN2_SET2,
88093433708SPali Rohár 			    GS2_TX_SSC_AMP_4128, GS2_TX_SSC_AMP_MASK);
88193433708SPali Rohár 
88293433708SPali Rohár 	/*
88393433708SPali Rohár 	 * 7. Unset G3 Spread Spectrum Clock Amplitude
88493433708SPali Rohár 	 *    set G3 TX and RX Register Master Current Select
88593433708SPali Rohár 	 */
88693433708SPali Rohár 	data = GS2_VREG_RXTX_MAS_ISET_60U;
88793433708SPali Rohár 	mask = GS2_TX_SSC_AMP_MASK | GS2_VREG_RXTX_MAS_ISET_MASK |
88893433708SPali Rohár 	       GS2_RSVD_6_0_MASK;
88993433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_GEN3_SET2, data, mask);
89093433708SPali Rohár 
89193433708SPali Rohár 	/*
89293433708SPali Rohár 	 * 8. Check crystal jumper setting and program the Power and PLL Control
89393433708SPali Rohár 	 * accordingly Change RX wait
89493433708SPali Rohár 	 */
89593433708SPali Rohár 	if (lane->priv->xtal_is_40m) {
89693433708SPali Rohár 		ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ;
89793433708SPali Rohár 		cfg = CFG_PM_RXDLOZ_WAIT_12_UNIT;
89893433708SPali Rohár 	} else {
89993433708SPali Rohár 		ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ;
90093433708SPali Rohár 		cfg = CFG_PM_RXDLOZ_WAIT_7_UNIT;
90193433708SPali Rohár 	}
90293433708SPali Rohár 
90393433708SPali Rohár 	data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT |
90493433708SPali Rohár 	       PU_TX_INTP_BIT | PU_DFE_BIT | COMPHY_MODE_USB3 | ref_clk;
90593433708SPali Rohár 	mask = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT |
90693433708SPali Rohár 	       PU_TX_INTP_BIT | PU_DFE_BIT | PLL_LOCK_BIT | COMPHY_MODE_MASK |
90793433708SPali Rohár 	       REF_FREF_SEL_MASK;
90893433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask);
90993433708SPali Rohár 
91093433708SPali Rohár 	data = CFG_PM_RXDEN_WAIT_1_UNIT | cfg;
91193433708SPali Rohár 	mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK |
91293433708SPali Rohár 	       CFG_PM_RXDLOZ_WAIT_MASK;
91393433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_PWR_MGM_TIM1, data, mask);
91493433708SPali Rohár 
91593433708SPali Rohár 	/*
91693433708SPali Rohár 	 * 9. Enable idle sync
91793433708SPali Rohár 	 */
91893433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_IDLE_SYNC_EN,
91993433708SPali Rohár 			    IDLE_SYNC_EN, IDLE_SYNC_EN);
92093433708SPali Rohár 
92193433708SPali Rohár 	/*
92293433708SPali Rohár 	 * 10. Enable the output of 500M clock
92393433708SPali Rohár 	 */
92493433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, CLK500M_EN, CLK500M_EN);
92593433708SPali Rohár 
92693433708SPali Rohár 	/*
92793433708SPali Rohár 	 * 11. Set 20-bit data width
92893433708SPali Rohár 	 */
92993433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_DIG_LOOPBACK_EN,
93093433708SPali Rohár 			    DATA_WIDTH_20BIT, 0xFFFF);
93193433708SPali Rohár 
93293433708SPali Rohár 	/*
93393433708SPali Rohár 	 * 12. Override Speed_PLL value and use MAC PLL
93493433708SPali Rohár 	 */
93593433708SPali Rohár 	data = SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT;
93693433708SPali Rohár 	mask = 0xFFFF;
93793433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL, data, mask);
93893433708SPali Rohár 
93993433708SPali Rohár 	/*
94093433708SPali Rohár 	 * 13. Check the Polarity invert bit
94193433708SPali Rohár 	 */
94293433708SPali Rohár 	data = 0x0;
94393433708SPali Rohár 	if (lane->invert_tx)
94493433708SPali Rohár 		data |= TXD_INVERT_BIT;
94593433708SPali Rohár 	if (lane->invert_rx)
94693433708SPali Rohár 		data |= RXD_INVERT_BIT;
94793433708SPali Rohár 	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
94893433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask);
94993433708SPali Rohár 
95093433708SPali Rohár 	/*
95193433708SPali Rohár 	 * 14. Set max speed generation to USB3.0 5Gbps
95293433708SPali Rohár 	 */
95393433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_SYNC_MASK_GEN,
95493433708SPali Rohár 			    PHY_GEN_MAX_USB3_5G, PHY_GEN_MAX_MASK);
95593433708SPali Rohár 
95693433708SPali Rohár 	/*
95793433708SPali Rohár 	 * 15. Set capacitor value for FFE gain peaking to 0xF
95893433708SPali Rohár 	 */
95993433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_GEN2_SET3,
96093433708SPali Rohár 			    GS3_FFE_CAP_SEL_VALUE, GS3_FFE_CAP_SEL_MASK);
96193433708SPali Rohár 
96293433708SPali Rohár 	/*
96393433708SPali Rohár 	 * 16. Release SW reset
96493433708SPali Rohár 	 */
96593433708SPali Rohár 	data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32 | MODE_REFDIV_BY_4;
96693433708SPali Rohár 	mask = 0xFFFF;
96793433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, data, mask);
96893433708SPali Rohár 
96993433708SPali Rohár 	/* Wait for > 55 us to allow PCLK be enabled */
97093433708SPali Rohár 	udelay(PLL_SET_DELAY_US);
97193433708SPali Rohár 
97293433708SPali Rohár 	ret = comphy_lane_reg_poll(lane, COMPHY_PIPE_LANE_STAT1, TXDCLK_PCLK_EN,
97393433708SPali Rohár 				   COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT);
97493433708SPali Rohár 	if (ret)
97593433708SPali Rohár 		dev_err(lane->dev, "Failed to lock USB3 PLL\n");
97693433708SPali Rohár 
97793433708SPali Rohár 	return ret;
97893433708SPali Rohár }
97993433708SPali Rohár 
98093433708SPali Rohár static int
98193433708SPali Rohár mvebu_a3700_comphy_pcie_power_on(struct mvebu_a3700_comphy_lane *lane)
98293433708SPali Rohár {
98393433708SPali Rohár 	u32 mask, data, ref_clk;
98493433708SPali Rohár 	int ret;
98593433708SPali Rohár 
98693433708SPali Rohár 	/* Configure phy selector for PCIe */
98793433708SPali Rohár 	ret = mvebu_a3700_comphy_set_phy_selector(lane);
98893433708SPali Rohár 	if (ret)
98993433708SPali Rohár 		return ret;
99093433708SPali Rohár 
99193433708SPali Rohár 	/* 1. Enable max PLL. */
99293433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_LANE_CFG1,
99393433708SPali Rohár 			    USE_MAX_PLL_RATE_EN, USE_MAX_PLL_RATE_EN);
99493433708SPali Rohár 
99593433708SPali Rohár 	/* 2. Select 20 bit SERDES interface. */
99693433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_CLK_SRC_LO,
99793433708SPali Rohár 			    CFG_SEL_20B, CFG_SEL_20B);
99893433708SPali Rohár 
99993433708SPali Rohár 	/* 3. Force to use reg setting for PCIe mode */
100093433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_MISC_CTRL1,
100193433708SPali Rohár 			    SEL_BITS_PCIE_FORCE, SEL_BITS_PCIE_FORCE);
100293433708SPali Rohár 
100393433708SPali Rohár 	/* 4. Change RX wait */
100493433708SPali Rohár 	data = CFG_PM_RXDEN_WAIT_1_UNIT | CFG_PM_RXDLOZ_WAIT_12_UNIT;
100593433708SPali Rohár 	mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK |
100693433708SPali Rohár 	       CFG_PM_RXDLOZ_WAIT_MASK;
100793433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_PWR_MGM_TIM1, data, mask);
100893433708SPali Rohár 
100993433708SPali Rohár 	/* 5. Enable idle sync */
101093433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_IDLE_SYNC_EN,
101193433708SPali Rohár 			    IDLE_SYNC_EN, IDLE_SYNC_EN);
101293433708SPali Rohár 
101393433708SPali Rohár 	/* 6. Enable the output of 100M/125M/500M clock */
101493433708SPali Rohár 	data = CLK500M_EN | TXDCLK_2X_SEL | CLK100M_125M_EN;
101593433708SPali Rohár 	mask = data;
101693433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_MISC_CTRL0, data, mask);
101793433708SPali Rohár 
101893433708SPali Rohár 	/*
101993433708SPali Rohár 	 * 7. Enable TX, PCIE global register, 0xd0074814, it is done in
102093433708SPali Rohár 	 * PCI-E driver
102193433708SPali Rohár 	 */
102293433708SPali Rohár 
102393433708SPali Rohár 	/*
102493433708SPali Rohár 	 * 8. Check crystal jumper setting and program the Power and PLL
102593433708SPali Rohár 	 * Control accordingly
102693433708SPali Rohár 	 */
102793433708SPali Rohár 
102893433708SPali Rohár 	if (lane->priv->xtal_is_40m)
102993433708SPali Rohár 		ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ;
103093433708SPali Rohár 	else
103193433708SPali Rohár 		ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ;
103293433708SPali Rohár 
103393433708SPali Rohár 	data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT |
103493433708SPali Rohár 	       PU_TX_INTP_BIT | PU_DFE_BIT | COMPHY_MODE_PCIE | ref_clk;
103593433708SPali Rohár 	mask = 0xFFFF;
103693433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL, data, mask);
103793433708SPali Rohár 
103893433708SPali Rohár 	/* 9. Override Speed_PLL value and use MAC PLL */
103993433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_KVCO_CAL_CTRL,
104093433708SPali Rohár 			    SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT,
104193433708SPali Rohár 			    0xFFFF);
104293433708SPali Rohár 
104393433708SPali Rohár 	/* 10. Check the Polarity invert bit */
104493433708SPali Rohár 	data = 0x0;
104593433708SPali Rohár 	if (lane->invert_tx)
104693433708SPali Rohár 		data |= TXD_INVERT_BIT;
104793433708SPali Rohár 	if (lane->invert_rx)
104893433708SPali Rohár 		data |= RXD_INVERT_BIT;
104993433708SPali Rohár 	mask = TXD_INVERT_BIT | RXD_INVERT_BIT;
105093433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_SYNC_PATTERN, data, mask);
105193433708SPali Rohár 
105293433708SPali Rohár 	/* 11. Release SW reset */
105393433708SPali Rohár 	data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32;
105493433708SPali Rohár 	mask = data | PIPE_SOFT_RESET | MODE_REFDIV_MASK;
105593433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_PIPE_RST_CLK_CTRL, data, mask);
105693433708SPali Rohár 
105793433708SPali Rohár 	/* Wait for > 55 us to allow PCLK be enabled */
105893433708SPali Rohár 	udelay(PLL_SET_DELAY_US);
105993433708SPali Rohár 
106093433708SPali Rohár 	ret = comphy_lane_reg_poll(lane, COMPHY_PIPE_LANE_STAT1, TXDCLK_PCLK_EN,
106193433708SPali Rohár 				   COMPHY_PLL_SLEEP, COMPHY_PLL_TIMEOUT);
106293433708SPali Rohár 	if (ret)
106393433708SPali Rohár 		dev_err(lane->dev, "Failed to lock PCIE PLL\n");
106493433708SPali Rohár 
106593433708SPali Rohár 	return ret;
106693433708SPali Rohár }
106793433708SPali Rohár 
106893433708SPali Rohár static void
106993433708SPali Rohár mvebu_a3700_comphy_sata_power_off(struct mvebu_a3700_comphy_lane *lane)
107093433708SPali Rohár {
107193433708SPali Rohár 	/* Set phy isolation mode */
107293433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_ISOLATION_CTRL,
107393433708SPali Rohár 			    PHY_ISOLATE_MODE, PHY_ISOLATE_MODE);
107493433708SPali Rohár 
107593433708SPali Rohár 	/* Power off PLL, Tx, Rx */
107693433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL,
107793433708SPali Rohár 			    0x0, PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT);
107893433708SPali Rohár }
107993433708SPali Rohár 
108093433708SPali Rohár static void
108193433708SPali Rohár mvebu_a3700_comphy_ethernet_power_off(struct mvebu_a3700_comphy_lane *lane)
108293433708SPali Rohár {
108393433708SPali Rohár 	u32 mask, data;
108493433708SPali Rohár 
108593433708SPali Rohár 	data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT | PIN_PU_IVREF_BIT |
108693433708SPali Rohár 	       PHY_RX_INIT_BIT;
108793433708SPali Rohár 	mask = data;
108893433708SPali Rohár 	comphy_periph_reg_set(lane, COMPHY_PHY_CFG1, data, mask);
108993433708SPali Rohár }
109093433708SPali Rohár 
109193433708SPali Rohár static void
109293433708SPali Rohár mvebu_a3700_comphy_pcie_power_off(struct mvebu_a3700_comphy_lane *lane)
109393433708SPali Rohár {
109493433708SPali Rohár 	/* Power off PLL, Tx, Rx */
109593433708SPali Rohár 	comphy_lane_reg_set(lane, COMPHY_POWER_PLL_CTRL,
109693433708SPali Rohár 			    0x0, PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT);
109793433708SPali Rohár }
109893433708SPali Rohár 
1099*0a6fc70dSPali Rohár static void mvebu_a3700_comphy_usb3_power_off(struct mvebu_a3700_comphy_lane *lane)
110093433708SPali Rohár {
1101*0a6fc70dSPali Rohár 	/*
1102*0a6fc70dSPali Rohár 	 * The USB3 MAC sets the USB3 PHY to low state, so we do not
1103*0a6fc70dSPali Rohár 	 * need to power off USB3 PHY again.
1104*0a6fc70dSPali Rohár 	 */
110593433708SPali Rohár }
110693433708SPali Rohár 
110793433708SPali Rohár static bool mvebu_a3700_comphy_check_mode(int lane,
11089695375aSMiquel Raynal 					  enum phy_mode mode,
11099695375aSMiquel Raynal 					  int submode)
11109695375aSMiquel Raynal {
11119695375aSMiquel Raynal 	int i, n = ARRAY_SIZE(mvebu_a3700_comphy_modes);
11129695375aSMiquel Raynal 
11139695375aSMiquel Raynal 	/* Unused PHY mux value is 0x0 */
11149695375aSMiquel Raynal 	if (mode == PHY_MODE_INVALID)
111593433708SPali Rohár 		return false;
11169695375aSMiquel Raynal 
11179695375aSMiquel Raynal 	for (i = 0; i < n; i++) {
11189695375aSMiquel Raynal 		if (mvebu_a3700_comphy_modes[i].lane == lane &&
11199695375aSMiquel Raynal 		    mvebu_a3700_comphy_modes[i].mode == mode &&
11209695375aSMiquel Raynal 		    mvebu_a3700_comphy_modes[i].submode == submode)
11219695375aSMiquel Raynal 			break;
11229695375aSMiquel Raynal 	}
11239695375aSMiquel Raynal 
11249695375aSMiquel Raynal 	if (i == n)
112593433708SPali Rohár 		return false;
11269695375aSMiquel Raynal 
112793433708SPali Rohár 	return true;
11289695375aSMiquel Raynal }
11299695375aSMiquel Raynal 
11309695375aSMiquel Raynal static int mvebu_a3700_comphy_set_mode(struct phy *phy, enum phy_mode mode,
11319695375aSMiquel Raynal 				       int submode)
11329695375aSMiquel Raynal {
11339695375aSMiquel Raynal 	struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
11349695375aSMiquel Raynal 
113593433708SPali Rohár 	if (!mvebu_a3700_comphy_check_mode(lane->id, mode, submode)) {
11369695375aSMiquel Raynal 		dev_err(lane->dev, "invalid COMPHY mode\n");
113793433708SPali Rohár 		return -EINVAL;
11389695375aSMiquel Raynal 	}
11399695375aSMiquel Raynal 
114093433708SPali Rohár 	/* Mode cannot be changed while the PHY is powered on */
114193433708SPali Rohár 	if (phy->power_count &&
114293433708SPali Rohár 	    (lane->mode != mode || lane->submode != submode))
114393433708SPali Rohár 		return -EBUSY;
114493433708SPali Rohár 
11459695375aSMiquel Raynal 	/* Just remember the mode, ->power_on() will do the real setup */
11469695375aSMiquel Raynal 	lane->mode = mode;
11479695375aSMiquel Raynal 	lane->submode = submode;
11489695375aSMiquel Raynal 
11499695375aSMiquel Raynal 	return 0;
11509695375aSMiquel Raynal }
11519695375aSMiquel Raynal 
11529695375aSMiquel Raynal static int mvebu_a3700_comphy_power_on(struct phy *phy)
11539695375aSMiquel Raynal {
11549695375aSMiquel Raynal 	struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
11559695375aSMiquel Raynal 
115693433708SPali Rohár 	if (!mvebu_a3700_comphy_check_mode(lane->id, lane->mode,
115793433708SPali Rohár 					   lane->submode)) {
11589695375aSMiquel Raynal 		dev_err(lane->dev, "invalid COMPHY mode\n");
115993433708SPali Rohár 		return -EINVAL;
116093433708SPali Rohár 	}
116193433708SPali Rohár 
11629695375aSMiquel Raynal 	switch (lane->mode) {
11639695375aSMiquel Raynal 	case PHY_MODE_USB_HOST_SS:
11649695375aSMiquel Raynal 		dev_dbg(lane->dev, "set lane %d to USB3 host mode\n", lane->id);
116593433708SPali Rohár 		return mvebu_a3700_comphy_usb3_power_on(lane);
11669695375aSMiquel Raynal 	case PHY_MODE_SATA:
11679695375aSMiquel Raynal 		dev_dbg(lane->dev, "set lane %d to SATA mode\n", lane->id);
116893433708SPali Rohár 		return mvebu_a3700_comphy_sata_power_on(lane);
11699695375aSMiquel Raynal 	case PHY_MODE_ETHERNET:
117093433708SPali Rohár 		dev_dbg(lane->dev, "set lane %d to Ethernet mode\n", lane->id);
117193433708SPali Rohár 		return mvebu_a3700_comphy_ethernet_power_on(lane);
11729695375aSMiquel Raynal 	case PHY_MODE_PCIE:
11739695375aSMiquel Raynal 		dev_dbg(lane->dev, "set lane %d to PCIe mode\n", lane->id);
117493433708SPali Rohár 		return mvebu_a3700_comphy_pcie_power_on(lane);
11759695375aSMiquel Raynal 	default:
11769695375aSMiquel Raynal 		dev_err(lane->dev, "unsupported PHY mode (%d)\n", lane->mode);
117793433708SPali Rohár 		return -EOPNOTSUPP;
11789695375aSMiquel Raynal 	}
11799695375aSMiquel Raynal }
11809695375aSMiquel Raynal 
11819695375aSMiquel Raynal static int mvebu_a3700_comphy_power_off(struct phy *phy)
11829695375aSMiquel Raynal {
11839695375aSMiquel Raynal 	struct mvebu_a3700_comphy_lane *lane = phy_get_drvdata(phy);
11849695375aSMiquel Raynal 
1185*0a6fc70dSPali Rohár 	switch (lane->id) {
1186*0a6fc70dSPali Rohár 	case 0:
1187*0a6fc70dSPali Rohár 		mvebu_a3700_comphy_usb3_power_off(lane);
118893433708SPali Rohár 		mvebu_a3700_comphy_ethernet_power_off(lane);
1189*0a6fc70dSPali Rohár 		return 0;
1190*0a6fc70dSPali Rohár 	case 1:
119193433708SPali Rohár 		mvebu_a3700_comphy_pcie_power_off(lane);
1192*0a6fc70dSPali Rohár 		mvebu_a3700_comphy_ethernet_power_off(lane);
1193*0a6fc70dSPali Rohár 		return 0;
1194*0a6fc70dSPali Rohár 	case 2:
1195*0a6fc70dSPali Rohár 		mvebu_a3700_comphy_usb3_power_off(lane);
1196*0a6fc70dSPali Rohár 		mvebu_a3700_comphy_sata_power_off(lane);
1197*0a6fc70dSPali Rohár 		return 0;
119893433708SPali Rohár 	default:
119993433708SPali Rohár 		dev_err(lane->dev, "invalid COMPHY mode\n");
120093433708SPali Rohár 		return -EINVAL;
120193433708SPali Rohár 	}
12029695375aSMiquel Raynal }
12039695375aSMiquel Raynal 
12049695375aSMiquel Raynal static const struct phy_ops mvebu_a3700_comphy_ops = {
12059695375aSMiquel Raynal 	.power_on	= mvebu_a3700_comphy_power_on,
12069695375aSMiquel Raynal 	.power_off	= mvebu_a3700_comphy_power_off,
12079695375aSMiquel Raynal 	.set_mode	= mvebu_a3700_comphy_set_mode,
12089695375aSMiquel Raynal 	.owner		= THIS_MODULE,
12099695375aSMiquel Raynal };
12109695375aSMiquel Raynal 
12119695375aSMiquel Raynal static struct phy *mvebu_a3700_comphy_xlate(struct device *dev,
12129695375aSMiquel Raynal 					    struct of_phandle_args *args)
12139695375aSMiquel Raynal {
12149695375aSMiquel Raynal 	struct mvebu_a3700_comphy_lane *lane;
12154bf18d5aSPali Rohár 	unsigned int port;
12169695375aSMiquel Raynal 	struct phy *phy;
12179695375aSMiquel Raynal 
12189695375aSMiquel Raynal 	phy = of_phy_simple_xlate(dev, args);
12199695375aSMiquel Raynal 	if (IS_ERR(phy))
12209695375aSMiquel Raynal 		return phy;
12219695375aSMiquel Raynal 
12229695375aSMiquel Raynal 	lane = phy_get_drvdata(phy);
12234bf18d5aSPali Rohár 
12244bf18d5aSPali Rohár 	port = args->args[0];
12254bf18d5aSPali Rohár 	if (port != 0 && (port != 1 || lane->id != 0)) {
12264bf18d5aSPali Rohár 		dev_err(lane->dev, "invalid port number %u\n", port);
12274bf18d5aSPali Rohár 		return ERR_PTR(-EINVAL);
12284bf18d5aSPali Rohár 	}
12299695375aSMiquel Raynal 
123093433708SPali Rohár 	lane->invert_tx = args->args[1] & BIT(0);
123193433708SPali Rohár 	lane->invert_rx = args->args[1] & BIT(1);
123293433708SPali Rohár 
12339695375aSMiquel Raynal 	return phy;
12349695375aSMiquel Raynal }
12359695375aSMiquel Raynal 
12369695375aSMiquel Raynal static int mvebu_a3700_comphy_probe(struct platform_device *pdev)
12379695375aSMiquel Raynal {
123893433708SPali Rohár 	struct mvebu_a3700_comphy_priv *priv;
12399695375aSMiquel Raynal 	struct phy_provider *provider;
12409695375aSMiquel Raynal 	struct device_node *child;
124193433708SPali Rohár 	struct resource *res;
124293433708SPali Rohár 	struct clk *clk;
124393433708SPali Rohár 	int ret;
124493433708SPali Rohár 
124593433708SPali Rohár 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
124693433708SPali Rohár 	if (!priv)
124793433708SPali Rohár 		return -ENOMEM;
124893433708SPali Rohár 
124993433708SPali Rohár 	spin_lock_init(&priv->lock);
125093433708SPali Rohár 
125193433708SPali Rohár 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "comphy");
125293433708SPali Rohár 	priv->comphy_regs = devm_ioremap_resource(&pdev->dev, res);
125393433708SPali Rohár 	if (IS_ERR(priv->comphy_regs))
125493433708SPali Rohár 		return PTR_ERR(priv->comphy_regs);
125593433708SPali Rohár 
125693433708SPali Rohár 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
125793433708SPali Rohár 					   "lane1_pcie_gbe");
125893433708SPali Rohár 	priv->lane1_phy_regs = devm_ioremap_resource(&pdev->dev, res);
125993433708SPali Rohár 	if (IS_ERR(priv->lane1_phy_regs))
126093433708SPali Rohár 		return PTR_ERR(priv->lane1_phy_regs);
126193433708SPali Rohár 
126293433708SPali Rohár 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
126393433708SPali Rohár 					   "lane0_usb3_gbe");
126493433708SPali Rohár 	priv->lane0_phy_regs = devm_ioremap_resource(&pdev->dev, res);
126593433708SPali Rohár 	if (IS_ERR(priv->lane0_phy_regs))
126693433708SPali Rohár 		return PTR_ERR(priv->lane0_phy_regs);
126793433708SPali Rohár 
126893433708SPali Rohár 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
126993433708SPali Rohár 					   "lane2_sata_usb3");
127093433708SPali Rohár 	priv->lane2_phy_indirect = devm_ioremap_resource(&pdev->dev, res);
127193433708SPali Rohár 	if (IS_ERR(priv->lane2_phy_indirect))
127293433708SPali Rohár 		return PTR_ERR(priv->lane2_phy_indirect);
127393433708SPali Rohár 
127493433708SPali Rohár 	/*
127593433708SPali Rohár 	 * Driver needs to know if reference xtal clock is 40MHz or 25MHz.
127693433708SPali Rohár 	 * Old DT bindings do not have xtal clk present. So do not fail here
127793433708SPali Rohár 	 * and expects that default 25MHz reference clock is used.
127893433708SPali Rohár 	 */
127993433708SPali Rohár 	clk = clk_get(&pdev->dev, "xtal");
128093433708SPali Rohár 	if (IS_ERR(clk)) {
128193433708SPali Rohár 		if (PTR_ERR(clk) == -EPROBE_DEFER)
128293433708SPali Rohár 			return -EPROBE_DEFER;
128393433708SPali Rohár 		dev_warn(&pdev->dev, "missing 'xtal' clk (%ld)\n",
128493433708SPali Rohár 			 PTR_ERR(clk));
128593433708SPali Rohár 	} else {
128693433708SPali Rohár 		ret = clk_prepare_enable(clk);
128793433708SPali Rohár 		if (ret) {
128893433708SPali Rohár 			dev_warn(&pdev->dev, "enabling xtal clk failed (%d)\n",
128993433708SPali Rohár 				 ret);
129093433708SPali Rohár 		} else {
129193433708SPali Rohár 			if (clk_get_rate(clk) == 40000000)
129293433708SPali Rohár 				priv->xtal_is_40m = true;
129393433708SPali Rohár 			clk_disable_unprepare(clk);
129493433708SPali Rohár 		}
129593433708SPali Rohár 		clk_put(clk);
129693433708SPali Rohár 	}
129793433708SPali Rohár 
129893433708SPali Rohár 	dev_set_drvdata(&pdev->dev, priv);
12999695375aSMiquel Raynal 
13009695375aSMiquel Raynal 	for_each_available_child_of_node(pdev->dev.of_node, child) {
13019695375aSMiquel Raynal 		struct mvebu_a3700_comphy_lane *lane;
13029695375aSMiquel Raynal 		struct phy *phy;
13039695375aSMiquel Raynal 		int ret;
13049695375aSMiquel Raynal 		u32 lane_id;
13059695375aSMiquel Raynal 
13069695375aSMiquel Raynal 		ret = of_property_read_u32(child, "reg", &lane_id);
13079695375aSMiquel Raynal 		if (ret < 0) {
13089695375aSMiquel Raynal 			dev_err(&pdev->dev, "missing 'reg' property (%d)\n",
13099695375aSMiquel Raynal 				ret);
13109695375aSMiquel Raynal 			continue;
13119695375aSMiquel Raynal 		}
13129695375aSMiquel Raynal 
131393433708SPali Rohár 		if (lane_id >= 3) {
13149695375aSMiquel Raynal 			dev_err(&pdev->dev, "invalid 'reg' property\n");
13159695375aSMiquel Raynal 			continue;
13169695375aSMiquel Raynal 		}
13179695375aSMiquel Raynal 
13189695375aSMiquel Raynal 		lane = devm_kzalloc(&pdev->dev, sizeof(*lane), GFP_KERNEL);
1319beae796dSNishka Dasgupta 		if (!lane) {
1320beae796dSNishka Dasgupta 			of_node_put(child);
13219695375aSMiquel Raynal 			return -ENOMEM;
1322beae796dSNishka Dasgupta 		}
13239695375aSMiquel Raynal 
13249695375aSMiquel Raynal 		phy = devm_phy_create(&pdev->dev, child,
13259695375aSMiquel Raynal 				      &mvebu_a3700_comphy_ops);
1326beae796dSNishka Dasgupta 		if (IS_ERR(phy)) {
1327beae796dSNishka Dasgupta 			of_node_put(child);
13289695375aSMiquel Raynal 			return PTR_ERR(phy);
1329beae796dSNishka Dasgupta 		}
13309695375aSMiquel Raynal 
133193433708SPali Rohár 		lane->priv = priv;
13329695375aSMiquel Raynal 		lane->dev = &pdev->dev;
13339695375aSMiquel Raynal 		lane->mode = PHY_MODE_INVALID;
13349695375aSMiquel Raynal 		lane->submode = PHY_INTERFACE_MODE_NA;
13359695375aSMiquel Raynal 		lane->id = lane_id;
133693433708SPali Rohár 		lane->invert_tx = false;
133793433708SPali Rohár 		lane->invert_rx = false;
13389695375aSMiquel Raynal 		phy_set_drvdata(phy, lane);
133993433708SPali Rohár 
134093433708SPali Rohár 		/*
134193433708SPali Rohár 		 * To avoid relying on the bootloader/firmware configuration,
134293433708SPali Rohár 		 * power off all comphys.
134393433708SPali Rohár 		 */
1344*0a6fc70dSPali Rohár 		mvebu_a3700_comphy_power_off(phy);
13459695375aSMiquel Raynal 	}
13469695375aSMiquel Raynal 
13479695375aSMiquel Raynal 	provider = devm_of_phy_provider_register(&pdev->dev,
13489695375aSMiquel Raynal 						 mvebu_a3700_comphy_xlate);
134993433708SPali Rohár 
13509695375aSMiquel Raynal 	return PTR_ERR_OR_ZERO(provider);
13519695375aSMiquel Raynal }
13529695375aSMiquel Raynal 
13539695375aSMiquel Raynal static const struct of_device_id mvebu_a3700_comphy_of_match_table[] = {
13549695375aSMiquel Raynal 	{ .compatible = "marvell,comphy-a3700" },
13559695375aSMiquel Raynal 	{ },
13569695375aSMiquel Raynal };
13579695375aSMiquel Raynal MODULE_DEVICE_TABLE(of, mvebu_a3700_comphy_of_match_table);
13589695375aSMiquel Raynal 
13599695375aSMiquel Raynal static struct platform_driver mvebu_a3700_comphy_driver = {
13609695375aSMiquel Raynal 	.probe	= mvebu_a3700_comphy_probe,
13619695375aSMiquel Raynal 	.driver	= {
13629695375aSMiquel Raynal 		.name = "mvebu-a3700-comphy",
13639695375aSMiquel Raynal 		.of_match_table = mvebu_a3700_comphy_of_match_table,
13649695375aSMiquel Raynal 	},
13659695375aSMiquel Raynal };
13669695375aSMiquel Raynal module_platform_driver(mvebu_a3700_comphy_driver);
13679695375aSMiquel Raynal 
13689695375aSMiquel Raynal MODULE_AUTHOR("Miquèl Raynal <miquel.raynal@bootlin.com>");
136993433708SPali Rohár MODULE_AUTHOR("Pali Rohár <pali@kernel.org>");
137093433708SPali Rohár MODULE_AUTHOR("Marek Behún <kabel@kernel.org>");
13719695375aSMiquel Raynal MODULE_DESCRIPTION("Common PHY driver for A3700");
13729695375aSMiquel Raynal MODULE_LICENSE("GPL v2");
1373