xref: /rk3399_rockchip-uboot/drivers/net/phy/rk630phy.c (revision bc1bea613fb0b7d3ea1e9901141acc989fd801f8)
1 // SPDX-License-Identifier: GPL-2.0+
2 /**
3  *
4  * Driver for ROCKCHIP RK630 Ethernet PHYs
5  *
6  * Copyright (c) 2020, Fuzhou Rockchip Electronics Co., Ltd
7  *
8  * David Wu <david.wu@rock-chips.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  */
16 
17 #include <config.h>
18 #include <common.h>
19 #include <phy.h>
20 
21 #define RK630_PHY_ID				0x00441400
22 
23 /* PAGE 0 */
24 #define REG_INTERRUPT_STATUS			0X10
25 #define REG_INTERRUPT_MASK			0X11
26 #define REG_GLOBAL_CONFIGURATION		0X13
27 #define REG_MAC_ADDRESS0			0x16
28 #define REG_MAC_ADDRESS1			0x17
29 #define REG_MAC_ADDRESS2			0x18
30 
31 #define REG_PAGE_SEL				0x1F
32 
33 /* PAGE 1 */
34 #define REG_PAGE1_APS_CTRL			0x12
35 #define REG_PAGE1_UAPS_CONFIGURE		0X13
36 #define REG_PAGE1_EEE_CONFIGURE			0x17
37 
38 /* PAGE 2 */
39 #define REG_PAGE2_AFE_CTRL			0x18
40 
41 /* PAGE 6 */
42 #define REG_PAGE6_ADC_ANONTROL			0x10
43 #define REG_PAGE6_GAIN_ANONTROL			0x12
44 #define REG_PAGE6_AFE_RX_CTRL			0x13
45 #define REG_PAGE6_AFE_TX_CTRL			0x14
46 #define REG_PAGE6_AFE_DRIVER2			0x15
47 #define REG_PAGE6_CP_CURRENT			0x17
48 #define REG_PAGE6_ADC_OP_BIAS			0x18
49 #define REG_PAGE6_RX_DECTOR			0x19
50 #define REG_PAGE6_AFE_PDCW			0x1c
51 
52 /* PAGE 8 */
53 #define REG_PAGE8_AFE_CTRL			0x18
54 #define REG_PAGE8_AUTO_CAL			0x1d
55 
56 /*
57  * Fixed address:
58  * Addr: 1 --- RK630@S40
59  *       2 --- RV1106@T22
60  */
61 #define PHY_ADDR_S40 1
62 #define PHY_ADDR_T22 2
63 
64 static int rk630_phy_startup(struct phy_device *phydev)
65 {
66 	int ret;
67 
68 	/* Read the Status (2x to make sure link is right) */
69 	ret = genphy_update_link(phydev);
70 	if (ret)
71 		return ret;
72 	/* Read the Status (2x to make sure link is right) */
73 	phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);
74 
75 	return genphy_parse_link(phydev);
76 }
77 
78 static void rk630_phy_s40_config_init(struct phy_device *phydev)
79 {
80 	phy_write(phydev, 0, MDIO_DEVAD_NONE,
81 		  phy_read(phydev, MDIO_DEVAD_NONE, 0) & ~BIT(13));
82 
83 	/* Switch to page 1 */
84 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0100);
85 	/* Disable APS */
86 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE1_APS_CTRL, 0x4824);
87 	/* Switch to page 2 */
88 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0200);
89 	/* PHYAFE TRX optimization */
90 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE2_AFE_CTRL, 0x0000);
91 	/* Switch to page 6 */
92 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0600);
93 	/* PHYAFE TX optimization */
94 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_TX_CTRL, 0x708f);
95 	/* PHYAFE RX optimization */
96 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_RX_CTRL, 0xf000);
97 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_DRIVER2, 0x1530);
98 
99 	/* Switch to page 8 */
100 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0800);
101 	/* PHYAFE TRX optimization */
102 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE8_AFE_CTRL, 0x00bc);
103 
104 	/* Switch to page 0 */
105 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0000);
106 }
107 
108 static void rk630_phy_t22_config_init(struct phy_device *phydev)
109 {
110 	/* Switch to page 1 */
111 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0100);
112 	/* Disable APS */
113 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE1_APS_CTRL, 0x4824);
114 	/* Switch to page 2 */
115 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0200);
116 	/* PHYAFE TRX optimization */
117 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE2_AFE_CTRL, 0x0000);
118 	/* Switch to page 6 */
119 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0600);
120 	/* PHYAFE ADC optimization */
121 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_ADC_ANONTROL, 0x5540);
122 	/* PHYAFE Gain optimization */
123 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_GAIN_ANONTROL, 0x0400);
124 	/* PHYAFE EQ optimization */
125 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_TX_CTRL, 0x1088);
126 	/* PHYAFE TX optimization */
127 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_DRIVER2, 0x3030);
128 	/* PHYAFE CP current optimization */
129 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_CP_CURRENT, 0x0575);
130 	/* ADC OP BIAS optimization */
131 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_ADC_OP_BIAS, 0x0000);
132 	/* Rx signal detctor level optimization */
133 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_RX_DECTOR, 0x0408);
134 	/* PHYAFE PDCW optimization */
135 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_PDCW, 0x8880);
136 
137 	/* Switch to page 8 */
138 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0800);
139 	/* Disable auto-cal */
140 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE8_AUTO_CAL, 0x0844);
141 
142 	/* Switch to page 0 */
143 	phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0000);
144 }
145 static int rk630_phy_config_init(struct phy_device *phydev)
146 {
147 	switch (phydev->addr) {
148 	case PHY_ADDR_S40:
149 		rk630_phy_s40_config_init(phydev);
150 		break;
151 	case PHY_ADDR_T22:
152 		rk630_phy_t22_config_init(phydev);
153 		break;
154 	default:
155 		printf("Unsupported address for current phy: %d\n",
156 		       phydev->addr);
157 		return -EINVAL;
158 	}
159 
160 	return 0;
161 }
162 
163 static struct phy_driver RK630_driver = {
164 	.name = "Rockchip RK630",
165 	.uid = RK630_PHY_ID,
166 	.mask = 0xffffff,
167 	.features = PHY_BASIC_FEATURES,
168 	.config = &rk630_phy_config_init,
169 	.startup = &rk630_phy_startup,
170 };
171 
172 int phy_rk630_init(void)
173 {
174 	phy_register(&RK630_driver);
175 	return 0;
176 }
177