|
163 | 163 |
|
164 | 164 | #define YT8521_CHIP_CONFIG_REG 0xA001 |
165 | 165 | #define YT8521_CCR_SW_RST BIT(15) |
| 166 | +#define YT8531_RGMII_LDO_VOL_MASK GENMASK(5, 4) |
| 167 | +#define YT8531_LDO_VOL_3V3 0x0 |
| 168 | +#define YT8531_LDO_VOL_1V8 0x2 |
| 169 | + |
166 | 170 | /* 1b0 disable 1.9ns rxc clock delay *default* |
167 | 171 | * 1b1 enable 1.9ns rxc clock delay |
168 | 172 | */ |
|
236 | 240 | */ |
237 | 241 | #define YTPHY_WCR_TYPE_PULSE BIT(0) |
238 | 242 |
|
| 243 | +#define YTPHY_PAD_DRIVE_STRENGTH_REG 0xA010 |
| 244 | +#define YT8531_RGMII_RXC_DS_MASK GENMASK(15, 13) |
| 245 | +#define YT8531_RGMII_RXD_DS_HI_MASK BIT(12) /* Bit 2 of rxd_ds */ |
| 246 | +#define YT8531_RGMII_RXD_DS_LOW_MASK GENMASK(5, 4) /* Bit 1/0 of rxd_ds */ |
| 247 | +#define YT8531_RGMII_RX_DS_DEFAULT 0x3 |
| 248 | + |
239 | 249 | #define YTPHY_SYNCE_CFG_REG 0xA012 |
240 | 250 | #define YT8521_SCR_SYNCE_ENABLE BIT(5) |
241 | 251 | /* 1b0 output 25m clock |
@@ -834,6 +844,110 @@ static int ytphy_rgmii_clk_delay_config_with_lock(struct phy_device *phydev) |
834 | 844 | return ret; |
835 | 845 | } |
836 | 846 |
|
| 847 | +/** |
| 848 | + * struct ytphy_ldo_vol_map - map a current value to a register value |
| 849 | + * @vol: ldo voltage |
| 850 | + * @ds: value in the register |
| 851 | + * @cur: value in device configuration |
| 852 | + */ |
| 853 | +struct ytphy_ldo_vol_map { |
| 854 | + u32 vol; |
| 855 | + u32 ds; |
| 856 | + u32 cur; |
| 857 | +}; |
| 858 | + |
| 859 | +static const struct ytphy_ldo_vol_map yt8531_ldo_vol[] = { |
| 860 | + {.vol = YT8531_LDO_VOL_1V8, .ds = 0, .cur = 1200}, |
| 861 | + {.vol = YT8531_LDO_VOL_1V8, .ds = 1, .cur = 2100}, |
| 862 | + {.vol = YT8531_LDO_VOL_1V8, .ds = 2, .cur = 2700}, |
| 863 | + {.vol = YT8531_LDO_VOL_1V8, .ds = 3, .cur = 2910}, |
| 864 | + {.vol = YT8531_LDO_VOL_1V8, .ds = 4, .cur = 3110}, |
| 865 | + {.vol = YT8531_LDO_VOL_1V8, .ds = 5, .cur = 3600}, |
| 866 | + {.vol = YT8531_LDO_VOL_1V8, .ds = 6, .cur = 3970}, |
| 867 | + {.vol = YT8531_LDO_VOL_1V8, .ds = 7, .cur = 4350}, |
| 868 | + {.vol = YT8531_LDO_VOL_3V3, .ds = 0, .cur = 3070}, |
| 869 | + {.vol = YT8531_LDO_VOL_3V3, .ds = 1, .cur = 4080}, |
| 870 | + {.vol = YT8531_LDO_VOL_3V3, .ds = 2, .cur = 4370}, |
| 871 | + {.vol = YT8531_LDO_VOL_3V3, .ds = 3, .cur = 4680}, |
| 872 | + {.vol = YT8531_LDO_VOL_3V3, .ds = 4, .cur = 5020}, |
| 873 | + {.vol = YT8531_LDO_VOL_3V3, .ds = 5, .cur = 5450}, |
| 874 | + {.vol = YT8531_LDO_VOL_3V3, .ds = 6, .cur = 5740}, |
| 875 | + {.vol = YT8531_LDO_VOL_3V3, .ds = 7, .cur = 6140}, |
| 876 | +}; |
| 877 | + |
| 878 | +static u32 yt8531_get_ldo_vol(struct phy_device *phydev) |
| 879 | +{ |
| 880 | + u32 val; |
| 881 | + |
| 882 | + val = ytphy_read_ext_with_lock(phydev, YT8521_CHIP_CONFIG_REG); |
| 883 | + val = FIELD_GET(YT8531_RGMII_LDO_VOL_MASK, val); |
| 884 | + |
| 885 | + return val <= YT8531_LDO_VOL_1V8 ? val : YT8531_LDO_VOL_1V8; |
| 886 | +} |
| 887 | + |
| 888 | +static int yt8531_get_ds_map(struct phy_device *phydev, u32 cur) |
| 889 | +{ |
| 890 | + u32 vol; |
| 891 | + int i; |
| 892 | + |
| 893 | + vol = yt8531_get_ldo_vol(phydev); |
| 894 | + for (i = 0; i < ARRAY_SIZE(yt8531_ldo_vol); i++) { |
| 895 | + if (yt8531_ldo_vol[i].vol == vol && yt8531_ldo_vol[i].cur == cur) |
| 896 | + return yt8531_ldo_vol[i].ds; |
| 897 | + } |
| 898 | + |
| 899 | + return -EINVAL; |
| 900 | +} |
| 901 | + |
| 902 | +static int yt8531_set_ds(struct phy_device *phydev) |
| 903 | +{ |
| 904 | + struct device_node *node = phydev->mdio.dev.of_node; |
| 905 | + u32 ds_field_low, ds_field_hi, val; |
| 906 | + int ret, ds; |
| 907 | + |
| 908 | + /* set rgmii rx clk driver strength */ |
| 909 | + if (!of_property_read_u32(node, "motorcomm,rx-clk-drv-microamp", &val)) { |
| 910 | + ds = yt8531_get_ds_map(phydev, val); |
| 911 | + if (ds < 0) |
| 912 | + return dev_err_probe(&phydev->mdio.dev, ds, |
| 913 | + "No matching current value was found.\n"); |
| 914 | + } else { |
| 915 | + ds = YT8531_RGMII_RX_DS_DEFAULT; |
| 916 | + } |
| 917 | + |
| 918 | + ret = ytphy_modify_ext_with_lock(phydev, |
| 919 | + YTPHY_PAD_DRIVE_STRENGTH_REG, |
| 920 | + YT8531_RGMII_RXC_DS_MASK, |
| 921 | + FIELD_PREP(YT8531_RGMII_RXC_DS_MASK, ds)); |
| 922 | + if (ret < 0) |
| 923 | + return ret; |
| 924 | + |
| 925 | + /* set rgmii rx data driver strength */ |
| 926 | + if (!of_property_read_u32(node, "motorcomm,rx-data-drv-microamp", &val)) { |
| 927 | + ds = yt8531_get_ds_map(phydev, val); |
| 928 | + if (ds < 0) |
| 929 | + return dev_err_probe(&phydev->mdio.dev, ds, |
| 930 | + "No matching current value was found.\n"); |
| 931 | + } else { |
| 932 | + ds = YT8531_RGMII_RX_DS_DEFAULT; |
| 933 | + } |
| 934 | + |
| 935 | + ds_field_hi = FIELD_GET(BIT(2), ds); |
| 936 | + ds_field_hi = FIELD_PREP(YT8531_RGMII_RXD_DS_HI_MASK, ds_field_hi); |
| 937 | + |
| 938 | + ds_field_low = FIELD_GET(GENMASK(1, 0), ds); |
| 939 | + ds_field_low = FIELD_PREP(YT8531_RGMII_RXD_DS_LOW_MASK, ds_field_low); |
| 940 | + |
| 941 | + ret = ytphy_modify_ext_with_lock(phydev, |
| 942 | + YTPHY_PAD_DRIVE_STRENGTH_REG, |
| 943 | + YT8531_RGMII_RXD_DS_LOW_MASK | YT8531_RGMII_RXD_DS_HI_MASK, |
| 944 | + ds_field_low | ds_field_hi); |
| 945 | + if (ret < 0) |
| 946 | + return ret; |
| 947 | + |
| 948 | + return 0; |
| 949 | +} |
| 950 | + |
837 | 951 | /** |
838 | 952 | * yt8521_probe() - read chip config then set suitable polling_mode |
839 | 953 | * @phydev: a pointer to a &struct phy_device |
@@ -1518,6 +1632,10 @@ static int yt8531_config_init(struct phy_device *phydev) |
1518 | 1632 | return ret; |
1519 | 1633 | } |
1520 | 1634 |
|
| 1635 | + ret = yt8531_set_ds(phydev); |
| 1636 | + if (ret < 0) |
| 1637 | + return ret; |
| 1638 | + |
1521 | 1639 | return 0; |
1522 | 1640 | } |
1523 | 1641 |
|
|
0 commit comments