1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/module.h>
5 #include <linux/netdevice.h>
9 int mtk_phy_read_page(struct phy_device
*phydev
)
11 return __phy_read(phydev
, MTK_EXT_PAGE_ACCESS
);
13 EXPORT_SYMBOL_GPL(mtk_phy_read_page
);
15 int mtk_phy_write_page(struct phy_device
*phydev
, int page
)
17 return __phy_write(phydev
, MTK_EXT_PAGE_ACCESS
, page
);
19 EXPORT_SYMBOL_GPL(mtk_phy_write_page
);
21 int mtk_phy_led_hw_is_supported(struct phy_device
*phydev
, u8 index
,
23 unsigned long supported_triggers
)
28 /* All combinations of the supported triggers are allowed */
29 if (rules
& ~supported_triggers
)
34 EXPORT_SYMBOL_GPL(mtk_phy_led_hw_is_supported
);
36 int mtk_phy_led_hw_ctrl_get(struct phy_device
*phydev
, u8 index
,
37 unsigned long *rules
, u16 on_set
,
38 u16 rx_blink_set
, u16 tx_blink_set
)
40 unsigned int bit_blink
= MTK_PHY_LED_STATE_FORCE_BLINK
+
42 unsigned int bit_netdev
= MTK_PHY_LED_STATE_NETDEV
+ (index
? 16 : 0);
43 unsigned int bit_on
= MTK_PHY_LED_STATE_FORCE_ON
+ (index
? 16 : 0);
44 struct mtk_socphy_priv
*priv
= phydev
->priv
;
50 on
= phy_read_mmd(phydev
, MDIO_MMD_VEND2
,
51 index
? MTK_PHY_LED1_ON_CTRL
: MTK_PHY_LED0_ON_CTRL
);
56 blink
= phy_read_mmd(phydev
, MDIO_MMD_VEND2
,
57 index
? MTK_PHY_LED1_BLINK_CTRL
:
58 MTK_PHY_LED0_BLINK_CTRL
);
62 if ((on
& (on_set
| MTK_PHY_LED_ON_FDX
|
63 MTK_PHY_LED_ON_HDX
| MTK_PHY_LED_ON_LINKDOWN
)) ||
64 (blink
& (rx_blink_set
| tx_blink_set
)))
65 set_bit(bit_netdev
, &priv
->led_state
);
67 clear_bit(bit_netdev
, &priv
->led_state
);
69 if (on
& MTK_PHY_LED_ON_FORCE_ON
)
70 set_bit(bit_on
, &priv
->led_state
);
72 clear_bit(bit_on
, &priv
->led_state
);
74 if (blink
& MTK_PHY_LED_BLINK_FORCE_BLINK
)
75 set_bit(bit_blink
, &priv
->led_state
);
77 clear_bit(bit_blink
, &priv
->led_state
);
83 *rules
|= BIT(TRIGGER_NETDEV_LINK
);
85 if (on
& MTK_PHY_LED_ON_LINK10
)
86 *rules
|= BIT(TRIGGER_NETDEV_LINK_10
);
88 if (on
& MTK_PHY_LED_ON_LINK100
)
89 *rules
|= BIT(TRIGGER_NETDEV_LINK_100
);
91 if (on
& MTK_PHY_LED_ON_LINK1000
)
92 *rules
|= BIT(TRIGGER_NETDEV_LINK_1000
);
94 if (on
& MTK_PHY_LED_ON_LINK2500
)
95 *rules
|= BIT(TRIGGER_NETDEV_LINK_2500
);
97 if (on
& MTK_PHY_LED_ON_FDX
)
98 *rules
|= BIT(TRIGGER_NETDEV_FULL_DUPLEX
);
100 if (on
& MTK_PHY_LED_ON_HDX
)
101 *rules
|= BIT(TRIGGER_NETDEV_HALF_DUPLEX
);
103 if (blink
& rx_blink_set
)
104 *rules
|= BIT(TRIGGER_NETDEV_RX
);
106 if (blink
& tx_blink_set
)
107 *rules
|= BIT(TRIGGER_NETDEV_TX
);
111 EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_get
);
113 int mtk_phy_led_hw_ctrl_set(struct phy_device
*phydev
, u8 index
,
114 unsigned long rules
, u16 on_set
,
115 u16 rx_blink_set
, u16 tx_blink_set
)
117 unsigned int bit_netdev
= MTK_PHY_LED_STATE_NETDEV
+ (index
? 16 : 0);
118 struct mtk_socphy_priv
*priv
= phydev
->priv
;
119 u16 on
= 0, blink
= 0;
125 if (rules
& BIT(TRIGGER_NETDEV_FULL_DUPLEX
))
126 on
|= MTK_PHY_LED_ON_FDX
;
128 if (rules
& BIT(TRIGGER_NETDEV_HALF_DUPLEX
))
129 on
|= MTK_PHY_LED_ON_HDX
;
131 if (rules
& (BIT(TRIGGER_NETDEV_LINK_10
) | BIT(TRIGGER_NETDEV_LINK
)))
132 on
|= MTK_PHY_LED_ON_LINK10
;
134 if (rules
& (BIT(TRIGGER_NETDEV_LINK_100
) | BIT(TRIGGER_NETDEV_LINK
)))
135 on
|= MTK_PHY_LED_ON_LINK100
;
137 if (rules
& (BIT(TRIGGER_NETDEV_LINK_1000
) | BIT(TRIGGER_NETDEV_LINK
)))
138 on
|= MTK_PHY_LED_ON_LINK1000
;
140 if (rules
& (BIT(TRIGGER_NETDEV_LINK_2500
) | BIT(TRIGGER_NETDEV_LINK
)))
141 on
|= MTK_PHY_LED_ON_LINK2500
;
143 if (rules
& BIT(TRIGGER_NETDEV_RX
)) {
145 if (on
& MTK_PHY_LED_ON_LINK10
)
146 blink
|= MTK_PHY_LED_BLINK_10RX
;
147 if (on
& MTK_PHY_LED_ON_LINK100
)
148 blink
|= MTK_PHY_LED_BLINK_100RX
;
149 if (on
& MTK_PHY_LED_ON_LINK1000
)
150 blink
|= MTK_PHY_LED_BLINK_1000RX
;
151 if (on
& MTK_PHY_LED_ON_LINK2500
)
152 blink
|= MTK_PHY_LED_BLINK_2500RX
;
154 blink
|= rx_blink_set
;
158 if (rules
& BIT(TRIGGER_NETDEV_TX
)) {
160 if (on
& MTK_PHY_LED_ON_LINK10
)
161 blink
|= MTK_PHY_LED_BLINK_10TX
;
162 if (on
& MTK_PHY_LED_ON_LINK100
)
163 blink
|= MTK_PHY_LED_BLINK_100TX
;
164 if (on
& MTK_PHY_LED_ON_LINK1000
)
165 blink
|= MTK_PHY_LED_BLINK_1000TX
;
166 if (on
& MTK_PHY_LED_ON_LINK2500
)
167 blink
|= MTK_PHY_LED_BLINK_2500TX
;
169 blink
|= tx_blink_set
;
174 set_bit(bit_netdev
, &priv
->led_state
);
176 clear_bit(bit_netdev
, &priv
->led_state
);
178 ret
= phy_modify_mmd(phydev
, MDIO_MMD_VEND2
, index
?
179 MTK_PHY_LED1_ON_CTRL
: MTK_PHY_LED0_ON_CTRL
,
180 MTK_PHY_LED_ON_FDX
| MTK_PHY_LED_ON_HDX
| on_set
,
186 return phy_write_mmd(phydev
, MDIO_MMD_VEND2
, index
?
187 MTK_PHY_LED1_BLINK_CTRL
:
188 MTK_PHY_LED0_BLINK_CTRL
, blink
);
190 EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_set
);
192 int mtk_phy_led_num_dly_cfg(u8 index
, unsigned long *delay_on
,
193 unsigned long *delay_off
, bool *blinking
)
198 if (delay_on
&& delay_off
&& (*delay_on
> 0) && (*delay_off
> 0)) {
206 EXPORT_SYMBOL_GPL(mtk_phy_led_num_dly_cfg
);
208 int mtk_phy_hw_led_on_set(struct phy_device
*phydev
, u8 index
,
209 u16 led_on_mask
, bool on
)
211 unsigned int bit_on
= MTK_PHY_LED_STATE_FORCE_ON
+ (index
? 16 : 0);
212 struct mtk_socphy_priv
*priv
= phydev
->priv
;
216 changed
= !test_and_set_bit(bit_on
, &priv
->led_state
);
218 changed
= !!test_and_clear_bit(bit_on
, &priv
->led_state
);
220 changed
|= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV
+
221 (index
? 16 : 0), &priv
->led_state
);
223 return phy_modify_mmd(phydev
, MDIO_MMD_VEND2
, index
?
224 MTK_PHY_LED1_ON_CTRL
:
225 MTK_PHY_LED0_ON_CTRL
,
227 on
? MTK_PHY_LED_ON_FORCE_ON
: 0);
231 EXPORT_SYMBOL_GPL(mtk_phy_hw_led_on_set
);
233 int mtk_phy_hw_led_blink_set(struct phy_device
*phydev
, u8 index
, bool blinking
)
235 unsigned int bit_blink
= MTK_PHY_LED_STATE_FORCE_BLINK
+
237 struct mtk_socphy_priv
*priv
= phydev
->priv
;
241 changed
= !test_and_set_bit(bit_blink
, &priv
->led_state
);
243 changed
= !!test_and_clear_bit(bit_blink
, &priv
->led_state
);
245 changed
|= !!test_bit(MTK_PHY_LED_STATE_NETDEV
+
246 (index
? 16 : 0), &priv
->led_state
);
248 return phy_write_mmd(phydev
, MDIO_MMD_VEND2
, index
?
249 MTK_PHY_LED1_BLINK_CTRL
:
250 MTK_PHY_LED0_BLINK_CTRL
,
252 MTK_PHY_LED_BLINK_FORCE_BLINK
: 0);
256 EXPORT_SYMBOL_GPL(mtk_phy_hw_led_blink_set
);
258 void mtk_phy_leds_state_init(struct phy_device
*phydev
)
262 for (i
= 0; i
< 2; ++i
)
263 phydev
->drv
->led_hw_control_get(phydev
, i
, NULL
);
265 EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init
);
267 MODULE_DESCRIPTION("MediaTek Ethernet PHY driver common");
268 MODULE_AUTHOR("Sky Huang <SkyLake.Huang@mediatek.com>");
269 MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
270 MODULE_LICENSE("GPL");