blob: 60ef22cb1e1c12c397b817a3d3a2905dc19ad2e0 [file] [log] [blame]
developerc50c2352021-12-01 10:45:35 +08001// SPDX-License-Identifier: GPL-2.0+
2#include <linux/bitfield.h>
3#include <linux/module.h>
developerc50c2352021-12-01 10:45:35 +08004#include <linux/phy.h>
5
developerc50c2352021-12-01 10:45:35 +08006#define MTK_EXT_PAGE_ACCESS 0x1f
7#define MTK_PHY_PAGE_STANDARD 0x0000
8#define MTK_PHY_PAGE_EXTENDED 0x0001
9#define MTK_PHY_PAGE_EXTENDED_2 0x0002
10#define MTK_PHY_PAGE_EXTENDED_3 0x0003
11#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
12#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
13
developer432b8c02023-08-09 16:33:49 +080014#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7
15#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0)
16#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8)
17
developer2149cd92023-03-10 19:01:41 +080018static int mtk_gephy_read_page(struct phy_device *phydev)
19{
20 return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
21}
developerc50c2352021-12-01 10:45:35 +080022
developer2149cd92023-03-10 19:01:41 +080023static int mtk_gephy_write_page(struct phy_device *phydev, int page)
24{
25 return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
26}
developerc50c2352021-12-01 10:45:35 +080027
developer2149cd92023-03-10 19:01:41 +080028static void mtk_gephy_config_init(struct phy_device *phydev)
29{
30 /* Disable EEE */
31 phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
developerc50c2352021-12-01 10:45:35 +080032
developer2149cd92023-03-10 19:01:41 +080033 /* Enable HW auto downshift */
34 phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4));
developerc50c2352021-12-01 10:45:35 +080035
developer2149cd92023-03-10 19:01:41 +080036 /* Increase SlvDPSready time */
37 phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
38 __phy_write(phydev, 0x10, 0xafae);
39 __phy_write(phydev, 0x12, 0x2f);
40 __phy_write(phydev, 0x10, 0x8fae);
41 phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
developerc50c2352021-12-01 10:45:35 +080042
developer2149cd92023-03-10 19:01:41 +080043 /* Adjust 100_mse_threshold */
44 phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff);
developerc50c2352021-12-01 10:45:35 +080045
developer2149cd92023-03-10 19:01:41 +080046 /* Disable mcc */
47 phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300);
48}
developerc50c2352021-12-01 10:45:35 +080049
developer2149cd92023-03-10 19:01:41 +080050static int mt7530_phy_config_init(struct phy_device *phydev)
developerc50c2352021-12-01 10:45:35 +080051{
developer2149cd92023-03-10 19:01:41 +080052 mtk_gephy_config_init(phydev);
53
54 /* Increase post_update_timer */
55 phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b);
56
57 return 0;
developerc50c2352021-12-01 10:45:35 +080058}
59
developer2149cd92023-03-10 19:01:41 +080060static int mt7531_phy_config_init(struct phy_device *phydev)
developerc50c2352021-12-01 10:45:35 +080061{
developer2149cd92023-03-10 19:01:41 +080062 mtk_gephy_config_init(phydev);
63
64 /* PHY link down power saving enable */
65 phy_set_bits(phydev, 0x17, BIT(4));
66 phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300);
67
68 /* Set TX Pair delay selection */
69 phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404);
70 phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404);
71
developer432b8c02023-08-09 16:33:49 +080072 /* Adjust RX min/max gain to fix CH395 100Mbps link up fail */
73 phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7,
74 FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) |
75 FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13));
76
developer2149cd92023-03-10 19:01:41 +080077 return 0;
developerc50c2352021-12-01 10:45:35 +080078}
79
developerc50c2352021-12-01 10:45:35 +080080static struct phy_driver mtk_gephy_driver[] = {
developerc50c2352021-12-01 10:45:35 +080081 {
developer394d5eb2023-04-14 16:46:45 +080082 PHY_ID_MATCH_EXACT(0x03a29412),
developerc50c2352021-12-01 10:45:35 +080083 .name = "MediaTek MT7530 PHY",
84 .config_init = mt7530_phy_config_init,
85 /* Interrupts are handled by the switch, not the PHY
86 * itself.
87 */
88 .config_intr = genphy_no_config_intr,
89 .handle_interrupt = genphy_no_ack_interrupt,
90 .suspend = genphy_suspend,
91 .resume = genphy_resume,
92 .read_page = mtk_gephy_read_page,
93 .write_page = mtk_gephy_write_page,
94 },
95 {
developer394d5eb2023-04-14 16:46:45 +080096 PHY_ID_MATCH_EXACT(0x03a29441),
developerc50c2352021-12-01 10:45:35 +080097 .name = "MediaTek MT7531 PHY",
98 .config_init = mt7531_phy_config_init,
99 /* Interrupts are handled by the switch, not the PHY
100 * itself.
101 */
102 .config_intr = genphy_no_config_intr,
103 .handle_interrupt = genphy_no_ack_interrupt,
104 .suspend = genphy_suspend,
105 .resume = genphy_resume,
106 .read_page = mtk_gephy_read_page,
107 .write_page = mtk_gephy_write_page,
108 },
developerc50c2352021-12-01 10:45:35 +0800109};
110
111module_phy_driver(mtk_gephy_driver);
112
113static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
114 { PHY_ID_MATCH_VENDOR(0x03a29400) },
115 { }
116};
117
118MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver");
developerc50c2352021-12-01 10:45:35 +0800119MODULE_AUTHOR("DENG, Qingfang <dqfext@gmail.com>");
120MODULE_LICENSE("GPL");
121
122MODULE_DEVICE_TABLE(mdio, mtk_gephy_tbl);