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(&ethqos->pdev->dev, "Rgmii register dump\n");
1198c2ecf20Sopenharmony_ci	dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n",
1208c2ecf20Sopenharmony_ci		rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG));
1218c2ecf20Sopenharmony_ci	dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
1228c2ecf20Sopenharmony_ci		rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG));
1238c2ecf20Sopenharmony_ci	dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
1248c2ecf20Sopenharmony_ci		rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG));
1258c2ecf20Sopenharmony_ci	dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
1268c2ecf20Sopenharmony_ci		rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2));
1278c2ecf20Sopenharmony_ci	dev_dbg(&ethqos->pdev->dev, "SDC4_STATUS: %x\n",
1288c2ecf20Sopenharmony_ci		rgmii_readl(ethqos, SDC4_STATUS));
1298c2ecf20Sopenharmony_ci	dev_dbg(&ethqos->pdev->dev, "SDCC_USR_CTL: %x\n",
1308c2ecf20Sopenharmony_ci		rgmii_readl(ethqos, SDCC_USR_CTL));
1318c2ecf20Sopenharmony_ci	dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
1328c2ecf20Sopenharmony_ci		rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2));
1338c2ecf20Sopenharmony_ci	dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
1348c2ecf20Sopenharmony_ci		rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1));
1358c2ecf20Sopenharmony_ci	dev_dbg(&ethqos->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(&ethqos->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(&ethqos->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(&ethqos->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(&ethqos->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