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 <misc.h> 20 #include <phy.h> 21 22 #define RK630_PHY_ID 0x00441400 23 24 /* PAGE 0 */ 25 #define REG_MMD_ACCESS_CONTROL 0x0d 26 #define REG_MMD_ACCESS_DATA_ADDRESS 0x0e 27 #define REG_INTERRUPT_STATUS 0X10 28 #define REG_INTERRUPT_MASK 0X11 29 #define REG_GLOBAL_CONFIGURATION 0X13 30 #define REG_MAC_ADDRESS0 0x16 31 #define REG_MAC_ADDRESS1 0x17 32 #define REG_MAC_ADDRESS2 0x18 33 34 #define REG_PAGE_SEL 0x1F 35 36 /* PAGE 1 */ 37 #define REG_PAGE1_APS_CTRL 0x12 38 #define REG_PAGE1_UAPS_CONFIGURE 0X13 39 #define REG_PAGE1_EEE_CONFIGURE 0x17 40 41 /* PAGE 2 */ 42 #define REG_PAGE2_AFE_CTRL 0x18 43 44 /* PAGE 6 */ 45 #define REG_PAGE6_ADC_ANONTROL 0x10 46 #define REG_PAGE6_GAIN_ANONTROL 0x12 47 #define REG_PAGE6_AFE_RX_CTRL 0x13 48 #define REG_PAGE6_AFE_TX_CTRL 0x14 49 #define REG_PAGE6_AFE_DRIVER2 0x15 50 #define REG_PAGE6_CP_CURRENT 0x17 51 #define REG_PAGE6_ADC_OP_BIAS 0x18 52 #define REG_PAGE6_RX_DECTOR 0x19 53 #define REG_PAGE6_AFE_PDCW 0x1c 54 55 /* PAGE 8 */ 56 #define REG_PAGE8_AFE_CTRL 0x18 57 #define REG_PAGE8_AUTO_CAL 0x1d 58 59 /* 60 * Fixed address: 61 * Addr: 1 --- RK630@S40 62 * 2 --- RV1106@T22 63 */ 64 #define PHY_ADDR_S40 1 65 #define PHY_ADDR_T22 2 66 67 #define T22_TX_LEVEL_100M 0x2d 68 #define T22_TX_LEVEL_10M 0x32 69 70 static int rk630_phy_t22_get_txlevel_from_efuse(unsigned char *txlevel_100, 71 unsigned char *txlevel_10) 72 { 73 #if defined(CONFIG_ROCKCHIP_EFUSE) || defined(CONFIG_ROCKCHIP_OTP) 74 unsigned char tx_level[2]; 75 struct udevice *dev; 76 u32 regs[2] = {0}; 77 ofnode node; 78 int ret; 79 80 /* retrieve the device */ 81 if (IS_ENABLED(CONFIG_ROCKCHIP_EFUSE)) 82 ret = uclass_get_device_by_driver(UCLASS_MISC, 83 DM_GET_DRIVER(rockchip_efuse), 84 &dev); 85 else 86 ret = uclass_get_device_by_driver(UCLASS_MISC, 87 DM_GET_DRIVER(rockchip_otp), 88 &dev); 89 90 if (ret) { 91 printf("%s: could not find efuse/otp device\n", __func__); 92 return ret; 93 } 94 95 node = dev_read_subnode(dev, "macphy-txlevel"); 96 if (!ofnode_valid(node)) 97 return -EINVAL; 98 99 ret = ofnode_read_u32_array(node, "reg", regs, 2); 100 if (ret) { 101 printf("Cannot get efuse reg\n"); 102 return -EINVAL; 103 } 104 105 /* read the txlevel from the efuses */ 106 ret = misc_read(dev, regs[0], &tx_level, 2); 107 if (ret) { 108 printf("%s: read txlevel from efuse/otp failed, ret=%d\n", 109 __func__, ret); 110 return ret; 111 } 112 *txlevel_100 = tx_level[1]; 113 *txlevel_10 = tx_level[0]; 114 115 return 0; 116 #else 117 return -EINVAL; 118 #endif 119 } 120 121 static int rk630_phy_startup(struct phy_device *phydev) 122 { 123 int ret; 124 125 /* Read the Status (2x to make sure link is right) */ 126 ret = genphy_update_link(phydev); 127 if (ret) 128 return ret; 129 130 /* Read the Status (2x to make sure link is right) */ 131 phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR); 132 133 return genphy_parse_link(phydev); 134 } 135 136 static void rk630_phy_s40_config_init(struct phy_device *phydev) 137 { 138 phy_write(phydev, 0, MDIO_DEVAD_NONE, 139 phy_read(phydev, MDIO_DEVAD_NONE, 0) & ~BIT(13)); 140 141 /* Switch to page 1 */ 142 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0100); 143 /* Disable APS */ 144 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE1_APS_CTRL, 0x4824); 145 /* Switch to page 2 */ 146 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0200); 147 /* PHYAFE TRX optimization */ 148 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE2_AFE_CTRL, 0x0000); 149 /* Switch to page 6 */ 150 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0600); 151 /* PHYAFE TX optimization */ 152 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_TX_CTRL, 0x708f); 153 /* PHYAFE RX optimization */ 154 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_RX_CTRL, 0xf000); 155 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_DRIVER2, 0x1530); 156 157 /* Switch to page 8 */ 158 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0800); 159 /* PHYAFE TRX optimization */ 160 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE8_AFE_CTRL, 0x00bc); 161 162 /* Switch to page 0 */ 163 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0000); 164 } 165 166 static void rk630_phy_t22_config_init(struct phy_device *phydev) 167 { 168 unsigned char tx_level_100M = T22_TX_LEVEL_100M; 169 unsigned char tx_level_10M = T22_TX_LEVEL_10M; 170 171 /* Switch to page 1 */ 172 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0100); 173 /* Disable APS */ 174 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE1_APS_CTRL, 0x4824); 175 /* Switch to page 2 */ 176 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0200); 177 /* PHYAFE TRX optimization */ 178 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE2_AFE_CTRL, 0x0000); 179 /* Switch to page 6 */ 180 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0600); 181 /* PHYAFE ADC optimization */ 182 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_ADC_ANONTROL, 0x5540); 183 /* PHYAFE Gain optimization */ 184 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_GAIN_ANONTROL, 0x0400); 185 /* PHYAFE EQ optimization */ 186 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_TX_CTRL, 0x1088); 187 188 if (rk630_phy_t22_get_txlevel_from_efuse(&tx_level_100M, &tx_level_10M)) { 189 tx_level_100M = T22_TX_LEVEL_100M; 190 tx_level_10M = T22_TX_LEVEL_10M; 191 } 192 /* PHYAFE TX optimization */ 193 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_DRIVER2, 194 (tx_level_100M << 8) | tx_level_10M); 195 196 /* PHYAFE CP current optimization */ 197 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_CP_CURRENT, 0x0575); 198 /* ADC OP BIAS optimization */ 199 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_ADC_OP_BIAS, 0x0000); 200 /* Rx signal detctor level optimization */ 201 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_RX_DECTOR, 0x0408); 202 /* PHYAFE PDCW optimization */ 203 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE6_AFE_PDCW, 0x8880); 204 205 /* Switch to page 8 */ 206 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0800); 207 /* Disable auto-cal */ 208 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE8_AUTO_CAL, 0x0844); 209 210 /* Switch to page 0 */ 211 phy_write(phydev, MDIO_DEVAD_NONE, REG_PAGE_SEL, 0x0000); 212 213 /* Disable eee mode advertised */ 214 phy_write(phydev, MDIO_DEVAD_NONE, REG_MMD_ACCESS_CONTROL, 0x0007); 215 phy_write(phydev, MDIO_DEVAD_NONE, REG_MMD_ACCESS_DATA_ADDRESS, 0x003c); 216 phy_write(phydev, MDIO_DEVAD_NONE, REG_MMD_ACCESS_CONTROL, 0x4007); 217 phy_write(phydev, MDIO_DEVAD_NONE, REG_MMD_ACCESS_DATA_ADDRESS, 0x0000); 218 } 219 static int rk630_phy_config_init(struct phy_device *phydev) 220 { 221 switch (phydev->addr) { 222 case PHY_ADDR_S40: 223 rk630_phy_s40_config_init(phydev); 224 break; 225 case PHY_ADDR_T22: 226 rk630_phy_t22_config_init(phydev); 227 break; 228 default: 229 printf("Unsupported address for current phy: %d\n", 230 phydev->addr); 231 return -EINVAL; 232 } 233 234 genphy_config_aneg(phydev); 235 return 0; 236 } 237 238 static struct phy_driver RK630_driver = { 239 .name = "Rockchip RK630", 240 .uid = RK630_PHY_ID, 241 .mask = 0xffffff, 242 .features = PHY_BASIC_FEATURES, 243 .config = &rk630_phy_config_init, 244 .startup = &rk630_phy_startup, 245 }; 246 247 int phy_rk630_init(void) 248 { 249 phy_register(&RK630_driver); 250 return 0; 251 } 252