aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch')
-rw-r--r--target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch213
1 files changed, 213 insertions, 0 deletions
diff --git a/target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch b/target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch
new file mode 100644
index 0000000000..83d0f26bf4
--- /dev/null
+++ b/target/linux/mediatek/patches-5.15/731-net-phy-mediatek-ge-soc-initialize-MT7988-PHY-LEDs-d.patch
@@ -0,0 +1,213 @@
+From 5d2d78860f98eb5c03bc404eb024606878901ac8 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Tue, 13 Jun 2023 03:27:14 +0100
+Subject: [PATCH] net: phy: mediatek-ge-soc: initialize MT7988 PHY LEDs default
+ state
+
+Initialize LEDs and set sane default values.
+Read boottrap register and apply LED polarities accordingly to get
+uniform behavior from all LEDs on MT7988.
+Requires syscon phandle 'mediatek,pio' present in parenting MDIO bus
+which should point to the syscon holding the boottrap register.
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+---
+ drivers/net/phy/mediatek-ge-soc.c | 144 ++++++++++++++++++++++++++++--
+ 1 file changed, 136 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/phy/mediatek-ge-soc.c
++++ b/drivers/net/phy/mediatek-ge-soc.c
+@@ -1,11 +1,13 @@
+ // SPDX-License-Identifier: GPL-2.0+
+ #include <linux/bitfield.h>
++#include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+ #include <linux/nvmem-consumer.h>
+ #include <linux/of_address.h>
+ #include <linux/of_platform.h>
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/phy.h>
++#include <linux/regmap.h>
+
+ #define MTK_GPHY_ID_MT7981 0x03a29461
+ #define MTK_GPHY_ID_MT7988 0x03a29481
+@@ -208,9 +210,40 @@
+ #define MTK_PHY_DA_TX_R50_PAIR_C 0x53f
+ #define MTK_PHY_DA_TX_R50_PAIR_D 0x540
+
++/* Registers on MDIO_MMD_VEND2 */
++#define MTK_PHY_LED0_ON_CTRL 0x24
++#define MTK_PHY_LED1_ON_CTRL 0x26
++#define MTK_PHY_LED_ON_MASK GENMASK(6, 0)
++#define MTK_PHY_LED_ON_LINK1000 BIT(0)
++#define MTK_PHY_LED_ON_LINK100 BIT(1)
++#define MTK_PHY_LED_ON_LINK10 BIT(2)
++#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
++#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
++#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
++#define MTK_PHY_LED_FORCE_ON BIT(6)
++#define MTK_PHY_LED_POLARITY BIT(14)
++#define MTK_PHY_LED_ENABLE BIT(15)
++
++#define MTK_PHY_LED0_BLINK_CTRL 0x25
++#define MTK_PHY_LED1_BLINK_CTRL 0x27
++#define MTK_PHY_LED_1000TX BIT(0)
++#define MTK_PHY_LED_1000RX BIT(1)
++#define MTK_PHY_LED_100TX BIT(2)
++#define MTK_PHY_LED_100RX BIT(3)
++#define MTK_PHY_LED_10TX BIT(4)
++#define MTK_PHY_LED_10RX BIT(5)
++#define MTK_PHY_LED_COLLISION BIT(6)
++#define MTK_PHY_LED_RX_CRC_ERR BIT(7)
++#define MTK_PHY_LED_RX_IDLE_ERR BIT(8)
++#define MTK_PHY_LED_FORCE_BLINK BIT(9)
++
+ #define MTK_PHY_RG_BG_RASEL 0x115
+ #define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0)
+
++/* Register in boottrap syscon defining the initial state of the 4 PHY LEDs */
++#define RG_GPIO_MISC_TPBANK0 0x6f0
++#define RG_GPIO_MISC_TPBANK0_BOOTMODE GENMASK(11, 8)
++
+ /* These macro privides efuse parsing for internal phy. */
+ #define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0))
+ #define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0))
+@@ -238,13 +271,6 @@ enum {
+ PAIR_D,
+ };
+
+-enum {
+- GPHY_PORT0,
+- GPHY_PORT1,
+- GPHY_PORT2,
+- GPHY_PORT3,
+-};
+-
+ enum calibration_mode {
+ EFUSE_K,
+ SW_K
+@@ -263,6 +289,10 @@ enum CAL_MODE {
+ SW_M
+ };
+
++struct mtk_socphy_shared {
++ u32 boottrap;
++};
++
+ static int mtk_socphy_read_page(struct phy_device *phydev)
+ {
+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
+@@ -1073,6 +1103,104 @@ static int mt798x_phy_config_init(struct
+ return mt798x_phy_calibration(phydev);
+ }
+
++static int mt798x_phy_setup_led(struct phy_device *phydev, bool inverted)
++{
++ struct pinctrl *pinctrl;
++ const u16 led_on_ctrl_defaults = MTK_PHY_LED_ENABLE |
++ MTK_PHY_LED_ON_LINK1000 |
++ MTK_PHY_LED_ON_LINK100 |
++ MTK_PHY_LED_ON_LINK10;
++ const u16 led_blink_defaults = MTK_PHY_LED_1000TX |
++ MTK_PHY_LED_1000RX |
++ MTK_PHY_LED_100TX |
++ MTK_PHY_LED_100RX |
++ MTK_PHY_LED_10TX |
++ MTK_PHY_LED_10RX;
++
++ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
++ led_on_ctrl_defaults ^
++ (inverted ? MTK_PHY_LED_POLARITY : 0));
++
++ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
++ led_on_ctrl_defaults);
++
++ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_BLINK_CTRL,
++ led_blink_defaults);
++
++ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_BLINK_CTRL,
++ led_blink_defaults);
++
++ pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
++ if (IS_ERR(pinctrl))
++ dev_err(&phydev->mdio.bus->dev, "Failed to setup PHY LED\n");
++
++ return 0;
++}
++
++static int mt7988_phy_probe_shared(struct phy_device *phydev)
++{
++ struct device_node *np = dev_of_node(&phydev->mdio.bus->dev);
++ struct mtk_socphy_shared *priv = phydev->shared->priv;
++ struct regmap *regmap;
++ u32 reg;
++ int ret;
++
++ /* The LED0 of the 4 PHYs in MT7988 are wired to SoC pins LED_A, LED_B,
++ * LED_C and LED_D respectively. At the same time those pins are used to
++ * bootstrap configuration of the reference clock source (LED_A),
++ * DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D).
++ * In practise this is done using a LED and a resistor pulling the pin
++ * either to GND or to VIO.
++ * The detected value at boot time is accessible at run-time using the
++ * TPBANK0 register located in the gpio base of the pinctrl, in order
++ * to read it here it needs to be referenced by a phandle called
++ * 'mediatek,pio' in the MDIO bus hosting the PHY.
++ * The 4 bits in TPBANK0 are kept as package shared data and are used to
++ * set LED polarity for each of the LED0.
++ */
++ regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,pio");
++ if (IS_ERR(regmap))
++ return PTR_ERR(regmap);
++
++ ret = regmap_read(regmap, RG_GPIO_MISC_TPBANK0, &reg);
++ if (ret)
++ return ret;
++
++ priv->boottrap = FIELD_GET(RG_GPIO_MISC_TPBANK0_BOOTMODE, reg);
++
++ return 0;
++}
++
++static bool mt7988_phy_get_boottrap_polarity(struct phy_device *phydev)
++{
++ struct mtk_socphy_shared *priv = phydev->shared->priv;
++
++ if (priv->boottrap & BIT(phydev->mdio.addr))
++ return false;
++
++ return true;
++}
++
++static int mt7988_phy_probe(struct phy_device *phydev)
++{
++ int err;
++
++ err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0,
++ sizeof(struct mtk_socphy_shared));
++ if (err)
++ return err;
++
++ if (phy_package_probe_once(phydev)) {
++ err = mt7988_phy_probe_shared(phydev);
++ if (err)
++ return err;
++ }
++
++ mt798x_phy_setup_led(phydev, mt7988_phy_get_boottrap_polarity(phydev));
++
++ return mt798x_phy_calibration(phydev);
++}
++
+ static struct phy_driver mtk_socphy_driver[] = {
+ {
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
+@@ -1092,7 +1220,7 @@ static struct phy_driver mtk_socphy_driv
+ .config_init = mt798x_phy_config_init,
+ .config_intr = genphy_no_config_intr,
+ .handle_interrupt = genphy_handle_interrupt_no_ack,
+- .probe = mt798x_phy_calibration,
++ .probe = mt7988_phy_probe,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_socphy_read_page,