From: Bartosz Golaszewski <[email protected]>
There are three ethernet ports on sa8775p-ride. This series contains changes
required to enable one of the two 1Gb ports (the third one is 10Gb). We need
to add a new driver for the internal SerDes PHY, introduce several extensions
to the MAC driver (while at it: tweak coding style a bit etc.) and finally
add the relevant DT nodes.
Bartosz Golaszewski (26):
phy: qualcomm: fix indentation in Makefile
dt-bindings: phy: describe the Qualcomm SGMII PHY
phy: qcom: add the SGMII SerDes PHY driver
arm64: defconfig: enable the SerDes PHY for Qualcomm DWMAC
net: stmmac: dwmac-qcom-ethqos: shrink clock code with devres
net: stmmac: dwmac-qcom-ethqos: rename a label in probe()
net: stmmac: dwmac-qcom-ethqos: tweak the order of local variables
net: stmmac: dwmac-qcom-ethqos: use a helper variable for &pdev->dev
net: stmmac: dwmac-qcom-ethqos: add missing include
net: stmmac: dwmac-qcom-ethqos: add a newline between headers
net: stmmac: dwmac-qcom-ethqos: remove stray space
net: stmmac: dwmac-qcom-ethqos: add support for the optional serdes
phy
net: stmmac: dwmac-qcom-ethqos: make the rgmii clock optional
net: stmmac: dwmac-qcom-ethqos: add optional phyaux clock
net: stmmac: dwmac-qcom-ethqos: add support for the optional
phy-supply
net: stmmac: dwmac-qcom-ethqos: prepare the driver for more PHY modes
net: stmmac: dwmac-qcom-ethqos: add support for SGMII
net: stmmac: add new switch to struct plat_stmmacenet_data
dt-bindings: net: snps,dwmac: add compatible for sa8775p ethqos
dt-bindings: net: qcom,ethqos: add description for sa8775p
net: stmmac: dwmac-qcom-ethqos: add support for emac4 on sa8775p
platforms
arm64: dts: qcom: sa8775p-ride: add the SGMII PHY node
arm64: dts: qcom: sa8775p: add the first 1Gb ethernet interface
arm64: dts: qcom: sa8775p-ride: enable the SerDes PHY
arm64: dts: qcom: sa8775p-ride: add pin functions for ethernet0
arm64: dts: qcom: sa8775p-ride: enable ethernet0
.../devicetree/bindings/net/qcom,ethqos.yaml | 14 +-
.../devicetree/bindings/net/snps,dwmac.yaml | 3 +
.../phy/qcom,sa8775p-dwmac-sgmii-phy.yaml | 52 ++
arch/arm64/boot/dts/qcom/sa8775p-ride.dts | 109 +++++
arch/arm64/boot/dts/qcom/sa8775p.dtsi | 39 ++
arch/arm64/configs/defconfig | 1 +
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 273 ++++++++---
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
drivers/phy/qualcomm/Kconfig | 9 +
drivers/phy/qualcomm/Makefile | 3 +-
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 446 ++++++++++++++++++
include/linux/stmmac.h | 1 +
12 files changed, 890 insertions(+), 62 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/qcom,sa8775p-dwmac-sgmii-phy.yaml
create mode 100644 drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
There's an unnecessary space in the rgmii_updatel() function, remove it.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 5b56abacbf6b..8ed05f29fe8b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -117,7 +117,7 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos,
{
unsigned int temp;
- temp = rgmii_readl(ethqos, offset);
+ temp = rgmii_readl(ethqos, offset);
temp = (temp & ~(mask)) | val;
rgmii_writel(ethqos, temp, offset);
}
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
The err_mem label's name is unclear. It actually should be reached on
any error after stmmac_probe_config_dt() succeeds. Name it after the
cleanup action that needs to be called before exiting.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
.../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 2da0738eed24..16e856861558 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -615,14 +615,14 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL);
if (!ethqos) {
ret = -ENOMEM;
- goto err_mem;
+ goto out_config_dt;
}
ethqos->pdev = pdev;
ethqos->rgmii_base = devm_platform_ioremap_resource_byname(pdev, "rgmii");
if (IS_ERR(ethqos->rgmii_base)) {
ret = PTR_ERR(ethqos->rgmii_base);
- goto err_mem;
+ goto out_config_dt;
}
data = of_device_get_match_data(&pdev->dev);
@@ -634,16 +634,16 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
if (IS_ERR(ethqos->rgmii_clk)) {
ret = PTR_ERR(ethqos->rgmii_clk);
- goto err_mem;
+ goto out_config_dt;
}
ret = ethqos_clks_config(ethqos, true);
if (ret)
- goto err_mem;
+ goto out_config_dt;
ret = devm_add_action_or_reset(&pdev->dev, ethqos_clks_disable, ethqos);
if (ret)
- goto err_mem;
+ goto out_config_dt;
ethqos->speed = SPEED_1000;
ethqos_update_rgmii_clk(ethqos, SPEED_1000);
@@ -662,11 +662,11 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
- goto err_mem;
+ goto out_config_dt;
return ret;
-err_mem:
+out_config_dt:
stmmac_remove_config_dt(pdev, plat_dat);
return ret;
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
On sa8775p there's no RGMII clock so make it optional in the driver.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 3438b6229351..252dca400071 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -663,7 +663,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
ethqos->has_emac3 = data->has_emac3;
- ethqos->rgmii_clk = devm_clk_get(dev, "rgmii");
+ ethqos->rgmii_clk = devm_clk_get_optional(dev, "rgmii");
if (IS_ERR(ethqos->rgmii_clk)) {
ret = PTR_ERR(ethqos->rgmii_clk);
goto out_config_dt;
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
Shrink code and avoid line breaks by using a helper variable for
&pdev->dev.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 48 ++++++++++---------
1 file changed, 26 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 28d2514a8795..e19d142630d3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -123,25 +123,26 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos,
static void rgmii_dump(void *priv)
{
struct qcom_ethqos *ethqos = priv;
+ struct device *dev = ðqos->pdev->dev;
- dev_dbg(ðqos->pdev->dev, "Rgmii register dump\n");
- dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n",
+ dev_dbg(dev, "Rgmii register dump\n");
+ dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %x\n",
rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG));
- dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
+ dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG));
- dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
+ dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG));
- dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
+ dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2));
- dev_dbg(ðqos->pdev->dev, "SDC4_STATUS: %x\n",
+ dev_dbg(dev, "SDC4_STATUS: %x\n",
rgmii_readl(ethqos, SDC4_STATUS));
- dev_dbg(ðqos->pdev->dev, "SDCC_USR_CTL: %x\n",
+ dev_dbg(dev, "SDCC_USR_CTL: %x\n",
rgmii_readl(ethqos, SDCC_USR_CTL));
- dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
+ dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2));
- dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
+ dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1));
- dev_dbg(ðqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
+ dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG));
}
@@ -242,6 +243,7 @@ static const struct ethqos_emac_driver_data emac_v3_0_0_data = {
static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
{
+ struct device *dev = ðqos->pdev->dev;
unsigned int val;
int retry = 1000;
@@ -279,7 +281,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
retry--;
} while (retry > 0);
if (!retry)
- dev_err(ðqos->pdev->dev, "Clear CK_OUT_EN timedout\n");
+ dev_err(dev, "Clear CK_OUT_EN timedout\n");
/* Set CK_OUT_EN */
rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
@@ -296,7 +298,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
retry--;
} while (retry > 0);
if (!retry)
- dev_err(ðqos->pdev->dev, "Set CK_OUT_EN timedout\n");
+ dev_err(dev, "Set CK_OUT_EN timedout\n");
/* Set DDR_CAL_EN */
rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN,
@@ -322,12 +324,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
{
+ struct device *dev = ðqos->pdev->dev;
int phase_shift;
int phy_mode;
int loopback;
/* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
- phy_mode = device_get_phy_mode(ðqos->pdev->dev);
+ phy_mode = device_get_phy_mode(dev);
if (phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
phase_shift = 0;
@@ -468,7 +471,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
loopback, RGMII_IO_MACRO_CONFIG);
break;
default:
- dev_err(ðqos->pdev->dev,
+ dev_err(dev,
"Invalid speed %d\n", ethqos->speed);
return -EINVAL;
}
@@ -478,6 +481,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
static int ethqos_configure(struct qcom_ethqos *ethqos)
{
+ struct device *dev = ðqos->pdev->dev;
volatile unsigned int dll_lock;
unsigned int i, retry = 1000;
@@ -540,8 +544,7 @@ static int ethqos_configure(struct qcom_ethqos *ethqos)
retry--;
} while (retry > 0);
if (!retry)
- dev_err(ðqos->pdev->dev,
- "Timeout while waiting for DLL lock\n");
+ dev_err(dev, "Timeout while waiting for DLL lock\n");
}
if (ethqos->speed == SPEED_1000)
@@ -597,6 +600,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
const struct ethqos_emac_driver_data *data;
struct plat_stmmacenet_data *plat_dat;
struct stmmac_resources stmmac_res;
+ struct device *dev = &pdev->dev;
struct qcom_ethqos *ethqos;
int ret;
@@ -606,13 +610,13 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
if (IS_ERR(plat_dat)) {
- dev_err(&pdev->dev, "dt configuration failed\n");
+ dev_err(dev, "dt configuration failed\n");
return PTR_ERR(plat_dat);
}
plat_dat->clks_config = ethqos_clks_config;
- ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL);
+ ethqos = devm_kzalloc(dev, sizeof(*ethqos), GFP_KERNEL);
if (!ethqos) {
ret = -ENOMEM;
goto out_config_dt;
@@ -625,13 +629,13 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
goto out_config_dt;
}
- data = of_device_get_match_data(&pdev->dev);
+ data = of_device_get_match_data(dev);
ethqos->por = data->por;
ethqos->num_por = data->num_por;
ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
ethqos->has_emac3 = data->has_emac3;
- ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
+ ethqos->rgmii_clk = devm_clk_get(dev, "rgmii");
if (IS_ERR(ethqos->rgmii_clk)) {
ret = PTR_ERR(ethqos->rgmii_clk);
goto out_config_dt;
@@ -641,7 +645,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
if (ret)
goto out_config_dt;
- ret = devm_add_action_or_reset(&pdev->dev, ethqos_clks_disable, ethqos);
+ ret = devm_add_action_or_reset(dev, ethqos_clks_disable, ethqos);
if (ret)
goto out_config_dt;
@@ -660,7 +664,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
plat_dat->rx_clk_runs_in_lpi = 1;
- ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ ret = stmmac_dvr_probe(dev, plat_dat, &stmmac_res);
if (ret)
goto out_config_dt;
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
Implement support for the SGMII/SerDes PHY present on various Qualcomm
platforms.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/phy/qualcomm/Kconfig | 9 +
drivers/phy/qualcomm/Makefile | 1 +
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 446 ++++++++++++++++++++++
3 files changed, 456 insertions(+)
create mode 100644 drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 67a45d95250d..97ca5952e34e 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -188,3 +188,12 @@ config PHY_QCOM_IPQ806X_USB
This option enables support for the Synopsis PHYs present inside the
Qualcomm USB3.0 DWC3 controller on ipq806x SoC. This driver supports
both HS and SS PHY controllers.
+
+config PHY_QCOM_SGMII_ETH
+ tristate "Qualcomm DWMAC SGMII SerDes/PHY driver"
+ depends on OF && (ARCH_QCOM || COMPILE_TEST)
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ help
+ Enable this to support the internal SerDes/SGMII PHY on various
+ Qualcomm chipsets.
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
index 5fb33628566b..b030858e0f8d 100644
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o
obj-$(CONFIG_PHY_QCOM_USB_SS) += phy-qcom-usb-ss.o
obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2)+= phy-qcom-snps-femto-v2.o
obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o
+obj-$(CONFIG_PHY_QCOM_SGMII_ETH) += phy-qcom-sgmii-eth.o
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
new file mode 100644
index 000000000000..c9f0324a987c
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, Linaro Limited
+ */
+
+#include <linux/clk.h>
+#include <linux/ethtool.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define QSERDES_QMP_PLL 0x0
+#define QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0 (QSERDES_QMP_PLL + 0x1ac)
+#define QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0 (QSERDES_QMP_PLL + 0x1b0)
+#define QSERDES_COM_BIN_VCOCAL_HSCLK_SEL (QSERDES_QMP_PLL + 0x1bc)
+#define QSERDES_COM_CORE_CLK_EN (QSERDES_QMP_PLL + 0x174)
+#define QSERDES_COM_CORECLK_DIV_MODE0 (QSERDES_QMP_PLL + 0x168)
+#define QSERDES_COM_CP_CTRL_MODE0 (QSERDES_QMP_PLL + 0x74)
+#define QSERDES_COM_DEC_START_MODE0 (QSERDES_QMP_PLL + 0xbc)
+#define QSERDES_COM_DIV_FRAC_START1_MODE0 (QSERDES_QMP_PLL + 0xcc)
+#define QSERDES_COM_DIV_FRAC_START2_MODE0 (QSERDES_QMP_PLL + 0xd0)
+#define QSERDES_COM_DIV_FRAC_START3_MODE0 (QSERDES_QMP_PLL + 0xd4)
+#define QSERDES_COM_HSCLK_HS_SWITCH_SEL (QSERDES_QMP_PLL + 0x15c)
+#define QSERDES_COM_HSCLK_SEL (QSERDES_QMP_PLL + 0x158)
+#define QSERDES_COM_LOCK_CMP1_MODE0 (QSERDES_QMP_PLL + 0xac)
+#define QSERDES_COM_LOCK_CMP2_MODE0 (QSERDES_QMP_PLL + 0xb0)
+#define QSERDES_COM_PLL_CCTRL_MODE0 (QSERDES_QMP_PLL + 0x84)
+#define QSERDES_COM_PLL_IVCO (QSERDES_QMP_PLL + 0x58)
+#define QSERDES_COM_PLL_RCTRL_MODE0 (QSERDES_QMP_PLL + 0x7c)
+#define QSERDES_COM_SYSCLK_EN_SEL (QSERDES_QMP_PLL + 0x94)
+#define QSERDES_COM_VCO_TUNE1_MODE0 (QSERDES_QMP_PLL + 0x110)
+#define QSERDES_COM_VCO_TUNE2_MODE0 (QSERDES_QMP_PLL + 0x114)
+#define QSERDES_COM_VCO_TUNE_INITVAL2 (QSERDES_QMP_PLL + 0x124)
+#define QSERDES_COM_C_READY_STATUS (QSERDES_QMP_PLL + 0x178)
+#define QSERDES_COM_CMN_STATUS (QSERDES_QMP_PLL + 0x140)
+
+#define QSERDES_RX 0x600
+#define QSERDES_RX_UCDR_FO_GAIN (QSERDES_RX + 0x8)
+#define QSERDES_RX_UCDR_SO_GAIN (QSERDES_RX + 0x14)
+#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN (QSERDES_RX + 0x30)
+#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE (QSERDES_RX + 0x34)
+#define QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW (QSERDES_RX + 0x3c)
+#define QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH (QSERDES_RX + 0x40)
+#define QSERDES_RX_UCDR_PI_CONTROLS (QSERDES_RX + 0x44)
+#define QSERDES_RX_UCDR_PI_CTRL2 (QSERDES_RX + 0x48)
+#define QSERDES_RX_RX_TERM_BW (QSERDES_RX + 0x80)
+#define QSERDES_RX_VGA_CAL_CNTRL2 (QSERDES_RX + 0xd8)
+#define QSERDES_RX_GM_CAL (QSERDES_RX + 0xdc)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1 (QSERDES_RX + 0xe8)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 (QSERDES_RX + 0xec)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 (QSERDES_RX + 0xf0)
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 (QSERDES_RX + 0xf4)
+#define QSERDES_RX_RX_IDAC_TSETTLE_LOW (QSERDES_RX + 0xf8)
+#define QSERDES_RX_RX_IDAC_TSETTLE_HIGH (QSERDES_RX + 0xfc)
+#define QSERDES_RX_RX_IDAC_MEASURE_TIME (QSERDES_RX + 0x100)
+#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 (QSERDES_RX + 0x110)
+#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 (QSERDES_RX + 0x114)
+#define QSERDES_RX_SIGDET_CNTRL (QSERDES_RX + 0x11c)
+#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL (QSERDES_RX + 0x124)
+#define QSERDES_RX_RX_BAND (QSERDES_RX + 0x128)
+#define QSERDES_RX_RX_MODE_00_LOW (QSERDES_RX + 0x15c)
+#define QSERDES_RX_RX_MODE_00_HIGH (QSERDES_RX + 0x160)
+#define QSERDES_RX_RX_MODE_00_HIGH2 (QSERDES_RX + 0x164)
+#define QSERDES_RX_RX_MODE_00_HIGH3 (QSERDES_RX + 0x168)
+#define QSERDES_RX_RX_MODE_00_HIGH4 (QSERDES_RX + 0x16c)
+#define QSERDES_RX_RX_MODE_01_LOW (QSERDES_RX + 0x170)
+#define QSERDES_RX_RX_MODE_01_HIGH (QSERDES_RX + 0x174)
+#define QSERDES_RX_RX_MODE_01_HIGH2 (QSERDES_RX + 0x178)
+#define QSERDES_RX_RX_MODE_01_HIGH3 (QSERDES_RX + 0x17c)
+#define QSERDES_RX_RX_MODE_01_HIGH4 (QSERDES_RX + 0x180)
+#define QSERDES_RX_RX_MODE_10_LOW (QSERDES_RX + 0x184)
+#define QSERDES_RX_RX_MODE_10_HIGH (QSERDES_RX + 0x188)
+#define QSERDES_RX_RX_MODE_10_HIGH2 (QSERDES_RX + 0x18c)
+#define QSERDES_RX_RX_MODE_10_HIGH3 (QSERDES_RX + 0x190)
+#define QSERDES_RX_RX_MODE_10_HIGH4 (QSERDES_RX + 0x194)
+#define QSERDES_RX_DCC_CTRL1 (QSERDES_RX + 0x1a8)
+
+#define QSERDES_TX 0x400
+#define QSERDES_TX_TX_BAND (QSERDES_TX + 0x24)
+#define QSERDES_TX_SLEW_CNTL (QSERDES_TX + 0x28)
+#define QSERDES_TX_RES_CODE_LANE_OFFSET_TX (QSERDES_TX + 0x3c)
+#define QSERDES_TX_RES_CODE_LANE_OFFSET_RX (QSERDES_TX + 0x40)
+#define QSERDES_TX_LANE_MODE_1 (QSERDES_TX + 0x84)
+#define QSERDES_TX_LANE_MODE_3 (QSERDES_TX + 0x8c)
+#define QSERDES_TX_RCV_DETECT_LVL_2 (QSERDES_TX + 0xa4)
+#define QSERDES_TX_TRAN_DRVR_EMP_EN (QSERDES_TX + 0xc0)
+
+#define QSERDES_PCS 0xC00
+#define QSERDES_PCS_PHY_START (QSERDES_PCS + 0x0)
+#define QSERDES_PCS_POWER_DOWN_CONTROL (QSERDES_PCS + 0x4)
+#define QSERDES_PCS_SW_RESET (QSERDES_PCS + 0x8)
+#define QSERDES_PCS_LINE_RESET_TIME (QSERDES_PCS + 0xc)
+#define QSERDES_PCS_TX_LARGE_AMP_DRV_LVL (QSERDES_PCS + 0x20)
+#define QSERDES_PCS_TX_SMALL_AMP_DRV_LVL (QSERDES_PCS + 0x28)
+#define QSERDES_PCS_TX_MID_TERM_CTRL1 (QSERDES_PCS + 0xd8)
+#define QSERDES_PCS_TX_MID_TERM_CTRL2 (QSERDES_PCS + 0xdc)
+#define QSERDES_PCS_SGMII_MISC_CTRL8 (QSERDES_PCS + 0x118)
+#define QSERDES_PCS_PCS_READY_STATUS (QSERDES_PCS + 0x94)
+
+#define QSERDES_COM_C_READY BIT(0)
+#define QSERDES_PCS_READY BIT(0)
+#define QSERDES_PCS_SGMIIPHY_READY BIT(7)
+#define QSERDES_COM_C_PLL_LOCKED BIT(1)
+
+struct qcom_dwmac_sgmii_phy_data {
+ struct regmap *regmap;
+ int speed;
+};
+
+static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)
+{
+ regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
+ regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
+
+ regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
+ regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
+ regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
+ regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
+ regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
+ regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x0A);
+ regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x1A);
+ regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x82);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03);
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0x24);
+
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
+ regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x04);
+ regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
+ regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x0A);
+ regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xB9);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1E);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
+
+ regmap_write(regmap, QSERDES_TX_TX_BAND, 0x05);
+ regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
+ regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
+ regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x09);
+ regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
+ regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
+ regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
+ regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
+
+ regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
+ regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
+ regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x04);
+ regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
+ regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
+ regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
+ regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
+ regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
+ regmap_write(regmap, QSERDES_RX_RX_BAND, 0x05);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x09);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB1);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
+ regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
+
+ regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
+ regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
+ regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
+ regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
+ regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
+ regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x0C);
+ regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
+
+ regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
+}
+
+static void qcom_dwmac_sgmii_phy_init_2p5g(struct regmap *regmap)
+{
+ regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x01);
+ regmap_write(regmap, QSERDES_PCS_POWER_DOWN_CONTROL, 0x01);
+
+ regmap_write(regmap, QSERDES_COM_PLL_IVCO, 0x0F);
+ regmap_write(regmap, QSERDES_COM_CP_CTRL_MODE0, 0x06);
+ regmap_write(regmap, QSERDES_COM_PLL_RCTRL_MODE0, 0x16);
+ regmap_write(regmap, QSERDES_COM_PLL_CCTRL_MODE0, 0x36);
+ regmap_write(regmap, QSERDES_COM_SYSCLK_EN_SEL, 0x1A);
+ regmap_write(regmap, QSERDES_COM_LOCK_CMP1_MODE0, 0x1A);
+ regmap_write(regmap, QSERDES_COM_LOCK_CMP2_MODE0, 0x41);
+ regmap_write(regmap, QSERDES_COM_DEC_START_MODE0, 0x7A);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x20);
+ regmap_write(regmap, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x01);
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE1_MODE0, 0xA1);
+
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE2_MODE0, 0x02);
+ regmap_write(regmap, QSERDES_COM_VCO_TUNE_INITVAL2, 0x00);
+ regmap_write(regmap, QSERDES_COM_HSCLK_SEL, 0x03);
+ regmap_write(regmap, QSERDES_COM_HSCLK_HS_SWITCH_SEL, 0x00);
+ regmap_write(regmap, QSERDES_COM_CORECLK_DIV_MODE0, 0x05);
+ regmap_write(regmap, QSERDES_COM_CORE_CLK_EN, 0x00);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xCD);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1C);
+ regmap_write(regmap, QSERDES_COM_BIN_VCOCAL_HSCLK_SEL, 0x11);
+
+ regmap_write(regmap, QSERDES_TX_TX_BAND, 0x04);
+ regmap_write(regmap, QSERDES_TX_SLEW_CNTL, 0x0A);
+ regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_TX, 0x09);
+ regmap_write(regmap, QSERDES_TX_RES_CODE_LANE_OFFSET_RX, 0x02);
+ regmap_write(regmap, QSERDES_TX_LANE_MODE_1, 0x05);
+ regmap_write(regmap, QSERDES_TX_LANE_MODE_3, 0x00);
+ regmap_write(regmap, QSERDES_TX_RCV_DETECT_LVL_2, 0x12);
+ regmap_write(regmap, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x0C);
+
+ regmap_write(regmap, QSERDES_RX_UCDR_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX_UCDR_SO_GAIN, 0x06);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0A);
+ regmap_write(regmap, QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7F);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00);
+ regmap_write(regmap, QSERDES_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX_UCDR_PI_CONTROLS, 0x81);
+ regmap_write(regmap, QSERDES_RX_UCDR_PI_CTRL2, 0x80);
+ regmap_write(regmap, QSERDES_RX_RX_TERM_BW, 0x00);
+ regmap_write(regmap, QSERDES_RX_VGA_CAL_CNTRL2, 0x08);
+ regmap_write(regmap, QSERDES_RX_GM_CAL, 0x0F);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4A);
+ regmap_write(regmap, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0A);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_LOW, 0x80);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_TSETTLE_HIGH, 0x01);
+ regmap_write(regmap, QSERDES_RX_RX_IDAC_MEASURE_TIME, 0x20);
+ regmap_write(regmap, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17);
+ regmap_write(regmap, QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00);
+ regmap_write(regmap, QSERDES_RX_SIGDET_CNTRL, 0x0F);
+ regmap_write(regmap, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E);
+ regmap_write(regmap, QSERDES_RX_RX_BAND, 0x18);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_LOW, 0x18);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH3, 0x0C);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_00_HIGH4, 0xB8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH3, 0x09);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_01_HIGH4, 0xB1);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_LOW, 0xE0);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH2, 0xC8);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH3, 0x3B);
+ regmap_write(regmap, QSERDES_RX_RX_MODE_10_HIGH4, 0xB7);
+ regmap_write(regmap, QSERDES_RX_DCC_CTRL1, 0x0C);
+
+ regmap_write(regmap, QSERDES_PCS_LINE_RESET_TIME, 0x0C);
+ regmap_write(regmap, QSERDES_PCS_TX_LARGE_AMP_DRV_LVL, 0x1F);
+ regmap_write(regmap, QSERDES_PCS_TX_SMALL_AMP_DRV_LVL, 0x03);
+ regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL1, 0x83);
+ regmap_write(regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
+ regmap_write(regmap, QSERDES_PCS_SGMII_MISC_CTRL8, 0x8C);
+ regmap_write(regmap, QSERDES_PCS_SW_RESET, 0x00);
+
+ regmap_write(regmap, QSERDES_PCS_PHY_START, 0x01);
+}
+
+static inline int
+qcom_dwmac_sgmii_phy_poll_status(struct regmap *regmap, unsigned int reg,
+ unsigned int bit)
+{
+ unsigned int val;
+
+ return regmap_read_poll_timeout(regmap, reg, val,
+ val & bit, 1500, 750000);
+}
+
+static int qcom_dwmac_sgmii_phy_init(struct phy *phy)
+{
+ struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+ struct device *dev = phy->dev.parent;
+
+ switch (data->speed) {
+ case SPEED_10:
+ case SPEED_100:
+ case SPEED_1000:
+ qcom_dwmac_sgmii_phy_init_1g(data->regmap);
+ break;
+ case SPEED_2500:
+ qcom_dwmac_sgmii_phy_init_2p5g(data->regmap);
+ break;
+ }
+
+ if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
+ QSERDES_COM_C_READY_STATUS,
+ QSERDES_COM_C_READY)) {
+ dev_err(dev, "QSERDES_COM_C_READY_STATUS timedout");
+ return -ETIMEDOUT;
+ }
+
+ if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
+ QSERDES_PCS_PCS_READY_STATUS,
+ QSERDES_PCS_READY)) {
+ dev_err(dev, "PCS_READY timedout");
+ return -ETIMEDOUT;
+ }
+
+ if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
+ QSERDES_PCS_PCS_READY_STATUS,
+ QSERDES_PCS_SGMIIPHY_READY)) {
+ dev_err(dev, "SGMIIPHY_READY timedout");
+ return -ETIMEDOUT;
+ }
+
+ if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
+ QSERDES_COM_CMN_STATUS,
+ QSERDES_COM_C_PLL_LOCKED)) {
+ dev_err(dev, "PLL Lock Status timedout");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int qcom_dwmac_sgmii_phy_exit(struct phy *phy)
+{
+ struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+
+ regmap_write(data->regmap, QSERDES_PCS_TX_MID_TERM_CTRL2, 0x08);
+ regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x01);
+ udelay(100);
+ regmap_write(data->regmap, QSERDES_PCS_SW_RESET, 0x00);
+ regmap_write(data->regmap, QSERDES_PCS_PHY_START, 0x01);
+
+ return 0;
+}
+
+static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
+{
+ struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+
+ if (speed != data->speed)
+ data->speed = speed;
+
+ return 0;
+}
+
+static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
+{
+ return qcom_dwmac_sgmii_phy_init(phy);
+}
+
+static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
+ .init = qcom_dwmac_sgmii_phy_init,
+ .exit = qcom_dwmac_sgmii_phy_exit,
+ .set_speed = qcom_dwmac_sgmii_phy_set_speed,
+ .calibrate = qcom_dwmac_sgmii_phy_calibrate,
+ .owner = THIS_MODULE,
+};
+
+static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .use_relaxed_mmio = true,
+ .disable_locking = true,
+};
+
+static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
+{
+ struct qcom_dwmac_sgmii_phy_data *data;
+ struct device *dev = &pdev->dev;
+ struct phy_provider *provider;
+ struct clk *refclk;
+ void __iomem *base;
+ struct phy *phy;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ data->regmap = devm_regmap_init_mmio(dev, base,
+ &qcom_dwmac_sgmii_phy_regmap_cfg);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
+ phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ refclk = devm_clk_get_enabled(dev, "sgmi_ref");
+ if (IS_ERR(refclk))
+ return PTR_ERR(refclk);
+
+ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(provider))
+ return PTR_ERR(provider);
+
+ phy_set_drvdata(phy, data);
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+}
+
+static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {
+ { .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);
+
+static struct platform_driver qcom_dwmac_sgmii_phy_driver = {
+ .probe = qcom_dwmac_sgmii_phy_probe,
+ .driver = {
+ .name = "qcom-dwmac-sgmii-phy",
+ .of_match_table = qcom_dwmac_sgmii_phy_of_match,
+ }
+};
+
+module_platform_driver(qcom_dwmac_sgmii_phy_driver);
+
+MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");
+MODULE_LICENSE("GPL");
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
Enable the SGMII/SerDes PHY driver. This module is required to enable
ethernet on sa8775p platforms.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 8d850be05835..f62c96fd4335 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1367,6 +1367,7 @@ CONFIG_PHY_QCOM_USB_HS=m
CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=m
CONFIG_PHY_QCOM_USB_HS_28NM=m
CONFIG_PHY_QCOM_USB_SS=m
+CONFIG_PHY_QCOM_SGMII_ETH=m
CONFIG_PHY_R8A779F0_ETHERNET_SERDES=y
CONFIG_PHY_RCAR_GEN3_PCIE=y
CONFIG_PHY_RCAR_GEN3_USB2=y
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
On sa8775p-ride we need to enable the power supply for the external PHY.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 2f6b9b419601..21f329d2f7eb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -8,6 +8,7 @@
#include <linux/phy.h>
#include <linux/phy/phy.h>
#include <linux/property.h>
+#include <linux/regulator/consumer.h>
#include "stmmac.h"
#include "stmmac_platform.h"
@@ -692,6 +693,10 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
if (ret)
goto out_config_dt;
+ ret = devm_regulator_get_enable_optional(dev, "phy");
+ if (ret < 0 && ret != -ENODEV)
+ goto out_config_dt;
+
ethqos->serdes_phy = devm_phy_optional_get(dev, "serdes");
if (IS_ERR(ethqos->serdes_phy)) {
ret = PTR_ERR(ethqos->serdes_phy);
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
Add the MDC and MDIO pin functions for ethernet0 on sa8775p-ride.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
arch/arm64/boot/dts/qcom/sa8775p-ride.dts | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
index 7754788ea775..dbd9553aa5c7 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
+++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
@@ -370,6 +370,22 @@ &spi16 {
};
&tlmm {
+ ethernet0_default: ethernet0-default-state {
+ ethernet0_mdc: ethernet0-mdc-pins {
+ pins = "gpio8";
+ function = "emac0_mdc";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ ethernet0_mdio: ethernet0-mdio-pins {
+ pins = "gpio9";
+ function = "emac0_mdio";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+ };
+
qup_uart10_default: qup-uart10-state {
pins = "gpio46", "gpio47";
function = "qup1_se3";
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
On sa8775p we don't use the RGMII clock but have an additional PHYAUX
clock so add support for it to the driver.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
.../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 252dca400071..2f6b9b419601 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -94,6 +94,7 @@ struct qcom_ethqos {
unsigned int rgmii_clk_rate;
struct clk *rgmii_clk;
+ struct clk *phyaux_clk;
struct phy *serdes_phy;
unsigned int speed;
@@ -604,6 +605,13 @@ static int ethqos_clks_config(void *priv, bool enabled)
return ret;
}
+ ret = clk_prepare_enable(ethqos->phyaux_clk);
+ if (ret) {
+ clk_disable_unprepare(ethqos->rgmii_clk);
+ dev_err(ðqos->pdev->dev, "phyaux enable failed\n");
+ return ret;
+ }
+
/* Enable functional clock to prevent DMA reset to timeout due
* to lacking PHY clock after the hardware block has been power
* cycled. The actual configuration will be adjusted once
@@ -611,6 +619,7 @@ static int ethqos_clks_config(void *priv, bool enabled)
*/
ethqos_set_func_clk_en(ethqos);
} else {
+ clk_disable_unprepare(ethqos->phyaux_clk);
clk_disable_unprepare(ethqos->rgmii_clk);
}
@@ -669,6 +678,12 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
goto out_config_dt;
}
+ ethqos->phyaux_clk = devm_clk_get_optional(dev, "phyaux");
+ if (IS_ERR(ethqos->phyaux_clk)) {
+ ret = PTR_ERR(ethqos->phyaux_clk);
+ goto out_config_dt;
+ }
+
ret = ethqos_clks_config(ethqos, true);
if (ret)
goto out_config_dt;
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
Add the internal SGMII/SerDes PHY node for sa8775p platforms.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
arch/arm64/boot/dts/qcom/sa8775p.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
index b130136acffe..0e59000a0c82 100644
--- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
@@ -1837,6 +1837,15 @@ adreno_smmu: iommu@3da0000 {
<GIC_SPI 687 IRQ_TYPE_LEVEL_HIGH>;
};
+ serdes_phy: phy@8901000 {
+ compatible = "qcom,sa8775p-dwmac-sgmii-phy";
+ reg = <0 0x08901000 0 0xe10>;
+ clocks = <&gcc GCC_SGMI_CLKREF_EN>;
+ clock-names = "sgmi_ref";
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
pdc: interrupt-controller@b220000 {
compatible = "qcom,sa8775p-pdc", "qcom,pdc";
reg = <0x0 0x0b220000 0x0 0x30000>,
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
We can use a devm action to completely drop the remove callback and use
stmmac_pltfr_remove() directly for remove. We can also drop one of the
goto labels.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 24 +++++++++----------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index c801838fae2a..2da0738eed24 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -586,6 +586,11 @@ static int ethqos_clks_config(void *priv, bool enabled)
return ret;
}
+static void ethqos_clks_disable(void *data)
+{
+ ethqos_clks_config(data, false);
+}
+
static int qcom_ethqos_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -636,6 +641,10 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
if (ret)
goto err_mem;
+ ret = devm_add_action_or_reset(&pdev->dev, ethqos_clks_disable, ethqos);
+ if (ret)
+ goto err_mem;
+
ethqos->speed = SPEED_1000;
ethqos_update_rgmii_clk(ethqos, SPEED_1000);
ethqos_set_func_clk_en(ethqos);
@@ -653,27 +662,16 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (ret)
- goto err_clk;
+ goto err_mem;
return ret;
-err_clk:
- ethqos_clks_config(ethqos, false);
-
err_mem:
stmmac_remove_config_dt(pdev, plat_dat);
return ret;
}
-static void qcom_ethqos_remove(struct platform_device *pdev)
-{
- struct qcom_ethqos *ethqos = get_stmmac_bsp_priv(&pdev->dev);
-
- stmmac_pltfr_remove(pdev);
- ethqos_clks_config(ethqos, false);
-}
-
static const struct of_device_id qcom_ethqos_match[] = {
{ .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data},
{ .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data},
@@ -684,7 +682,7 @@ MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
static struct platform_driver qcom_ethqos_driver = {
.probe = qcom_ethqos_probe,
- .remove_new = qcom_ethqos_remove,
+ .remove_new = stmmac_pltfr_remove,
.driver = {
.name = "qcom-ethqos",
.pm = &stmmac_pltfr_pm_ops,
--
2.39.2
From: Bartosz Golaszewski <[email protected]>
Align all entries in Makefile.
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/phy/qualcomm/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
index de3dc9ccf067..5fb33628566b 100644
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -20,4 +20,4 @@ obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o
obj-$(CONFIG_PHY_QCOM_USB_SS) += phy-qcom-usb-ss.o
obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2)+= phy-qcom-snps-femto-v2.o
-obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o
+obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o
--
2.39.2
On 12.06.2023 11:23, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> Add the internal SGMII/SerDes PHY node for sa8775p platforms.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
> ---
> arch/arm64/boot/dts/qcom/sa8775p.dtsi | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/sa8775p.dtsi b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
> index b130136acffe..0e59000a0c82 100644
> --- a/arch/arm64/boot/dts/qcom/sa8775p.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sa8775p.dtsi
> @@ -1837,6 +1837,15 @@ adreno_smmu: iommu@3da0000 {
> <GIC_SPI 687 IRQ_TYPE_LEVEL_HIGH>;
> };
>
> + serdes_phy: phy@8901000 {
> + compatible = "qcom,sa8775p-dwmac-sgmii-phy";
> + reg = <0 0x08901000 0 0xe10>;
The usage of 0 is inconsistent with 0x0 everywhere else
Konrad
> + clocks = <&gcc GCC_SGMI_CLKREF_EN>;
> + clock-names = "sgmi_ref";
> + #phy-cells = <0>;
> + status = "disabled";
> + };
> +
> pdc: interrupt-controller@b220000 {
> compatible = "qcom,sa8775p-pdc", "qcom,pdc";
> reg = <0x0 0x0b220000 0x0 0x30000>,
On 12.06.2023 11:23, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> Implement support for the SGMII/SerDes PHY present on various Qualcomm
> platforms.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
> ---
> +static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = {
> + .reg_bits = 32,
> + .val_bits = 32,
> + .reg_stride = 4,
> + .use_relaxed_mmio = true,
> + .disable_locking = true,
The last two are rather brave, no?
Konrad
> +};
> +
> +static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
> +{
> + struct qcom_dwmac_sgmii_phy_data *data;
> + struct device *dev = &pdev->dev;
> + struct phy_provider *provider;
> + struct clk *refclk;
> + void __iomem *base;
> + struct phy *phy;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + data->regmap = devm_regmap_init_mmio(dev, base,
> + &qcom_dwmac_sgmii_phy_regmap_cfg);
> + if (IS_ERR(data->regmap))
> + return PTR_ERR(data->regmap);
> +
> + phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);
> + if (IS_ERR(phy))
> + return PTR_ERR(phy);
> +
> + refclk = devm_clk_get_enabled(dev, "sgmi_ref");
> + if (IS_ERR(refclk))
> + return PTR_ERR(refclk);
> +
> + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> + if (IS_ERR(provider))
> + return PTR_ERR(provider);
> +
> + phy_set_drvdata(phy, data);
> + platform_set_drvdata(pdev, data);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {
> + { .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);
> +
> +static struct platform_driver qcom_dwmac_sgmii_phy_driver = {
> + .probe = qcom_dwmac_sgmii_phy_probe,
> + .driver = {
> + .name = "qcom-dwmac-sgmii-phy",
> + .of_match_table = qcom_dwmac_sgmii_phy_of_match,
> + }
> +};
> +
> +module_platform_driver(qcom_dwmac_sgmii_phy_driver);
> +
> +MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");
> +MODULE_LICENSE("GPL");
On Mon, Jun 12, 2023 at 11:23:30AM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> Align all entries in Makefile.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
Reviewed-by: Andrew Halaney <[email protected]>
> ---
> drivers/phy/qualcomm/Makefile | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
> index de3dc9ccf067..5fb33628566b 100644
> --- a/drivers/phy/qualcomm/Makefile
> +++ b/drivers/phy/qualcomm/Makefile
> @@ -20,4 +20,4 @@ obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
> obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o
> obj-$(CONFIG_PHY_QCOM_USB_SS) += phy-qcom-usb-ss.o
> obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2)+= phy-qcom-snps-femto-v2.o
> -obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o
> +obj-$(CONFIG_PHY_QCOM_IPQ806X_USB) += phy-qcom-ipq806x-usb.o
> --
> 2.39.2
>
On Mon, Jun 12, 2023 at 11:23:34AM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> We can use a devm action to completely drop the remove callback and use
> stmmac_pltfr_remove() directly for remove. We can also drop one of the
> goto labels.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
I think using the remove callback seems more direct to a reader, but
that's pretty opinionated. The change itself looks good so:
Reviewed-by: Andrew Halaney <[email protected]>
> ---
> .../stmicro/stmmac/dwmac-qcom-ethqos.c | 24 +++++++++----------
> 1 file changed, 11 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> index c801838fae2a..2da0738eed24 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> @@ -586,6 +586,11 @@ static int ethqos_clks_config(void *priv, bool enabled)
> return ret;
> }
>
> +static void ethqos_clks_disable(void *data)
> +{
> + ethqos_clks_config(data, false);
> +}
> +
> static int qcom_ethqos_probe(struct platform_device *pdev)
> {
> struct device_node *np = pdev->dev.of_node;
> @@ -636,6 +641,10 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
> if (ret)
> goto err_mem;
>
> + ret = devm_add_action_or_reset(&pdev->dev, ethqos_clks_disable, ethqos);
> + if (ret)
> + goto err_mem;
> +
> ethqos->speed = SPEED_1000;
> ethqos_update_rgmii_clk(ethqos, SPEED_1000);
> ethqos_set_func_clk_en(ethqos);
> @@ -653,27 +662,16 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
>
> ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
> if (ret)
> - goto err_clk;
> + goto err_mem;
>
> return ret;
>
> -err_clk:
> - ethqos_clks_config(ethqos, false);
> -
> err_mem:
> stmmac_remove_config_dt(pdev, plat_dat);
>
> return ret;
> }
>
> -static void qcom_ethqos_remove(struct platform_device *pdev)
> -{
> - struct qcom_ethqos *ethqos = get_stmmac_bsp_priv(&pdev->dev);
> -
> - stmmac_pltfr_remove(pdev);
> - ethqos_clks_config(ethqos, false);
> -}
> -
> static const struct of_device_id qcom_ethqos_match[] = {
> { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data},
> { .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data},
> @@ -684,7 +682,7 @@ MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
>
> static struct platform_driver qcom_ethqos_driver = {
> .probe = qcom_ethqos_probe,
> - .remove_new = qcom_ethqos_remove,
> + .remove_new = stmmac_pltfr_remove,
> .driver = {
> .name = "qcom-ethqos",
> .pm = &stmmac_pltfr_pm_ops,
> --
> 2.39.2
>
On Mon, Jun 12, 2023 at 11:23:37AM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> Shrink code and avoid line breaks by using a helper variable for
> &pdev->dev.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
> ---
> .../stmicro/stmmac/dwmac-qcom-ethqos.c | 48 ++++++++++---------
> 1 file changed, 26 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> index 28d2514a8795..e19d142630d3 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> @@ -123,25 +123,26 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos,
> static void rgmii_dump(void *priv)
> {
> struct qcom_ethqos *ethqos = priv;
> + struct device *dev = ðqos->pdev->dev;
>
> - dev_dbg(ðqos->pdev->dev, "Rgmii register dump\n");
> - dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n",
> + dev_dbg(dev, "Rgmii register dump\n");
> + dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %x\n",
> rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG));
> - dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
> + dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
> rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG));
> - dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
> + dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
> rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG));
> - dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
> + dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
> rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2));
> - dev_dbg(ðqos->pdev->dev, "SDC4_STATUS: %x\n",
> + dev_dbg(dev, "SDC4_STATUS: %x\n",
> rgmii_readl(ethqos, SDC4_STATUS));
> - dev_dbg(ðqos->pdev->dev, "SDCC_USR_CTL: %x\n",
> + dev_dbg(dev, "SDCC_USR_CTL: %x\n",
> rgmii_readl(ethqos, SDCC_USR_CTL));
> - dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
> + dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
> rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2));
> - dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
> + dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
> rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1));
> - dev_dbg(ðqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
> + dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
> rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG));
> }
>
> @@ -242,6 +243,7 @@ static const struct ethqos_emac_driver_data emac_v3_0_0_data = {
>
> static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
> {
> + struct device *dev = ðqos->pdev->dev;
> unsigned int val;
> int retry = 1000;
>
> @@ -279,7 +281,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
> retry--;
> } while (retry > 0);
> if (!retry)
> - dev_err(ðqos->pdev->dev, "Clear CK_OUT_EN timedout\n");
> + dev_err(dev, "Clear CK_OUT_EN timedout\n");
>
> /* Set CK_OUT_EN */
> rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
> @@ -296,7 +298,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
> retry--;
> } while (retry > 0);
> if (!retry)
> - dev_err(ðqos->pdev->dev, "Set CK_OUT_EN timedout\n");
> + dev_err(dev, "Set CK_OUT_EN timedout\n");
>
> /* Set DDR_CAL_EN */
> rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN,
> @@ -322,12 +324,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
>
> static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
> {
> + struct device *dev = ðqos->pdev->dev;
> int phase_shift;
> int phy_mode;
> int loopback;
>
> /* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
> - phy_mode = device_get_phy_mode(ðqos->pdev->dev);
> + phy_mode = device_get_phy_mode(dev);
> if (phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
> phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
> phase_shift = 0;
> @@ -468,7 +471,7 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
> loopback, RGMII_IO_MACRO_CONFIG);
> break;
> default:
> - dev_err(ðqos->pdev->dev,
> + dev_err(dev,
> "Invalid speed %d\n", ethqos->speed);
nit: You could put this on the prior line now
With that in place, feel free to add:
Reviewed-by: Andrew Halaney <[email protected]>
On Mon, Jun 12, 2023 at 11:23:35AM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> The err_mem label's name is unclear. It actually should be reached on
> any error after stmmac_probe_config_dt() succeeds. Name it after the
> cleanup action that needs to be called before exiting.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
Reviewed-by: Andrew Halaney <[email protected]>
> ---
> .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> index 2da0738eed24..16e856861558 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> @@ -615,14 +615,14 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
> ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL);
> if (!ethqos) {
> ret = -ENOMEM;
> - goto err_mem;
> + goto out_config_dt;
> }
>
> ethqos->pdev = pdev;
> ethqos->rgmii_base = devm_platform_ioremap_resource_byname(pdev, "rgmii");
> if (IS_ERR(ethqos->rgmii_base)) {
> ret = PTR_ERR(ethqos->rgmii_base);
> - goto err_mem;
> + goto out_config_dt;
> }
>
> data = of_device_get_match_data(&pdev->dev);
> @@ -634,16 +634,16 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
> ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
> if (IS_ERR(ethqos->rgmii_clk)) {
> ret = PTR_ERR(ethqos->rgmii_clk);
> - goto err_mem;
> + goto out_config_dt;
> }
>
> ret = ethqos_clks_config(ethqos, true);
> if (ret)
> - goto err_mem;
> + goto out_config_dt;
>
> ret = devm_add_action_or_reset(&pdev->dev, ethqos_clks_disable, ethqos);
> if (ret)
> - goto err_mem;
> + goto out_config_dt;
>
> ethqos->speed = SPEED_1000;
> ethqos_update_rgmii_clk(ethqos, SPEED_1000);
> @@ -662,11 +662,11 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
>
> ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
> if (ret)
> - goto err_mem;
> + goto out_config_dt;
>
> return ret;
>
> -err_mem:
> +out_config_dt:
> stmmac_remove_config_dt(pdev, plat_dat);
>
> return ret;
> --
> 2.39.2
>
On Mon, Jun 12, 2023 at 11:23:40AM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> There's an unnecessary space in the rgmii_updatel() function, remove it.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
Reviewed-by: Andrew Halaney <[email protected]>
> ---
> drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> index 5b56abacbf6b..8ed05f29fe8b 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> @@ -117,7 +117,7 @@ static void rgmii_updatel(struct qcom_ethqos *ethqos,
> {
> unsigned int temp;
>
> - temp = rgmii_readl(ethqos, offset);
> + temp = rgmii_readl(ethqos, offset);
> temp = (temp & ~(mask)) | val;
> rgmii_writel(ethqos, temp, offset);
> }
> --
> 2.39.2
>
On Mon, Jun 12, 2023 at 11:23:42AM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> On sa8775p there's no RGMII clock so make it optional in the driver.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
> ---
> drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> index 3438b6229351..252dca400071 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> @@ -663,7 +663,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
> ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
> ethqos->has_emac3 = data->has_emac3;
>
> - ethqos->rgmii_clk = devm_clk_get(dev, "rgmii");
> + ethqos->rgmii_clk = devm_clk_get_optional(dev, "rgmii");
This makes it optional for older platforms too, but as far as I know on
those platforms it is mandatory.
This can be enforced in dt-binding checks, but should we also enforce
that in the driver still? Honestly I feel like yes, but there's probably
some precedent maintainers follow on this front that I don't know of.
> if (IS_ERR(ethqos->rgmii_clk)) {
> ret = PTR_ERR(ethqos->rgmii_clk);
> goto out_config_dt;
> --
> 2.39.2
>
On Mon, Jun 12, 2023 at 11:23:43AM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> On sa8775p we don't use the RGMII clock but have an additional PHYAUX
> clock so add support for it to the driver.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
> ---
> .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> index 252dca400071..2f6b9b419601 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> @@ -94,6 +94,7 @@ struct qcom_ethqos {
>
> unsigned int rgmii_clk_rate;
> struct clk *rgmii_clk;
> + struct clk *phyaux_clk;
> struct phy *serdes_phy;
> unsigned int speed;
>
> @@ -604,6 +605,13 @@ static int ethqos_clks_config(void *priv, bool enabled)
> return ret;
> }
>
> + ret = clk_prepare_enable(ethqos->phyaux_clk);
> + if (ret) {
> + clk_disable_unprepare(ethqos->rgmii_clk);
> + dev_err(ðqos->pdev->dev, "phyaux enable failed\n");
> + return ret;
> + }
> +
> /* Enable functional clock to prevent DMA reset to timeout due
> * to lacking PHY clock after the hardware block has been power
> * cycled. The actual configuration will be adjusted once
> @@ -611,6 +619,7 @@ static int ethqos_clks_config(void *priv, bool enabled)
> */
> ethqos_set_func_clk_en(ethqos);
> } else {
> + clk_disable_unprepare(ethqos->phyaux_clk);
> clk_disable_unprepare(ethqos->rgmii_clk);
> }
>
> @@ -669,6 +678,12 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
> goto out_config_dt;
> }
>
> + ethqos->phyaux_clk = devm_clk_get_optional(dev, "phyaux");
> + if (IS_ERR(ethqos->phyaux_clk)) {
> + ret = PTR_ERR(ethqos->phyaux_clk);
> + goto out_config_dt;
> + }
> +
Similar comment to the prior patch about whether or not this should be
optional (or selected via platform compatible and required),
otherwise looks good.
> ret = ethqos_clks_config(ethqos, true);
> if (ret)
> goto out_config_dt;
> --
> 2.39.2
>
On Mon, Jun 12, 2023 at 11:23:44AM +0200, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> On sa8775p-ride we need to enable the power supply for the external PHY.
Is this for the external phy? It doesn't seem like it from the board
schematic I have... the regulator never makes it out of the black box that
is the SIP/SOM if I'm reading right.
My (poor) understanding was this was for the serdes phy that's doing the
conversion to SGMII before hitting the board... good chance I'm wrong
though.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
> ---
> drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> index 2f6b9b419601..21f329d2f7eb 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> @@ -8,6 +8,7 @@
> #include <linux/phy.h>
> #include <linux/phy/phy.h>
> #include <linux/property.h>
> +#include <linux/regulator/consumer.h>
>
> #include "stmmac.h"
> #include "stmmac_platform.h"
> @@ -692,6 +693,10 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
> if (ret)
> goto out_config_dt;
>
> + ret = devm_regulator_get_enable_optional(dev, "phy");
> + if (ret < 0 && ret != -ENODEV)
> + goto out_config_dt;
> +
> ethqos->serdes_phy = devm_phy_optional_get(dev, "serdes");
> if (IS_ERR(ethqos->serdes_phy)) {
> ret = PTR_ERR(ethqos->serdes_phy);
> --
> 2.39.2
>
On Mon, Jun 12, 2023 at 10:40 PM Andrew Halaney <[email protected]> wrote:
>
> On Mon, Jun 12, 2023 at 11:23:42AM +0200, Bartosz Golaszewski wrote:
> > From: Bartosz Golaszewski <[email protected]>
> >
> > On sa8775p there's no RGMII clock so make it optional in the driver.
> >
> > Signed-off-by: Bartosz Golaszewski <[email protected]>
> > ---
> > drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> > index 3438b6229351..252dca400071 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> > @@ -663,7 +663,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
> > ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
> > ethqos->has_emac3 = data->has_emac3;
> >
> > - ethqos->rgmii_clk = devm_clk_get(dev, "rgmii");
> > + ethqos->rgmii_clk = devm_clk_get_optional(dev, "rgmii");
>
> This makes it optional for older platforms too, but as far as I know on
> those platforms it is mandatory.
>
> This can be enforced in dt-binding checks, but should we also enforce
> that in the driver still? Honestly I feel like yes, but there's probably
> some precedent maintainers follow on this front that I don't know of.
>
While my gut feeling is that enforcing the clock list on the DT
binding lever is enough, we can also do a different thing: rename the
clock from rgmii_clk to link_clk or something similar and just
determine the name based on the HW variant ("rgmii" or "phyaux"). Or
even get the clock by its index? this way we could fold the next patch
in the series into this one and simplify the code.
Bart
>
> > if (IS_ERR(ethqos->rgmii_clk)) {
> > ret = PTR_ERR(ethqos->rgmii_clk);
> > goto out_config_dt;
> > --
> > 2.39.2
> >
>
On Mon, Jun 12, 2023 at 11:06 PM Andrew Halaney <[email protected]> wrote:
>
> On Mon, Jun 12, 2023 at 11:23:44AM +0200, Bartosz Golaszewski wrote:
> > From: Bartosz Golaszewski <[email protected]>
> >
> > On sa8775p-ride we need to enable the power supply for the external PHY.
>
> Is this for the external phy? It doesn't seem like it from the board
> schematic I have... the regulator never makes it out of the black box that
> is the SIP/SOM if I'm reading right.
>
> My (poor) understanding was this was for the serdes phy that's doing the
> conversion to SGMII before hitting the board... good chance I'm wrong
> though.
>
No, you're right. In which case I think the regulator calls should be
moved into the serdes driver instead as phy-supply is defined as the
supply of the external PHY in stmmac bindings.
Bart
> >
> > Signed-off-by: Bartosz Golaszewski <[email protected]>
> > ---
> > drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 5 +++++
> > 1 file changed, 5 insertions(+)
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> > index 2f6b9b419601..21f329d2f7eb 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
> > @@ -8,6 +8,7 @@
> > #include <linux/phy.h>
> > #include <linux/phy/phy.h>
> > #include <linux/property.h>
> > +#include <linux/regulator/consumer.h>
> >
> > #include "stmmac.h"
> > #include "stmmac_platform.h"
> > @@ -692,6 +693,10 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
> > if (ret)
> > goto out_config_dt;
> >
> > + ret = devm_regulator_get_enable_optional(dev, "phy");
> > + if (ret < 0 && ret != -ENODEV)
> > + goto out_config_dt;
> > +
> > ethqos->serdes_phy = devm_phy_optional_get(dev, "serdes");
> > if (IS_ERR(ethqos->serdes_phy)) {
> > ret = PTR_ERR(ethqos->serdes_phy);
> > --
> > 2.39.2
> >
>
On Mon, Jun 12, 2023 at 11:23:32AM +0200, Bartosz Golaszewski wrote:
> diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
[..]
> +static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
> +{
> + struct qcom_dwmac_sgmii_phy_data *data;
> + struct device *dev = &pdev->dev;
> + struct phy_provider *provider;
> + struct clk *refclk;
> + void __iomem *base;
> + struct phy *phy;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(base))
> + return PTR_ERR(base);
> +
> + data->regmap = devm_regmap_init_mmio(dev, base,
> + &qcom_dwmac_sgmii_phy_regmap_cfg);
> + if (IS_ERR(data->regmap))
> + return PTR_ERR(data->regmap);
> +
> + phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);
> + if (IS_ERR(phy))
> + return PTR_ERR(phy);
> +
> + refclk = devm_clk_get_enabled(dev, "sgmi_ref");
> + if (IS_ERR(refclk))
> + return PTR_ERR(refclk);
> +
> + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> + if (IS_ERR(provider))
> + return PTR_ERR(provider);
> +
> + phy_set_drvdata(phy, data);
> + platform_set_drvdata(pdev, data);
You don't use the pdev's dev's drvdata, so I think you can drop the
platform_set_drvdata()
Regards,
Bjorn
> +
> + return 0;
> +}
On 12.06.2023 11:23, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> Add the MDC and MDIO pin functions for ethernet0 on sa8775p-ride.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
> ---
Reviewed-by: Konrad Dybcio <[email protected]>
Konrad
> arch/arm64/boot/dts/qcom/sa8775p-ride.dts | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
> index 7754788ea775..dbd9553aa5c7 100644
> --- a/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
> +++ b/arch/arm64/boot/dts/qcom/sa8775p-ride.dts
> @@ -370,6 +370,22 @@ &spi16 {
> };
>
> &tlmm {
> + ethernet0_default: ethernet0-default-state {
> + ethernet0_mdc: ethernet0-mdc-pins {
> + pins = "gpio8";
> + function = "emac0_mdc";
> + drive-strength = <16>;
> + bias-pull-up;
> + };
> +
> + ethernet0_mdio: ethernet0-mdio-pins {
> + pins = "gpio9";
> + function = "emac0_mdio";
> + drive-strength = <16>;
> + bias-pull-up;
> + };
> + };
> +
> qup_uart10_default: qup-uart10-state {
> pins = "gpio46", "gpio47";
> function = "qup1_se3";
On 12/06/2023 11:23, Bartosz Golaszewski wrote:
> From: Bartosz Golaszewski <[email protected]>
>
> Enable the SGMII/SerDes PHY driver. This module is required to enable
> ethernet on sa8775p platforms.
>
> Signed-off-by: Bartosz Golaszewski <[email protected]>
> ---
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Best regards,
Krzysztof
On Mon, Jun 12, 2023 at 11:45 AM Konrad Dybcio <[email protected]> wrote:
>
>
>
> On 12.06.2023 11:23, Bartosz Golaszewski wrote:
> > From: Bartosz Golaszewski <[email protected]>
> >
> > Implement support for the SGMII/SerDes PHY present on various Qualcomm
> > platforms.
> >
> > Signed-off-by: Bartosz Golaszewski <[email protected]>
> > ---
> > +static const struct regmap_config qcom_dwmac_sgmii_phy_regmap_cfg = {
> > + .reg_bits = 32,
> > + .val_bits = 32,
> > + .reg_stride = 4,
> > + .use_relaxed_mmio = true,
> > + .disable_locking = true,
> The last two are rather brave, no?
>
We don't need locking because all callbacks are already protected by
the phy subsystem with a mutex and I don't really see anything that
would make it dangerous to use relaxed semantics in this driver. It's
just basic configuration.
Bart
> Konrad
> > +};
> > +
> > +static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
> > +{
> > + struct qcom_dwmac_sgmii_phy_data *data;
> > + struct device *dev = &pdev->dev;
> > + struct phy_provider *provider;
> > + struct clk *refclk;
> > + void __iomem *base;
> > + struct phy *phy;
> > +
> > + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> > + if (!data)
> > + return -ENOMEM;
> > +
> > + base = devm_platform_ioremap_resource(pdev, 0);
> > + if (IS_ERR(base))
> > + return PTR_ERR(base);
> > +
> > + data->regmap = devm_regmap_init_mmio(dev, base,
> > + &qcom_dwmac_sgmii_phy_regmap_cfg);
> > + if (IS_ERR(data->regmap))
> > + return PTR_ERR(data->regmap);
> > +
> > + phy = devm_phy_create(dev, NULL, &qcom_dwmac_sgmii_phy_ops);
> > + if (IS_ERR(phy))
> > + return PTR_ERR(phy);
> > +
> > + refclk = devm_clk_get_enabled(dev, "sgmi_ref");
> > + if (IS_ERR(refclk))
> > + return PTR_ERR(refclk);
> > +
> > + provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> > + if (IS_ERR(provider))
> > + return PTR_ERR(provider);
> > +
> > + phy_set_drvdata(phy, data);
> > + platform_set_drvdata(pdev, data);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id qcom_dwmac_sgmii_phy_of_match[] = {
> > + { .compatible = "qcom,sa8775p-dwmac-sgmii-phy" },
> > + { },
> > +};
> > +MODULE_DEVICE_TABLE(of, qcom_dwmac_sgmii_phy_of_match);
> > +
> > +static struct platform_driver qcom_dwmac_sgmii_phy_driver = {
> > + .probe = qcom_dwmac_sgmii_phy_probe,
> > + .driver = {
> > + .name = "qcom-dwmac-sgmii-phy",
> > + .of_match_table = qcom_dwmac_sgmii_phy_of_match,
> > + }
> > +};
> > +
> > +module_platform_driver(qcom_dwmac_sgmii_phy_driver);
> > +
> > +MODULE_DESCRIPTION("Qualcomm DWMAC SGMII PHY driver");
> > +MODULE_LICENSE("GPL");