1 From 5d2d78860f98eb5c03bc404eb024606878901ac8 Mon Sep 17 00:00:00 2001
2 From: Daniel Golle <daniel@makrotopia.org>
3 Date: Tue, 13 Jun 2023 03:27:14 +0100
4 Subject: [PATCH] net: phy: mediatek-ge-soc: initialize MT7988 PHY LEDs default
7 Initialize LEDs and set sane default values.
8 Read boottrap register and apply LED polarities accordingly to get
9 uniform behavior from all LEDs on MT7988.
10 Requires syscon phandle 'mediatek,pio' present in parenting MDIO bus
11 which should point to the syscon holding the boottrap register.
13 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
15 drivers/net/phy/mediatek-ge-soc.c | 144 ++++++++++++++++++++++++++++--
16 1 file changed, 136 insertions(+), 8 deletions(-)
18 --- a/drivers/net/phy/mediatek-ge-soc.c
19 +++ b/drivers/net/phy/mediatek-ge-soc.c
21 // SPDX-License-Identifier: GPL-2.0+
22 #include <linux/bitfield.h>
23 +#include <linux/mfd/syscon.h>
24 #include <linux/module.h>
25 #include <linux/nvmem-consumer.h>
26 #include <linux/of_address.h>
27 #include <linux/of_platform.h>
28 #include <linux/pinctrl/consumer.h>
29 #include <linux/phy.h>
30 +#include <linux/regmap.h>
32 #define MTK_GPHY_ID_MT7981 0x03a29461
33 #define MTK_GPHY_ID_MT7988 0x03a29481
35 #define MTK_PHY_DA_TX_R50_PAIR_C 0x53f
36 #define MTK_PHY_DA_TX_R50_PAIR_D 0x540
38 +/* Registers on MDIO_MMD_VEND2 */
39 +#define MTK_PHY_LED0_ON_CTRL 0x24
40 +#define MTK_PHY_LED1_ON_CTRL 0x26
41 +#define MTK_PHY_LED_ON_MASK GENMASK(6, 0)
42 +#define MTK_PHY_LED_ON_LINK1000 BIT(0)
43 +#define MTK_PHY_LED_ON_LINK100 BIT(1)
44 +#define MTK_PHY_LED_ON_LINK10 BIT(2)
45 +#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
46 +#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
47 +#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
48 +#define MTK_PHY_LED_FORCE_ON BIT(6)
49 +#define MTK_PHY_LED_POLARITY BIT(14)
50 +#define MTK_PHY_LED_ENABLE BIT(15)
52 +#define MTK_PHY_LED0_BLINK_CTRL 0x25
53 +#define MTK_PHY_LED1_BLINK_CTRL 0x27
54 +#define MTK_PHY_LED_1000TX BIT(0)
55 +#define MTK_PHY_LED_1000RX BIT(1)
56 +#define MTK_PHY_LED_100TX BIT(2)
57 +#define MTK_PHY_LED_100RX BIT(3)
58 +#define MTK_PHY_LED_10TX BIT(4)
59 +#define MTK_PHY_LED_10RX BIT(5)
60 +#define MTK_PHY_LED_COLLISION BIT(6)
61 +#define MTK_PHY_LED_RX_CRC_ERR BIT(7)
62 +#define MTK_PHY_LED_RX_IDLE_ERR BIT(8)
63 +#define MTK_PHY_LED_FORCE_BLINK BIT(9)
65 #define MTK_PHY_RG_BG_RASEL 0x115
66 #define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0)
68 +/* Register in boottrap syscon defining the initial state of the 4 PHY LEDs */
69 +#define RG_GPIO_MISC_TPBANK0 0x6f0
70 +#define RG_GPIO_MISC_TPBANK0_BOOTMODE GENMASK(11, 8)
72 /* These macro privides efuse parsing for internal phy. */
73 #define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0))
74 #define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0))
75 @@ -238,13 +271,6 @@ enum {
86 enum calibration_mode {
89 @@ -263,6 +289,10 @@ enum CAL_MODE {
93 +struct mtk_socphy_shared {
97 static int mtk_socphy_read_page(struct phy_device *phydev)
99 return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
100 @@ -1073,6 +1103,104 @@ static int mt798x_phy_config_init(struct
101 return mt798x_phy_calibration(phydev);
104 +static int mt798x_phy_setup_led(struct phy_device *phydev, bool inverted)
106 + struct pinctrl *pinctrl;
107 + const u16 led_on_ctrl_defaults = MTK_PHY_LED_ENABLE |
108 + MTK_PHY_LED_ON_LINK1000 |
109 + MTK_PHY_LED_ON_LINK100 |
110 + MTK_PHY_LED_ON_LINK10;
111 + const u16 led_blink_defaults = MTK_PHY_LED_1000TX |
112 + MTK_PHY_LED_1000RX |
113 + MTK_PHY_LED_100TX |
114 + MTK_PHY_LED_100RX |
118 + phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
119 + led_on_ctrl_defaults ^
120 + (inverted ? MTK_PHY_LED_POLARITY : 0));
122 + phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
123 + led_on_ctrl_defaults);
125 + phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_BLINK_CTRL,
126 + led_blink_defaults);
128 + phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_BLINK_CTRL,
129 + led_blink_defaults);
131 + pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
132 + if (IS_ERR(pinctrl))
133 + dev_err(&phydev->mdio.bus->dev, "Failed to setup PHY LED\n");
138 +static int mt7988_phy_probe_shared(struct phy_device *phydev)
140 + struct device_node *np = dev_of_node(&phydev->mdio.bus->dev);
141 + struct mtk_socphy_shared *priv = phydev->shared->priv;
142 + struct regmap *regmap;
146 + /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B,
147 + * LED_C and LED_D respectively. At the same time those pins are used to
148 + * bootstrap configuration of the reference clock source (LED_A),
149 + * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D).
150 + * In practise this is done using a LED and a resistor pulling the pin
151 + * either to GND or to VIO.
152 + * The detected value at boot time is accessible at run-time using the
153 + * TPBANK0 register located in the gpio base of the pinctrl, in order
154 + * to read it here it needs to be referenced by a phandle called
155 + * 'mediatek,pio' in the MDIO bus hosting the PHY.
156 + * The 4 bits in TPBANK0 are kept as package shared data and are used to
157 + * set LED polarity for each of the LED0.
159 + regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio");
160 + if (IS_ERR(regmap))
161 + return PTR_ERR(regmap);
163 + ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, ®);
167 + priv->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg);
172 +static bool mt7988_phy_get_boottrap_polarity(struct phy_device *phydev)
174 + struct mtk_socphy_shared *priv = phydev->shared->priv;
176 + if (priv->boottrap & BIT(phydev->mdio.addr))
182 +static int mt7988_phy_probe(struct phy_device *phydev)
186 + err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0,
187 + sizeof(struct mtk_socphy_shared));
191 + if (phy_package_probe_once(phydev)) {
192 + err = mt7988_phy_probe_shared(phydev);
197 + mt798x_phy_setup_led(phydev, mt7988_phy_get_boottrap_polarity(phydev));
199 + return mt798x_phy_calibration(phydev);
202 static struct phy_driver mtk_socphy_driver[] = {
204 PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
205 @@ -1092,7 +1220,7 @@ static struct phy_driver mtk_socphy_driv
206 .config_init = mt798x_phy_config_init,
207 .config_intr = genphy_no_config_intr,
208 .handle_interrupt = genphy_handle_interrupt_no_ack,
209 - .probe = mt798x_phy_calibration,
210 + .probe = mt7988_phy_probe,
211 .suspend = genphy_suspend,
212 .resume = genphy_resume,
213 .read_page = mtk_socphy_read_page,