1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
// SPDX-License-Identifier: GPL-2.0+
#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/phy.h>
#include "mtk.h"
#define MTK_GPHY_ID_MT7530 0x03a29412
#define MTK_GPHY_ID_MT7531 0x03a29441
#define MTK_PHY_PAGE_EXTENDED_2 0x0002
#define MTK_PHY_PAGE_EXTENDED_3 0x0003
#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11 0x11
#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
/* Registers on Token Ring debug nodes */
/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */
#define SLAVE_DSP_READY_TIME_MASK GENMASK(22, 15)
/* Registers on MDIO_MMD_VEND1 */
#define MTK_PHY_GBE_MODE_TX_DELAY_SEL 0x13
#define MTK_PHY_TEST_MODE_TX_DELAY_SEL 0x14
#define MTK_TX_DELAY_PAIR_B_MASK GENMASK(10, 8)
#define MTK_TX_DELAY_PAIR_D_MASK GENMASK(2, 0)
#define MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL 0xa6
#define MTK_MCC_NEARECHO_OFFSET_MASK GENMASK(15, 8)
#define MTK_PHY_RXADC_CTRL_RG7 0xc6
#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8)
#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123 0x123
#define MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK GENMASK(15, 8)
#define MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK GENMASK(7, 0)
static void mtk_gephy_config_init(struct phy_device *phydev)
{
/* Enable HW auto downshift */
phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
MTK_PHY_AUX_CTRL_AND_STATUS,
0, MTK_PHY_ENABLE_DOWNSHIFT);
/* Increase SlvDPSready time */
mtk_tr_modify(phydev, 0x1, 0xf, 0x17, SLAVE_DSP_READY_TIME_MASK,
FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x5e));
/* Adjust 100_mse_threshold */
phy_modify_mmd(phydev, MDIO_MMD_VEND1,
MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123,
MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK |
MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
FIELD_PREP(MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK,
0xff) |
FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
0xff));
/* If echo time is narrower than 0x3, it will be regarded as noise */
phy_modify_mmd(phydev, MDIO_MMD_VEND1,
MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL,
MTK_MCC_NEARECHO_OFFSET_MASK,
FIELD_PREP(MTK_MCC_NEARECHO_OFFSET_MASK, 0x3));
}
static int mt7530_phy_config_init(struct phy_device *phydev)
{
mtk_gephy_config_init(phydev);
/* Increase post_update_timer */
phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3,
MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11, 0x4b);
return 0;
}
static int mt7531_phy_config_init(struct phy_device *phydev)
{
mtk_gephy_config_init(phydev);
/* PHY link down power saving enable */
phy_set_bits(phydev, 0x17, BIT(4));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
MTK_PHY_DA_AD_BUF_BIAS_LP_MASK,
FIELD_PREP(MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3));
/* Set TX Pair delay selection */
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_GBE_MODE_TX_DELAY_SEL,
MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TEST_MODE_TX_DELAY_SEL,
MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
return 0;
}
static struct phy_driver mtk_gephy_driver[] = {
{
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
.name = "MediaTek MT7530 PHY",
.config_init = mt7530_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
* itself.
*/
.config_intr = genphy_no_config_intr,
.handle_interrupt = genphy_handle_interrupt_no_ack,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_page = mtk_phy_read_page,
.write_page = mtk_phy_write_page,
},
{
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531),
.name = "MediaTek MT7531 PHY",
.config_init = mt7531_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
* itself.
*/
.config_intr = genphy_no_config_intr,
.handle_interrupt = genphy_handle_interrupt_no_ack,
.suspend = genphy_suspend,
.resume = genphy_resume,
.read_page = mtk_phy_read_page,
.write_page = mtk_phy_write_page,
},
};
module_phy_driver(mtk_gephy_driver);
static const struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) },
{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) },
{ }
};
MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver");
MODULE_AUTHOR("DENG, Qingfang <dqfext@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(mdio, mtk_gephy_tbl);
|