Loading drivers/net/ethernet/stmicro/stmmac/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-gpio.o obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o Loading drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +92 −79 Original line number Diff line number Diff line Loading @@ -6,16 +6,12 @@ #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/phy.h> #include <linux/regulator/consumer.h> #include "stmmac.h" #include "stmmac_platform.h" #include "dwmac-qcom-ethqos.h" #define RGMII_IO_MACRO_CONFIG 0x0 #define SDCC_HC_REG_DLL_CONFIG 0x4 #define SDCC_HC_REG_DDR_CONFIG 0xC #define SDCC_HC_REG_DLL_CONFIG2 0x10 #define SDC4_STATUS 0x14 #define SDCC_USR_CTL 0x18 #define RGMII_IO_MACRO_CONFIG2 0x1C #define RGMII_IO_MACRO_DEBUG1 0x20 #define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28 Loading Loading @@ -70,27 +66,8 @@ #define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6) #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5) struct ethqos_emac_por { unsigned int offset; unsigned int value; }; struct ethqos_emac_driver_data { const struct ethqos_emac_por *por; unsigned int num_por; }; struct qcom_ethqos { struct platform_device *pdev; void __iomem *rgmii_base; unsigned int rgmii_clk_rate; struct clk *rgmii_clk; unsigned int speed; const struct ethqos_emac_por *por; unsigned int num_por; }; #define EMAC_I0_EMAC_CORE_HW_VERSION_RGOFFADDR 0x00000070 #define EMAC_HW_v2_3_2_RG 0x20030002 static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) { Loading Loading @@ -167,26 +144,16 @@ static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG); } static const struct ethqos_emac_por emac_v2_3_0_por[] = { { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 }, { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 }, { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, { .offset = SDCC_USR_CTL, .value = 0x00010800 }, { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, }; static const struct ethqos_emac_driver_data emac_v2_3_0_data = { .por = emac_v2_3_0_por, .num_por = ARRAY_SIZE(emac_v2_3_0_por), }; static int ethqos_dll_configure(struct qcom_ethqos *ethqos) { unsigned int val; int retry = 1000; /* Set CDR_EN */ if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN, 0, SDCC_HC_REG_DLL_CONFIG); else rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN, SDCC_DLL_CONFIG_CDR_EN, SDCC_HC_REG_DLL_CONFIG); Loading @@ -202,12 +169,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN, SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG); if (ethqos->emac_ver != EMAC_HW_v2_3_2_RG) { rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN, 0, SDCC_HC_REG_DLL_CONFIG); rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE, 0, SDCC_HC_REG_DLL_CONFIG); } /* Wait for CK_OUT_EN clear */ do { val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); Loading Loading @@ -241,6 +209,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2); if (ethqos->emac_ver != EMAC_HW_v2_3_2_RG) { rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS, 0, SDCC_HC_REG_DLL_CONFIG2); Loading @@ -253,6 +222,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, SDCC_HC_REG_DLL_CONFIG2); } return 0; } Loading Loading @@ -290,13 +260,22 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) RGMII_IO_MACRO_CONFIG2); /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */ if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, 69, SDCC_HC_REG_DDR_CONFIG); else rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, 57, SDCC_HC_REG_DDR_CONFIG); rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, SDCC_DDR_CONFIG_PRG_DLY_EN, SDCC_HC_REG_DDR_CONFIG); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, 0, RGMII_IO_MACRO_CONFIG); else rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); break; case SPEED_100: Loading @@ -318,6 +297,11 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) BIT(6), RGMII_IO_MACRO_CONFIG); rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 0, RGMII_IO_MACRO_CONFIG2); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); else rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, 0, RGMII_IO_MACRO_CONFIG2); /* Write 0x5 to PRG_RCLK_DLY_CODE */ Loading @@ -329,8 +313,13 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_HC_REG_DDR_CONFIG); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, 0, RGMII_IO_MACRO_CONFIG); else rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); break; case SPEED_10: Loading @@ -345,13 +334,25 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) 0, RGMII_IO_MACRO_CONFIG); rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, 0, RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, RGMII_IO_MACRO_CONFIG2); else rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 0, RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, BIT(12) | GENMASK(9, 8), RGMII_IO_MACRO_CONFIG); rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 0, RGMII_IO_MACRO_CONFIG2); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); else rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, 0, RGMII_IO_MACRO_CONFIG2); /* Write 0x5 to PRG_RCLK_DLY_CODE */ Loading @@ -363,8 +364,13 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_HC_REG_DDR_CONFIG); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, 0, RGMII_IO_MACRO_CONFIG); else rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); break; default: dev_err(ðqos->pdev->dev, Loading Loading @@ -461,19 +467,21 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (ret) return ret; ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL); if (!ethqos) { ret = -ENOMEM; goto err_mem; } ethqos->pdev = pdev; ethqos_init_reqgulators(ethqos); plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); if (IS_ERR(plat_dat)) { dev_err(&pdev->dev, "dt configuration failed\n"); return PTR_ERR(plat_dat); } ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL); if (!ethqos) { ret = -ENOMEM; goto err_mem; } ethqos->pdev = pdev; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rgmii"); ethqos->rgmii_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(ethqos->rgmii_base)) { Loading Loading @@ -510,6 +518,9 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (ret) goto err_clk; ethqos->emac_ver = rgmii_readl(ethqos, EMAC_I0_EMAC_CORE_HW_VERSION_RGOFFADDR); rgmii_dump(ethqos); return ret; Loading @@ -534,12 +545,14 @@ static int qcom_ethqos_remove(struct platform_device *pdev) ret = stmmac_pltfr_remove(pdev); clk_disable_unprepare(ethqos->rgmii_clk); ethqos_disable_regulators(ethqos); return ret; } static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data}, { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_por}, { .compatible = "qcom,sdxprairie-ethqos", .data = &emac_v2_3_2_por}, { } }; MODULE_DEVICE_TABLE(of, qcom_ethqos_match); Loading drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h 0 → 100644 +66 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #ifndef _DWMAC_QCOM_ETHQOS_H #define _DWMAC_QCOM_ETHQOS_H #define DRV_NAME "qcom-ethqos" #define ETHQOSDBG(fmt, args...) \ pr_debug(DRV_NAME " %s:%d " fmt, __func__, ## args) #define ETHQOSERR(fmt, args...) \ pr_err(DRV_NAME " %s:%d " fmt, __func__, ## args) #define ETHQOSINFO(fmt, args...) \ pr_info(DRV_NAME " %s:%d " fmt, __func__, ## args) #define RGMII_IO_MACRO_CONFIG 0x0 #define SDCC_HC_REG_DLL_CONFIG 0x4 #define SDCC_HC_REG_DDR_CONFIG 0xC #define SDCC_HC_REG_DLL_CONFIG2 0x10 #define SDC4_STATUS 0x14 #define SDCC_USR_CTL 0x18 #define RGMII_IO_MACRO_CONFIG2 0x1C struct ethqos_emac_por { unsigned int offset; unsigned int value; }; static const struct ethqos_emac_por emac_v2_3_0_por[] = { { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 }, { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 }, { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, { .offset = SDCC_USR_CTL, .value = 0x00010800 }, { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, }; static const struct ethqos_emac_por emac_v2_3_2_por[] = { { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 }, { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x80040800 }, { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, { .offset = SDCC_USR_CTL, .value = 0x00010800 }, { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, }; struct qcom_ethqos { struct platform_device *pdev; void __iomem *rgmii_base; unsigned int rgmii_clk_rate; struct clk *rgmii_clk; unsigned int speed; const struct ethqos_emac_por *por; unsigned int num_por; unsigned int emac_ver; struct regulator *gdsc_emac; struct regulator *reg_rgmii; struct regulator *reg_emac_phy; struct regulator *reg_rgmii_io_pads; }; int ethqos_init_reqgulators(struct qcom_ethqos *ethqos); void ethqos_disable_regulators(struct qcom_ethqos *ethqos); #endif drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-gpio.c 0 → 100644 +129 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/phy.h> #include <linux/regulator/consumer.h> #include "stmmac.h" #include "dwmac-qcom-ethqos.h" #define EMAC_GDSC_EMAC_NAME "gdsc_emac" #define EMAC_VREG_RGMII_NAME "vreg_rgmii" #define EMAC_VREG_EMAC_PHY_NAME "vreg_emac_phy" #define EMAC_VREG_RGMII_IO_PADS_NAME "vreg_rgmii_io_pads" int ethqos_init_reqgulators(struct qcom_ethqos *ethqos) { int ret = 0; if (of_property_read_bool(ethqos->pdev->dev.of_node, "gdsc_emac-supply")) { ethqos->gdsc_emac = devm_regulator_get(ðqos->pdev->dev, EMAC_GDSC_EMAC_NAME); if (IS_ERR(ethqos->gdsc_emac)) { ETHQOSERR("Can not get <%s>\n", EMAC_GDSC_EMAC_NAME); return PTR_ERR(ethqos->gdsc_emac); } ret = regulator_enable(ethqos->gdsc_emac); if (ret) { ETHQOSERR("Can not enable <%s>\n", EMAC_GDSC_EMAC_NAME); goto reg_error; } ETHQOSDBG("Enabled <%s>\n", EMAC_GDSC_EMAC_NAME); } if (of_property_read_bool(ethqos->pdev->dev.of_node, "vreg_rgmii-supply")) { ethqos->reg_rgmii = devm_regulator_get(ðqos->pdev->dev, EMAC_VREG_RGMII_NAME); if (IS_ERR(ethqos->reg_rgmii)) { ETHQOSERR("Can not get <%s>\n", EMAC_VREG_RGMII_NAME); return PTR_ERR(ethqos->reg_rgmii); } ret = regulator_enable(ethqos->reg_rgmii); if (ret) { ETHQOSERR("Can not enable <%s>\n", EMAC_VREG_RGMII_NAME); goto reg_error; } ETHQOSDBG("Enabled <%s>\n", EMAC_VREG_RGMII_NAME); } if (of_property_read_bool(ethqos->pdev->dev.of_node, "vreg_emac_phy-supply")) { ethqos->reg_emac_phy = devm_regulator_get(ðqos->pdev->dev, EMAC_VREG_EMAC_PHY_NAME); if (IS_ERR(ethqos->reg_emac_phy)) { ETHQOSERR("Can not get <%s>\n", EMAC_VREG_EMAC_PHY_NAME); return PTR_ERR(ethqos->reg_emac_phy); } ret = regulator_enable(ethqos->reg_emac_phy); if (ret) { ETHQOSERR("Can not enable <%s>\n", EMAC_VREG_EMAC_PHY_NAME); goto reg_error; } ETHQOSDBG("Enabled <%s>\n", EMAC_VREG_EMAC_PHY_NAME); } if (of_property_read_bool(ethqos->pdev->dev.of_node, "vreg_rgmii_io_pads-supply")) { ethqos->reg_rgmii_io_pads = devm_regulator_get (ðqos->pdev->dev, EMAC_VREG_RGMII_IO_PADS_NAME); if (IS_ERR(ethqos->reg_rgmii_io_pads)) { ETHQOSERR("Can not get <%s>\n", EMAC_VREG_RGMII_IO_PADS_NAME); return PTR_ERR(ethqos->reg_rgmii_io_pads); } ret = regulator_enable(ethqos->reg_rgmii_io_pads); if (ret) { ETHQOSERR("Can not enable <%s>\n", EMAC_VREG_RGMII_IO_PADS_NAME); goto reg_error; } ETHQOSDBG("Enabled <%s>\n", EMAC_VREG_RGMII_IO_PADS_NAME); } return ret; reg_error: ETHQOSERR("%s failed\n", __func__); ethqos_disable_regulators(ethqos); return ret; } void ethqos_disable_regulators(struct qcom_ethqos *ethqos) { if (ethqos->reg_rgmii) { regulator_disable(ethqos->reg_rgmii); ethqos->reg_rgmii = NULL; } if (ethqos->reg_emac_phy) { regulator_disable(ethqos->reg_emac_phy); ethqos->reg_emac_phy = NULL; } if (ethqos->reg_rgmii_io_pads) { regulator_disable(ethqos->reg_rgmii_io_pads); ethqos->reg_rgmii_io_pads = NULL; } if (ethqos->gdsc_emac) { regulator_disable(ethqos->gdsc_emac); ethqos->gdsc_emac = NULL; } } Loading
drivers/net/ethernet/stmicro/stmmac/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-gpio.o obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o Loading
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +92 −79 Original line number Diff line number Diff line Loading @@ -6,16 +6,12 @@ #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/phy.h> #include <linux/regulator/consumer.h> #include "stmmac.h" #include "stmmac_platform.h" #include "dwmac-qcom-ethqos.h" #define RGMII_IO_MACRO_CONFIG 0x0 #define SDCC_HC_REG_DLL_CONFIG 0x4 #define SDCC_HC_REG_DDR_CONFIG 0xC #define SDCC_HC_REG_DLL_CONFIG2 0x10 #define SDC4_STATUS 0x14 #define SDCC_USR_CTL 0x18 #define RGMII_IO_MACRO_CONFIG2 0x1C #define RGMII_IO_MACRO_DEBUG1 0x20 #define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28 Loading Loading @@ -70,27 +66,8 @@ #define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6) #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5) struct ethqos_emac_por { unsigned int offset; unsigned int value; }; struct ethqos_emac_driver_data { const struct ethqos_emac_por *por; unsigned int num_por; }; struct qcom_ethqos { struct platform_device *pdev; void __iomem *rgmii_base; unsigned int rgmii_clk_rate; struct clk *rgmii_clk; unsigned int speed; const struct ethqos_emac_por *por; unsigned int num_por; }; #define EMAC_I0_EMAC_CORE_HW_VERSION_RGOFFADDR 0x00000070 #define EMAC_HW_v2_3_2_RG 0x20030002 static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) { Loading Loading @@ -167,26 +144,16 @@ static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG); } static const struct ethqos_emac_por emac_v2_3_0_por[] = { { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 }, { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 }, { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, { .offset = SDCC_USR_CTL, .value = 0x00010800 }, { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, }; static const struct ethqos_emac_driver_data emac_v2_3_0_data = { .por = emac_v2_3_0_por, .num_por = ARRAY_SIZE(emac_v2_3_0_por), }; static int ethqos_dll_configure(struct qcom_ethqos *ethqos) { unsigned int val; int retry = 1000; /* Set CDR_EN */ if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN, 0, SDCC_HC_REG_DLL_CONFIG); else rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN, SDCC_DLL_CONFIG_CDR_EN, SDCC_HC_REG_DLL_CONFIG); Loading @@ -202,12 +169,13 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN, SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG); if (ethqos->emac_ver != EMAC_HW_v2_3_2_RG) { rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN, 0, SDCC_HC_REG_DLL_CONFIG); rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE, 0, SDCC_HC_REG_DLL_CONFIG); } /* Wait for CK_OUT_EN clear */ do { val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); Loading Loading @@ -241,6 +209,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2); if (ethqos->emac_ver != EMAC_HW_v2_3_2_RG) { rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS, 0, SDCC_HC_REG_DLL_CONFIG2); Loading @@ -253,6 +222,7 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, SDCC_HC_REG_DLL_CONFIG2); } return 0; } Loading Loading @@ -290,13 +260,22 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) RGMII_IO_MACRO_CONFIG2); /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */ if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, 69, SDCC_HC_REG_DDR_CONFIG); else rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, 57, SDCC_HC_REG_DDR_CONFIG); rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, SDCC_DDR_CONFIG_PRG_DLY_EN, SDCC_HC_REG_DDR_CONFIG); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, 0, RGMII_IO_MACRO_CONFIG); else rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); break; case SPEED_100: Loading @@ -318,6 +297,11 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) BIT(6), RGMII_IO_MACRO_CONFIG); rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 0, RGMII_IO_MACRO_CONFIG2); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); else rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, 0, RGMII_IO_MACRO_CONFIG2); /* Write 0x5 to PRG_RCLK_DLY_CODE */ Loading @@ -329,8 +313,13 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_HC_REG_DDR_CONFIG); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, 0, RGMII_IO_MACRO_CONFIG); else rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); break; case SPEED_10: Loading @@ -345,13 +334,25 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) 0, RGMII_IO_MACRO_CONFIG); rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, 0, RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, RGMII_IO_MACRO_CONFIG2); else rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 0, RGMII_IO_MACRO_CONFIG2); rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, BIT(12) | GENMASK(9, 8), RGMII_IO_MACRO_CONFIG); rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 0, RGMII_IO_MACRO_CONFIG2); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_CONFIG2_RX_PROG_SWAP, RGMII_IO_MACRO_CONFIG2); else rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, 0, RGMII_IO_MACRO_CONFIG2); /* Write 0x5 to PRG_RCLK_DLY_CODE */ Loading @@ -363,8 +364,13 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, SDCC_HC_REG_DDR_CONFIG); if (ethqos->emac_ver == EMAC_HW_v2_3_2_RG) rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, 0, RGMII_IO_MACRO_CONFIG); else rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); break; default: dev_err(ðqos->pdev->dev, Loading Loading @@ -461,19 +467,21 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (ret) return ret; ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL); if (!ethqos) { ret = -ENOMEM; goto err_mem; } ethqos->pdev = pdev; ethqos_init_reqgulators(ethqos); plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); if (IS_ERR(plat_dat)) { dev_err(&pdev->dev, "dt configuration failed\n"); return PTR_ERR(plat_dat); } ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL); if (!ethqos) { ret = -ENOMEM; goto err_mem; } ethqos->pdev = pdev; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rgmii"); ethqos->rgmii_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(ethqos->rgmii_base)) { Loading Loading @@ -510,6 +518,9 @@ static int qcom_ethqos_probe(struct platform_device *pdev) if (ret) goto err_clk; ethqos->emac_ver = rgmii_readl(ethqos, EMAC_I0_EMAC_CORE_HW_VERSION_RGOFFADDR); rgmii_dump(ethqos); return ret; Loading @@ -534,12 +545,14 @@ static int qcom_ethqos_remove(struct platform_device *pdev) ret = stmmac_pltfr_remove(pdev); clk_disable_unprepare(ethqos->rgmii_clk); ethqos_disable_regulators(ethqos); return ret; } static const struct of_device_id qcom_ethqos_match[] = { { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data}, { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_por}, { .compatible = "qcom,sdxprairie-ethqos", .data = &emac_v2_3_2_por}, { } }; MODULE_DEVICE_TABLE(of, qcom_ethqos_match); Loading
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h 0 → 100644 +66 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #ifndef _DWMAC_QCOM_ETHQOS_H #define _DWMAC_QCOM_ETHQOS_H #define DRV_NAME "qcom-ethqos" #define ETHQOSDBG(fmt, args...) \ pr_debug(DRV_NAME " %s:%d " fmt, __func__, ## args) #define ETHQOSERR(fmt, args...) \ pr_err(DRV_NAME " %s:%d " fmt, __func__, ## args) #define ETHQOSINFO(fmt, args...) \ pr_info(DRV_NAME " %s:%d " fmt, __func__, ## args) #define RGMII_IO_MACRO_CONFIG 0x0 #define SDCC_HC_REG_DLL_CONFIG 0x4 #define SDCC_HC_REG_DDR_CONFIG 0xC #define SDCC_HC_REG_DLL_CONFIG2 0x10 #define SDC4_STATUS 0x14 #define SDCC_USR_CTL 0x18 #define RGMII_IO_MACRO_CONFIG2 0x1C struct ethqos_emac_por { unsigned int offset; unsigned int value; }; static const struct ethqos_emac_por emac_v2_3_0_por[] = { { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 }, { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 }, { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, { .offset = SDCC_USR_CTL, .value = 0x00010800 }, { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, }; static const struct ethqos_emac_por emac_v2_3_2_por[] = { { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 }, { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x80040800 }, { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, { .offset = SDCC_USR_CTL, .value = 0x00010800 }, { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, }; struct qcom_ethqos { struct platform_device *pdev; void __iomem *rgmii_base; unsigned int rgmii_clk_rate; struct clk *rgmii_clk; unsigned int speed; const struct ethqos_emac_por *por; unsigned int num_por; unsigned int emac_ver; struct regulator *gdsc_emac; struct regulator *reg_rgmii; struct regulator *reg_emac_phy; struct regulator *reg_rgmii_io_pads; }; int ethqos_init_reqgulators(struct qcom_ethqos *ethqos); void ethqos_disable_regulators(struct qcom_ethqos *ethqos); #endif
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-gpio.c 0 → 100644 +129 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/phy.h> #include <linux/regulator/consumer.h> #include "stmmac.h" #include "dwmac-qcom-ethqos.h" #define EMAC_GDSC_EMAC_NAME "gdsc_emac" #define EMAC_VREG_RGMII_NAME "vreg_rgmii" #define EMAC_VREG_EMAC_PHY_NAME "vreg_emac_phy" #define EMAC_VREG_RGMII_IO_PADS_NAME "vreg_rgmii_io_pads" int ethqos_init_reqgulators(struct qcom_ethqos *ethqos) { int ret = 0; if (of_property_read_bool(ethqos->pdev->dev.of_node, "gdsc_emac-supply")) { ethqos->gdsc_emac = devm_regulator_get(ðqos->pdev->dev, EMAC_GDSC_EMAC_NAME); if (IS_ERR(ethqos->gdsc_emac)) { ETHQOSERR("Can not get <%s>\n", EMAC_GDSC_EMAC_NAME); return PTR_ERR(ethqos->gdsc_emac); } ret = regulator_enable(ethqos->gdsc_emac); if (ret) { ETHQOSERR("Can not enable <%s>\n", EMAC_GDSC_EMAC_NAME); goto reg_error; } ETHQOSDBG("Enabled <%s>\n", EMAC_GDSC_EMAC_NAME); } if (of_property_read_bool(ethqos->pdev->dev.of_node, "vreg_rgmii-supply")) { ethqos->reg_rgmii = devm_regulator_get(ðqos->pdev->dev, EMAC_VREG_RGMII_NAME); if (IS_ERR(ethqos->reg_rgmii)) { ETHQOSERR("Can not get <%s>\n", EMAC_VREG_RGMII_NAME); return PTR_ERR(ethqos->reg_rgmii); } ret = regulator_enable(ethqos->reg_rgmii); if (ret) { ETHQOSERR("Can not enable <%s>\n", EMAC_VREG_RGMII_NAME); goto reg_error; } ETHQOSDBG("Enabled <%s>\n", EMAC_VREG_RGMII_NAME); } if (of_property_read_bool(ethqos->pdev->dev.of_node, "vreg_emac_phy-supply")) { ethqos->reg_emac_phy = devm_regulator_get(ðqos->pdev->dev, EMAC_VREG_EMAC_PHY_NAME); if (IS_ERR(ethqos->reg_emac_phy)) { ETHQOSERR("Can not get <%s>\n", EMAC_VREG_EMAC_PHY_NAME); return PTR_ERR(ethqos->reg_emac_phy); } ret = regulator_enable(ethqos->reg_emac_phy); if (ret) { ETHQOSERR("Can not enable <%s>\n", EMAC_VREG_EMAC_PHY_NAME); goto reg_error; } ETHQOSDBG("Enabled <%s>\n", EMAC_VREG_EMAC_PHY_NAME); } if (of_property_read_bool(ethqos->pdev->dev.of_node, "vreg_rgmii_io_pads-supply")) { ethqos->reg_rgmii_io_pads = devm_regulator_get (ðqos->pdev->dev, EMAC_VREG_RGMII_IO_PADS_NAME); if (IS_ERR(ethqos->reg_rgmii_io_pads)) { ETHQOSERR("Can not get <%s>\n", EMAC_VREG_RGMII_IO_PADS_NAME); return PTR_ERR(ethqos->reg_rgmii_io_pads); } ret = regulator_enable(ethqos->reg_rgmii_io_pads); if (ret) { ETHQOSERR("Can not enable <%s>\n", EMAC_VREG_RGMII_IO_PADS_NAME); goto reg_error; } ETHQOSDBG("Enabled <%s>\n", EMAC_VREG_RGMII_IO_PADS_NAME); } return ret; reg_error: ETHQOSERR("%s failed\n", __func__); ethqos_disable_regulators(ethqos); return ret; } void ethqos_disable_regulators(struct qcom_ethqos *ethqos) { if (ethqos->reg_rgmii) { regulator_disable(ethqos->reg_rgmii); ethqos->reg_rgmii = NULL; } if (ethqos->reg_emac_phy) { regulator_disable(ethqos->reg_emac_phy); ethqos->reg_emac_phy = NULL; } if (ethqos->reg_rgmii_io_pads) { regulator_disable(ethqos->reg_rgmii_io_pads); ethqos->reg_rgmii_io_pads = NULL; } if (ethqos->gdsc_emac) { regulator_disable(ethqos->gdsc_emac); ethqos->gdsc_emac = NULL; } }