1a7c30e62SVinod Koul // SPDX-License-Identifier: GPL-2.0
2a7c30e62SVinod Koul // Copyright (c) 2018-19, Linaro Limited
3a7c30e62SVinod Koul 
4a7c30e62SVinod Koul #include <linux/module.h>
5a7c30e62SVinod Koul #include <linux/of.h>
6a7c30e62SVinod Koul #include <linux/of_device.h>
7a7c30e62SVinod Koul #include <linux/platform_device.h>
8a7c30e62SVinod Koul #include <linux/phy.h>
9a7c30e62SVinod Koul #include "stmmac.h"
10a7c30e62SVinod Koul #include "stmmac_platform.h"
11a7c30e62SVinod Koul 
12a7c30e62SVinod Koul #define RGMII_IO_MACRO_CONFIG		0x0
13a7c30e62SVinod Koul #define SDCC_HC_REG_DLL_CONFIG		0x4
14a7c30e62SVinod Koul #define SDCC_HC_REG_DDR_CONFIG		0xC
15a7c30e62SVinod Koul #define SDCC_HC_REG_DLL_CONFIG2		0x10
16a7c30e62SVinod Koul #define SDC4_STATUS			0x14
17a7c30e62SVinod Koul #define SDCC_USR_CTL			0x18
18a7c30e62SVinod Koul #define RGMII_IO_MACRO_CONFIG2		0x1C
19a7c30e62SVinod Koul #define RGMII_IO_MACRO_DEBUG1		0x20
20a7c30e62SVinod Koul #define EMAC_SYSTEM_LOW_POWER_DEBUG	0x28
21a7c30e62SVinod Koul 
22a7c30e62SVinod Koul /* RGMII_IO_MACRO_CONFIG fields */
23a7c30e62SVinod Koul #define RGMII_CONFIG_FUNC_CLK_EN		BIT(30)
24a7c30e62SVinod Koul #define RGMII_CONFIG_POS_NEG_DATA_SEL		BIT(23)
25a7c30e62SVinod Koul #define RGMII_CONFIG_GPIO_CFG_RX_INT		GENMASK(21, 20)
26a7c30e62SVinod Koul #define RGMII_CONFIG_GPIO_CFG_TX_INT		GENMASK(19, 17)
27a7c30e62SVinod Koul #define RGMII_CONFIG_MAX_SPD_PRG_9		GENMASK(16, 8)
28a7c30e62SVinod Koul #define RGMII_CONFIG_MAX_SPD_PRG_2		GENMASK(7, 6)
29a7c30e62SVinod Koul #define RGMII_CONFIG_INTF_SEL			GENMASK(5, 4)
30a7c30e62SVinod Koul #define RGMII_CONFIG_BYPASS_TX_ID_EN		BIT(3)
31a7c30e62SVinod Koul #define RGMII_CONFIG_LOOPBACK_EN		BIT(2)
32a7c30e62SVinod Koul #define RGMII_CONFIG_PROG_SWAP			BIT(1)
33a7c30e62SVinod Koul #define RGMII_CONFIG_DDR_MODE			BIT(0)
34a7c30e62SVinod Koul 
35a7c30e62SVinod Koul /* SDCC_HC_REG_DLL_CONFIG fields */
36a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_DLL_RST			BIT(30)
37a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_PDN			BIT(29)
38a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_MCLK_FREQ		GENMASK(26, 24)
39a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_CDR_SELEXT		GENMASK(23, 20)
40a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_CDR_EXT_EN		BIT(19)
41a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_CK_OUT_EN		BIT(18)
42a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_CDR_EN			BIT(17)
43a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_DLL_EN			BIT(16)
44a7c30e62SVinod Koul #define SDCC_DLL_MCLK_GATING_EN			BIT(5)
45a7c30e62SVinod Koul #define SDCC_DLL_CDR_FINE_PHASE			GENMASK(3, 2)
46a7c30e62SVinod Koul 
47a7c30e62SVinod Koul /* SDCC_HC_REG_DDR_CONFIG fields */
48a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_PRG_DLY_EN		BIT(31)
49a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY	GENMASK(26, 21)
50a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE	GENMASK(29, 27)
51a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN	BIT(30)
52a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_PRG_RCLK_DLY		GENMASK(8, 0)
53a7c30e62SVinod Koul 
54a7c30e62SVinod Koul /* SDCC_HC_REG_DLL_CONFIG2 fields */
55a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS		BIT(21)
56a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC		GENMASK(17, 10)
57a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL	GENMASK(3, 2)
58a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW	BIT(1)
59a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_DDR_CAL_EN		BIT(0)
60a7c30e62SVinod Koul 
61a7c30e62SVinod Koul /* SDC4_STATUS bits */
62a7c30e62SVinod Koul #define SDC4_STATUS_DLL_LOCK			BIT(7)
63a7c30e62SVinod Koul 
64a7c30e62SVinod Koul /* RGMII_IO_MACRO_CONFIG2 fields */
65a7c30e62SVinod Koul #define RGMII_CONFIG2_RSVD_CONFIG15		GENMASK(31, 17)
66a7c30e62SVinod Koul #define RGMII_CONFIG2_RGMII_CLK_SEL_CFG		BIT(16)
67a7c30e62SVinod Koul #define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN	BIT(13)
68a7c30e62SVinod Koul #define RGMII_CONFIG2_CLK_DIVIDE_SEL		BIT(12)
69a7c30e62SVinod Koul #define RGMII_CONFIG2_RX_PROG_SWAP		BIT(7)
70a7c30e62SVinod Koul #define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL	BIT(6)
71a7c30e62SVinod Koul #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN	BIT(5)
72a7c30e62SVinod Koul 
73a7c30e62SVinod Koul struct ethqos_emac_por {
74a7c30e62SVinod Koul 	unsigned int offset;
75a7c30e62SVinod Koul 	unsigned int value;
76a7c30e62SVinod Koul };
77a7c30e62SVinod Koul 
78fd4a5177SVinod Koul struct ethqos_emac_driver_data {
79fd4a5177SVinod Koul 	const struct ethqos_emac_por *por;
80fd4a5177SVinod Koul 	unsigned int num_por;
81a7bf6d7cSBjorn Andersson 	bool rgmii_config_looback_en;
82fd4a5177SVinod Koul };
83fd4a5177SVinod Koul 
84a7c30e62SVinod Koul struct qcom_ethqos {
85a7c30e62SVinod Koul 	struct platform_device *pdev;
86a7c30e62SVinod Koul 	void __iomem *rgmii_base;
87a7c30e62SVinod Koul 
88a7c30e62SVinod Koul 	unsigned int rgmii_clk_rate;
89a7c30e62SVinod Koul 	struct clk *rgmii_clk;
90a7c30e62SVinod Koul 	unsigned int speed;
91a7c30e62SVinod Koul 
92a7c30e62SVinod Koul 	const struct ethqos_emac_por *por;
93a7c30e62SVinod Koul 	unsigned int num_por;
94a7bf6d7cSBjorn Andersson 	bool rgmii_config_looback_en;
95a7c30e62SVinod Koul };
96a7c30e62SVinod Koul 
97a7c30e62SVinod Koul static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
98a7c30e62SVinod Koul {
99a7c30e62SVinod Koul 	return readl(ethqos->rgmii_base + offset);
100a7c30e62SVinod Koul }
101a7c30e62SVinod Koul 
102a7c30e62SVinod Koul static void rgmii_writel(struct qcom_ethqos *ethqos,
103a7c30e62SVinod Koul 			 int value, unsigned int offset)
104a7c30e62SVinod Koul {
105a7c30e62SVinod Koul 	writel(value, ethqos->rgmii_base + offset);
106a7c30e62SVinod Koul }
107a7c30e62SVinod Koul 
108a7c30e62SVinod Koul static void rgmii_updatel(struct qcom_ethqos *ethqos,
109a7c30e62SVinod Koul 			  int mask, int val, unsigned int offset)
110a7c30e62SVinod Koul {
111a7c30e62SVinod Koul 	unsigned int temp;
112a7c30e62SVinod Koul 
113a7c30e62SVinod Koul 	temp =  rgmii_readl(ethqos, offset);
114a7c30e62SVinod Koul 	temp = (temp & ~(mask)) | val;
115a7c30e62SVinod Koul 	rgmii_writel(ethqos, temp, offset);
116a7c30e62SVinod Koul }
117a7c30e62SVinod Koul 
1184047b9dbSBhupesh Sharma static void rgmii_dump(void *priv)
119a7c30e62SVinod Koul {
1204047b9dbSBhupesh Sharma 	struct qcom_ethqos *ethqos = priv;
1214047b9dbSBhupesh Sharma 
122a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "Rgmii register dump\n");
123a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n",
124a7c30e62SVinod Koul 		rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG));
125a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
126a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG));
127a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
128a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG));
129a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
130a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2));
131a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "SDC4_STATUS: %x\n",
132a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDC4_STATUS));
133a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "SDCC_USR_CTL: %x\n",
134a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDCC_USR_CTL));
135a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
136a7c30e62SVinod Koul 		rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2));
137a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
138a7c30e62SVinod Koul 		rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1));
139a7c30e62SVinod Koul 	dev_dbg(&ethqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
140a7c30e62SVinod Koul 		rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG));
141a7c30e62SVinod Koul }
142a7c30e62SVinod Koul 
143a7c30e62SVinod Koul /* Clock rates */
144a7c30e62SVinod Koul #define RGMII_1000_NOM_CLK_FREQ			(250 * 1000 * 1000UL)
145a7c30e62SVinod Koul #define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ	 (50 * 1000 * 1000UL)
146a7c30e62SVinod Koul #define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ	  (5 * 1000 * 1000UL)
147a7c30e62SVinod Koul 
148a7c30e62SVinod Koul static void
149a7c30e62SVinod Koul ethqos_update_rgmii_clk(struct qcom_ethqos *ethqos, unsigned int speed)
150a7c30e62SVinod Koul {
151a7c30e62SVinod Koul 	switch (speed) {
152a7c30e62SVinod Koul 	case SPEED_1000:
153a7c30e62SVinod Koul 		ethqos->rgmii_clk_rate =  RGMII_1000_NOM_CLK_FREQ;
154a7c30e62SVinod Koul 		break;
155a7c30e62SVinod Koul 
156a7c30e62SVinod Koul 	case SPEED_100:
157a7c30e62SVinod Koul 		ethqos->rgmii_clk_rate =  RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
158a7c30e62SVinod Koul 		break;
159a7c30e62SVinod Koul 
160a7c30e62SVinod Koul 	case SPEED_10:
161a7c30e62SVinod Koul 		ethqos->rgmii_clk_rate =  RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
162a7c30e62SVinod Koul 		break;
163a7c30e62SVinod Koul 	}
164a7c30e62SVinod Koul 
165a7c30e62SVinod Koul 	clk_set_rate(ethqos->rgmii_clk, ethqos->rgmii_clk_rate);
166a7c30e62SVinod Koul }
167a7c30e62SVinod Koul 
168a7c30e62SVinod Koul static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos)
169a7c30e62SVinod Koul {
170a7c30e62SVinod Koul 	rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN,
171a7c30e62SVinod Koul 		      RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG);
172a7c30e62SVinod Koul }
173a7c30e62SVinod Koul 
174a7c30e62SVinod Koul static const struct ethqos_emac_por emac_v2_3_0_por[] = {
175a7c30e62SVinod Koul 	{ .offset = RGMII_IO_MACRO_CONFIG,	.value = 0x00C01343 },
176a7c30e62SVinod Koul 	{ .offset = SDCC_HC_REG_DLL_CONFIG,	.value = 0x2004642C },
177a7c30e62SVinod Koul 	{ .offset = SDCC_HC_REG_DDR_CONFIG,	.value = 0x00000000 },
178a7c30e62SVinod Koul 	{ .offset = SDCC_HC_REG_DLL_CONFIG2,	.value = 0x00200000 },
179a7c30e62SVinod Koul 	{ .offset = SDCC_USR_CTL,		.value = 0x00010800 },
180a7c30e62SVinod Koul 	{ .offset = RGMII_IO_MACRO_CONFIG2,	.value = 0x00002060 },
181a7c30e62SVinod Koul };
182a7c30e62SVinod Koul 
183fd4a5177SVinod Koul static const struct ethqos_emac_driver_data emac_v2_3_0_data = {
184fd4a5177SVinod Koul 	.por = emac_v2_3_0_por,
185fd4a5177SVinod Koul 	.num_por = ARRAY_SIZE(emac_v2_3_0_por),
186a7bf6d7cSBjorn Andersson 	.rgmii_config_looback_en = true,
187fd4a5177SVinod Koul };
188fd4a5177SVinod Koul 
189d90b3120SVinod Koul static const struct ethqos_emac_por emac_v2_1_0_por[] = {
190d90b3120SVinod Koul 	{ .offset = RGMII_IO_MACRO_CONFIG,	.value = 0x40C01343 },
191d90b3120SVinod Koul 	{ .offset = SDCC_HC_REG_DLL_CONFIG,	.value = 0x2004642C },
192d90b3120SVinod Koul 	{ .offset = SDCC_HC_REG_DDR_CONFIG,	.value = 0x00000000 },
193d90b3120SVinod Koul 	{ .offset = SDCC_HC_REG_DLL_CONFIG2,	.value = 0x00200000 },
194d90b3120SVinod Koul 	{ .offset = SDCC_USR_CTL,		.value = 0x00010800 },
195d90b3120SVinod Koul 	{ .offset = RGMII_IO_MACRO_CONFIG2,	.value = 0x00002060 },
196d90b3120SVinod Koul };
197d90b3120SVinod Koul 
198d90b3120SVinod Koul static const struct ethqos_emac_driver_data emac_v2_1_0_data = {
199d90b3120SVinod Koul 	.por = emac_v2_1_0_por,
200d90b3120SVinod Koul 	.num_por = ARRAY_SIZE(emac_v2_1_0_por),
201a7bf6d7cSBjorn Andersson 	.rgmii_config_looback_en = false,
202d90b3120SVinod Koul };
203d90b3120SVinod Koul 
204a7c30e62SVinod Koul static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
205a7c30e62SVinod Koul {
206a7c30e62SVinod Koul 	unsigned int val;
207a7c30e62SVinod Koul 	int retry = 1000;
208a7c30e62SVinod Koul 
209a7c30e62SVinod Koul 	/* Set CDR_EN */
210a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN,
211a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_CDR_EN, SDCC_HC_REG_DLL_CONFIG);
212a7c30e62SVinod Koul 
213a7c30e62SVinod Koul 	/* Set CDR_EXT_EN */
214a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EXT_EN,
215a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_CDR_EXT_EN, SDCC_HC_REG_DLL_CONFIG);
216a7c30e62SVinod Koul 
217a7c30e62SVinod Koul 	/* Clear CK_OUT_EN */
218a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
219a7c30e62SVinod Koul 		      0, SDCC_HC_REG_DLL_CONFIG);
220a7c30e62SVinod Koul 
221a7c30e62SVinod Koul 	/* Set DLL_EN */
222a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
223a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
224a7c30e62SVinod Koul 
225a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN,
226a7c30e62SVinod Koul 		      0, SDCC_HC_REG_DLL_CONFIG);
227a7c30e62SVinod Koul 
228a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE,
229a7c30e62SVinod Koul 		      0, SDCC_HC_REG_DLL_CONFIG);
230a7c30e62SVinod Koul 
231a7c30e62SVinod Koul 	/* Wait for CK_OUT_EN clear */
232a7c30e62SVinod Koul 	do {
233a7c30e62SVinod Koul 		val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG);
234a7c30e62SVinod Koul 		val &= SDCC_DLL_CONFIG_CK_OUT_EN;
235a7c30e62SVinod Koul 		if (!val)
236a7c30e62SVinod Koul 			break;
237a7c30e62SVinod Koul 		mdelay(1);
238a7c30e62SVinod Koul 		retry--;
239a7c30e62SVinod Koul 	} while (retry > 0);
240a7c30e62SVinod Koul 	if (!retry)
241a7c30e62SVinod Koul 		dev_err(&ethqos->pdev->dev, "Clear CK_OUT_EN timedout\n");
242a7c30e62SVinod Koul 
243a7c30e62SVinod Koul 	/* Set CK_OUT_EN */
244a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
245a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_CK_OUT_EN, SDCC_HC_REG_DLL_CONFIG);
246a7c30e62SVinod Koul 
247a7c30e62SVinod Koul 	/* Wait for CK_OUT_EN set */
248a7c30e62SVinod Koul 	retry = 1000;
249a7c30e62SVinod Koul 	do {
250a7c30e62SVinod Koul 		val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG);
251a7c30e62SVinod Koul 		val &= SDCC_DLL_CONFIG_CK_OUT_EN;
252a7c30e62SVinod Koul 		if (val)
253a7c30e62SVinod Koul 			break;
254a7c30e62SVinod Koul 		mdelay(1);
255a7c30e62SVinod Koul 		retry--;
256a7c30e62SVinod Koul 	} while (retry > 0);
257a7c30e62SVinod Koul 	if (!retry)
258a7c30e62SVinod Koul 		dev_err(&ethqos->pdev->dev, "Set CK_OUT_EN timedout\n");
259a7c30e62SVinod Koul 
260a7c30e62SVinod Koul 	/* Set DDR_CAL_EN */
261a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN,
262a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2);
263a7c30e62SVinod Koul 
264a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS,
265a7c30e62SVinod Koul 		      0, SDCC_HC_REG_DLL_CONFIG2);
266a7c30e62SVinod Koul 
267a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC,
268a7c30e62SVinod Koul 		      0x1A << 10, SDCC_HC_REG_DLL_CONFIG2);
269a7c30e62SVinod Koul 
270a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL,
271a7c30e62SVinod Koul 		      BIT(2), SDCC_HC_REG_DLL_CONFIG2);
272a7c30e62SVinod Koul 
273a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
274a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
275a7c30e62SVinod Koul 		      SDCC_HC_REG_DLL_CONFIG2);
276a7c30e62SVinod Koul 
277a7c30e62SVinod Koul 	return 0;
278a7c30e62SVinod Koul }
279a7c30e62SVinod Koul 
280a7c30e62SVinod Koul static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
281a7c30e62SVinod Koul {
282*164a9ebeSAndrew Halaney 	int phase_shift;
283*164a9ebeSAndrew Halaney 	int phy_mode;
284*164a9ebeSAndrew Halaney 
285*164a9ebeSAndrew Halaney 	/* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
286*164a9ebeSAndrew Halaney 	phy_mode = device_get_phy_mode(&ethqos->pdev->dev);
287*164a9ebeSAndrew Halaney 	if (phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
288*164a9ebeSAndrew Halaney 	    phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
289*164a9ebeSAndrew Halaney 		phase_shift = 0;
290*164a9ebeSAndrew Halaney 	else
291*164a9ebeSAndrew Halaney 		phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN;
292*164a9ebeSAndrew Halaney 
293a7c30e62SVinod Koul 	/* Disable loopback mode */
294a7c30e62SVinod Koul 	rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN,
295a7c30e62SVinod Koul 		      0, RGMII_IO_MACRO_CONFIG2);
296a7c30e62SVinod Koul 
297a7c30e62SVinod Koul 	/* Select RGMII, write 0 to interface select */
298a7c30e62SVinod Koul 	rgmii_updatel(ethqos, RGMII_CONFIG_INTF_SEL,
299a7c30e62SVinod Koul 		      0, RGMII_IO_MACRO_CONFIG);
300a7c30e62SVinod Koul 
301a7c30e62SVinod Koul 	switch (ethqos->speed) {
302a7c30e62SVinod Koul 	case SPEED_1000:
303a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
304a7c30e62SVinod Koul 			      RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
305a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
306a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
307a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
308a7c30e62SVinod Koul 			      RGMII_CONFIG_POS_NEG_DATA_SEL,
309a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG);
310a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
311a7c30e62SVinod Koul 			      RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG);
312a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
313a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
314*164a9ebeSAndrew Halaney 
315a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
316*164a9ebeSAndrew Halaney 			      phase_shift, RGMII_IO_MACRO_CONFIG2);
317a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
318a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
319a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
320a7c30e62SVinod Koul 			      RGMII_CONFIG2_RX_PROG_SWAP,
321a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG2);
322a7c30e62SVinod Koul 
323a7c30e62SVinod Koul 		/* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */
324a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
325a7c30e62SVinod Koul 			      57, SDCC_HC_REG_DDR_CONFIG);
326a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN,
327a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_PRG_DLY_EN,
328a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
329a7bf6d7cSBjorn Andersson 		if (ethqos->rgmii_config_looback_en)
330a7c30e62SVinod Koul 			rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
331a7c30e62SVinod Koul 				      RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
332a7bf6d7cSBjorn Andersson 		else
333a7bf6d7cSBjorn Andersson 			rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
334a7bf6d7cSBjorn Andersson 				      0, RGMII_IO_MACRO_CONFIG);
335a7c30e62SVinod Koul 		break;
336a7c30e62SVinod Koul 
337a7c30e62SVinod Koul 	case SPEED_100:
338a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
339a7c30e62SVinod Koul 			      RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
340a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
341a7c30e62SVinod Koul 			      RGMII_CONFIG_BYPASS_TX_ID_EN,
342a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG);
343a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
344a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
345a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
346a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
347a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
348a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
349a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
350*164a9ebeSAndrew Halaney 			      phase_shift, RGMII_IO_MACRO_CONFIG2);
351a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2,
352a7c30e62SVinod Koul 			      BIT(6), RGMII_IO_MACRO_CONFIG);
353a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
354a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
355a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
356a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
357a7c30e62SVinod Koul 		/* Write 0x5 to PRG_RCLK_DLY_CODE */
358a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
359a7c30e62SVinod Koul 			      (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
360a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
361a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
362a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
363a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
364a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
365a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
366a7bf6d7cSBjorn Andersson 		if (ethqos->rgmii_config_looback_en)
367a7c30e62SVinod Koul 			rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
368a7c30e62SVinod Koul 				      RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
369a7bf6d7cSBjorn Andersson 		else
370a7bf6d7cSBjorn Andersson 			rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
371a7bf6d7cSBjorn Andersson 				      0, RGMII_IO_MACRO_CONFIG);
372a7bf6d7cSBjorn Andersson 
373a7c30e62SVinod Koul 		break;
374a7c30e62SVinod Koul 
375a7c30e62SVinod Koul 	case SPEED_10:
376a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
377a7c30e62SVinod Koul 			      RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
378a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
379a7c30e62SVinod Koul 			      RGMII_CONFIG_BYPASS_TX_ID_EN,
380a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG);
381a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
382a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
383a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
384a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
385a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
386a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
387a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
388*164a9ebeSAndrew Halaney 			      phase_shift, RGMII_IO_MACRO_CONFIG2);
389a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9,
390a7c30e62SVinod Koul 			      BIT(12) | GENMASK(9, 8),
391a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG);
392a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
393a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
394a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
395a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
396a7c30e62SVinod Koul 		/* Write 0x5 to PRG_RCLK_DLY_CODE */
397a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
398a7c30e62SVinod Koul 			      (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
399a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
400a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
401a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
402a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
403a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
404a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
405a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
406a7c30e62SVinod Koul 			      RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
407a7c30e62SVinod Koul 		break;
408a7c30e62SVinod Koul 	default:
409a7c30e62SVinod Koul 		dev_err(&ethqos->pdev->dev,
410a7c30e62SVinod Koul 			"Invalid speed %d\n", ethqos->speed);
411a7c30e62SVinod Koul 		return -EINVAL;
412a7c30e62SVinod Koul 	}
413a7c30e62SVinod Koul 
414a7c30e62SVinod Koul 	return 0;
415a7c30e62SVinod Koul }
416a7c30e62SVinod Koul 
417a7c30e62SVinod Koul static int ethqos_configure(struct qcom_ethqos *ethqos)
418a7c30e62SVinod Koul {
419a7c30e62SVinod Koul 	volatile unsigned int dll_lock;
420a7c30e62SVinod Koul 	unsigned int i, retry = 1000;
421a7c30e62SVinod Koul 
422a7c30e62SVinod Koul 	/* Reset to POR values and enable clk */
423a7c30e62SVinod Koul 	for (i = 0; i < ethqos->num_por; i++)
424a7c30e62SVinod Koul 		rgmii_writel(ethqos, ethqos->por[i].value,
425a7c30e62SVinod Koul 			     ethqos->por[i].offset);
426a7c30e62SVinod Koul 	ethqos_set_func_clk_en(ethqos);
427a7c30e62SVinod Koul 
428a7c30e62SVinod Koul 	/* Initialize the DLL first */
429a7c30e62SVinod Koul 
430a7c30e62SVinod Koul 	/* Set DLL_RST */
431a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST,
432a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_DLL_RST, SDCC_HC_REG_DLL_CONFIG);
433a7c30e62SVinod Koul 
434a7c30e62SVinod Koul 	/* Set PDN */
435a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN,
436a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG);
437a7c30e62SVinod Koul 
438a7c30e62SVinod Koul 	/* Clear DLL_RST */
439a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, 0,
440a7c30e62SVinod Koul 		      SDCC_HC_REG_DLL_CONFIG);
441a7c30e62SVinod Koul 
442a7c30e62SVinod Koul 	/* Clear PDN */
443a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, 0,
444a7c30e62SVinod Koul 		      SDCC_HC_REG_DLL_CONFIG);
445a7c30e62SVinod Koul 
446a7c30e62SVinod Koul 	if (ethqos->speed != SPEED_100 && ethqos->speed != SPEED_10) {
447a7c30e62SVinod Koul 		/* Set DLL_EN */
448a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
449a7c30e62SVinod Koul 			      SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
450a7c30e62SVinod Koul 
451a7c30e62SVinod Koul 		/* Set CK_OUT_EN */
452a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
453a7c30e62SVinod Koul 			      SDCC_DLL_CONFIG_CK_OUT_EN,
454a7c30e62SVinod Koul 			      SDCC_HC_REG_DLL_CONFIG);
455a7c30e62SVinod Koul 
456a7c30e62SVinod Koul 		/* Set USR_CTL bit 26 with mask of 3 bits */
457a7c30e62SVinod Koul 		rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26), SDCC_USR_CTL);
458a7c30e62SVinod Koul 
459a7c30e62SVinod Koul 		/* wait for DLL LOCK */
460a7c30e62SVinod Koul 		do {
461a7c30e62SVinod Koul 			mdelay(1);
462a7c30e62SVinod Koul 			dll_lock = rgmii_readl(ethqos, SDC4_STATUS);
463a7c30e62SVinod Koul 			if (dll_lock & SDC4_STATUS_DLL_LOCK)
464a7c30e62SVinod Koul 				break;
4657d10f077SDejin Zheng 			retry--;
466a7c30e62SVinod Koul 		} while (retry > 0);
467a7c30e62SVinod Koul 		if (!retry)
468a7c30e62SVinod Koul 			dev_err(&ethqos->pdev->dev,
469a7c30e62SVinod Koul 				"Timeout while waiting for DLL lock\n");
470a7c30e62SVinod Koul 	}
471a7c30e62SVinod Koul 
472a7c30e62SVinod Koul 	if (ethqos->speed == SPEED_1000)
473a7c30e62SVinod Koul 		ethqos_dll_configure(ethqos);
474a7c30e62SVinod Koul 
475a7c30e62SVinod Koul 	ethqos_rgmii_macro_init(ethqos);
476a7c30e62SVinod Koul 
477a7c30e62SVinod Koul 	return 0;
478a7c30e62SVinod Koul }
479a7c30e62SVinod Koul 
480a7c30e62SVinod Koul static void ethqos_fix_mac_speed(void *priv, unsigned int speed)
481a7c30e62SVinod Koul {
482a7c30e62SVinod Koul 	struct qcom_ethqos *ethqos = priv;
483a7c30e62SVinod Koul 
484a7c30e62SVinod Koul 	ethqos->speed = speed;
485a7c30e62SVinod Koul 	ethqos_update_rgmii_clk(ethqos, speed);
486a7c30e62SVinod Koul 	ethqos_configure(ethqos);
487a7c30e62SVinod Koul }
488a7c30e62SVinod Koul 
4896c950ca7SBhupesh Sharma static int ethqos_clks_config(void *priv, bool enabled)
4906c950ca7SBhupesh Sharma {
4916c950ca7SBhupesh Sharma 	struct qcom_ethqos *ethqos = priv;
4926c950ca7SBhupesh Sharma 	int ret = 0;
4936c950ca7SBhupesh Sharma 
4946c950ca7SBhupesh Sharma 	if (enabled) {
4956c950ca7SBhupesh Sharma 		ret = clk_prepare_enable(ethqos->rgmii_clk);
4966c950ca7SBhupesh Sharma 		if (ret) {
4976c950ca7SBhupesh Sharma 			dev_err(&ethqos->pdev->dev, "rgmii_clk enable failed\n");
4986c950ca7SBhupesh Sharma 			return ret;
4996c950ca7SBhupesh Sharma 		}
500ffba2123SBjorn Andersson 
501ffba2123SBjorn Andersson 		/* Enable functional clock to prevent DMA reset to timeout due
502ffba2123SBjorn Andersson 		 * to lacking PHY clock after the hardware block has been power
503ffba2123SBjorn Andersson 		 * cycled. The actual configuration will be adjusted once
504ffba2123SBjorn Andersson 		 * ethqos_fix_mac_speed() is invoked.
505ffba2123SBjorn Andersson 		 */
506ffba2123SBjorn Andersson 		ethqos_set_func_clk_en(ethqos);
5076c950ca7SBhupesh Sharma 	} else {
5086c950ca7SBhupesh Sharma 		clk_disable_unprepare(ethqos->rgmii_clk);
5096c950ca7SBhupesh Sharma 	}
5106c950ca7SBhupesh Sharma 
5116c950ca7SBhupesh Sharma 	return ret;
5126c950ca7SBhupesh Sharma }
5136c950ca7SBhupesh Sharma 
514a7c30e62SVinod Koul static int qcom_ethqos_probe(struct platform_device *pdev)
515a7c30e62SVinod Koul {
516a7c30e62SVinod Koul 	struct device_node *np = pdev->dev.of_node;
517a7c30e62SVinod Koul 	struct plat_stmmacenet_data *plat_dat;
518a7c30e62SVinod Koul 	struct stmmac_resources stmmac_res;
519fd4a5177SVinod Koul 	const struct ethqos_emac_driver_data *data;
520a7c30e62SVinod Koul 	struct qcom_ethqos *ethqos;
521a7c30e62SVinod Koul 	int ret;
522a7c30e62SVinod Koul 
523a7c30e62SVinod Koul 	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
524a7c30e62SVinod Koul 	if (ret)
525a7c30e62SVinod Koul 		return ret;
526a7c30e62SVinod Koul 
52783216e39SMichael Walle 	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
528a7c30e62SVinod Koul 	if (IS_ERR(plat_dat)) {
529a7c30e62SVinod Koul 		dev_err(&pdev->dev, "dt configuration failed\n");
530a7c30e62SVinod Koul 		return PTR_ERR(plat_dat);
531a7c30e62SVinod Koul 	}
532a7c30e62SVinod Koul 
5336c950ca7SBhupesh Sharma 	plat_dat->clks_config = ethqos_clks_config;
5346c950ca7SBhupesh Sharma 
535a7c30e62SVinod Koul 	ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL);
536a7c30e62SVinod Koul 	if (!ethqos) {
537a7c30e62SVinod Koul 		ret = -ENOMEM;
538a7c30e62SVinod Koul 		goto err_mem;
539a7c30e62SVinod Koul 	}
540a7c30e62SVinod Koul 
541a7c30e62SVinod Koul 	ethqos->pdev = pdev;
5423a5a32b5SYang Yingliang 	ethqos->rgmii_base = devm_platform_ioremap_resource_byname(pdev, "rgmii");
543a7c30e62SVinod Koul 	if (IS_ERR(ethqos->rgmii_base)) {
544a7c30e62SVinod Koul 		ret = PTR_ERR(ethqos->rgmii_base);
545a7c30e62SVinod Koul 		goto err_mem;
546a7c30e62SVinod Koul 	}
547a7c30e62SVinod Koul 
548fd4a5177SVinod Koul 	data = of_device_get_match_data(&pdev->dev);
549fd4a5177SVinod Koul 	ethqos->por = data->por;
550fd4a5177SVinod Koul 	ethqos->num_por = data->num_por;
551a7bf6d7cSBjorn Andersson 	ethqos->rgmii_config_looback_en = data->rgmii_config_looback_en;
552a7c30e62SVinod Koul 
553a7c30e62SVinod Koul 	ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
5548f4ebaaaSWei Yongjun 	if (IS_ERR(ethqos->rgmii_clk)) {
5558f4ebaaaSWei Yongjun 		ret = PTR_ERR(ethqos->rgmii_clk);
556a7c30e62SVinod Koul 		goto err_mem;
557a7c30e62SVinod Koul 	}
558a7c30e62SVinod Koul 
5596c950ca7SBhupesh Sharma 	ret = ethqos_clks_config(ethqos, true);
560a7c30e62SVinod Koul 	if (ret)
561a7c30e62SVinod Koul 		goto err_mem;
562a7c30e62SVinod Koul 
563a7c30e62SVinod Koul 	ethqos->speed = SPEED_1000;
564a7c30e62SVinod Koul 	ethqos_update_rgmii_clk(ethqos, SPEED_1000);
565a7c30e62SVinod Koul 	ethqos_set_func_clk_en(ethqos);
566a7c30e62SVinod Koul 
567a7c30e62SVinod Koul 	plat_dat->bsp_priv = ethqos;
568a7c30e62SVinod Koul 	plat_dat->fix_mac_speed = ethqos_fix_mac_speed;
5694047b9dbSBhupesh Sharma 	plat_dat->dump_debug_regs = rgmii_dump;
570a7c30e62SVinod Koul 	plat_dat->has_gmac4 = 1;
571a7c30e62SVinod Koul 	plat_dat->pmt = 1;
572a7c30e62SVinod Koul 	plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
57354aa39a5SAndrey Konovalov 	if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
57454aa39a5SAndrey Konovalov 		plat_dat->rx_clk_runs_in_lpi = 1;
575a7c30e62SVinod Koul 
576a7c30e62SVinod Koul 	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
577a7c30e62SVinod Koul 	if (ret)
578a7c30e62SVinod Koul 		goto err_clk;
579a7c30e62SVinod Koul 
580a7c30e62SVinod Koul 	return ret;
581a7c30e62SVinod Koul 
582a7c30e62SVinod Koul err_clk:
5836c950ca7SBhupesh Sharma 	ethqos_clks_config(ethqos, false);
584a7c30e62SVinod Koul 
585a7c30e62SVinod Koul err_mem:
586a7c30e62SVinod Koul 	stmmac_remove_config_dt(pdev, plat_dat);
587a7c30e62SVinod Koul 
588a7c30e62SVinod Koul 	return ret;
589a7c30e62SVinod Koul }
590a7c30e62SVinod Koul 
591a7c30e62SVinod Koul static int qcom_ethqos_remove(struct platform_device *pdev)
592a7c30e62SVinod Koul {
593a7c30e62SVinod Koul 	struct qcom_ethqos *ethqos;
594a7c30e62SVinod Koul 	int ret;
595a7c30e62SVinod Koul 
596a7c30e62SVinod Koul 	ethqos = get_stmmac_bsp_priv(&pdev->dev);
597a7c30e62SVinod Koul 	if (!ethqos)
598a7c30e62SVinod Koul 		return -ENODEV;
599a7c30e62SVinod Koul 
600a7c30e62SVinod Koul 	ret = stmmac_pltfr_remove(pdev);
6016c950ca7SBhupesh Sharma 	ethqos_clks_config(ethqos, false);
602a7c30e62SVinod Koul 
603a7c30e62SVinod Koul 	return ret;
604a7c30e62SVinod Koul }
605a7c30e62SVinod Koul 
606a7c30e62SVinod Koul static const struct of_device_id qcom_ethqos_match[] = {
607fd4a5177SVinod Koul 	{ .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data},
608d90b3120SVinod Koul 	{ .compatible = "qcom,sm8150-ethqos", .data = &emac_v2_1_0_data},
609a7c30e62SVinod Koul 	{ }
610a7c30e62SVinod Koul };
611a7c30e62SVinod Koul MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
612a7c30e62SVinod Koul 
613a7c30e62SVinod Koul static struct platform_driver qcom_ethqos_driver = {
614a7c30e62SVinod Koul 	.probe  = qcom_ethqos_probe,
615a7c30e62SVinod Koul 	.remove = qcom_ethqos_remove,
616a7c30e62SVinod Koul 	.driver = {
617a7c30e62SVinod Koul 		.name           = "qcom-ethqos",
618a7c30e62SVinod Koul 		.pm		= &stmmac_pltfr_pm_ops,
619dc54e450SKrzysztof Kozlowski 		.of_match_table = qcom_ethqos_match,
620a7c30e62SVinod Koul 	},
621a7c30e62SVinod Koul };
622a7c30e62SVinod Koul module_platform_driver(qcom_ethqos_driver);
623a7c30e62SVinod Koul 
624a7c30e62SVinod Koul MODULE_DESCRIPTION("Qualcomm ETHQOS driver");
625a7c30e62SVinod Koul MODULE_LICENSE("GPL v2");
626