18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// Copyright (c) 2018-19, Linaro Limited 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/module.h> 58c2ecf20Sopenharmony_ci#include <linux/of.h> 68c2ecf20Sopenharmony_ci#include <linux/of_device.h> 78c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 88c2ecf20Sopenharmony_ci#include <linux/phy.h> 98c2ecf20Sopenharmony_ci#include "stmmac.h" 108c2ecf20Sopenharmony_ci#include "stmmac_platform.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define RGMII_IO_MACRO_CONFIG 0x0 138c2ecf20Sopenharmony_ci#define SDCC_HC_REG_DLL_CONFIG 0x4 148c2ecf20Sopenharmony_ci#define SDCC_HC_REG_DDR_CONFIG 0xC 158c2ecf20Sopenharmony_ci#define SDCC_HC_REG_DLL_CONFIG2 0x10 168c2ecf20Sopenharmony_ci#define SDC4_STATUS 0x14 178c2ecf20Sopenharmony_ci#define SDCC_USR_CTL 0x18 188c2ecf20Sopenharmony_ci#define RGMII_IO_MACRO_CONFIG2 0x1C 198c2ecf20Sopenharmony_ci#define RGMII_IO_MACRO_DEBUG1 0x20 208c2ecf20Sopenharmony_ci#define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* RGMII_IO_MACRO_CONFIG fields */ 238c2ecf20Sopenharmony_ci#define RGMII_CONFIG_FUNC_CLK_EN BIT(30) 248c2ecf20Sopenharmony_ci#define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23) 258c2ecf20Sopenharmony_ci#define RGMII_CONFIG_GPIO_CFG_RX_INT GENMASK(21, 20) 268c2ecf20Sopenharmony_ci#define RGMII_CONFIG_GPIO_CFG_TX_INT GENMASK(19, 17) 278c2ecf20Sopenharmony_ci#define RGMII_CONFIG_MAX_SPD_PRG_9 GENMASK(16, 8) 288c2ecf20Sopenharmony_ci#define RGMII_CONFIG_MAX_SPD_PRG_2 GENMASK(7, 6) 298c2ecf20Sopenharmony_ci#define RGMII_CONFIG_INTF_SEL GENMASK(5, 4) 308c2ecf20Sopenharmony_ci#define RGMII_CONFIG_BYPASS_TX_ID_EN BIT(3) 318c2ecf20Sopenharmony_ci#define RGMII_CONFIG_LOOPBACK_EN BIT(2) 328c2ecf20Sopenharmony_ci#define RGMII_CONFIG_PROG_SWAP BIT(1) 338c2ecf20Sopenharmony_ci#define RGMII_CONFIG_DDR_MODE BIT(0) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* SDCC_HC_REG_DLL_CONFIG fields */ 368c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG_DLL_RST BIT(30) 378c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG_PDN BIT(29) 388c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG_MCLK_FREQ GENMASK(26, 24) 398c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG_CDR_SELEXT GENMASK(23, 20) 408c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG_CDR_EXT_EN BIT(19) 418c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG_CK_OUT_EN BIT(18) 428c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG_CDR_EN BIT(17) 438c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG_DLL_EN BIT(16) 448c2ecf20Sopenharmony_ci#define SDCC_DLL_MCLK_GATING_EN BIT(5) 458c2ecf20Sopenharmony_ci#define SDCC_DLL_CDR_FINE_PHASE GENMASK(3, 2) 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci/* SDCC_HC_REG_DDR_CONFIG fields */ 488c2ecf20Sopenharmony_ci#define SDCC_DDR_CONFIG_PRG_DLY_EN BIT(31) 498c2ecf20Sopenharmony_ci#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21) 508c2ecf20Sopenharmony_ci#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27) 518c2ecf20Sopenharmony_ci#define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30) 528c2ecf20Sopenharmony_ci#define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* SDCC_HC_REG_DLL_CONFIG2 fields */ 558c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS BIT(21) 568c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC GENMASK(17, 10) 578c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL GENMASK(3, 2) 588c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW BIT(1) 598c2ecf20Sopenharmony_ci#define SDCC_DLL_CONFIG2_DDR_CAL_EN BIT(0) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* SDC4_STATUS bits */ 628c2ecf20Sopenharmony_ci#define SDC4_STATUS_DLL_LOCK BIT(7) 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* RGMII_IO_MACRO_CONFIG2 fields */ 658c2ecf20Sopenharmony_ci#define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17) 668c2ecf20Sopenharmony_ci#define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16) 678c2ecf20Sopenharmony_ci#define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN BIT(13) 688c2ecf20Sopenharmony_ci#define RGMII_CONFIG2_CLK_DIVIDE_SEL BIT(12) 698c2ecf20Sopenharmony_ci#define RGMII_CONFIG2_RX_PROG_SWAP BIT(7) 708c2ecf20Sopenharmony_ci#define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6) 718c2ecf20Sopenharmony_ci#define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5) 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistruct ethqos_emac_por { 748c2ecf20Sopenharmony_ci unsigned int offset; 758c2ecf20Sopenharmony_ci unsigned int value; 768c2ecf20Sopenharmony_ci}; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistruct ethqos_emac_driver_data { 798c2ecf20Sopenharmony_ci const struct ethqos_emac_por *por; 808c2ecf20Sopenharmony_ci unsigned int num_por; 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistruct qcom_ethqos { 848c2ecf20Sopenharmony_ci struct platform_device *pdev; 858c2ecf20Sopenharmony_ci void __iomem *rgmii_base; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci unsigned int rgmii_clk_rate; 888c2ecf20Sopenharmony_ci struct clk *rgmii_clk; 898c2ecf20Sopenharmony_ci unsigned int speed; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci const struct ethqos_emac_por *por; 928c2ecf20Sopenharmony_ci unsigned int num_por; 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci return readl(ethqos->rgmii_base + offset); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic void rgmii_writel(struct qcom_ethqos *ethqos, 1018c2ecf20Sopenharmony_ci int value, unsigned int offset) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci writel(value, ethqos->rgmii_base + offset); 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic void rgmii_updatel(struct qcom_ethqos *ethqos, 1078c2ecf20Sopenharmony_ci int mask, int val, unsigned int offset) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci unsigned int temp; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci temp = rgmii_readl(ethqos, offset); 1128c2ecf20Sopenharmony_ci temp = (temp & ~(mask)) | val; 1138c2ecf20Sopenharmony_ci rgmii_writel(ethqos, temp, offset); 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic void rgmii_dump(struct qcom_ethqos *ethqos) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "Rgmii register dump\n"); 1198c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n", 1208c2ecf20Sopenharmony_ci rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG)); 1218c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n", 1228c2ecf20Sopenharmony_ci rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG)); 1238c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n", 1248c2ecf20Sopenharmony_ci rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG)); 1258c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n", 1268c2ecf20Sopenharmony_ci rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2)); 1278c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "SDC4_STATUS: %x\n", 1288c2ecf20Sopenharmony_ci rgmii_readl(ethqos, SDC4_STATUS)); 1298c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "SDCC_USR_CTL: %x\n", 1308c2ecf20Sopenharmony_ci rgmii_readl(ethqos, SDCC_USR_CTL)); 1318c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n", 1328c2ecf20Sopenharmony_ci rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2)); 1338c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n", 1348c2ecf20Sopenharmony_ci rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1)); 1358c2ecf20Sopenharmony_ci dev_dbg(ðqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n", 1368c2ecf20Sopenharmony_ci rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG)); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/* Clock rates */ 1408c2ecf20Sopenharmony_ci#define RGMII_1000_NOM_CLK_FREQ (250 * 1000 * 1000UL) 1418c2ecf20Sopenharmony_ci#define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ (50 * 1000 * 1000UL) 1428c2ecf20Sopenharmony_ci#define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL) 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic void 1458c2ecf20Sopenharmony_ciethqos_update_rgmii_clk(struct qcom_ethqos *ethqos, unsigned int speed) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci switch (speed) { 1488c2ecf20Sopenharmony_ci case SPEED_1000: 1498c2ecf20Sopenharmony_ci ethqos->rgmii_clk_rate = RGMII_1000_NOM_CLK_FREQ; 1508c2ecf20Sopenharmony_ci break; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci case SPEED_100: 1538c2ecf20Sopenharmony_ci ethqos->rgmii_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ; 1548c2ecf20Sopenharmony_ci break; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci case SPEED_10: 1578c2ecf20Sopenharmony_ci ethqos->rgmii_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ; 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci clk_set_rate(ethqos->rgmii_clk, ethqos->rgmii_clk_rate); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN, 1678c2ecf20Sopenharmony_ci RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic const struct ethqos_emac_por emac_v2_3_0_por[] = { 1718c2ecf20Sopenharmony_ci { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 }, 1728c2ecf20Sopenharmony_ci { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C }, 1738c2ecf20Sopenharmony_ci { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 }, 1748c2ecf20Sopenharmony_ci { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 }, 1758c2ecf20Sopenharmony_ci { .offset = SDCC_USR_CTL, .value = 0x00010800 }, 1768c2ecf20Sopenharmony_ci { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 }, 1778c2ecf20Sopenharmony_ci}; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic const struct ethqos_emac_driver_data emac_v2_3_0_data = { 1808c2ecf20Sopenharmony_ci .por = emac_v2_3_0_por, 1818c2ecf20Sopenharmony_ci .num_por = ARRAY_SIZE(emac_v2_3_0_por), 1828c2ecf20Sopenharmony_ci}; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic int ethqos_dll_configure(struct qcom_ethqos *ethqos) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci unsigned int val; 1878c2ecf20Sopenharmony_ci int retry = 1000; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci /* Set CDR_EN */ 1908c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN, 1918c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG_CDR_EN, SDCC_HC_REG_DLL_CONFIG); 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* Set CDR_EXT_EN */ 1948c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EXT_EN, 1958c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG_CDR_EXT_EN, SDCC_HC_REG_DLL_CONFIG); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* Clear CK_OUT_EN */ 1988c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, 1998c2ecf20Sopenharmony_ci 0, SDCC_HC_REG_DLL_CONFIG); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* Set DLL_EN */ 2028c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN, 2038c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN, 2068c2ecf20Sopenharmony_ci 0, SDCC_HC_REG_DLL_CONFIG); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE, 2098c2ecf20Sopenharmony_ci 0, SDCC_HC_REG_DLL_CONFIG); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* Wait for CK_OUT_EN clear */ 2128c2ecf20Sopenharmony_ci do { 2138c2ecf20Sopenharmony_ci val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); 2148c2ecf20Sopenharmony_ci val &= SDCC_DLL_CONFIG_CK_OUT_EN; 2158c2ecf20Sopenharmony_ci if (!val) 2168c2ecf20Sopenharmony_ci break; 2178c2ecf20Sopenharmony_ci mdelay(1); 2188c2ecf20Sopenharmony_ci retry--; 2198c2ecf20Sopenharmony_ci } while (retry > 0); 2208c2ecf20Sopenharmony_ci if (!retry) 2218c2ecf20Sopenharmony_ci dev_err(ðqos->pdev->dev, "Clear CK_OUT_EN timedout\n"); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* Set CK_OUT_EN */ 2248c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, 2258c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG_CK_OUT_EN, SDCC_HC_REG_DLL_CONFIG); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* Wait for CK_OUT_EN set */ 2288c2ecf20Sopenharmony_ci retry = 1000; 2298c2ecf20Sopenharmony_ci do { 2308c2ecf20Sopenharmony_ci val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG); 2318c2ecf20Sopenharmony_ci val &= SDCC_DLL_CONFIG_CK_OUT_EN; 2328c2ecf20Sopenharmony_ci if (val) 2338c2ecf20Sopenharmony_ci break; 2348c2ecf20Sopenharmony_ci mdelay(1); 2358c2ecf20Sopenharmony_ci retry--; 2368c2ecf20Sopenharmony_ci } while (retry > 0); 2378c2ecf20Sopenharmony_ci if (!retry) 2388c2ecf20Sopenharmony_ci dev_err(ðqos->pdev->dev, "Set CK_OUT_EN timedout\n"); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci /* Set DDR_CAL_EN */ 2418c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN, 2428c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS, 2458c2ecf20Sopenharmony_ci 0, SDCC_HC_REG_DLL_CONFIG2); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC, 2488c2ecf20Sopenharmony_ci 0x1A << 10, SDCC_HC_REG_DLL_CONFIG2); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL, 2518c2ecf20Sopenharmony_ci BIT(2), SDCC_HC_REG_DLL_CONFIG2); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, 2548c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW, 2558c2ecf20Sopenharmony_ci SDCC_HC_REG_DLL_CONFIG2); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci return 0; 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci /* Disable loopback mode */ 2638c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, 2648c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* Select RGMII, write 0 to interface select */ 2678c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_INTF_SEL, 2688c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci switch (ethqos->speed) { 2718c2ecf20Sopenharmony_ci case SPEED_1000: 2728c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, 2738c2ecf20Sopenharmony_ci RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); 2748c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, 2758c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG); 2768c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, 2778c2ecf20Sopenharmony_ci RGMII_CONFIG_POS_NEG_DATA_SEL, 2788c2ecf20Sopenharmony_ci RGMII_IO_MACRO_CONFIG); 2798c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, 2808c2ecf20Sopenharmony_ci RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); 2818c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, 2828c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 2838c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 2848c2ecf20Sopenharmony_ci RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 2858c2ecf20Sopenharmony_ci RGMII_IO_MACRO_CONFIG2); 2868c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 2878c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 2888c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, 2898c2ecf20Sopenharmony_ci RGMII_CONFIG2_RX_PROG_SWAP, 2908c2ecf20Sopenharmony_ci RGMII_IO_MACRO_CONFIG2); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */ 2938c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, 2948c2ecf20Sopenharmony_ci 57, SDCC_HC_REG_DDR_CONFIG); 2958c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, 2968c2ecf20Sopenharmony_ci SDCC_DDR_CONFIG_PRG_DLY_EN, 2978c2ecf20Sopenharmony_ci SDCC_HC_REG_DDR_CONFIG); 2988c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, 2998c2ecf20Sopenharmony_ci RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); 3008c2ecf20Sopenharmony_ci break; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci case SPEED_100: 3038c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, 3048c2ecf20Sopenharmony_ci RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); 3058c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, 3068c2ecf20Sopenharmony_ci RGMII_CONFIG_BYPASS_TX_ID_EN, 3078c2ecf20Sopenharmony_ci RGMII_IO_MACRO_CONFIG); 3088c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, 3098c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG); 3108c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, 3118c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG); 3128c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, 3138c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 3148c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 3158c2ecf20Sopenharmony_ci RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 3168c2ecf20Sopenharmony_ci RGMII_IO_MACRO_CONFIG2); 3178c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, 3188c2ecf20Sopenharmony_ci BIT(6), RGMII_IO_MACRO_CONFIG); 3198c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 3208c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 3218c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, 3228c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 3238c2ecf20Sopenharmony_ci /* Write 0x5 to PRG_RCLK_DLY_CODE */ 3248c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, 3258c2ecf20Sopenharmony_ci (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); 3268c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, 3278c2ecf20Sopenharmony_ci SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, 3288c2ecf20Sopenharmony_ci SDCC_HC_REG_DDR_CONFIG); 3298c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, 3308c2ecf20Sopenharmony_ci SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, 3318c2ecf20Sopenharmony_ci SDCC_HC_REG_DDR_CONFIG); 3328c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, 3338c2ecf20Sopenharmony_ci RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); 3348c2ecf20Sopenharmony_ci break; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci case SPEED_10: 3378c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, 3388c2ecf20Sopenharmony_ci RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); 3398c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, 3408c2ecf20Sopenharmony_ci RGMII_CONFIG_BYPASS_TX_ID_EN, 3418c2ecf20Sopenharmony_ci RGMII_IO_MACRO_CONFIG); 3428c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, 3438c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG); 3448c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, 3458c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG); 3468c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, 3478c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 3488c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, 3498c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 3508c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, 3518c2ecf20Sopenharmony_ci BIT(12) | GENMASK(9, 8), 3528c2ecf20Sopenharmony_ci RGMII_IO_MACRO_CONFIG); 3538c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, 3548c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 3558c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, 3568c2ecf20Sopenharmony_ci 0, RGMII_IO_MACRO_CONFIG2); 3578c2ecf20Sopenharmony_ci /* Write 0x5 to PRG_RCLK_DLY_CODE */ 3588c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, 3598c2ecf20Sopenharmony_ci (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); 3608c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, 3618c2ecf20Sopenharmony_ci SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, 3628c2ecf20Sopenharmony_ci SDCC_HC_REG_DDR_CONFIG); 3638c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, 3648c2ecf20Sopenharmony_ci SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, 3658c2ecf20Sopenharmony_ci SDCC_HC_REG_DDR_CONFIG); 3668c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, 3678c2ecf20Sopenharmony_ci RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG); 3688c2ecf20Sopenharmony_ci break; 3698c2ecf20Sopenharmony_ci default: 3708c2ecf20Sopenharmony_ci dev_err(ðqos->pdev->dev, 3718c2ecf20Sopenharmony_ci "Invalid speed %d\n", ethqos->speed); 3728c2ecf20Sopenharmony_ci return -EINVAL; 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci return 0; 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic int ethqos_configure(struct qcom_ethqos *ethqos) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci volatile unsigned int dll_lock; 3818c2ecf20Sopenharmony_ci unsigned int i, retry = 1000; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci /* Reset to POR values and enable clk */ 3848c2ecf20Sopenharmony_ci for (i = 0; i < ethqos->num_por; i++) 3858c2ecf20Sopenharmony_ci rgmii_writel(ethqos, ethqos->por[i].value, 3868c2ecf20Sopenharmony_ci ethqos->por[i].offset); 3878c2ecf20Sopenharmony_ci ethqos_set_func_clk_en(ethqos); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci /* Initialize the DLL first */ 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* Set DLL_RST */ 3928c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, 3938c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG_DLL_RST, SDCC_HC_REG_DLL_CONFIG); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci /* Set PDN */ 3968c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, 3978c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci /* Clear DLL_RST */ 4008c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, 0, 4018c2ecf20Sopenharmony_ci SDCC_HC_REG_DLL_CONFIG); 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci /* Clear PDN */ 4048c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, 0, 4058c2ecf20Sopenharmony_ci SDCC_HC_REG_DLL_CONFIG); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci if (ethqos->speed != SPEED_100 && ethqos->speed != SPEED_10) { 4088c2ecf20Sopenharmony_ci /* Set DLL_EN */ 4098c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN, 4108c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci /* Set CK_OUT_EN */ 4138c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, 4148c2ecf20Sopenharmony_ci SDCC_DLL_CONFIG_CK_OUT_EN, 4158c2ecf20Sopenharmony_ci SDCC_HC_REG_DLL_CONFIG); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci /* Set USR_CTL bit 26 with mask of 3 bits */ 4188c2ecf20Sopenharmony_ci rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26), SDCC_USR_CTL); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci /* wait for DLL LOCK */ 4218c2ecf20Sopenharmony_ci do { 4228c2ecf20Sopenharmony_ci mdelay(1); 4238c2ecf20Sopenharmony_ci dll_lock = rgmii_readl(ethqos, SDC4_STATUS); 4248c2ecf20Sopenharmony_ci if (dll_lock & SDC4_STATUS_DLL_LOCK) 4258c2ecf20Sopenharmony_ci break; 4268c2ecf20Sopenharmony_ci retry--; 4278c2ecf20Sopenharmony_ci } while (retry > 0); 4288c2ecf20Sopenharmony_ci if (!retry) 4298c2ecf20Sopenharmony_ci dev_err(ðqos->pdev->dev, 4308c2ecf20Sopenharmony_ci "Timeout while waiting for DLL lock\n"); 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci if (ethqos->speed == SPEED_1000) 4348c2ecf20Sopenharmony_ci ethqos_dll_configure(ethqos); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci ethqos_rgmii_macro_init(ethqos); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci return 0; 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic void ethqos_fix_mac_speed(void *priv, unsigned int speed) 4428c2ecf20Sopenharmony_ci{ 4438c2ecf20Sopenharmony_ci struct qcom_ethqos *ethqos = priv; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci ethqos->speed = speed; 4468c2ecf20Sopenharmony_ci ethqos_update_rgmii_clk(ethqos, speed); 4478c2ecf20Sopenharmony_ci ethqos_configure(ethqos); 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_cistatic int qcom_ethqos_probe(struct platform_device *pdev) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 4538c2ecf20Sopenharmony_ci struct plat_stmmacenet_data *plat_dat; 4548c2ecf20Sopenharmony_ci struct stmmac_resources stmmac_res; 4558c2ecf20Sopenharmony_ci const struct ethqos_emac_driver_data *data; 4568c2ecf20Sopenharmony_ci struct qcom_ethqos *ethqos; 4578c2ecf20Sopenharmony_ci struct resource *res; 4588c2ecf20Sopenharmony_ci int ret; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci ret = stmmac_get_platform_resources(pdev, &stmmac_res); 4618c2ecf20Sopenharmony_ci if (ret) 4628c2ecf20Sopenharmony_ci return ret; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); 4658c2ecf20Sopenharmony_ci if (IS_ERR(plat_dat)) { 4668c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "dt configuration failed\n"); 4678c2ecf20Sopenharmony_ci return PTR_ERR(plat_dat); 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL); 4718c2ecf20Sopenharmony_ci if (!ethqos) { 4728c2ecf20Sopenharmony_ci ret = -ENOMEM; 4738c2ecf20Sopenharmony_ci goto err_mem; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci ethqos->pdev = pdev; 4778c2ecf20Sopenharmony_ci res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rgmii"); 4788c2ecf20Sopenharmony_ci ethqos->rgmii_base = devm_ioremap_resource(&pdev->dev, res); 4798c2ecf20Sopenharmony_ci if (IS_ERR(ethqos->rgmii_base)) { 4808c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Can't get rgmii base\n"); 4818c2ecf20Sopenharmony_ci ret = PTR_ERR(ethqos->rgmii_base); 4828c2ecf20Sopenharmony_ci goto err_mem; 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci data = of_device_get_match_data(&pdev->dev); 4868c2ecf20Sopenharmony_ci ethqos->por = data->por; 4878c2ecf20Sopenharmony_ci ethqos->num_por = data->num_por; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii"); 4908c2ecf20Sopenharmony_ci if (IS_ERR(ethqos->rgmii_clk)) { 4918c2ecf20Sopenharmony_ci ret = PTR_ERR(ethqos->rgmii_clk); 4928c2ecf20Sopenharmony_ci goto err_mem; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci ret = clk_prepare_enable(ethqos->rgmii_clk); 4968c2ecf20Sopenharmony_ci if (ret) 4978c2ecf20Sopenharmony_ci goto err_mem; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci ethqos->speed = SPEED_1000; 5008c2ecf20Sopenharmony_ci ethqos_update_rgmii_clk(ethqos, SPEED_1000); 5018c2ecf20Sopenharmony_ci ethqos_set_func_clk_en(ethqos); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci plat_dat->bsp_priv = ethqos; 5048c2ecf20Sopenharmony_ci plat_dat->fix_mac_speed = ethqos_fix_mac_speed; 5058c2ecf20Sopenharmony_ci plat_dat->has_gmac4 = 1; 5068c2ecf20Sopenharmony_ci plat_dat->pmt = 1; 5078c2ecf20Sopenharmony_ci plat_dat->tso_en = of_property_read_bool(np, "snps,tso"); 5088c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "qcom,qcs404-ethqos")) 5098c2ecf20Sopenharmony_ci plat_dat->rx_clk_runs_in_lpi = 1; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 5128c2ecf20Sopenharmony_ci if (ret) 5138c2ecf20Sopenharmony_ci goto err_clk; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci rgmii_dump(ethqos); 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci return ret; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cierr_clk: 5208c2ecf20Sopenharmony_ci clk_disable_unprepare(ethqos->rgmii_clk); 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_cierr_mem: 5238c2ecf20Sopenharmony_ci stmmac_remove_config_dt(pdev, plat_dat); 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci return ret; 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_cistatic int qcom_ethqos_remove(struct platform_device *pdev) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci struct qcom_ethqos *ethqos; 5318c2ecf20Sopenharmony_ci int ret; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci ethqos = get_stmmac_bsp_priv(&pdev->dev); 5348c2ecf20Sopenharmony_ci if (!ethqos) 5358c2ecf20Sopenharmony_ci return -ENODEV; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci ret = stmmac_pltfr_remove(pdev); 5388c2ecf20Sopenharmony_ci clk_disable_unprepare(ethqos->rgmii_clk); 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci return ret; 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_cistatic const struct of_device_id qcom_ethqos_match[] = { 5448c2ecf20Sopenharmony_ci { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data}, 5458c2ecf20Sopenharmony_ci { } 5468c2ecf20Sopenharmony_ci}; 5478c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, qcom_ethqos_match); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_cistatic struct platform_driver qcom_ethqos_driver = { 5508c2ecf20Sopenharmony_ci .probe = qcom_ethqos_probe, 5518c2ecf20Sopenharmony_ci .remove = qcom_ethqos_remove, 5528c2ecf20Sopenharmony_ci .driver = { 5538c2ecf20Sopenharmony_ci .name = "qcom-ethqos", 5548c2ecf20Sopenharmony_ci .pm = &stmmac_pltfr_pm_ops, 5558c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(qcom_ethqos_match), 5568c2ecf20Sopenharmony_ci }, 5578c2ecf20Sopenharmony_ci}; 5588c2ecf20Sopenharmony_cimodule_platform_driver(qcom_ethqos_driver); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Qualcomm ETHQOS driver"); 5618c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 562