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