xref: /openbmc/u-boot/drivers/net/phy/mscc.c (revision 6f443330)
183d290c5STom Rini // SPDX-License-Identifier: MIT
2a5fd13adSJohn Haechten /*
3a5fd13adSJohn Haechten  * Microsemi PHY drivers
4a5fd13adSJohn Haechten  *
5a5fd13adSJohn Haechten  *
6a5fd13adSJohn Haechten  * Copyright (c) 2016 Microsemi Corporation
7a5fd13adSJohn Haechten  *
8a5fd13adSJohn Haechten  * Author: John Haechten
9a5fd13adSJohn Haechten  *
10a5fd13adSJohn Haechten  */
11a5fd13adSJohn Haechten 
12a5fd13adSJohn Haechten #include <miiphy.h>
13a5fd13adSJohn Haechten #include <bitfield.h>
1404087fc4SQuentin Schulz #include <time.h>
1504087fc4SQuentin Schulz #include <linux/delay.h>
16a5fd13adSJohn Haechten 
17a5fd13adSJohn Haechten /* Microsemi PHY ID's */
18a5fd13adSJohn Haechten #define PHY_ID_VSC8530                  0x00070560
19a5fd13adSJohn Haechten #define PHY_ID_VSC8531                  0x00070570
20a5fd13adSJohn Haechten #define PHY_ID_VSC8540                  0x00070760
21a5fd13adSJohn Haechten #define PHY_ID_VSC8541                  0x00070770
22*05bbd676SQuentin Schulz #define PHY_ID_VSC8574			0x000704a0
2304087fc4SQuentin Schulz #define PHY_ID_VSC8584                  0x000707c0
24a5fd13adSJohn Haechten 
25a5fd13adSJohn Haechten /* Microsemi VSC85xx PHY Register Pages */
26a5fd13adSJohn Haechten #define MSCC_EXT_PAGE_ACCESS            31     /* Page Access Register */
27a5fd13adSJohn Haechten #define MSCC_PHY_PAGE_STD		0x0000 /* Standard registers */
28a5fd13adSJohn Haechten #define MSCC_PHY_PAGE_EXT1		0x0001 /* Extended registers - page 1 */
29a5fd13adSJohn Haechten #define MSCC_PHY_PAGE_EXT2		0x0002 /* Extended registers - page 2 */
30a5fd13adSJohn Haechten #define MSCC_PHY_PAGE_EXT3		0x0003 /* Extended registers - page 3 */
31a5fd13adSJohn Haechten #define MSCC_PHY_PAGE_EXT4		0x0004 /* Extended registers - page 4 */
32a5fd13adSJohn Haechten #define MSCC_PHY_PAGE_GPIO		0x0010 /* GPIO registers */
33a5fd13adSJohn Haechten #define MSCC_PHY_PAGE_TEST		0x2A30 /* TEST Page registers */
34a5fd13adSJohn Haechten #define MSCC_PHY_PAGE_TR		0x52B5 /* Token Ring Page registers */
35a5fd13adSJohn Haechten 
3604087fc4SQuentin Schulz /* Std Page Register 18 */
3704087fc4SQuentin Schulz #define MSCC_PHY_BYPASS_CONTROL           18
3804087fc4SQuentin Schulz #define PARALLEL_DET_IGNORE_ADVERTISED    BIT(3)
3904087fc4SQuentin Schulz 
4004087fc4SQuentin Schulz /* Std Page Register 22 */
4104087fc4SQuentin Schulz #define MSCC_PHY_EXT_CNTL_STATUS          22
4204087fc4SQuentin Schulz #define SMI_BROADCAST_WR_EN              BIT(0)
4304087fc4SQuentin Schulz 
44*05bbd676SQuentin Schulz /* Std Page Register 24 */
45*05bbd676SQuentin Schulz #define MSCC_PHY_EXT_PHY_CNTL_2           24
46*05bbd676SQuentin Schulz 
47a5fd13adSJohn Haechten /* Std Page Register 28 - PHY AUX Control/Status */
48a5fd13adSJohn Haechten #define MIIM_AUX_CNTRL_STAT_REG		28
49a5fd13adSJohn Haechten #define MIIM_AUX_CNTRL_STAT_ACTIPHY_TO	(0x0004)
50a5fd13adSJohn Haechten #define MIIM_AUX_CNTRL_STAT_F_DUPLEX	(0x0020)
51a5fd13adSJohn Haechten #define MIIM_AUX_CNTRL_STAT_SPEED_MASK	(0x0018)
52a5fd13adSJohn Haechten #define MIIM_AUX_CNTRL_STAT_SPEED_POS	(3)
53a5fd13adSJohn Haechten #define MIIM_AUX_CNTRL_STAT_SPEED_10M	(0x0)
54a5fd13adSJohn Haechten #define MIIM_AUX_CNTRL_STAT_SPEED_100M	(0x1)
55a5fd13adSJohn Haechten #define MIIM_AUX_CNTRL_STAT_SPEED_1000M	(0x2)
56a5fd13adSJohn Haechten 
57a5fd13adSJohn Haechten /* Std Page Register 23 - Extended PHY CTRL_1 */
58a5fd13adSJohn Haechten #define MSCC_PHY_EXT_PHY_CNTL_1_REG	23
59a5fd13adSJohn Haechten #define MAC_IF_SELECTION_MASK		(0x1800)
60a5fd13adSJohn Haechten #define MAC_IF_SELECTION_GMII		(0)
61a5fd13adSJohn Haechten #define MAC_IF_SELECTION_RMII		(1)
62a5fd13adSJohn Haechten #define MAC_IF_SELECTION_RGMII		(2)
63a5fd13adSJohn Haechten #define MAC_IF_SELECTION_POS		(11)
64a5fd13adSJohn Haechten #define MAC_IF_SELECTION_WIDTH		(2)
6504087fc4SQuentin Schulz #define VSC8584_MAC_IF_SELECTION_MASK     BIT(12)
6604087fc4SQuentin Schulz #define VSC8584_MAC_IF_SELECTION_SGMII    0
6704087fc4SQuentin Schulz #define VSC8584_MAC_IF_SELECTION_1000BASEX 1
6804087fc4SQuentin Schulz #define VSC8584_MAC_IF_SELECTION_POS      12
6904087fc4SQuentin Schulz #define MEDIA_OP_MODE_MASK		  GENMASK(10, 8)
7004087fc4SQuentin Schulz #define MEDIA_OP_MODE_COPPER		  0
7104087fc4SQuentin Schulz #define MEDIA_OP_MODE_SERDES		  1
7204087fc4SQuentin Schulz #define MEDIA_OP_MODE_1000BASEX		  2
7304087fc4SQuentin Schulz #define MEDIA_OP_MODE_100BASEFX		  3
7404087fc4SQuentin Schulz #define MEDIA_OP_MODE_AMS_COPPER_SERDES	  5
7504087fc4SQuentin Schulz #define MEDIA_OP_MODE_AMS_COPPER_1000BASEX	6
7604087fc4SQuentin Schulz #define MEDIA_OP_MODE_AMS_COPPER_100BASEFX	7
7704087fc4SQuentin Schulz #define MEDIA_OP_MODE_POS		  8
7804087fc4SQuentin Schulz 
7904087fc4SQuentin Schulz /* Extended Page 1 Register 20E1 */
8004087fc4SQuentin Schulz #define MSCC_PHY_ACTIPHY_CNTL		  20
8104087fc4SQuentin Schulz #define PHY_ADDR_REVERSED		  BIT(9)
8204087fc4SQuentin Schulz 
8304087fc4SQuentin Schulz /* Extended Page 1 Register 23E1 */
8404087fc4SQuentin Schulz 
8504087fc4SQuentin Schulz #define MSCC_PHY_EXT_PHY_CNTL_4           23
8604087fc4SQuentin Schulz #define PHY_CNTL_4_ADDR_POS		  11
8704087fc4SQuentin Schulz 
8804087fc4SQuentin Schulz /* Extended Page 1 Register 25E1 */
8904087fc4SQuentin Schulz #define MSCC_PHY_VERIPHY_CNTL_2		25
9004087fc4SQuentin Schulz 
9104087fc4SQuentin Schulz /* Extended Page 1 Register 26E1 */
9204087fc4SQuentin Schulz #define MSCC_PHY_VERIPHY_CNTL_3		26
9304087fc4SQuentin Schulz 
9404087fc4SQuentin Schulz /* Extended Page 2 Register 16E2 */
9504087fc4SQuentin Schulz #define MSCC_PHY_CU_PMD_TX_CNTL         16
96a5fd13adSJohn Haechten 
97a5fd13adSJohn Haechten /* Extended Page 2 Register 20E2 */
98a5fd13adSJohn Haechten #define MSCC_PHY_RGMII_CNTL_REG		20
99a5fd13adSJohn Haechten #define VSC_FAST_LINK_FAIL2_ENA_MASK	(0x8000)
100a5fd13adSJohn Haechten #define RX_CLK_OUT_MASK			(0x0800)
101a5fd13adSJohn Haechten #define RX_CLK_OUT_POS			(11)
102a5fd13adSJohn Haechten #define RX_CLK_OUT_WIDTH		(1)
103a5fd13adSJohn Haechten #define RX_CLK_OUT_NORMAL		(0)
104a5fd13adSJohn Haechten #define RX_CLK_OUT_DISABLE		(1)
105a5fd13adSJohn Haechten #define RGMII_RX_CLK_DELAY_POS		(4)
106a5fd13adSJohn Haechten #define RGMII_RX_CLK_DELAY_WIDTH	(3)
107a5fd13adSJohn Haechten #define RGMII_RX_CLK_DELAY_MASK		(0x0070)
108a5fd13adSJohn Haechten #define RGMII_TX_CLK_DELAY_POS		(0)
109a5fd13adSJohn Haechten #define RGMII_TX_CLK_DELAY_WIDTH	(3)
110a5fd13adSJohn Haechten #define RGMII_TX_CLK_DELAY_MASK		(0x0007)
111a5fd13adSJohn Haechten 
112a5fd13adSJohn Haechten /* Extended Page 2 Register 27E2 */
113a5fd13adSJohn Haechten #define MSCC_PHY_WOL_MAC_CONTROL	27
114a5fd13adSJohn Haechten #define EDGE_RATE_CNTL_POS		(5)
115a5fd13adSJohn Haechten #define EDGE_RATE_CNTL_WIDTH		(3)
116a5fd13adSJohn Haechten #define EDGE_RATE_CNTL_MASK		(0x00E0)
117a5fd13adSJohn Haechten #define RMII_CLK_OUT_ENABLE_POS		(4)
118a5fd13adSJohn Haechten #define RMII_CLK_OUT_ENABLE_WIDTH	(1)
119a5fd13adSJohn Haechten #define RMII_CLK_OUT_ENABLE_MASK	(0x10)
120a5fd13adSJohn Haechten 
12104087fc4SQuentin Schulz /* Extended Page 3 Register 22E3 */
12204087fc4SQuentin Schulz #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT	22
12304087fc4SQuentin Schulz 
12404087fc4SQuentin Schulz /* Extended page GPIO register 00G */
12504087fc4SQuentin Schulz #define MSCC_DW8051_CNTL_STATUS		0
12604087fc4SQuentin Schulz #define MICRO_NSOFT_RESET		BIT(15)
12704087fc4SQuentin Schulz #define RUN_FROM_INT_ROM		BIT(14)
12804087fc4SQuentin Schulz #define AUTOINC_ADDR			BIT(13)
12904087fc4SQuentin Schulz #define PATCH_RAM_CLK			BIT(12)
13004087fc4SQuentin Schulz #define MICRO_PATCH_EN			BIT(7)
13104087fc4SQuentin Schulz #define DW8051_CLK_EN			BIT(4)
13204087fc4SQuentin Schulz #define MICRO_CLK_EN			BIT(3)
13304087fc4SQuentin Schulz #define MICRO_CLK_DIVIDE(x)		((x) >> 1)
134*05bbd676SQuentin Schulz #define MSCC_DW8051_VLD_MASK		0xf1ff
13504087fc4SQuentin Schulz 
13604087fc4SQuentin Schulz /* Extended page GPIO register 09G */
13704087fc4SQuentin Schulz #define MSCC_TRAP_ROM_ADDR(x)		((x) * 2 + 1)
138*05bbd676SQuentin Schulz #define MSCC_TRAP_ROM_ADDR_SERDES_INIT	0x3eb7
13904087fc4SQuentin Schulz 
14004087fc4SQuentin Schulz /* Extended page GPIO register 10G */
14104087fc4SQuentin Schulz #define MSCC_PATCH_RAM_ADDR(x)		(((x) + 1) * 2)
142*05bbd676SQuentin Schulz #define MSCC_PATCH_RAM_ADDR_SERDES_INIT	0x4012
14304087fc4SQuentin Schulz 
14404087fc4SQuentin Schulz /* Extended page GPIO register 11G */
14504087fc4SQuentin Schulz #define MSCC_INT_MEM_ADDR		11
14604087fc4SQuentin Schulz 
14704087fc4SQuentin Schulz /* Extended page GPIO register 12G */
14804087fc4SQuentin Schulz #define MSCC_INT_MEM_CNTL		12
14904087fc4SQuentin Schulz #define READ_SFR			(BIT(14) | BIT(13))
15004087fc4SQuentin Schulz #define READ_PRAM			BIT(14)
15104087fc4SQuentin Schulz #define READ_ROM			BIT(13)
15204087fc4SQuentin Schulz #define READ_RAM			(0x00 << 13)
15304087fc4SQuentin Schulz #define INT_MEM_WRITE_EN		BIT(12)
15404087fc4SQuentin Schulz #define EN_PATCH_RAM_TRAP_ADDR(x)	BIT((x) + 7)
15504087fc4SQuentin Schulz #define INT_MEM_DATA_M			GENMASK(7, 0)
15604087fc4SQuentin Schulz #define INT_MEM_DATA(x)			(INT_MEM_DATA_M & (x))
15704087fc4SQuentin Schulz 
15804087fc4SQuentin Schulz /* Extended page GPIO register 18G */
15904087fc4SQuentin Schulz #define MSCC_PHY_PROC_CMD		  18
16004087fc4SQuentin Schulz #define PROC_CMD_NCOMPLETED		  BIT(15)
16104087fc4SQuentin Schulz #define PROC_CMD_FAILED			  BIT(14)
16204087fc4SQuentin Schulz #define PROC_CMD_SGMII_PORT(x)		  ((x) << 8)
16304087fc4SQuentin Schulz #define PROC_CMD_FIBER_PORT(x)		  BIT(8 + (x) % 4)
16404087fc4SQuentin Schulz #define PROC_CMD_QSGMII_PORT		  (BIT(11) | BIT(10))
16504087fc4SQuentin Schulz #define PROC_CMD_RST_CONF_PORT		  BIT(7)
16604087fc4SQuentin Schulz #define PROC_CMD_RECONF_PORT		  (0 << 7)
16704087fc4SQuentin Schulz #define PROC_CMD_READ_MOD_WRITE_PORT	  BIT(6)
16804087fc4SQuentin Schulz #define PROC_CMD_WRITE			  BIT(6)
16904087fc4SQuentin Schulz #define PROC_CMD_READ			  (0 << 6)
17004087fc4SQuentin Schulz #define PROC_CMD_FIBER_DISABLE		  BIT(5)
17104087fc4SQuentin Schulz #define PROC_CMD_FIBER_100BASE_FX	  BIT(4)
17204087fc4SQuentin Schulz #define PROC_CMD_FIBER_1000BASE_X	  (0 << 4)
17304087fc4SQuentin Schulz #define PROC_CMD_SGMII_MAC		  (BIT(5) | BIT(4))
17404087fc4SQuentin Schulz #define PROC_CMD_QSGMII_MAC		  BIT(5)
17504087fc4SQuentin Schulz #define PROC_CMD_NO_MAC_CONF		  (0x00 << 4)
176*05bbd676SQuentin Schulz #define PROC_CMD_1588_DEFAULT_INIT	  BIT(4)
17704087fc4SQuentin Schulz #define PROC_CMD_NOP			  GENMASK(3, 0)
178*05bbd676SQuentin Schulz #define PROC_CMD_PHY_INIT		  (BIT(3) | BIT(1))
17904087fc4SQuentin Schulz #define PROC_CMD_CRC16			  BIT(3)
18004087fc4SQuentin Schulz #define PROC_CMD_FIBER_MEDIA_CONF	  BIT(0)
18104087fc4SQuentin Schulz #define PROC_CMD_MCB_ACCESS_MAC_CONF	  (0x0000 << 0)
18204087fc4SQuentin Schulz #define PROC_CMD_NCOMPLETED_TIMEOUT_MS    500
18304087fc4SQuentin Schulz 
18404087fc4SQuentin Schulz /* Extended page GPIO register 19G */
18504087fc4SQuentin Schulz #define MSCC_PHY_MAC_CFG_FASTLINK	  19
18604087fc4SQuentin Schulz #define MAC_CFG_MASK			  GENMASK(15, 14)
18704087fc4SQuentin Schulz #define MAC_CFG_SGMII			  (0x00 << 14)
18804087fc4SQuentin Schulz #define MAC_CFG_QSGMII			  BIT(14)
18904087fc4SQuentin Schulz 
19004087fc4SQuentin Schulz /* Test Registers */
19104087fc4SQuentin Schulz #define MSCC_PHY_TEST_PAGE_5		5
19204087fc4SQuentin Schulz 
19304087fc4SQuentin Schulz #define MSCC_PHY_TEST_PAGE_8		8
19404087fc4SQuentin Schulz #define TR_CLK_DISABLE			BIT(15)
19504087fc4SQuentin Schulz 
196*05bbd676SQuentin Schulz #define MSCC_PHY_TEST_PAGE_9		9
197*05bbd676SQuentin Schulz #define MSCC_PHY_TEST_PAGE_20		20
198*05bbd676SQuentin Schulz #define MSCC_PHY_TEST_PAGE_24		24
199*05bbd676SQuentin Schulz 
200a5fd13adSJohn Haechten /* Token Ring Page 0x52B5 Registers */
201a5fd13adSJohn Haechten #define MSCC_PHY_REG_TR_ADDR_16		16
202a5fd13adSJohn Haechten #define MSCC_PHY_REG_TR_DATA_17		17
203a5fd13adSJohn Haechten #define MSCC_PHY_REG_TR_DATA_18		18
204a5fd13adSJohn Haechten 
205a5fd13adSJohn Haechten /* Token Ring - Read Value in */
206a5fd13adSJohn Haechten #define MSCC_PHY_TR_16_READ		(0xA000)
207a5fd13adSJohn Haechten /* Token Ring - Write Value out */
208a5fd13adSJohn Haechten #define MSCC_PHY_TR_16_WRITE		(0x8000)
209a5fd13adSJohn Haechten 
210a5fd13adSJohn Haechten /* Token Ring Registers */
211a5fd13adSJohn Haechten #define MSCC_PHY_TR_LINKDETCTRL_POS	(3)
212a5fd13adSJohn Haechten #define MSCC_PHY_TR_LINKDETCTRL_WIDTH	(2)
213a5fd13adSJohn Haechten #define MSCC_PHY_TR_LINKDETCTRL_VAL	(3)
214a5fd13adSJohn Haechten #define MSCC_PHY_TR_LINKDETCTRL_MASK	(0x0018)
215a5fd13adSJohn Haechten #define MSCC_PHY_TR_LINKDETCTRL_ADDR	(0x07F8)
216a5fd13adSJohn Haechten 
217a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGATHRESH100_POS	(0)
218a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGATHRESH100_WIDTH	(7)
219a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGATHRESH100_VAL	(0x0018)
220a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGATHRESH100_MASK	(0x007f)
221a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGATHRESH100_ADDR	(0x0FA4)
222a5fd13adSJohn Haechten 
223a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGAGAIN10_U_POS	(0)
224a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGAGAIN10_U_WIDTH	(1)
225a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGAGAIN10_U_MASK	(0x0001)
226a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGAGAIN10_U_VAL	(0)
227a5fd13adSJohn Haechten 
228a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGAGAIN10_L_POS	(12)
229a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGAGAIN10_L_WIDTH	(4)
230a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGAGAIN10_L_MASK	(0xf000)
231a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGAGAIN10_L_VAL	(0x0001)
232a5fd13adSJohn Haechten #define MSCC_PHY_TR_VGAGAIN10_ADDR	(0x0F92)
233a5fd13adSJohn Haechten 
234a5fd13adSJohn Haechten /* General Timeout Values */
235a5fd13adSJohn Haechten #define MSCC_PHY_RESET_TIMEOUT		(100)
236a5fd13adSJohn Haechten #define MSCC_PHY_MICRO_TIMEOUT		(500)
237a5fd13adSJohn Haechten 
23804087fc4SQuentin Schulz #define VSC8584_REVB		0x0001
23904087fc4SQuentin Schulz #define MSCC_DEV_REV_MASK	GENMASK(3, 0)
24004087fc4SQuentin Schulz 
241*05bbd676SQuentin Schulz #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR 0x4000
242*05bbd676SQuentin Schulz #define MSCC_VSC8574_REVB_INT8051_FW_CRC	0x29e8
243*05bbd676SQuentin Schulz 
24404087fc4SQuentin Schulz #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR	0xe800
24504087fc4SQuentin Schulz #define MSCC_VSC8584_REVB_INT8051_FW_CRC	0xfb48
24604087fc4SQuentin Schulz 
247a5fd13adSJohn Haechten /* RGMII/GMII Clock Delay (Skew) Options */ enum vsc_phy_rgmii_skew {
248a5fd13adSJohn Haechten 	VSC_PHY_RGMII_DELAY_200_PS,
249a5fd13adSJohn Haechten 	VSC_PHY_RGMII_DELAY_800_PS,
250a5fd13adSJohn Haechten 	VSC_PHY_RGMII_DELAY_1100_PS,
251a5fd13adSJohn Haechten 	VSC_PHY_RGMII_DELAY_1700_PS,
252a5fd13adSJohn Haechten 	VSC_PHY_RGMII_DELAY_2000_PS,
253a5fd13adSJohn Haechten 	VSC_PHY_RGMII_DELAY_2300_PS,
254a5fd13adSJohn Haechten 	VSC_PHY_RGMII_DELAY_2600_PS,
255a5fd13adSJohn Haechten 	VSC_PHY_RGMII_DELAY_3400_PS,
256a5fd13adSJohn Haechten };
257a5fd13adSJohn Haechten 
258a5fd13adSJohn Haechten /* MAC i/f Clock Edge Rage Control (Slew), See Reg27E2  */ enum
259a5fd13adSJohn Haechten vsc_phy_clk_slew {
260a5fd13adSJohn Haechten 	VSC_PHY_CLK_SLEW_RATE_0,
261a5fd13adSJohn Haechten 	VSC_PHY_CLK_SLEW_RATE_1,
262a5fd13adSJohn Haechten 	VSC_PHY_CLK_SLEW_RATE_2,
263a5fd13adSJohn Haechten 	VSC_PHY_CLK_SLEW_RATE_3,
264a5fd13adSJohn Haechten 	VSC_PHY_CLK_SLEW_RATE_4,
265a5fd13adSJohn Haechten 	VSC_PHY_CLK_SLEW_RATE_5,
266a5fd13adSJohn Haechten 	VSC_PHY_CLK_SLEW_RATE_6,
267a5fd13adSJohn Haechten 	VSC_PHY_CLK_SLEW_RATE_7,
268a5fd13adSJohn Haechten };
269a5fd13adSJohn Haechten 
270b5bca65eSQuentin Schulz struct vsc85xx_priv {
271b5bca65eSQuentin Schulz 	int (*config_pre)(struct phy_device *phydev);
272b5bca65eSQuentin Schulz };
273b5bca65eSQuentin Schulz 
vsc8584_csr_write(struct mii_dev * bus,int phy0,u16 addr,u32 val)27404087fc4SQuentin Schulz static void vsc8584_csr_write(struct mii_dev *bus, int phy0, u16 addr, u32 val)
27504087fc4SQuentin Schulz {
27604087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18,
27704087fc4SQuentin Schulz 		   val >> 16);
27804087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17,
27904087fc4SQuentin Schulz 		   val & GENMASK(15, 0));
28004087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
28104087fc4SQuentin Schulz 		   MSCC_PHY_TR_16_WRITE | addr);
28204087fc4SQuentin Schulz }
28304087fc4SQuentin Schulz 
vsc8584_cmd(struct mii_dev * bus,int phy,u16 val)28404087fc4SQuentin Schulz static int vsc8584_cmd(struct mii_dev *bus, int phy, u16 val)
28504087fc4SQuentin Schulz {
28604087fc4SQuentin Schulz 	unsigned long deadline;
28704087fc4SQuentin Schulz 	u16 reg_val;
28804087fc4SQuentin Schulz 
28904087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
29004087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_GPIO);
29104087fc4SQuentin Schulz 
29204087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
29304087fc4SQuentin Schulz 		   PROC_CMD_NCOMPLETED | val);
29404087fc4SQuentin Schulz 
29504087fc4SQuentin Schulz 	deadline = timer_get_us() + PROC_CMD_NCOMPLETED_TIMEOUT_MS * 1000;
29604087fc4SQuentin Schulz 	do {
29704087fc4SQuentin Schulz 		reg_val = bus->read(bus, phy, MDIO_DEVAD_NONE,
29804087fc4SQuentin Schulz 				    MSCC_PHY_PROC_CMD);
29904087fc4SQuentin Schulz 	} while (timer_get_us() <= deadline &&
30004087fc4SQuentin Schulz 		 (reg_val & PROC_CMD_NCOMPLETED) &&
30104087fc4SQuentin Schulz 		 !(reg_val & PROC_CMD_FAILED));
30204087fc4SQuentin Schulz 
30304087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
30404087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_STD);
30504087fc4SQuentin Schulz 
30604087fc4SQuentin Schulz 	if (reg_val & PROC_CMD_FAILED)
30704087fc4SQuentin Schulz 		return -EIO;
30804087fc4SQuentin Schulz 	if (reg_val & PROC_CMD_NCOMPLETED)
30904087fc4SQuentin Schulz 		return -ETIMEDOUT;
31004087fc4SQuentin Schulz 
31104087fc4SQuentin Schulz 	return 0;
31204087fc4SQuentin Schulz }
31304087fc4SQuentin Schulz 
vsc8584_micro_deassert_reset(struct mii_dev * bus,int phy,bool patch_en)31404087fc4SQuentin Schulz static int vsc8584_micro_deassert_reset(struct mii_dev *bus, int phy,
31504087fc4SQuentin Schulz 					bool patch_en)
31604087fc4SQuentin Schulz {
31704087fc4SQuentin Schulz 	u32 enable, release;
31804087fc4SQuentin Schulz 
31904087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
32004087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_GPIO);
32104087fc4SQuentin Schulz 
32204087fc4SQuentin Schulz 	enable = RUN_FROM_INT_ROM | MICRO_CLK_EN | DW8051_CLK_EN;
32304087fc4SQuentin Schulz 	release = MICRO_NSOFT_RESET | RUN_FROM_INT_ROM | DW8051_CLK_EN |
32404087fc4SQuentin Schulz 		MICRO_CLK_EN;
32504087fc4SQuentin Schulz 
32604087fc4SQuentin Schulz 	if (patch_en) {
32704087fc4SQuentin Schulz 		enable |= MICRO_PATCH_EN;
32804087fc4SQuentin Schulz 		release |= MICRO_PATCH_EN;
32904087fc4SQuentin Schulz 
33004087fc4SQuentin Schulz 		/* Clear all patches */
33104087fc4SQuentin Schulz 		bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
33204087fc4SQuentin Schulz 			   READ_RAM);
33304087fc4SQuentin Schulz 	}
33404087fc4SQuentin Schulz 
33504087fc4SQuentin Schulz 	/*
33604087fc4SQuentin Schulz 	 * Enable 8051 Micro clock; CLEAR/SET patch present; disable PRAM clock
33704087fc4SQuentin Schulz 	 * override and addr. auto-incr; operate at 125 MHz
33804087fc4SQuentin Schulz 	 */
33904087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, enable);
34004087fc4SQuentin Schulz 	/* Release 8051 Micro SW reset */
34104087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, release);
34204087fc4SQuentin Schulz 
34304087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
34404087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_STD);
34504087fc4SQuentin Schulz 
34604087fc4SQuentin Schulz 	return 0;
34704087fc4SQuentin Schulz }
34804087fc4SQuentin Schulz 
vsc8584_micro_assert_reset(struct mii_dev * bus,int phy)34904087fc4SQuentin Schulz static int vsc8584_micro_assert_reset(struct mii_dev *bus, int phy)
35004087fc4SQuentin Schulz {
35104087fc4SQuentin Schulz 	int ret;
35204087fc4SQuentin Schulz 	u16 reg;
35304087fc4SQuentin Schulz 
35404087fc4SQuentin Schulz 	ret = vsc8584_cmd(bus, phy, PROC_CMD_NOP);
35504087fc4SQuentin Schulz 	if (ret)
35604087fc4SQuentin Schulz 		return ret;
35704087fc4SQuentin Schulz 
35804087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
35904087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_GPIO);
36004087fc4SQuentin Schulz 
36104087fc4SQuentin Schulz 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
36204087fc4SQuentin Schulz 	reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
36304087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
36404087fc4SQuentin Schulz 
36504087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(4), 0x005b);
36604087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(4), 0x005b);
36704087fc4SQuentin Schulz 
36804087fc4SQuentin Schulz 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
36904087fc4SQuentin Schulz 	reg |= EN_PATCH_RAM_TRAP_ADDR(4);
37004087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
37104087fc4SQuentin Schulz 
37204087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD, PROC_CMD_NOP);
37304087fc4SQuentin Schulz 
37404087fc4SQuentin Schulz 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
37504087fc4SQuentin Schulz 	reg &= ~MICRO_NSOFT_RESET;
37604087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS, reg);
37704087fc4SQuentin Schulz 
37804087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_PROC_CMD,
37904087fc4SQuentin Schulz 		   PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_SGMII_PORT(0) |
38004087fc4SQuentin Schulz 		   PROC_CMD_NO_MAC_CONF | PROC_CMD_READ);
38104087fc4SQuentin Schulz 
38204087fc4SQuentin Schulz 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
38304087fc4SQuentin Schulz 	reg &= ~EN_PATCH_RAM_TRAP_ADDR(4);
38404087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, reg);
38504087fc4SQuentin Schulz 
38604087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
38704087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_STD);
38804087fc4SQuentin Schulz 
38904087fc4SQuentin Schulz 	return 0;
39004087fc4SQuentin Schulz }
39104087fc4SQuentin Schulz 
392*05bbd676SQuentin Schulz static const u8 fw_patch_vsc8574[] = {
393*05bbd676SQuentin Schulz 	0x46, 0x4a, 0x02, 0x43, 0x37, 0x02, 0x46, 0x26, 0x02, 0x46, 0x77, 0x02,
394*05bbd676SQuentin Schulz 	0x45, 0x60, 0x02, 0x45, 0xaf, 0xed, 0xff, 0xe5, 0xfc, 0x54, 0x38, 0x64,
395*05bbd676SQuentin Schulz 	0x20, 0x70, 0x08, 0x65, 0xff, 0x70, 0x04, 0xed, 0x44, 0x80, 0xff, 0x22,
396*05bbd676SQuentin Schulz 	0x8f, 0x19, 0x7b, 0xbb, 0x7d, 0x0e, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0xef,
397*05bbd676SQuentin Schulz 	0x4e, 0x60, 0x03, 0x02, 0x41, 0xf9, 0xe4, 0xf5, 0x1a, 0x74, 0x01, 0x7e,
398*05bbd676SQuentin Schulz 	0x00, 0xa8, 0x1a, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8,
399*05bbd676SQuentin Schulz 	0xf9, 0xff, 0xef, 0x55, 0x19, 0x70, 0x03, 0x02, 0x41, 0xed, 0x85, 0x1a,
400*05bbd676SQuentin Schulz 	0xfb, 0x7b, 0xbb, 0xe4, 0xfd, 0xff, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
401*05bbd676SQuentin Schulz 	0x03, 0x02, 0x41, 0xed, 0xe5, 0x1a, 0x54, 0x02, 0x75, 0x1d, 0x00, 0x25,
402*05bbd676SQuentin Schulz 	0xe0, 0x25, 0xe0, 0xf5, 0x1c, 0xe4, 0x78, 0xc5, 0xf6, 0xd2, 0x0a, 0x12,
403*05bbd676SQuentin Schulz 	0x41, 0xfa, 0x7b, 0xff, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef,
404*05bbd676SQuentin Schulz 	0x4e, 0x60, 0x03, 0x02, 0x41, 0xe7, 0xc2, 0x0a, 0x74, 0xc7, 0x25, 0x1a,
405*05bbd676SQuentin Schulz 	0xf9, 0x74, 0xe7, 0x25, 0x1a, 0xf8, 0xe6, 0x27, 0xf5, 0x1b, 0xe5, 0x1d,
406*05bbd676SQuentin Schulz 	0x24, 0x5b, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x7b, 0xfc, 0x7d, 0x11,
407*05bbd676SQuentin Schulz 	0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x78, 0xcc, 0xef, 0xf6, 0x78, 0xc1, 0xe6,
408*05bbd676SQuentin Schulz 	0xfe, 0xef, 0xd3, 0x9e, 0x40, 0x06, 0x78, 0xcc, 0xe6, 0x78, 0xc1, 0xf6,
409*05bbd676SQuentin Schulz 	0x12, 0x41, 0xfa, 0x7b, 0xec, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7,
410*05bbd676SQuentin Schulz 	0x78, 0xcb, 0xef, 0xf6, 0xbf, 0x07, 0x06, 0x78, 0xc3, 0x76, 0x1a, 0x80,
411*05bbd676SQuentin Schulz 	0x1f, 0x78, 0xc5, 0xe6, 0xff, 0x60, 0x0f, 0xc3, 0xe5, 0x1b, 0x9f, 0xff,
412*05bbd676SQuentin Schulz 	0x78, 0xcb, 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x2f, 0x80, 0x07, 0x78, 0xcb,
413*05bbd676SQuentin Schulz 	0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x78, 0xc3, 0xf6, 0xe4, 0x78, 0xc2, 0xf6,
414*05bbd676SQuentin Schulz 	0x78, 0xc2, 0xe6, 0xff, 0xc3, 0x08, 0x96, 0x40, 0x03, 0x02, 0x41, 0xd1,
415*05bbd676SQuentin Schulz 	0xef, 0x54, 0x03, 0x60, 0x33, 0x14, 0x60, 0x46, 0x24, 0xfe, 0x60, 0x42,
416*05bbd676SQuentin Schulz 	0x04, 0x70, 0x4b, 0xef, 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0xef, 0x78,
417*05bbd676SQuentin Schulz 	0x02, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xff, 0xe5, 0x1d,
418*05bbd676SQuentin Schulz 	0x24, 0x5c, 0xcd, 0xe5, 0x1c, 0x34, 0xf0, 0xcd, 0x2f, 0xff, 0xed, 0x3e,
419*05bbd676SQuentin Schulz 	0xfe, 0x12, 0x46, 0x0d, 0x7d, 0x11, 0x80, 0x0b, 0x78, 0xc2, 0xe6, 0x70,
420*05bbd676SQuentin Schulz 	0x04, 0x7d, 0x11, 0x80, 0x02, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3e, 0x9a,
421*05bbd676SQuentin Schulz 	0x8e, 0x1e, 0x8f, 0x1f, 0x80, 0x03, 0xe5, 0x1e, 0xff, 0x78, 0xc5, 0xe6,
422*05bbd676SQuentin Schulz 	0x06, 0x24, 0xcd, 0xf8, 0xa6, 0x07, 0x78, 0xc2, 0x06, 0xe6, 0xb4, 0x1a,
423*05bbd676SQuentin Schulz 	0x0a, 0xe5, 0x1d, 0x24, 0x5c, 0x12, 0x45, 0xea, 0x12, 0x3e, 0xda, 0x78,
424*05bbd676SQuentin Schulz 	0xc5, 0xe6, 0x65, 0x1b, 0x70, 0x82, 0x75, 0xdb, 0x20, 0x75, 0xdb, 0x28,
425*05bbd676SQuentin Schulz 	0x12, 0x46, 0x02, 0x12, 0x46, 0x02, 0xe5, 0x1a, 0x12, 0x45, 0xf5, 0xe5,
426*05bbd676SQuentin Schulz 	0x1a, 0xc3, 0x13, 0x12, 0x45, 0xf5, 0x78, 0xc5, 0x16, 0xe6, 0x24, 0xcd,
427*05bbd676SQuentin Schulz 	0xf8, 0xe6, 0xff, 0x7e, 0x08, 0x1e, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02,
428*05bbd676SQuentin Schulz 	0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0xef,
429*05bbd676SQuentin Schulz 	0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33,
430*05bbd676SQuentin Schulz 	0x54, 0xe0, 0x44, 0x08, 0xf5, 0xdb, 0xee, 0x70, 0xd8, 0x78, 0xc5, 0xe6,
431*05bbd676SQuentin Schulz 	0x70, 0xc8, 0x75, 0xdb, 0x10, 0x02, 0x40, 0xfd, 0x78, 0xc2, 0xe6, 0xc3,
432*05bbd676SQuentin Schulz 	0x94, 0x17, 0x50, 0x0e, 0xe5, 0x1d, 0x24, 0x62, 0x12, 0x42, 0x08, 0xe5,
433*05bbd676SQuentin Schulz 	0x1d, 0x24, 0x5c, 0x12, 0x42, 0x08, 0x20, 0x0a, 0x03, 0x02, 0x40, 0x76,
434*05bbd676SQuentin Schulz 	0x05, 0x1a, 0xe5, 0x1a, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x02, 0x40, 0x3a,
435*05bbd676SQuentin Schulz 	0x22, 0xe5, 0x1d, 0x24, 0x5c, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12,
436*05bbd676SQuentin Schulz 	0x46, 0x0d, 0x22, 0xff, 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x46, 0x0d,
437*05bbd676SQuentin Schulz 	0x22, 0xe4, 0xf5, 0x19, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x1e, 0x7b, 0xfe,
438*05bbd676SQuentin Schulz 	0x12, 0x42, 0xf9, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0, 0x07,
439*05bbd676SQuentin Schulz 	0x7b, 0x54, 0x12, 0x42, 0xf9, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a, 0x25,
440*05bbd676SQuentin Schulz 	0x19, 0xf8, 0xa6, 0x07, 0x12, 0x46, 0x43, 0x20, 0xe7, 0x03, 0x02, 0x42,
441*05bbd676SQuentin Schulz 	0xdf, 0x54, 0x03, 0x64, 0x03, 0x70, 0x03, 0x02, 0x42, 0xcf, 0x7b, 0xcb,
442*05bbd676SQuentin Schulz 	0x12, 0x43, 0x2c, 0x8f, 0xfb, 0x7b, 0x30, 0x7d, 0x03, 0xe4, 0xff, 0x12,
443*05bbd676SQuentin Schulz 	0x3d, 0xd7, 0xc3, 0xef, 0x94, 0x02, 0xee, 0x94, 0x00, 0x50, 0x2a, 0x12,
444*05bbd676SQuentin Schulz 	0x42, 0xec, 0xef, 0x4e, 0x70, 0x23, 0x12, 0x43, 0x04, 0x60, 0x0a, 0x12,
445*05bbd676SQuentin Schulz 	0x43, 0x12, 0x70, 0x0c, 0x12, 0x43, 0x1f, 0x70, 0x07, 0x12, 0x46, 0x39,
446*05bbd676SQuentin Schulz 	0x7b, 0x03, 0x80, 0x07, 0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0xfb, 0x7a,
447*05bbd676SQuentin Schulz 	0x00, 0x7d, 0x54, 0x80, 0x3e, 0x12, 0x42, 0xec, 0xef, 0x4e, 0x70, 0x24,
448*05bbd676SQuentin Schulz 	0x12, 0x43, 0x04, 0x60, 0x0a, 0x12, 0x43, 0x12, 0x70, 0x0f, 0x12, 0x43,
449*05bbd676SQuentin Schulz 	0x1f, 0x70, 0x0a, 0x12, 0x46, 0x39, 0xe4, 0xfb, 0xfa, 0x7d, 0xee, 0x80,
450*05bbd676SQuentin Schulz 	0x1e, 0x12, 0x46, 0x39, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x80, 0x13,
451*05bbd676SQuentin Schulz 	0x12, 0x46, 0x39, 0x12, 0x46, 0x43, 0x54, 0x40, 0xfe, 0xc4, 0x13, 0x13,
452*05bbd676SQuentin Schulz 	0x54, 0x03, 0xfb, 0x7a, 0x00, 0x7d, 0xee, 0x12, 0x38, 0xbd, 0x7b, 0xff,
453*05bbd676SQuentin Schulz 	0x12, 0x43, 0x2c, 0xef, 0x4e, 0x70, 0x07, 0x74, 0x2a, 0x25, 0x19, 0xf8,
454*05bbd676SQuentin Schulz 	0xe4, 0xf6, 0x05, 0x19, 0xe5, 0x19, 0xc3, 0x94, 0x02, 0x50, 0x03, 0x02,
455*05bbd676SQuentin Schulz 	0x42, 0x15, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7b, 0x20, 0x7f, 0x04,
456*05bbd676SQuentin Schulz 	0x12, 0x3d, 0xd7, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12,
457*05bbd676SQuentin Schulz 	0x3d, 0xd7, 0x22, 0x7b, 0x22, 0x7d, 0x18, 0x7f, 0x06, 0x12, 0x3d, 0xd7,
458*05bbd676SQuentin Schulz 	0xef, 0x64, 0x01, 0x4e, 0x22, 0x7d, 0x1c, 0xe4, 0xff, 0x12, 0x3e, 0x9a,
459*05bbd676SQuentin Schulz 	0xef, 0x54, 0x1b, 0x64, 0x0a, 0x22, 0x7b, 0xcc, 0x7d, 0x10, 0xff, 0x12,
460*05bbd676SQuentin Schulz 	0x3d, 0xd7, 0xef, 0x64, 0x01, 0x4e, 0x22, 0xe5, 0x19, 0x24, 0x17, 0xfd,
461*05bbd676SQuentin Schulz 	0x7f, 0x04, 0x12, 0x3d, 0xd7, 0x22, 0xd2, 0x08, 0x75, 0xfb, 0x03, 0xab,
462*05bbd676SQuentin Schulz 	0x7e, 0xaa, 0x7d, 0x7d, 0x19, 0x7f, 0x03, 0x12, 0x3e, 0xda, 0xe5, 0x7e,
463*05bbd676SQuentin Schulz 	0x54, 0x0f, 0x24, 0xf3, 0x60, 0x03, 0x02, 0x43, 0xe9, 0x12, 0x46, 0x5a,
464*05bbd676SQuentin Schulz 	0x12, 0x46, 0x61, 0xd8, 0xfb, 0xff, 0x20, 0xe2, 0x35, 0x13, 0x92, 0x0c,
465*05bbd676SQuentin Schulz 	0xef, 0xa2, 0xe1, 0x92, 0x0b, 0x30, 0x0c, 0x2a, 0xe4, 0xf5, 0x10, 0x7b,
466*05bbd676SQuentin Schulz 	0xfe, 0x12, 0x43, 0xff, 0xef, 0xc4, 0x33, 0x33, 0x54, 0xc0, 0xff, 0xc0,
467*05bbd676SQuentin Schulz 	0x07, 0x7b, 0x54, 0x12, 0x43, 0xff, 0xd0, 0xe0, 0x4f, 0xff, 0x74, 0x2a,
468*05bbd676SQuentin Schulz 	0x25, 0x10, 0xf8, 0xa6, 0x07, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 0x02,
469*05bbd676SQuentin Schulz 	0x40, 0xd9, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb, 0x54, 0x05,
470*05bbd676SQuentin Schulz 	0x64, 0x04, 0x70, 0x27, 0x78, 0xc4, 0xe6, 0x78, 0xc6, 0xf6, 0xe5, 0x7d,
471*05bbd676SQuentin Schulz 	0xff, 0x33, 0x95, 0xe0, 0xef, 0x54, 0x0f, 0x78, 0xc4, 0xf6, 0x12, 0x44,
472*05bbd676SQuentin Schulz 	0x0a, 0x20, 0x0c, 0x0c, 0x12, 0x46, 0x5a, 0x12, 0x46, 0x61, 0xd8, 0xfb,
473*05bbd676SQuentin Schulz 	0x13, 0x92, 0x0d, 0x22, 0xc2, 0x0d, 0x22, 0x12, 0x46, 0x5a, 0x12, 0x46,
474*05bbd676SQuentin Schulz 	0x61, 0xd8, 0xfb, 0x54, 0x05, 0x64, 0x05, 0x70, 0x1e, 0x78, 0xc4, 0x7d,
475*05bbd676SQuentin Schulz 	0xb8, 0x12, 0x43, 0xf5, 0x78, 0xc1, 0x7d, 0x74, 0x12, 0x43, 0xf5, 0xe4,
476*05bbd676SQuentin Schulz 	0x78, 0xc1, 0xf6, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f, 0x92,
477*05bbd676SQuentin Schulz 	0x12, 0x38, 0xbd, 0x22, 0xe6, 0xfb, 0x7a, 0x00, 0x7f, 0x92, 0x12, 0x38,
478*05bbd676SQuentin Schulz 	0xbd, 0x22, 0xe5, 0x10, 0x24, 0x17, 0xfd, 0x7f, 0x04, 0x12, 0x3d, 0xd7,
479*05bbd676SQuentin Schulz 	0x22, 0x78, 0xc1, 0xe6, 0xfb, 0x7a, 0x00, 0x7d, 0x74, 0x7f, 0x92, 0x12,
480*05bbd676SQuentin Schulz 	0x38, 0xbd, 0xe4, 0x78, 0xc1, 0xf6, 0xf5, 0x11, 0x74, 0x01, 0x7e, 0x00,
481*05bbd676SQuentin Schulz 	0xa8, 0x11, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9,
482*05bbd676SQuentin Schulz 	0xff, 0x78, 0xc4, 0xe6, 0xfd, 0xef, 0x5d, 0x60, 0x44, 0x85, 0x11, 0xfb,
483*05bbd676SQuentin Schulz 	0xe5, 0x11, 0x54, 0x02, 0x25, 0xe0, 0x25, 0xe0, 0xfe, 0xe4, 0x24, 0x5b,
484*05bbd676SQuentin Schulz 	0xfb, 0xee, 0x12, 0x45, 0xed, 0x12, 0x3e, 0xda, 0x7b, 0x40, 0x7d, 0x11,
485*05bbd676SQuentin Schulz 	0x7f, 0x07, 0x12, 0x3d, 0xd7, 0x74, 0xc7, 0x25, 0x11, 0xf8, 0xa6, 0x07,
486*05bbd676SQuentin Schulz 	0x7b, 0x11, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
487*05bbd676SQuentin Schulz 	0x09, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, 0x04, 0x80, 0x07, 0x74, 0xe7,
488*05bbd676SQuentin Schulz 	0x25, 0x11, 0xf8, 0x76, 0x0a, 0x05, 0x11, 0xe5, 0x11, 0xc3, 0x94, 0x04,
489*05bbd676SQuentin Schulz 	0x40, 0x9a, 0x78, 0xc6, 0xe6, 0x70, 0x15, 0x78, 0xc4, 0xe6, 0x60, 0x10,
490*05bbd676SQuentin Schulz 	0x75, 0xd9, 0x38, 0x75, 0xdb, 0x10, 0x7d, 0xfe, 0x12, 0x44, 0xb8, 0x7d,
491*05bbd676SQuentin Schulz 	0x76, 0x12, 0x44, 0xb8, 0x79, 0xc6, 0xe7, 0x78, 0xc4, 0x66, 0xff, 0x60,
492*05bbd676SQuentin Schulz 	0x03, 0x12, 0x40, 0x25, 0x78, 0xc4, 0xe6, 0x70, 0x09, 0xfb, 0xfa, 0x7d,
493*05bbd676SQuentin Schulz 	0xfe, 0x7f, 0x8e, 0x12, 0x38, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7f,
494*05bbd676SQuentin Schulz 	0x8e, 0x12, 0x38, 0xbd, 0x22, 0xe4, 0xf5, 0xfb, 0x7d, 0x1c, 0xe4, 0xff,
495*05bbd676SQuentin Schulz 	0x12, 0x3e, 0x9a, 0xad, 0x07, 0xac, 0x06, 0xec, 0x54, 0xc0, 0xff, 0xed,
496*05bbd676SQuentin Schulz 	0x54, 0x3f, 0x4f, 0xf5, 0x20, 0x30, 0x06, 0x2c, 0x30, 0x01, 0x08, 0xa2,
497*05bbd676SQuentin Schulz 	0x04, 0x72, 0x03, 0x92, 0x07, 0x80, 0x21, 0x30, 0x04, 0x06, 0x7b, 0xcc,
498*05bbd676SQuentin Schulz 	0x7d, 0x11, 0x80, 0x0d, 0x30, 0x03, 0x06, 0x7b, 0xcc, 0x7d, 0x10, 0x80,
499*05bbd676SQuentin Schulz 	0x04, 0x7b, 0x66, 0x7d, 0x16, 0xe4, 0xff, 0x12, 0x3d, 0xd7, 0xee, 0x4f,
500*05bbd676SQuentin Schulz 	0x24, 0xff, 0x92, 0x07, 0xaf, 0xfb, 0x74, 0x26, 0x2f, 0xf8, 0xe6, 0xff,
501*05bbd676SQuentin Schulz 	0xa6, 0x20, 0x20, 0x07, 0x39, 0x8f, 0x20, 0x30, 0x07, 0x34, 0x30, 0x00,
502*05bbd676SQuentin Schulz 	0x31, 0x20, 0x04, 0x2e, 0x20, 0x03, 0x2b, 0xe4, 0xf5, 0xff, 0x75, 0xfc,
503*05bbd676SQuentin Schulz 	0xc2, 0xe5, 0xfc, 0x30, 0xe0, 0xfb, 0xaf, 0xfe, 0xef, 0x20, 0xe3, 0x1a,
504*05bbd676SQuentin Schulz 	0xae, 0xfd, 0x44, 0x08, 0xf5, 0xfe, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
505*05bbd676SQuentin Schulz 	0xe0, 0xfb, 0x8f, 0xfe, 0x8e, 0xfd, 0x75, 0xfc, 0x80, 0xe5, 0xfc, 0x30,
506*05bbd676SQuentin Schulz 	0xe0, 0xfb, 0x05, 0xfb, 0xaf, 0xfb, 0xef, 0xc3, 0x94, 0x04, 0x50, 0x03,
507*05bbd676SQuentin Schulz 	0x02, 0x44, 0xc5, 0xe4, 0xf5, 0xfb, 0x22, 0xe5, 0x7e, 0x54, 0x0f, 0x64,
508*05bbd676SQuentin Schulz 	0x01, 0x70, 0x23, 0xe5, 0x7e, 0x30, 0xe4, 0x1e, 0x90, 0x47, 0xd0, 0xe0,
509*05bbd676SQuentin Schulz 	0x44, 0x02, 0xf0, 0x54, 0xfb, 0xf0, 0x90, 0x47, 0xd4, 0xe0, 0x44, 0x04,
510*05bbd676SQuentin Schulz 	0xf0, 0x7b, 0x03, 0x7d, 0x5b, 0x7f, 0x5d, 0x12, 0x36, 0x29, 0x7b, 0x0e,
511*05bbd676SQuentin Schulz 	0x80, 0x1c, 0x90, 0x47, 0xd0, 0xe0, 0x54, 0xfd, 0xf0, 0x44, 0x04, 0xf0,
512*05bbd676SQuentin Schulz 	0x90, 0x47, 0xd4, 0xe0, 0x54, 0xfb, 0xf0, 0x7b, 0x02, 0x7d, 0x5b, 0x7f,
513*05bbd676SQuentin Schulz 	0x5d, 0x12, 0x36, 0x29, 0x7b, 0x06, 0x7d, 0x60, 0x7f, 0x63, 0x12, 0x36,
514*05bbd676SQuentin Schulz 	0x29, 0x22, 0xe5, 0x7e, 0x30, 0xe5, 0x35, 0x30, 0xe4, 0x0b, 0x7b, 0x02,
515*05bbd676SQuentin Schulz 	0x7d, 0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x80, 0x10, 0x7b, 0x01, 0x7d,
516*05bbd676SQuentin Schulz 	0x33, 0x7f, 0x35, 0x12, 0x36, 0x29, 0x90, 0x47, 0xd2, 0xe0, 0x44, 0x04,
517*05bbd676SQuentin Schulz 	0xf0, 0x90, 0x47, 0xd2, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x47, 0xd1, 0xe0,
518*05bbd676SQuentin Schulz 	0x44, 0x10, 0xf0, 0x7b, 0x05, 0x7d, 0x84, 0x7f, 0x86, 0x12, 0x36, 0x29,
519*05bbd676SQuentin Schulz 	0x22, 0xfb, 0xe5, 0x1c, 0x34, 0xf0, 0xfa, 0x7d, 0x10, 0x7f, 0x07, 0x22,
520*05bbd676SQuentin Schulz 	0x54, 0x01, 0xc4, 0x33, 0x54, 0xe0, 0xf5, 0xdb, 0x44, 0x08, 0xf5, 0xdb,
521*05bbd676SQuentin Schulz 	0x22, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0x22,
522*05bbd676SQuentin Schulz 	0xab, 0x07, 0xaa, 0x06, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3e, 0xda, 0x7b,
523*05bbd676SQuentin Schulz 	0xff, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 0xf3,
524*05bbd676SQuentin Schulz 	0x22, 0x12, 0x44, 0xc2, 0x30, 0x0c, 0x03, 0x12, 0x42, 0x12, 0x78, 0xc4,
525*05bbd676SQuentin Schulz 	0xe6, 0xff, 0x60, 0x03, 0x12, 0x40, 0x25, 0x22, 0xe5, 0x19, 0x24, 0x17,
526*05bbd676SQuentin Schulz 	0x54, 0x1f, 0x44, 0x80, 0xff, 0x22, 0x74, 0x2a, 0x25, 0x19, 0xf8, 0xe6,
527*05bbd676SQuentin Schulz 	0x22, 0x12, 0x46, 0x72, 0x12, 0x46, 0x68, 0x90, 0x47, 0xfa, 0xe0, 0x54,
528*05bbd676SQuentin Schulz 	0xf8, 0x44, 0x02, 0xf0, 0x22, 0xe5, 0x7e, 0xae, 0x7d, 0x78, 0x04, 0x22,
529*05bbd676SQuentin Schulz 	0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, 0xe4, 0x78, 0xc4, 0xf6, 0xc2,
530*05bbd676SQuentin Schulz 	0x0d, 0x78, 0xc1, 0xf6, 0x22, 0xc2, 0x0c, 0xc2, 0x0b, 0x22, 0x22,
531*05bbd676SQuentin Schulz };
532*05bbd676SQuentin Schulz 
53304087fc4SQuentin Schulz static const u8 fw_patch_vsc8584[] = {
53404087fc4SQuentin Schulz 	0xe8, 0x59, 0x02, 0xe8, 0x12, 0x02, 0xe8, 0x42, 0x02, 0xe8, 0x5a, 0x02,
53504087fc4SQuentin Schulz 	0xe8, 0x5b, 0x02, 0xe8, 0x5c, 0xe5, 0x69, 0x54, 0x0f, 0x24, 0xf7, 0x60,
53604087fc4SQuentin Schulz 	0x27, 0x24, 0xfc, 0x60, 0x23, 0x24, 0x08, 0x70, 0x14, 0xe5, 0x69, 0xae,
53704087fc4SQuentin Schulz 	0x68, 0x78, 0x04, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0x7e,
53804087fc4SQuentin Schulz 	0x00, 0x54, 0x0f, 0x80, 0x00, 0x7b, 0x01, 0x7a, 0x00, 0x7d, 0xee, 0x7f,
53904087fc4SQuentin Schulz 	0x92, 0x12, 0x50, 0xee, 0x22, 0xe4, 0xf5, 0x10, 0x85, 0x10, 0xfb, 0x7d,
54004087fc4SQuentin Schulz 	0x1c, 0xe4, 0xff, 0x12, 0x59, 0xea, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94,
54104087fc4SQuentin Schulz 	0x04, 0x40, 0xed, 0x22, 0x22, 0x22, 0x22, 0x22,
54204087fc4SQuentin Schulz };
54304087fc4SQuentin Schulz 
vsc8584_get_fw_crc(struct mii_dev * bus,int phy,u16 start,u16 * crc,const u8 * fw_patch,int fw_size)54404087fc4SQuentin Schulz static int vsc8584_get_fw_crc(struct mii_dev *bus, int phy, u16 start,
54504087fc4SQuentin Schulz 			      u16 *crc, const u8 *fw_patch, int fw_size)
54604087fc4SQuentin Schulz {
54704087fc4SQuentin Schulz 	int ret;
54804087fc4SQuentin Schulz 
54904087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
55004087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_EXT1);
55104087fc4SQuentin Schulz 
55204087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2, start);
55304087fc4SQuentin Schulz 	/* Add one byte to size for the one added by the patch_fw function */
55404087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_3,
55504087fc4SQuentin Schulz 		   fw_size + 1);
55604087fc4SQuentin Schulz 
55704087fc4SQuentin Schulz 	ret = vsc8584_cmd(bus, phy, PROC_CMD_CRC16);
55804087fc4SQuentin Schulz 	if (ret)
55904087fc4SQuentin Schulz 		goto out;
56004087fc4SQuentin Schulz 
56104087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
56204087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_EXT1);
56304087fc4SQuentin Schulz 
56404087fc4SQuentin Schulz 	*crc = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PHY_VERIPHY_CNTL_2);
56504087fc4SQuentin Schulz 
56604087fc4SQuentin Schulz out:
56704087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
56804087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_STD);
56904087fc4SQuentin Schulz 
57004087fc4SQuentin Schulz 	return ret;
57104087fc4SQuentin Schulz }
57204087fc4SQuentin Schulz 
vsc8584_patch_fw(struct mii_dev * bus,int phy,const u8 * fw_patch,int fw_size)57304087fc4SQuentin Schulz static int vsc8584_patch_fw(struct mii_dev *bus, int phy, const u8 *fw_patch,
57404087fc4SQuentin Schulz 			    int fw_size)
57504087fc4SQuentin Schulz {
57604087fc4SQuentin Schulz 	int i, ret;
57704087fc4SQuentin Schulz 
57804087fc4SQuentin Schulz 	ret = vsc8584_micro_assert_reset(bus, phy);
57904087fc4SQuentin Schulz 	if (ret) {
58004087fc4SQuentin Schulz 		pr_err("%s: failed to assert reset of micro\n", __func__);
58104087fc4SQuentin Schulz 		return ret;
58204087fc4SQuentin Schulz 	}
58304087fc4SQuentin Schulz 
58404087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
58504087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_GPIO);
58604087fc4SQuentin Schulz 
58704087fc4SQuentin Schulz 	/*
58804087fc4SQuentin Schulz 	 * Hold 8051 Micro in SW Reset, Enable auto incr address and patch clock
58904087fc4SQuentin Schulz 	 * Disable the 8051 Micro clock
59004087fc4SQuentin Schulz 	 */
59104087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS,
59204087fc4SQuentin Schulz 		   RUN_FROM_INT_ROM | AUTOINC_ADDR | PATCH_RAM_CLK |
59304087fc4SQuentin Schulz 		   MICRO_CLK_EN | MICRO_CLK_DIVIDE(2));
59404087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_PRAM |
59504087fc4SQuentin Schulz 		   INT_MEM_WRITE_EN | INT_MEM_DATA(2));
59604087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_ADDR, 0x0000);
59704087fc4SQuentin Schulz 
59804087fc4SQuentin Schulz 	for (i = 0; i < fw_size; i++)
59904087fc4SQuentin Schulz 		bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
60004087fc4SQuentin Schulz 			   READ_PRAM | INT_MEM_WRITE_EN | fw_patch[i]);
60104087fc4SQuentin Schulz 
60204087fc4SQuentin Schulz 	/* Clear internal memory access */
60304087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL, READ_RAM);
60404087fc4SQuentin Schulz 
60504087fc4SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
60604087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_STD);
60704087fc4SQuentin Schulz 
60804087fc4SQuentin Schulz 	return 0;
60904087fc4SQuentin Schulz }
61004087fc4SQuentin Schulz 
vsc8574_is_serdes_init(struct mii_dev * bus,int phy)611*05bbd676SQuentin Schulz static bool vsc8574_is_serdes_init(struct mii_dev *bus, int phy)
612*05bbd676SQuentin Schulz {
613*05bbd676SQuentin Schulz 	u16 reg;
614*05bbd676SQuentin Schulz 	bool ret;
615*05bbd676SQuentin Schulz 
616*05bbd676SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
617*05bbd676SQuentin Schulz 		   MSCC_PHY_PAGE_GPIO);
618*05bbd676SQuentin Schulz 
619*05bbd676SQuentin Schulz 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1));
620*05bbd676SQuentin Schulz 	if (reg != MSCC_TRAP_ROM_ADDR_SERDES_INIT) {
621*05bbd676SQuentin Schulz 		ret = false;
622*05bbd676SQuentin Schulz 		goto out;
623*05bbd676SQuentin Schulz 	}
624*05bbd676SQuentin Schulz 
625*05bbd676SQuentin Schulz 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1));
626*05bbd676SQuentin Schulz 	if (reg != MSCC_PATCH_RAM_ADDR_SERDES_INIT) {
627*05bbd676SQuentin Schulz 		ret = false;
628*05bbd676SQuentin Schulz 		goto out;
629*05bbd676SQuentin Schulz 	}
630*05bbd676SQuentin Schulz 
631*05bbd676SQuentin Schulz 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL);
632*05bbd676SQuentin Schulz 	if (reg != EN_PATCH_RAM_TRAP_ADDR(1)) {
633*05bbd676SQuentin Schulz 		ret = false;
634*05bbd676SQuentin Schulz 		goto out;
635*05bbd676SQuentin Schulz 	}
636*05bbd676SQuentin Schulz 
637*05bbd676SQuentin Schulz 	reg = bus->read(bus, phy, MDIO_DEVAD_NONE, MSCC_DW8051_CNTL_STATUS);
638*05bbd676SQuentin Schulz 	if ((MICRO_NSOFT_RESET | RUN_FROM_INT_ROM |  DW8051_CLK_EN |
639*05bbd676SQuentin Schulz 	     MICRO_CLK_EN) != (reg & MSCC_DW8051_VLD_MASK)) {
640*05bbd676SQuentin Schulz 		ret = false;
641*05bbd676SQuentin Schulz 		goto out;
642*05bbd676SQuentin Schulz 	}
643*05bbd676SQuentin Schulz 
644*05bbd676SQuentin Schulz 	ret = true;
645*05bbd676SQuentin Schulz 
646*05bbd676SQuentin Schulz out:
647*05bbd676SQuentin Schulz 	bus->write(bus, phy, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
648*05bbd676SQuentin Schulz 		   MSCC_PHY_PAGE_GPIO);
649*05bbd676SQuentin Schulz 
650*05bbd676SQuentin Schulz 	return ret;
651*05bbd676SQuentin Schulz }
652*05bbd676SQuentin Schulz 
vsc8574_config_pre_init(struct phy_device * phydev)653*05bbd676SQuentin Schulz static int vsc8574_config_pre_init(struct phy_device *phydev)
654*05bbd676SQuentin Schulz {
655*05bbd676SQuentin Schulz 	struct mii_dev *bus = phydev->bus;
656*05bbd676SQuentin Schulz 	u16 crc, reg, phy0, addr;
657*05bbd676SQuentin Schulz 	bool serdes_init;
658*05bbd676SQuentin Schulz 	int ret;
659*05bbd676SQuentin Schulz 
660*05bbd676SQuentin Schulz 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
661*05bbd676SQuentin Schulz 		  MSCC_PHY_PAGE_EXT1);
662*05bbd676SQuentin Schulz 	addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
663*05bbd676SQuentin Schulz 	addr >>= PHY_CNTL_4_ADDR_POS;
664*05bbd676SQuentin Schulz 
665*05bbd676SQuentin Schulz 	reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
666*05bbd676SQuentin Schulz 	if (reg & PHY_ADDR_REVERSED)
667*05bbd676SQuentin Schulz 		phy0 = phydev->addr + addr;
668*05bbd676SQuentin Schulz 	else
669*05bbd676SQuentin Schulz 		phy0 = phydev->addr - addr;
670*05bbd676SQuentin Schulz 
671*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
672*05bbd676SQuentin Schulz 		   MSCC_PHY_PAGE_STD);
673*05bbd676SQuentin Schulz 
674*05bbd676SQuentin Schulz 	/* all writes below are broadcasted to all PHYs in the same package */
675*05bbd676SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
676*05bbd676SQuentin Schulz 	reg |= SMI_BROADCAST_WR_EN;
677*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
678*05bbd676SQuentin Schulz 
679*05bbd676SQuentin Schulz 	/*
680*05bbd676SQuentin Schulz 	 * The below register writes are tweaking analog and electrical
681*05bbd676SQuentin Schulz 	 * configuration that were determined through characterization by PHY
682*05bbd676SQuentin Schulz 	 * engineers. These don't mean anything more than "these are the best
683*05bbd676SQuentin Schulz 	 * values".
684*05bbd676SQuentin Schulz 	 */
685*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_2, 0x0040);
686*05bbd676SQuentin Schulz 
687*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
688*05bbd676SQuentin Schulz 		   MSCC_PHY_PAGE_TEST);
689*05bbd676SQuentin Schulz 
690*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_20, 0x4320);
691*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_24, 0x0c00);
692*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_9, 0x18ca);
693*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1b20);
694*05bbd676SQuentin Schulz 
695*05bbd676SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
696*05bbd676SQuentin Schulz 	reg |= TR_CLK_DISABLE;
697*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
698*05bbd676SQuentin Schulz 
699*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
700*05bbd676SQuentin Schulz 		   MSCC_PHY_PAGE_TR);
701*05bbd676SQuentin Schulz 
702*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fae, 0x000401bd);
703*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fac, 0x000f000f);
704*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x17a0, 0x00a0f147);
705*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fe4, 0x00052f54);
706*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x1792, 0x0027303d);
707*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x07fe, 0x00000704);
708*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fe0, 0x00060150);
709*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b00a);
710*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0f80, 0x00000d74);
711*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x02e0, 0x00000012);
712*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x03a2, 0x00050208);
713*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x03b2, 0x00009186);
714*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fb0, 0x000e3700);
715*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
716*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fd2, 0x0000ffff);
717*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x168a, 0x00039fa2);
718*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x1690, 0x0020640b);
719*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0258, 0x00002220);
720*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x025a, 0x00002a20);
721*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x025c, 0x00003060);
722*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x025e, 0x00003fa0);
723*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x03a6, 0x0000e0f0);
724*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0f92, 0x00001489);
725*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16a2, 0x00007000);
726*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
727*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
728*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
729*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
730*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
731*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
732*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
733*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
734*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
735*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
736*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
737*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0796, 0x00000003);
738*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x07f8, 0x00c3ff98);
739*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fa4, 0x0018292a);
740*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
741*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
742*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
743*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
744*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
745*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901c09);
746*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fee, 0x0004a6a1);
747*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01807);
748*05bbd676SQuentin Schulz 
749*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
750*05bbd676SQuentin Schulz 			MSCC_PHY_PAGE_EXT2);
751*05bbd676SQuentin Schulz 
752*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
753*05bbd676SQuentin Schulz 
754*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
755*05bbd676SQuentin Schulz 		   MSCC_PHY_PAGE_TR);
756*05bbd676SQuentin Schulz 
757*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
758*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
759*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
760*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x048e, 0x00000db6);
761*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x049c, 0x00596596);
762*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x049e, 0x00000514);
763*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x04a2, 0x00410280);
764*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x04a4, 0x00000000);
765*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x04a6, 0x00000000);
766*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x04a8, 0x00000000);
767*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x04aa, 0x00000000);
768*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x04ae, 0x007df7dd);
769*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x04b0, 0x006d95d4);
770*05bbd676SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x04b2, 0x00492410);
771*05bbd676SQuentin Schulz 
772*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
773*05bbd676SQuentin Schulz 		   MSCC_PHY_PAGE_TEST);
774*05bbd676SQuentin Schulz 
775*05bbd676SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
776*05bbd676SQuentin Schulz 	reg &= ~TR_CLK_DISABLE;
777*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
778*05bbd676SQuentin Schulz 
779*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
780*05bbd676SQuentin Schulz 			MSCC_PHY_PAGE_STD);
781*05bbd676SQuentin Schulz 
782*05bbd676SQuentin Schulz 	/* end of write broadcasting */
783*05bbd676SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
784*05bbd676SQuentin Schulz 	reg &= ~SMI_BROADCAST_WR_EN;
785*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
786*05bbd676SQuentin Schulz 
787*05bbd676SQuentin Schulz 	ret = vsc8584_get_fw_crc(bus, phy0,
788*05bbd676SQuentin Schulz 				 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR, &crc,
789*05bbd676SQuentin Schulz 				 fw_patch_vsc8574,
790*05bbd676SQuentin Schulz 				 ARRAY_SIZE(fw_patch_vsc8574));
791*05bbd676SQuentin Schulz 	if (ret)
792*05bbd676SQuentin Schulz 		goto out;
793*05bbd676SQuentin Schulz 
794*05bbd676SQuentin Schulz 	if (crc == MSCC_VSC8574_REVB_INT8051_FW_CRC) {
795*05bbd676SQuentin Schulz 		serdes_init = vsc8574_is_serdes_init(bus, phy0);
796*05bbd676SQuentin Schulz 
797*05bbd676SQuentin Schulz 		if (!serdes_init) {
798*05bbd676SQuentin Schulz 			ret = vsc8584_micro_assert_reset(bus, phy0);
799*05bbd676SQuentin Schulz 			if (ret) {
800*05bbd676SQuentin Schulz 				pr_err("failed to assert reset of micro\n");
801*05bbd676SQuentin Schulz 				return ret;
802*05bbd676SQuentin Schulz 			}
803*05bbd676SQuentin Schulz 		}
804*05bbd676SQuentin Schulz 	} else {
805*05bbd676SQuentin Schulz 		pr_debug("FW CRC is not the expected one, patching FW\n");
806*05bbd676SQuentin Schulz 
807*05bbd676SQuentin Schulz 		serdes_init = false;
808*05bbd676SQuentin Schulz 
809*05bbd676SQuentin Schulz 		if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8574,
810*05bbd676SQuentin Schulz 				     ARRAY_SIZE(fw_patch_vsc8574)))
811*05bbd676SQuentin Schulz 			pr_warn("failed to patch FW, expect non-optimal device\n");
812*05bbd676SQuentin Schulz 	}
813*05bbd676SQuentin Schulz 
814*05bbd676SQuentin Schulz 	if (!serdes_init) {
815*05bbd676SQuentin Schulz 		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
816*05bbd676SQuentin Schulz 				MSCC_PHY_PAGE_GPIO);
817*05bbd676SQuentin Schulz 
818*05bbd676SQuentin Schulz 		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_TRAP_ROM_ADDR(1),
819*05bbd676SQuentin Schulz 			   MSCC_TRAP_ROM_ADDR_SERDES_INIT);
820*05bbd676SQuentin Schulz 		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PATCH_RAM_ADDR(1),
821*05bbd676SQuentin Schulz 			   MSCC_PATCH_RAM_ADDR_SERDES_INIT);
822*05bbd676SQuentin Schulz 
823*05bbd676SQuentin Schulz 		bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_INT_MEM_CNTL,
824*05bbd676SQuentin Schulz 				EN_PATCH_RAM_TRAP_ADDR(1));
825*05bbd676SQuentin Schulz 
826*05bbd676SQuentin Schulz 		vsc8584_micro_deassert_reset(bus, phy0, false);
827*05bbd676SQuentin Schulz 
828*05bbd676SQuentin Schulz 		ret = vsc8584_get_fw_crc(bus, phy0,
829*05bbd676SQuentin Schulz 					 MSCC_VSC8574_REVB_INT8051_FW_START_ADDR,
830*05bbd676SQuentin Schulz 					 &crc, fw_patch_vsc8574,
831*05bbd676SQuentin Schulz 					 ARRAY_SIZE(fw_patch_vsc8574));
832*05bbd676SQuentin Schulz 		if (ret)
833*05bbd676SQuentin Schulz 			goto out;
834*05bbd676SQuentin Schulz 
835*05bbd676SQuentin Schulz 		if (crc != MSCC_VSC8574_REVB_INT8051_FW_CRC)
836*05bbd676SQuentin Schulz 			pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
837*05bbd676SQuentin Schulz 	}
838*05bbd676SQuentin Schulz 
839*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
840*05bbd676SQuentin Schulz 		   MSCC_PHY_PAGE_GPIO);
841*05bbd676SQuentin Schulz 
842*05bbd676SQuentin Schulz 	ret = vsc8584_cmd(bus, phy0, PROC_CMD_1588_DEFAULT_INIT |
843*05bbd676SQuentin Schulz 			  PROC_CMD_PHY_INIT);
844*05bbd676SQuentin Schulz 
845*05bbd676SQuentin Schulz out:
846*05bbd676SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
847*05bbd676SQuentin Schulz 			MSCC_PHY_PAGE_STD);
848*05bbd676SQuentin Schulz 
849*05bbd676SQuentin Schulz 	return ret;
850*05bbd676SQuentin Schulz }
851*05bbd676SQuentin Schulz 
vsc8584_config_pre_init(struct phy_device * phydev)852b5bca65eSQuentin Schulz static int vsc8584_config_pre_init(struct phy_device *phydev)
85304087fc4SQuentin Schulz {
854b5bca65eSQuentin Schulz 	struct mii_dev *bus = phydev->bus;
855b5bca65eSQuentin Schulz 	u16 reg, crc, phy0, addr;
85604087fc4SQuentin Schulz 	int ret;
85704087fc4SQuentin Schulz 
858b5bca65eSQuentin Schulz 	if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
859b5bca65eSQuentin Schulz 		pr_warn("VSC8584 revA not officially supported, skipping firmware patching. Use at your own risk.\n");
860b5bca65eSQuentin Schulz 		return 0;
861b5bca65eSQuentin Schulz 	}
862b5bca65eSQuentin Schulz 
863b5bca65eSQuentin Schulz 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
864b5bca65eSQuentin Schulz 		  MSCC_PHY_PAGE_EXT1);
865b5bca65eSQuentin Schulz 	addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
866b5bca65eSQuentin Schulz 	addr >>= PHY_CNTL_4_ADDR_POS;
867b5bca65eSQuentin Schulz 
868b5bca65eSQuentin Schulz 	reg = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_ACTIPHY_CNTL);
869b5bca65eSQuentin Schulz 	if (reg & PHY_ADDR_REVERSED)
870b5bca65eSQuentin Schulz 		phy0 = phydev->addr + addr;
871b5bca65eSQuentin Schulz 	else
872b5bca65eSQuentin Schulz 		phy0 = phydev->addr - addr;
873b5bca65eSQuentin Schulz 
87404087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
87504087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_STD);
87604087fc4SQuentin Schulz 
87704087fc4SQuentin Schulz 	/* all writes below are broadcasted to all PHYs in the same package */
87804087fc4SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
87904087fc4SQuentin Schulz 	reg |= SMI_BROADCAST_WR_EN;
88004087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
88104087fc4SQuentin Schulz 
88204087fc4SQuentin Schulz 	/*
88304087fc4SQuentin Schulz 	 * The below register writes are tweaking analog and electrical
88404087fc4SQuentin Schulz 	 * configuration that were determined through characterization by PHY
88504087fc4SQuentin Schulz 	 * engineers. These don't mean anything more than "these are the best
88604087fc4SQuentin Schulz 	 * values".
88704087fc4SQuentin Schulz 	 */
88804087fc4SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL);
88904087fc4SQuentin Schulz 	reg |= PARALLEL_DET_IGNORE_ADVERTISED;
89004087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_BYPASS_CONTROL, reg);
89104087fc4SQuentin Schulz 
89204087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
89304087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_EXT3);
89404087fc4SQuentin Schulz 
89504087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_SERDES_TX_CRC_ERR_CNT,
89604087fc4SQuentin Schulz 		   0x2000);
89704087fc4SQuentin Schulz 
89804087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
89904087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_TEST);
90004087fc4SQuentin Schulz 
90104087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_5, 0x1f20);
90204087fc4SQuentin Schulz 
90304087fc4SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
90404087fc4SQuentin Schulz 	reg |= TR_CLK_DISABLE;
90504087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
90604087fc4SQuentin Schulz 
90704087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
90804087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_TR);
90904087fc4SQuentin Schulz 
91004087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0xafa4);
91104087fc4SQuentin Schulz 
91204087fc4SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
91304087fc4SQuentin Schulz 	reg &= ~0x007f;
91404087fc4SQuentin Schulz 	reg |= 0x0019;
91504087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg);
91604087fc4SQuentin Schulz 
91704087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16, 0x8fa4);
91804087fc4SQuentin Schulz 
91904087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x07fa, 0x0050100f);
92004087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x1688, 0x00049f81);
92104087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0f90, 0x00688980);
92204087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x03a4, 0x0000d8f0);
92304087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fc0, 0x00000400);
92404087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0f82, 0x0012b002);
92504087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x1686, 0x00000004);
92604087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x168c, 0x00d2c46f);
92704087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x17a2, 0x00000620);
92804087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16a0, 0x00eeffdd);
92904087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16a6, 0x00071448);
93004087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16a4, 0x0013132f);
93104087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16a8, 0x00000000);
93204087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0ffc, 0x00c0a028);
93304087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fe8, 0x0091b06c);
93404087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fea, 0x00041600);
93504087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0f80, 0x00fffaff);
93604087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0fec, 0x00901809);
93704087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0ffe, 0x00b01007);
93804087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16b0, 0x00eeff00);
93904087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16b2, 0x00007000);
94004087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x16b4, 0x00000814);
94104087fc4SQuentin Schulz 
94204087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
94304087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_EXT2);
94404087fc4SQuentin Schulz 
94504087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_CU_PMD_TX_CNTL, 0x028e);
94604087fc4SQuentin Schulz 
94704087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
94804087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_TR);
94904087fc4SQuentin Schulz 
95004087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0486, 0x0008a518);
95104087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x0488, 0x006dc696);
95204087fc4SQuentin Schulz 	vsc8584_csr_write(bus, phy0, 0x048a, 0x00000912);
95304087fc4SQuentin Schulz 
95404087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
95504087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_TEST);
95604087fc4SQuentin Schulz 
95704087fc4SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8);
95804087fc4SQuentin Schulz 	reg &= ~TR_CLK_DISABLE;
95904087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_TEST_PAGE_8, reg);
96004087fc4SQuentin Schulz 
96104087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
96204087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_STD);
96304087fc4SQuentin Schulz 
96404087fc4SQuentin Schulz 	/* end of write broadcasting */
96504087fc4SQuentin Schulz 	reg = bus->read(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS);
96604087fc4SQuentin Schulz 	reg &= ~SMI_BROADCAST_WR_EN;
96704087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_PHY_EXT_CNTL_STATUS, reg);
96804087fc4SQuentin Schulz 
96904087fc4SQuentin Schulz 	ret = vsc8584_get_fw_crc(bus, phy0,
97004087fc4SQuentin Schulz 				 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
97104087fc4SQuentin Schulz 				 fw_patch_vsc8584,
97204087fc4SQuentin Schulz 				 ARRAY_SIZE(fw_patch_vsc8584));
97304087fc4SQuentin Schulz 	if (ret)
97404087fc4SQuentin Schulz 		goto out;
97504087fc4SQuentin Schulz 
97604087fc4SQuentin Schulz 	if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC) {
97704087fc4SQuentin Schulz 		debug("FW CRC is not the expected one, patching FW...\n");
97804087fc4SQuentin Schulz 		if (vsc8584_patch_fw(bus, phy0, fw_patch_vsc8584,
97904087fc4SQuentin Schulz 				     ARRAY_SIZE(fw_patch_vsc8584)))
98004087fc4SQuentin Schulz 			pr_warn("failed to patch FW, expect non-optimal device\n");
98104087fc4SQuentin Schulz 	}
98204087fc4SQuentin Schulz 
98304087fc4SQuentin Schulz 	vsc8584_micro_deassert_reset(bus, phy0, false);
98404087fc4SQuentin Schulz 
98504087fc4SQuentin Schulz 	ret = vsc8584_get_fw_crc(bus, phy0,
98604087fc4SQuentin Schulz 				 MSCC_VSC8584_REVB_INT8051_FW_START_ADDR, &crc,
98704087fc4SQuentin Schulz 				 fw_patch_vsc8584,
98804087fc4SQuentin Schulz 				 ARRAY_SIZE(fw_patch_vsc8584));
98904087fc4SQuentin Schulz 	if (ret)
99004087fc4SQuentin Schulz 		goto out;
99104087fc4SQuentin Schulz 
99204087fc4SQuentin Schulz 	if (crc != MSCC_VSC8584_REVB_INT8051_FW_CRC)
99304087fc4SQuentin Schulz 		pr_warn("FW CRC after patching is not the expected one, expect non-optimal device\n");
99404087fc4SQuentin Schulz 
99504087fc4SQuentin Schulz 	ret = vsc8584_micro_assert_reset(bus, phy0);
99604087fc4SQuentin Schulz 	if (ret)
99704087fc4SQuentin Schulz 		goto out;
99804087fc4SQuentin Schulz 
99904087fc4SQuentin Schulz 	vsc8584_micro_deassert_reset(bus, phy0, true);
100004087fc4SQuentin Schulz 
100104087fc4SQuentin Schulz out:
100204087fc4SQuentin Schulz 	bus->write(bus, phy0, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
100304087fc4SQuentin Schulz 		   MSCC_PHY_PAGE_STD);
100404087fc4SQuentin Schulz 
100504087fc4SQuentin Schulz 	return ret;
100604087fc4SQuentin Schulz }
1007a5fd13adSJohn Haechten 
mscc_vsc8531_vsc8541_init_scripts(struct phy_device * phydev)1008a5fd13adSJohn Haechten static int mscc_vsc8531_vsc8541_init_scripts(struct phy_device *phydev)
1009a5fd13adSJohn Haechten {
1010a5fd13adSJohn Haechten 	u16	reg_val;
1011a5fd13adSJohn Haechten 
1012a5fd13adSJohn Haechten 	/* Set to Access Token Ring Registers */
1013a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE,
1014a5fd13adSJohn Haechten 		  MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_TR);
1015a5fd13adSJohn Haechten 
1016a5fd13adSJohn Haechten 	/* Update LinkDetectCtrl default to optimized values */
1017a5fd13adSJohn Haechten 	/* Determined during Silicon Validation Testing */
1018a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1019a5fd13adSJohn Haechten 		  (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_READ));
1020a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
1021a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_LINKDETCTRL_POS,
1022a5fd13adSJohn Haechten 				   MSCC_PHY_TR_LINKDETCTRL_WIDTH,
1023a5fd13adSJohn Haechten 				   MSCC_PHY_TR_LINKDETCTRL_VAL);
1024a5fd13adSJohn Haechten 
1025a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
1026a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1027a5fd13adSJohn Haechten 		  (MSCC_PHY_TR_LINKDETCTRL_ADDR | MSCC_PHY_TR_16_WRITE));
1028a5fd13adSJohn Haechten 
1029a5fd13adSJohn Haechten 	/* Update VgaThresh100 defaults to optimized values */
1030a5fd13adSJohn Haechten 	/* Determined during Silicon Validation Testing */
1031a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1032a5fd13adSJohn Haechten 		  (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_READ));
1033a5fd13adSJohn Haechten 
1034a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
1035a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGATHRESH100_POS,
1036a5fd13adSJohn Haechten 				   MSCC_PHY_TR_VGATHRESH100_WIDTH,
1037a5fd13adSJohn Haechten 				   MSCC_PHY_TR_VGATHRESH100_VAL);
1038a5fd13adSJohn Haechten 
1039a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
1040a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1041a5fd13adSJohn Haechten 		  (MSCC_PHY_TR_VGATHRESH100_ADDR | MSCC_PHY_TR_16_WRITE));
1042a5fd13adSJohn Haechten 
1043a5fd13adSJohn Haechten 	/* Update VgaGain10 defaults to optimized values */
1044a5fd13adSJohn Haechten 	/* Determined during Silicon Validation Testing */
1045a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1046a5fd13adSJohn Haechten 		  (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_READ));
1047a5fd13adSJohn Haechten 
1048a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18);
1049a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_U_POS,
1050a5fd13adSJohn Haechten 				   MSCC_PHY_TR_VGAGAIN10_U_WIDTH,
1051a5fd13adSJohn Haechten 				   MSCC_PHY_TR_VGAGAIN10_U_VAL);
1052a5fd13adSJohn Haechten 
1053a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_18, reg_val);
1054a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17);
1055a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, MSCC_PHY_TR_VGAGAIN10_L_POS,
1056a5fd13adSJohn Haechten 				   MSCC_PHY_TR_VGAGAIN10_L_WIDTH,
1057a5fd13adSJohn Haechten 				   MSCC_PHY_TR_VGAGAIN10_L_VAL);
1058a5fd13adSJohn Haechten 
1059a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_DATA_17, reg_val);
1060a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_REG_TR_ADDR_16,
1061a5fd13adSJohn Haechten 		  (MSCC_PHY_TR_VGAGAIN10_ADDR | MSCC_PHY_TR_16_WRITE));
1062a5fd13adSJohn Haechten 
1063a5fd13adSJohn Haechten 	/* Set back to Access Standard Page Registers */
1064a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1065a5fd13adSJohn Haechten 		  MSCC_PHY_PAGE_STD);
1066a5fd13adSJohn Haechten 
1067a5fd13adSJohn Haechten 	return 0;
1068a5fd13adSJohn Haechten }
1069a5fd13adSJohn Haechten 
mscc_parse_status(struct phy_device * phydev)1070a5fd13adSJohn Haechten static int mscc_parse_status(struct phy_device *phydev)
1071a5fd13adSJohn Haechten {
1072a5fd13adSJohn Haechten 	u16 speed;
1073a5fd13adSJohn Haechten 	u16 mii_reg;
1074a5fd13adSJohn Haechten 
1075a5fd13adSJohn Haechten 	mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_AUX_CNTRL_STAT_REG);
1076a5fd13adSJohn Haechten 
1077a5fd13adSJohn Haechten 	if (mii_reg & MIIM_AUX_CNTRL_STAT_F_DUPLEX)
1078a5fd13adSJohn Haechten 		phydev->duplex = DUPLEX_FULL;
1079a5fd13adSJohn Haechten 	else
1080a5fd13adSJohn Haechten 		phydev->duplex = DUPLEX_HALF;
1081a5fd13adSJohn Haechten 
1082a5fd13adSJohn Haechten 	speed = mii_reg & MIIM_AUX_CNTRL_STAT_SPEED_MASK;
1083a5fd13adSJohn Haechten 	speed = speed >> MIIM_AUX_CNTRL_STAT_SPEED_POS;
1084a5fd13adSJohn Haechten 
1085a5fd13adSJohn Haechten 	switch (speed) {
1086a5fd13adSJohn Haechten 	case MIIM_AUX_CNTRL_STAT_SPEED_1000M:
1087a5fd13adSJohn Haechten 		phydev->speed = SPEED_1000;
1088a5fd13adSJohn Haechten 		break;
1089a5fd13adSJohn Haechten 	case MIIM_AUX_CNTRL_STAT_SPEED_100M:
1090a5fd13adSJohn Haechten 		phydev->speed = SPEED_100;
1091a5fd13adSJohn Haechten 		break;
1092a5fd13adSJohn Haechten 	case MIIM_AUX_CNTRL_STAT_SPEED_10M:
1093a5fd13adSJohn Haechten 		phydev->speed = SPEED_10;
1094a5fd13adSJohn Haechten 		break;
1095a5fd13adSJohn Haechten 	default:
1096a5fd13adSJohn Haechten 		phydev->speed = SPEED_10;
1097a5fd13adSJohn Haechten 		break;
1098a5fd13adSJohn Haechten 	}
1099a5fd13adSJohn Haechten 
1100a5fd13adSJohn Haechten 	return 0;
1101a5fd13adSJohn Haechten }
1102a5fd13adSJohn Haechten 
mscc_startup(struct phy_device * phydev)1103a5fd13adSJohn Haechten static int mscc_startup(struct phy_device *phydev)
1104a5fd13adSJohn Haechten {
1105a5fd13adSJohn Haechten 	int retval;
1106a5fd13adSJohn Haechten 
1107a5fd13adSJohn Haechten 	retval = genphy_update_link(phydev);
1108a5fd13adSJohn Haechten 
1109a5fd13adSJohn Haechten 	if (retval)
1110a5fd13adSJohn Haechten 		return retval;
1111a5fd13adSJohn Haechten 
1112a5fd13adSJohn Haechten 	return mscc_parse_status(phydev);
1113a5fd13adSJohn Haechten }
1114a5fd13adSJohn Haechten 
mscc_phy_soft_reset(struct phy_device * phydev)1115a5fd13adSJohn Haechten static int mscc_phy_soft_reset(struct phy_device *phydev)
1116a5fd13adSJohn Haechten {
1117a5fd13adSJohn Haechten 	int     retval = 0;
1118a5fd13adSJohn Haechten 	u16     timeout = MSCC_PHY_RESET_TIMEOUT;
1119a5fd13adSJohn Haechten 	u16     reg_val = 0;
1120a5fd13adSJohn Haechten 
1121a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1122a5fd13adSJohn Haechten 		  MSCC_PHY_PAGE_STD);
1123a5fd13adSJohn Haechten 
1124a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1125a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, (reg_val | BMCR_RESET));
1126a5fd13adSJohn Haechten 
1127a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1128a5fd13adSJohn Haechten 
1129a5fd13adSJohn Haechten 	while ((reg_val & BMCR_RESET) && (timeout > 0)) {
1130a5fd13adSJohn Haechten 		reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
1131a5fd13adSJohn Haechten 		timeout--;
1132a5fd13adSJohn Haechten 		udelay(1000);   /* 1 ms */
1133a5fd13adSJohn Haechten 	}
1134a5fd13adSJohn Haechten 
1135a5fd13adSJohn Haechten 	if (timeout == 0) {
1136a5fd13adSJohn Haechten 		printf("MSCC PHY Soft_Reset Error: mac i/f = 0x%x\n",
1137a5fd13adSJohn Haechten 		       phydev->interface);
1138a5fd13adSJohn Haechten 		retval = -ETIME;
1139a5fd13adSJohn Haechten 	}
1140a5fd13adSJohn Haechten 
1141a5fd13adSJohn Haechten 	return retval;
1142a5fd13adSJohn Haechten }
1143a5fd13adSJohn Haechten 
vsc8531_vsc8541_mac_config(struct phy_device * phydev)1144a5fd13adSJohn Haechten static int vsc8531_vsc8541_mac_config(struct phy_device *phydev)
1145a5fd13adSJohn Haechten {
1146a5fd13adSJohn Haechten 	u16	reg_val = 0;
1147a5fd13adSJohn Haechten 	u16	mac_if = 0;
1148a5fd13adSJohn Haechten 	u16	rx_clk_out = 0;
1149a5fd13adSJohn Haechten 
1150a5fd13adSJohn Haechten 	/* For VSC8530/31 the only MAC modes are RMII/RGMII. */
1151a5fd13adSJohn Haechten 	/* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
1152a5fd13adSJohn Haechten 	/* Setup MAC Configuration */
1153a5fd13adSJohn Haechten 	switch (phydev->interface) {
1154a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_MII:
1155a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_GMII:
1156a5fd13adSJohn Haechten 		/* Set Reg23.12:11=0 */
1157a5fd13adSJohn Haechten 		mac_if = MAC_IF_SELECTION_GMII;
1158a5fd13adSJohn Haechten 		/* Set Reg20E2.11=1 */
1159a5fd13adSJohn Haechten 		rx_clk_out = RX_CLK_OUT_DISABLE;
1160a5fd13adSJohn Haechten 		break;
1161a5fd13adSJohn Haechten 
1162a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_RMII:
1163a5fd13adSJohn Haechten 		/* Set Reg23.12:11=1 */
1164a5fd13adSJohn Haechten 		mac_if = MAC_IF_SELECTION_RMII;
1165a5fd13adSJohn Haechten 		/* Set Reg20E2.11=0 */
1166a5fd13adSJohn Haechten 		rx_clk_out = RX_CLK_OUT_NORMAL;
1167a5fd13adSJohn Haechten 		break;
1168a5fd13adSJohn Haechten 
1169a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_RGMII:
1170a5fd13adSJohn Haechten 		/* Set Reg23.12:11=2 */
1171a5fd13adSJohn Haechten 		mac_if = MAC_IF_SELECTION_RGMII;
1172a5fd13adSJohn Haechten 		/* Set Reg20E2.11=0 */
1173a5fd13adSJohn Haechten 		rx_clk_out = RX_CLK_OUT_NORMAL;
1174a5fd13adSJohn Haechten 		break;
1175a5fd13adSJohn Haechten 
1176a5fd13adSJohn Haechten 	default:
1177a5fd13adSJohn Haechten 		printf("MSCC PHY - INVALID MAC i/f Config: mac i/f = 0x%x\n",
1178a5fd13adSJohn Haechten 		       phydev->interface);
1179a5fd13adSJohn Haechten 		return -EINVAL;
1180a5fd13adSJohn Haechten 	}
1181a5fd13adSJohn Haechten 
1182a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1183a5fd13adSJohn Haechten 		  MSCC_PHY_PAGE_STD);
1184a5fd13adSJohn Haechten 
1185a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1186a5fd13adSJohn Haechten 			   MSCC_PHY_EXT_PHY_CNTL_1_REG);
1187a5fd13adSJohn Haechten 	/* Set MAC i/f bits Reg23.12:11 */
1188a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, MAC_IF_SELECTION_POS,
1189a5fd13adSJohn Haechten 				   MAC_IF_SELECTION_WIDTH, mac_if);
1190a5fd13adSJohn Haechten 	/* Update Reg23.12:11 */
1191a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE,
1192a5fd13adSJohn Haechten 		  MSCC_PHY_EXT_PHY_CNTL_1_REG, reg_val);
1193a5fd13adSJohn Haechten 	/* Setup ExtPg_2 Register Access */
1194a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE,
1195a5fd13adSJohn Haechten 		  MSCC_EXT_PAGE_ACCESS, MSCC_PHY_PAGE_EXT2);
1196a5fd13adSJohn Haechten 	/* Read Reg20E2 */
1197a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
1198a5fd13adSJohn Haechten 			   MSCC_PHY_RGMII_CNTL_REG);
1199a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, RX_CLK_OUT_POS,
1200a5fd13adSJohn Haechten 				   RX_CLK_OUT_WIDTH, rx_clk_out);
1201a5fd13adSJohn Haechten 	/* Update Reg20E2.11 */
1202a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE,
1203a5fd13adSJohn Haechten 		  MSCC_PHY_RGMII_CNTL_REG, reg_val);
1204a5fd13adSJohn Haechten 	/* Before leaving - Change back to Std Page Register Access */
1205a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1206a5fd13adSJohn Haechten 		  MSCC_PHY_PAGE_STD);
1207a5fd13adSJohn Haechten 
1208a5fd13adSJohn Haechten 	return 0;
1209a5fd13adSJohn Haechten }
1210a5fd13adSJohn Haechten 
vsc8531_config(struct phy_device * phydev)1211a5fd13adSJohn Haechten static int vsc8531_config(struct phy_device *phydev)
1212a5fd13adSJohn Haechten {
1213a5fd13adSJohn Haechten 	int  retval = -EINVAL;
1214a5fd13adSJohn Haechten 	u16  reg_val;
1215a5fd13adSJohn Haechten 	u16  rmii_clk_out;
1216a5fd13adSJohn Haechten 	enum vsc_phy_rgmii_skew  rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
1217a5fd13adSJohn Haechten 	enum vsc_phy_rgmii_skew  tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
1218a5fd13adSJohn Haechten 	enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1219a5fd13adSJohn Haechten 
1220a5fd13adSJohn Haechten 	/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1221a5fd13adSJohn Haechten 	mscc_vsc8531_vsc8541_init_scripts(phydev);
1222a5fd13adSJohn Haechten 
1223a5fd13adSJohn Haechten 	/* For VSC8530/31 the only MAC modes are RMII/RGMII. */
1224a5fd13adSJohn Haechten 	switch (phydev->interface) {
1225a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_RMII:
1226a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_RGMII:
1227a5fd13adSJohn Haechten 		retval = vsc8531_vsc8541_mac_config(phydev);
1228a5fd13adSJohn Haechten 		if (retval != 0)
1229a5fd13adSJohn Haechten 			return retval;
1230a5fd13adSJohn Haechten 
1231a5fd13adSJohn Haechten 		retval = mscc_phy_soft_reset(phydev);
1232a5fd13adSJohn Haechten 		if (retval != 0)
1233a5fd13adSJohn Haechten 			return retval;
1234a5fd13adSJohn Haechten 		break;
1235a5fd13adSJohn Haechten 	default:
1236a5fd13adSJohn Haechten 		printf("PHY 8530/31 MAC i/f Config Error: mac i/f = 0x%x\n",
1237a5fd13adSJohn Haechten 		       phydev->interface);
1238a5fd13adSJohn Haechten 		return -EINVAL;
1239a5fd13adSJohn Haechten 	}
1240a5fd13adSJohn Haechten 	/* Default RMII Clk Output to 0=OFF/1=ON  */
1241a5fd13adSJohn Haechten 	rmii_clk_out = 0;
1242a5fd13adSJohn Haechten 
1243a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1244a5fd13adSJohn Haechten 		  MSCC_PHY_PAGE_EXT2);
1245a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
1246a5fd13adSJohn Haechten 
1247a5fd13adSJohn Haechten 	/* Reg20E2 - Update RGMII RX_Clk Skews. */
1248a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
1249a5fd13adSJohn Haechten 				   RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
1250a5fd13adSJohn Haechten 	/* Reg20E2 - Update RGMII TX_Clk Skews. */
1251a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
1252a5fd13adSJohn Haechten 				   RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
1253a5fd13adSJohn Haechten 
1254a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
1255a5fd13adSJohn Haechten 
1256a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1257a5fd13adSJohn Haechten 	/* Reg27E2 - Update Clk Slew Rate. */
1258a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1259a5fd13adSJohn Haechten 				   EDGE_RATE_CNTL_WIDTH, edge_rate);
1260a5fd13adSJohn Haechten 	/* Reg27E2 - Update RMII Clk Out. */
1261a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1262a5fd13adSJohn Haechten 				   RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1263a5fd13adSJohn Haechten 	/* Update Reg27E2 */
1264a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1265a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1266a5fd13adSJohn Haechten 		  MSCC_PHY_PAGE_STD);
1267a5fd13adSJohn Haechten 
1268a5fd13adSJohn Haechten 	return genphy_config_aneg(phydev);
1269a5fd13adSJohn Haechten }
1270a5fd13adSJohn Haechten 
vsc8541_config(struct phy_device * phydev)1271a5fd13adSJohn Haechten static int vsc8541_config(struct phy_device *phydev)
1272a5fd13adSJohn Haechten {
1273a5fd13adSJohn Haechten 	int  retval = -EINVAL;
1274a5fd13adSJohn Haechten 	u16  reg_val;
1275a5fd13adSJohn Haechten 	u16  rmii_clk_out;
1276a5fd13adSJohn Haechten 	enum vsc_phy_rgmii_skew  rx_clk_skew = VSC_PHY_RGMII_DELAY_1700_PS;
1277a5fd13adSJohn Haechten 	enum vsc_phy_rgmii_skew  tx_clk_skew = VSC_PHY_RGMII_DELAY_800_PS;
1278a5fd13adSJohn Haechten 	enum vsc_phy_clk_slew    edge_rate = VSC_PHY_CLK_SLEW_RATE_4;
1279a5fd13adSJohn Haechten 
1280a5fd13adSJohn Haechten 	/* For VSC8530/31 and VSC8540/41 the init scripts are the same */
1281a5fd13adSJohn Haechten 	mscc_vsc8531_vsc8541_init_scripts(phydev);
1282a5fd13adSJohn Haechten 
1283a5fd13adSJohn Haechten 	/* For VSC8540/41 the only MAC modes are (G)MII and RMII/RGMII. */
1284a5fd13adSJohn Haechten 	switch (phydev->interface) {
1285a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_MII:
1286a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_GMII:
1287a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_RMII:
1288a5fd13adSJohn Haechten 	case PHY_INTERFACE_MODE_RGMII:
1289a5fd13adSJohn Haechten 		retval = vsc8531_vsc8541_mac_config(phydev);
1290a5fd13adSJohn Haechten 		if (retval != 0)
1291a5fd13adSJohn Haechten 			return retval;
1292a5fd13adSJohn Haechten 
1293a5fd13adSJohn Haechten 		retval = mscc_phy_soft_reset(phydev);
1294a5fd13adSJohn Haechten 		if (retval != 0)
1295a5fd13adSJohn Haechten 			return retval;
1296a5fd13adSJohn Haechten 		break;
1297a5fd13adSJohn Haechten 	default:
1298a5fd13adSJohn Haechten 		printf("PHY 8541 MAC i/f config Error: mac i/f = 0x%x\n",
1299a5fd13adSJohn Haechten 		       phydev->interface);
1300a5fd13adSJohn Haechten 		return -EINVAL;
1301a5fd13adSJohn Haechten 	}
1302a5fd13adSJohn Haechten 	/* Default RMII Clk Output to 0=OFF/1=ON  */
1303a5fd13adSJohn Haechten 	rmii_clk_out = 0;
1304a5fd13adSJohn Haechten 
1305a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1306a5fd13adSJohn Haechten 		  MSCC_PHY_PAGE_EXT2);
1307a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG);
1308a5fd13adSJohn Haechten 	/* Reg20E2 - Update RGMII RX_Clk Skews. */
1309a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, RGMII_RX_CLK_DELAY_POS,
1310a5fd13adSJohn Haechten 				   RGMII_RX_CLK_DELAY_WIDTH, rx_clk_skew);
1311a5fd13adSJohn Haechten 	/* Reg20E2 - Update RGMII TX_Clk Skews. */
1312a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, RGMII_TX_CLK_DELAY_POS,
1313a5fd13adSJohn Haechten 				   RGMII_TX_CLK_DELAY_WIDTH, tx_clk_skew);
1314a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_RGMII_CNTL_REG, reg_val);
1315a5fd13adSJohn Haechten 
1316a5fd13adSJohn Haechten 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL);
1317a5fd13adSJohn Haechten 	/* Reg27E2 - Update Clk Slew Rate. */
1318a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, EDGE_RATE_CNTL_POS,
1319a5fd13adSJohn Haechten 				   EDGE_RATE_CNTL_WIDTH, edge_rate);
1320a5fd13adSJohn Haechten 	/* Reg27E2 - Update RMII Clk Out. */
1321a5fd13adSJohn Haechten 	reg_val = bitfield_replace(reg_val, RMII_CLK_OUT_ENABLE_POS,
1322a5fd13adSJohn Haechten 				   RMII_CLK_OUT_ENABLE_WIDTH, rmii_clk_out);
1323a5fd13adSJohn Haechten 	/* Update Reg27E2 */
1324a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
1325a5fd13adSJohn Haechten 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
1326a5fd13adSJohn Haechten 		  MSCC_PHY_PAGE_STD);
1327a5fd13adSJohn Haechten 
1328a5fd13adSJohn Haechten 	return genphy_config_aneg(phydev);
1329a5fd13adSJohn Haechten }
1330a5fd13adSJohn Haechten 
vsc8584_config_init(struct phy_device * phydev)1331b5bca65eSQuentin Schulz static int vsc8584_config_init(struct phy_device *phydev)
133204087fc4SQuentin Schulz {
1333b5bca65eSQuentin Schulz 	struct vsc85xx_priv *priv = phydev->priv;
133404087fc4SQuentin Schulz 	int ret;
133504087fc4SQuentin Schulz 	u16 addr;
133604087fc4SQuentin Schulz 	u16 reg_val;
133704087fc4SQuentin Schulz 	u16 val;
133804087fc4SQuentin Schulz 
133904087fc4SQuentin Schulz 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
134004087fc4SQuentin Schulz 		  MSCC_PHY_PAGE_EXT1);
134104087fc4SQuentin Schulz 	addr = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_4);
134204087fc4SQuentin Schulz 	addr >>= PHY_CNTL_4_ADDR_POS;
134304087fc4SQuentin Schulz 
1344b5bca65eSQuentin Schulz 	ret = priv->config_pre(phydev);
134504087fc4SQuentin Schulz 	if (ret)
134604087fc4SQuentin Schulz 		return ret;
134704087fc4SQuentin Schulz 
134804087fc4SQuentin Schulz 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
134904087fc4SQuentin Schulz 		  MSCC_PHY_PAGE_GPIO);
135004087fc4SQuentin Schulz 
135104087fc4SQuentin Schulz 	if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
135204087fc4SQuentin Schulz 		val = MAC_CFG_QSGMII;
135304087fc4SQuentin Schulz 	else
135404087fc4SQuentin Schulz 		val = MAC_CFG_SGMII;
135504087fc4SQuentin Schulz 
135604087fc4SQuentin Schulz 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK);
135704087fc4SQuentin Schulz 	reg_val &= ~MAC_CFG_MASK;
135804087fc4SQuentin Schulz 	reg_val |= val;
135904087fc4SQuentin Schulz 	ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_MAC_CFG_FASTLINK,
136004087fc4SQuentin Schulz 			reg_val);
136104087fc4SQuentin Schulz 	if (ret)
136204087fc4SQuentin Schulz 		return ret;
136304087fc4SQuentin Schulz 
136404087fc4SQuentin Schulz 	reg_val = PROC_CMD_MCB_ACCESS_MAC_CONF | PROC_CMD_RST_CONF_PORT |
136504087fc4SQuentin Schulz 		PROC_CMD_READ_MOD_WRITE_PORT;
136604087fc4SQuentin Schulz 	if (phydev->interface == PHY_INTERFACE_MODE_QSGMII)
136704087fc4SQuentin Schulz 		reg_val |= PROC_CMD_QSGMII_MAC;
136804087fc4SQuentin Schulz 	else
136904087fc4SQuentin Schulz 		reg_val |= PROC_CMD_SGMII_MAC;
137004087fc4SQuentin Schulz 
137104087fc4SQuentin Schulz 	ret = vsc8584_cmd(phydev->bus, phydev->addr, reg_val);
137204087fc4SQuentin Schulz 	if (ret)
137304087fc4SQuentin Schulz 		return ret;
137404087fc4SQuentin Schulz 
137504087fc4SQuentin Schulz 	mdelay(10);
137604087fc4SQuentin Schulz 
137704087fc4SQuentin Schulz 	/* Disable SerDes for 100Base-FX */
137804087fc4SQuentin Schulz 	ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
137904087fc4SQuentin Schulz 			  PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
138004087fc4SQuentin Schulz 			  PROC_CMD_READ_MOD_WRITE_PORT |
138104087fc4SQuentin Schulz 			  PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_100BASE_FX);
138204087fc4SQuentin Schulz 	if (ret)
138304087fc4SQuentin Schulz 		return ret;
138404087fc4SQuentin Schulz 
138504087fc4SQuentin Schulz 	/* Disable SerDes for 1000Base-X */
138604087fc4SQuentin Schulz 	ret = vsc8584_cmd(phydev->bus, phydev->addr, PROC_CMD_FIBER_MEDIA_CONF |
138704087fc4SQuentin Schulz 			  PROC_CMD_FIBER_PORT(addr) | PROC_CMD_FIBER_DISABLE |
138804087fc4SQuentin Schulz 			  PROC_CMD_READ_MOD_WRITE_PORT |
138904087fc4SQuentin Schulz 			  PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
139004087fc4SQuentin Schulz 	if (ret)
139104087fc4SQuentin Schulz 		return ret;
139204087fc4SQuentin Schulz 
139304087fc4SQuentin Schulz 	phy_write(phydev, MDIO_DEVAD_NONE, MSCC_EXT_PAGE_ACCESS,
139404087fc4SQuentin Schulz 		  MSCC_PHY_PAGE_STD);
139504087fc4SQuentin Schulz 	reg_val = phy_read(phydev, MDIO_DEVAD_NONE,
139604087fc4SQuentin Schulz 			   MSCC_PHY_EXT_PHY_CNTL_1_REG);
139704087fc4SQuentin Schulz 	reg_val &= ~(MEDIA_OP_MODE_MASK | VSC8584_MAC_IF_SELECTION_MASK);
139804087fc4SQuentin Schulz 	reg_val |= MEDIA_OP_MODE_COPPER |
139904087fc4SQuentin Schulz 		(VSC8584_MAC_IF_SELECTION_SGMII <<
140004087fc4SQuentin Schulz 		 VSC8584_MAC_IF_SELECTION_POS);
140104087fc4SQuentin Schulz 	ret = phy_write(phydev, MDIO_DEVAD_NONE, MSCC_PHY_EXT_PHY_CNTL_1_REG,
140204087fc4SQuentin Schulz 			reg_val);
140304087fc4SQuentin Schulz 
140404087fc4SQuentin Schulz 	ret = mscc_phy_soft_reset(phydev);
140504087fc4SQuentin Schulz 	if (ret != 0)
140604087fc4SQuentin Schulz 		return ret;
140704087fc4SQuentin Schulz 
140804087fc4SQuentin Schulz 	return genphy_config(phydev);
140904087fc4SQuentin Schulz }
141004087fc4SQuentin Schulz 
1411*05bbd676SQuentin Schulz static struct vsc85xx_priv vsc8574_priv = {
1412*05bbd676SQuentin Schulz 	.config_pre = vsc8574_config_pre_init,
1413*05bbd676SQuentin Schulz };
1414*05bbd676SQuentin Schulz 
vsc8574_config(struct phy_device * phydev)1415*05bbd676SQuentin Schulz static int vsc8574_config(struct phy_device *phydev)
1416*05bbd676SQuentin Schulz {
1417*05bbd676SQuentin Schulz 	phydev->priv = &vsc8574_priv;
1418*05bbd676SQuentin Schulz 
1419*05bbd676SQuentin Schulz 	return vsc8584_config_init(phydev);
1420*05bbd676SQuentin Schulz }
1421*05bbd676SQuentin Schulz 
1422b5bca65eSQuentin Schulz static struct vsc85xx_priv vsc8584_priv = {
1423b5bca65eSQuentin Schulz 	.config_pre = vsc8584_config_pre_init,
1424b5bca65eSQuentin Schulz };
1425b5bca65eSQuentin Schulz 
vsc8584_config(struct phy_device * phydev)1426b5bca65eSQuentin Schulz static int vsc8584_config(struct phy_device *phydev)
1427b5bca65eSQuentin Schulz {
1428b5bca65eSQuentin Schulz 	phydev->priv = &vsc8584_priv;
1429b5bca65eSQuentin Schulz 
1430b5bca65eSQuentin Schulz 	return vsc8584_config_init(phydev);
1431b5bca65eSQuentin Schulz }
1432b5bca65eSQuentin Schulz 
1433a5fd13adSJohn Haechten static struct phy_driver VSC8530_driver = {
1434a5fd13adSJohn Haechten 	.name = "Microsemi VSC8530",
1435a5fd13adSJohn Haechten 	.uid = PHY_ID_VSC8530,
1436a5fd13adSJohn Haechten 	.mask = 0x000ffff0,
1437a5fd13adSJohn Haechten 	.features = PHY_BASIC_FEATURES,
1438a5fd13adSJohn Haechten 	.config = &vsc8531_config,
1439a5fd13adSJohn Haechten 	.startup = &mscc_startup,
1440a5fd13adSJohn Haechten 	.shutdown = &genphy_shutdown,
1441a5fd13adSJohn Haechten };
1442a5fd13adSJohn Haechten 
1443a5fd13adSJohn Haechten static struct phy_driver VSC8531_driver = {
1444a5fd13adSJohn Haechten 	.name = "Microsemi VSC8531",
1445a5fd13adSJohn Haechten 	.uid = PHY_ID_VSC8531,
1446a5fd13adSJohn Haechten 	.mask = 0x000ffff0,
1447a5fd13adSJohn Haechten 	.features = PHY_GBIT_FEATURES,
1448a5fd13adSJohn Haechten 	.config = &vsc8531_config,
1449a5fd13adSJohn Haechten 	.startup = &mscc_startup,
1450a5fd13adSJohn Haechten 	.shutdown = &genphy_shutdown,
1451a5fd13adSJohn Haechten };
1452a5fd13adSJohn Haechten 
1453a5fd13adSJohn Haechten static struct phy_driver VSC8540_driver = {
1454a5fd13adSJohn Haechten 	.name = "Microsemi VSC8540",
1455a5fd13adSJohn Haechten 	.uid = PHY_ID_VSC8540,
1456a5fd13adSJohn Haechten 	.mask = 0x000ffff0,
1457a5fd13adSJohn Haechten 	.features = PHY_BASIC_FEATURES,
1458a5fd13adSJohn Haechten 	.config = &vsc8541_config,
1459a5fd13adSJohn Haechten 	.startup = &mscc_startup,
1460a5fd13adSJohn Haechten 	.shutdown = &genphy_shutdown,
1461a5fd13adSJohn Haechten };
1462a5fd13adSJohn Haechten 
1463a5fd13adSJohn Haechten static struct phy_driver VSC8541_driver = {
1464a5fd13adSJohn Haechten 	.name = "Microsemi VSC8541",
1465a5fd13adSJohn Haechten 	.uid = PHY_ID_VSC8541,
1466a5fd13adSJohn Haechten 	.mask = 0x000ffff0,
1467a5fd13adSJohn Haechten 	.features = PHY_GBIT_FEATURES,
1468a5fd13adSJohn Haechten 	.config = &vsc8541_config,
1469a5fd13adSJohn Haechten 	.startup = &mscc_startup,
1470a5fd13adSJohn Haechten 	.shutdown = &genphy_shutdown,
1471a5fd13adSJohn Haechten };
1472a5fd13adSJohn Haechten 
1473*05bbd676SQuentin Schulz static struct phy_driver VSC8574_driver = {
1474*05bbd676SQuentin Schulz 	.name = "Microsemi VSC8574",
1475*05bbd676SQuentin Schulz 	.uid = PHY_ID_VSC8574,
1476*05bbd676SQuentin Schulz 	.mask = 0x000ffff0,
1477*05bbd676SQuentin Schulz 	.features = PHY_GBIT_FEATURES,
1478*05bbd676SQuentin Schulz 	.config = &vsc8574_config,
1479*05bbd676SQuentin Schulz 	.startup = &mscc_startup,
1480*05bbd676SQuentin Schulz 	.shutdown = &genphy_shutdown,
1481*05bbd676SQuentin Schulz };
1482*05bbd676SQuentin Schulz 
148304087fc4SQuentin Schulz static struct phy_driver VSC8584_driver = {
148404087fc4SQuentin Schulz 	.name = "Microsemi VSC8584",
148504087fc4SQuentin Schulz 	.uid = PHY_ID_VSC8584,
148604087fc4SQuentin Schulz 	.mask = 0x000ffff0,
148704087fc4SQuentin Schulz 	.features = PHY_GBIT_FEATURES,
148804087fc4SQuentin Schulz 	.config = &vsc8584_config,
148904087fc4SQuentin Schulz 	.startup = &mscc_startup,
149004087fc4SQuentin Schulz 	.shutdown = &genphy_shutdown,
149104087fc4SQuentin Schulz };
149204087fc4SQuentin Schulz 
phy_mscc_init(void)1493a5fd13adSJohn Haechten int phy_mscc_init(void)
1494a5fd13adSJohn Haechten {
1495a5fd13adSJohn Haechten 	phy_register(&VSC8530_driver);
1496a5fd13adSJohn Haechten 	phy_register(&VSC8531_driver);
1497a5fd13adSJohn Haechten 	phy_register(&VSC8540_driver);
1498a5fd13adSJohn Haechten 	phy_register(&VSC8541_driver);
1499*05bbd676SQuentin Schulz 	phy_register(&VSC8574_driver);
150004087fc4SQuentin Schulz 	phy_register(&VSC8584_driver);
1501a5fd13adSJohn Haechten 
1502a5fd13adSJohn Haechten 	return 0;
1503a5fd13adSJohn Haechten }
1504