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>
6a8aa20a6SAndrew Halaney #include <linux/of_net.h>
7a7c30e62SVinod Koul #include <linux/platform_device.h>
8a7c30e62SVinod Koul #include <linux/phy.h>
90dec3b48SBartosz Golaszewski #include <linux/phy/phy.h>
1097f73bc5SBartosz Golaszewski 
11a7c30e62SVinod Koul #include "stmmac.h"
12a7c30e62SVinod Koul #include "stmmac_platform.h"
13a7c30e62SVinod Koul 
14a7c30e62SVinod Koul #define RGMII_IO_MACRO_CONFIG		0x0
15a7c30e62SVinod Koul #define SDCC_HC_REG_DLL_CONFIG		0x4
16b6837619SAndrew Halaney #define SDCC_TEST_CTL			0x8
17a7c30e62SVinod Koul #define SDCC_HC_REG_DDR_CONFIG		0xC
18a7c30e62SVinod Koul #define SDCC_HC_REG_DLL_CONFIG2		0x10
19a7c30e62SVinod Koul #define SDC4_STATUS			0x14
20a7c30e62SVinod Koul #define SDCC_USR_CTL			0x18
21a7c30e62SVinod Koul #define RGMII_IO_MACRO_CONFIG2		0x1C
22a7c30e62SVinod Koul #define RGMII_IO_MACRO_DEBUG1		0x20
23a7c30e62SVinod Koul #define EMAC_SYSTEM_LOW_POWER_DEBUG	0x28
24a7c30e62SVinod Koul 
25a7c30e62SVinod Koul /* RGMII_IO_MACRO_CONFIG fields */
26a7c30e62SVinod Koul #define RGMII_CONFIG_FUNC_CLK_EN		BIT(30)
27a7c30e62SVinod Koul #define RGMII_CONFIG_POS_NEG_DATA_SEL		BIT(23)
28a7c30e62SVinod Koul #define RGMII_CONFIG_GPIO_CFG_RX_INT		GENMASK(21, 20)
29a7c30e62SVinod Koul #define RGMII_CONFIG_GPIO_CFG_TX_INT		GENMASK(19, 17)
30a7c30e62SVinod Koul #define RGMII_CONFIG_MAX_SPD_PRG_9		GENMASK(16, 8)
31a7c30e62SVinod Koul #define RGMII_CONFIG_MAX_SPD_PRG_2		GENMASK(7, 6)
32a7c30e62SVinod Koul #define RGMII_CONFIG_INTF_SEL			GENMASK(5, 4)
33a7c30e62SVinod Koul #define RGMII_CONFIG_BYPASS_TX_ID_EN		BIT(3)
34a7c30e62SVinod Koul #define RGMII_CONFIG_LOOPBACK_EN		BIT(2)
35a7c30e62SVinod Koul #define RGMII_CONFIG_PROG_SWAP			BIT(1)
36a7c30e62SVinod Koul #define RGMII_CONFIG_DDR_MODE			BIT(0)
37ad531dfcSSneh Shah #define RGMII_CONFIG_SGMII_CLK_DVDR		GENMASK(18, 10)
38a7c30e62SVinod Koul 
39a7c30e62SVinod Koul /* SDCC_HC_REG_DLL_CONFIG fields */
40a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_DLL_RST			BIT(30)
41a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_PDN			BIT(29)
42a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_MCLK_FREQ		GENMASK(26, 24)
43a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_CDR_SELEXT		GENMASK(23, 20)
44a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_CDR_EXT_EN		BIT(19)
45a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_CK_OUT_EN		BIT(18)
46a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_CDR_EN			BIT(17)
47a7c30e62SVinod Koul #define SDCC_DLL_CONFIG_DLL_EN			BIT(16)
48a7c30e62SVinod Koul #define SDCC_DLL_MCLK_GATING_EN			BIT(5)
49a7c30e62SVinod Koul #define SDCC_DLL_CDR_FINE_PHASE			GENMASK(3, 2)
50a7c30e62SVinod Koul 
51a7c30e62SVinod Koul /* SDCC_HC_REG_DDR_CONFIG fields */
52a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_PRG_DLY_EN		BIT(31)
53a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY	GENMASK(26, 21)
54a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE	GENMASK(29, 27)
55a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN	BIT(30)
56b6837619SAndrew Halaney #define SDCC_DDR_CONFIG_TCXO_CYCLES_CNT		GENMASK(11, 9)
57a7c30e62SVinod Koul #define SDCC_DDR_CONFIG_PRG_RCLK_DLY		GENMASK(8, 0)
58a7c30e62SVinod Koul 
59a7c30e62SVinod Koul /* SDCC_HC_REG_DLL_CONFIG2 fields */
60a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS		BIT(21)
61a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC		GENMASK(17, 10)
62a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL	GENMASK(3, 2)
63a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW	BIT(1)
64a7c30e62SVinod Koul #define SDCC_DLL_CONFIG2_DDR_CAL_EN		BIT(0)
65a7c30e62SVinod Koul 
66a7c30e62SVinod Koul /* SDC4_STATUS bits */
67a7c30e62SVinod Koul #define SDC4_STATUS_DLL_LOCK			BIT(7)
68a7c30e62SVinod Koul 
69a7c30e62SVinod Koul /* RGMII_IO_MACRO_CONFIG2 fields */
70a7c30e62SVinod Koul #define RGMII_CONFIG2_RSVD_CONFIG15		GENMASK(31, 17)
71a7c30e62SVinod Koul #define RGMII_CONFIG2_RGMII_CLK_SEL_CFG		BIT(16)
72a7c30e62SVinod Koul #define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN	BIT(13)
73a7c30e62SVinod Koul #define RGMII_CONFIG2_CLK_DIVIDE_SEL		BIT(12)
74a7c30e62SVinod Koul #define RGMII_CONFIG2_RX_PROG_SWAP		BIT(7)
75a7c30e62SVinod Koul #define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL	BIT(6)
76a7c30e62SVinod Koul #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN	BIT(5)
77a7c30e62SVinod Koul 
78463120c3SBartosz Golaszewski /* MAC_CTRL_REG bits */
79463120c3SBartosz Golaszewski #define ETHQOS_MAC_CTRL_SPEED_MODE		BIT(14)
80463120c3SBartosz Golaszewski #define ETHQOS_MAC_CTRL_PORT_SEL		BIT(15)
81463120c3SBartosz Golaszewski 
82ad531dfcSSneh Shah #define SGMII_10M_RX_CLK_DVDR			0x31
83ad531dfcSSneh Shah 
84a7c30e62SVinod Koul struct ethqos_emac_por {
85a7c30e62SVinod Koul 	unsigned int offset;
86a7c30e62SVinod Koul 	unsigned int value;
87a7c30e62SVinod Koul };
88a7c30e62SVinod Koul 
89fd4a5177SVinod Koul struct ethqos_emac_driver_data {
90fd4a5177SVinod Koul 	const struct ethqos_emac_por *por;
91fd4a5177SVinod Koul 	unsigned int num_por;
92030f1d59SAndrew Halaney 	bool rgmii_config_loopback_en;
938c4d92e8SBartosz Golaszewski 	bool has_emac_ge_3;
94feeb2716SBartosz Golaszewski 	const char *link_clk_name;
958c4d92e8SBartosz Golaszewski 	bool has_integrated_pcs;
96f100031fSSagar Cheluvegowda 	u32 dma_addr_width;
97b6837619SAndrew Halaney 	struct dwmac4_addrs dwmac4_addrs;
98fd4a5177SVinod Koul };
99fd4a5177SVinod Koul 
100a7c30e62SVinod Koul struct qcom_ethqos {
101a7c30e62SVinod Koul 	struct platform_device *pdev;
102a7c30e62SVinod Koul 	void __iomem *rgmii_base;
103463120c3SBartosz Golaszewski 	void __iomem *mac_base;
10425c4a076SBartosz Golaszewski 	int (*configure_func)(struct qcom_ethqos *ethqos);
105a7c30e62SVinod Koul 
106feeb2716SBartosz Golaszewski 	unsigned int link_clk_rate;
107feeb2716SBartosz Golaszewski 	struct clk *link_clk;
1080dec3b48SBartosz Golaszewski 	struct phy *serdes_phy;
109a7c30e62SVinod Koul 	unsigned int speed;
110a8aa20a6SAndrew Halaney 	phy_interface_t phy_mode;
111a7c30e62SVinod Koul 
112a7c30e62SVinod Koul 	const struct ethqos_emac_por *por;
113a7c30e62SVinod Koul 	unsigned int num_por;
114030f1d59SAndrew Halaney 	bool rgmii_config_loopback_en;
1158c4d92e8SBartosz Golaszewski 	bool has_emac_ge_3;
116a7c30e62SVinod Koul };
117a7c30e62SVinod Koul 
rgmii_readl(struct qcom_ethqos * ethqos,unsigned int offset)118a7c30e62SVinod Koul static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
119a7c30e62SVinod Koul {
120a7c30e62SVinod Koul 	return readl(ethqos->rgmii_base + offset);
121a7c30e62SVinod Koul }
122a7c30e62SVinod Koul 
rgmii_writel(struct qcom_ethqos * ethqos,int value,unsigned int offset)123a7c30e62SVinod Koul static void rgmii_writel(struct qcom_ethqos *ethqos,
124a7c30e62SVinod Koul 			 int value, unsigned int offset)
125a7c30e62SVinod Koul {
126a7c30e62SVinod Koul 	writel(value, ethqos->rgmii_base + offset);
127a7c30e62SVinod Koul }
128a7c30e62SVinod Koul 
rgmii_updatel(struct qcom_ethqos * ethqos,int mask,int val,unsigned int offset)129a7c30e62SVinod Koul static void rgmii_updatel(struct qcom_ethqos *ethqos,
130a7c30e62SVinod Koul 			  int mask, int val, unsigned int offset)
131a7c30e62SVinod Koul {
132a7c30e62SVinod Koul 	unsigned int temp;
133a7c30e62SVinod Koul 
134a7c30e62SVinod Koul 	temp = rgmii_readl(ethqos, offset);
135a7c30e62SVinod Koul 	temp = (temp & ~(mask)) | val;
136a7c30e62SVinod Koul 	rgmii_writel(ethqos, temp, offset);
137a7c30e62SVinod Koul }
138a7c30e62SVinod Koul 
rgmii_dump(void * priv)1394047b9dbSBhupesh Sharma static void rgmii_dump(void *priv)
140a7c30e62SVinod Koul {
1414047b9dbSBhupesh Sharma 	struct qcom_ethqos *ethqos = priv;
142302555a0SBartosz Golaszewski 	struct device *dev = &ethqos->pdev->dev;
1434047b9dbSBhupesh Sharma 
144302555a0SBartosz Golaszewski 	dev_dbg(dev, "Rgmii register dump\n");
145302555a0SBartosz Golaszewski 	dev_dbg(dev, "RGMII_IO_MACRO_CONFIG: %x\n",
146a7c30e62SVinod Koul 		rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG));
147302555a0SBartosz Golaszewski 	dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
148a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG));
149302555a0SBartosz Golaszewski 	dev_dbg(dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
150a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG));
151302555a0SBartosz Golaszewski 	dev_dbg(dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
152a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2));
153302555a0SBartosz Golaszewski 	dev_dbg(dev, "SDC4_STATUS: %x\n",
154a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDC4_STATUS));
155302555a0SBartosz Golaszewski 	dev_dbg(dev, "SDCC_USR_CTL: %x\n",
156a7c30e62SVinod Koul 		rgmii_readl(ethqos, SDCC_USR_CTL));
157302555a0SBartosz Golaszewski 	dev_dbg(dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
158a7c30e62SVinod Koul 		rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2));
159302555a0SBartosz Golaszewski 	dev_dbg(dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
160a7c30e62SVinod Koul 		rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1));
161302555a0SBartosz Golaszewski 	dev_dbg(dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
162a7c30e62SVinod Koul 		rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG));
163a7c30e62SVinod Koul }
164a7c30e62SVinod Koul 
165a7c30e62SVinod Koul /* Clock rates */
166a7c30e62SVinod Koul #define RGMII_1000_NOM_CLK_FREQ			(250 * 1000 * 1000UL)
167a7c30e62SVinod Koul #define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ	 (50 * 1000 * 1000UL)
168a7c30e62SVinod Koul #define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ	  (5 * 1000 * 1000UL)
169a7c30e62SVinod Koul 
170a7c30e62SVinod Koul static void
ethqos_update_link_clk(struct qcom_ethqos * ethqos,unsigned int speed)171feeb2716SBartosz Golaszewski ethqos_update_link_clk(struct qcom_ethqos *ethqos, unsigned int speed)
172a7c30e62SVinod Koul {
173a7c30e62SVinod Koul 	switch (speed) {
174a7c30e62SVinod Koul 	case SPEED_1000:
175feeb2716SBartosz Golaszewski 		ethqos->link_clk_rate =  RGMII_1000_NOM_CLK_FREQ;
176a7c30e62SVinod Koul 		break;
177a7c30e62SVinod Koul 
178a7c30e62SVinod Koul 	case SPEED_100:
179feeb2716SBartosz Golaszewski 		ethqos->link_clk_rate =  RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
180a7c30e62SVinod Koul 		break;
181a7c30e62SVinod Koul 
182a7c30e62SVinod Koul 	case SPEED_10:
183feeb2716SBartosz Golaszewski 		ethqos->link_clk_rate =  RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
184a7c30e62SVinod Koul 		break;
185a7c30e62SVinod Koul 	}
186a7c30e62SVinod Koul 
187feeb2716SBartosz Golaszewski 	clk_set_rate(ethqos->link_clk, ethqos->link_clk_rate);
188a7c30e62SVinod Koul }
189a7c30e62SVinod Koul 
ethqos_set_func_clk_en(struct qcom_ethqos * ethqos)190a7c30e62SVinod Koul static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos)
191a7c30e62SVinod Koul {
192a7c30e62SVinod Koul 	rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN,
193a7c30e62SVinod Koul 		      RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG);
194a7c30e62SVinod Koul }
195a7c30e62SVinod Koul 
196a7c30e62SVinod Koul static const struct ethqos_emac_por emac_v2_3_0_por[] = {
197a7c30e62SVinod Koul 	{ .offset = RGMII_IO_MACRO_CONFIG,	.value = 0x00C01343 },
198a7c30e62SVinod Koul 	{ .offset = SDCC_HC_REG_DLL_CONFIG,	.value = 0x2004642C },
199a7c30e62SVinod Koul 	{ .offset = SDCC_HC_REG_DDR_CONFIG,	.value = 0x00000000 },
200a7c30e62SVinod Koul 	{ .offset = SDCC_HC_REG_DLL_CONFIG2,	.value = 0x00200000 },
201a7c30e62SVinod Koul 	{ .offset = SDCC_USR_CTL,		.value = 0x00010800 },
202a7c30e62SVinod Koul 	{ .offset = RGMII_IO_MACRO_CONFIG2,	.value = 0x00002060 },
203a7c30e62SVinod Koul };
204a7c30e62SVinod Koul 
205fd4a5177SVinod Koul static const struct ethqos_emac_driver_data emac_v2_3_0_data = {
206fd4a5177SVinod Koul 	.por = emac_v2_3_0_por,
207fd4a5177SVinod Koul 	.num_por = ARRAY_SIZE(emac_v2_3_0_por),
208030f1d59SAndrew Halaney 	.rgmii_config_loopback_en = true,
2098c4d92e8SBartosz Golaszewski 	.has_emac_ge_3 = false,
210fd4a5177SVinod Koul };
211fd4a5177SVinod Koul 
212d90b3120SVinod Koul static const struct ethqos_emac_por emac_v2_1_0_por[] = {
213d90b3120SVinod Koul 	{ .offset = RGMII_IO_MACRO_CONFIG,	.value = 0x40C01343 },
214d90b3120SVinod Koul 	{ .offset = SDCC_HC_REG_DLL_CONFIG,	.value = 0x2004642C },
215d90b3120SVinod Koul 	{ .offset = SDCC_HC_REG_DDR_CONFIG,	.value = 0x00000000 },
216d90b3120SVinod Koul 	{ .offset = SDCC_HC_REG_DLL_CONFIG2,	.value = 0x00200000 },
217d90b3120SVinod Koul 	{ .offset = SDCC_USR_CTL,		.value = 0x00010800 },
218d90b3120SVinod Koul 	{ .offset = RGMII_IO_MACRO_CONFIG2,	.value = 0x00002060 },
219d90b3120SVinod Koul };
220d90b3120SVinod Koul 
221d90b3120SVinod Koul static const struct ethqos_emac_driver_data emac_v2_1_0_data = {
222d90b3120SVinod Koul 	.por = emac_v2_1_0_por,
223d90b3120SVinod Koul 	.num_por = ARRAY_SIZE(emac_v2_1_0_por),
224030f1d59SAndrew Halaney 	.rgmii_config_loopback_en = false,
2258c4d92e8SBartosz Golaszewski 	.has_emac_ge_3 = false,
226b6837619SAndrew Halaney };
227b6837619SAndrew Halaney 
228b6837619SAndrew Halaney static const struct ethqos_emac_por emac_v3_0_0_por[] = {
229b6837619SAndrew Halaney 	{ .offset = RGMII_IO_MACRO_CONFIG,	.value = 0x40c01343 },
230b6837619SAndrew Halaney 	{ .offset = SDCC_HC_REG_DLL_CONFIG,	.value = 0x2004642c },
231b6837619SAndrew Halaney 	{ .offset = SDCC_HC_REG_DDR_CONFIG,	.value = 0x80040800 },
232b6837619SAndrew Halaney 	{ .offset = SDCC_HC_REG_DLL_CONFIG2,	.value = 0x00200000 },
233b6837619SAndrew Halaney 	{ .offset = SDCC_USR_CTL,		.value = 0x00010800 },
234b6837619SAndrew Halaney 	{ .offset = RGMII_IO_MACRO_CONFIG2,	.value = 0x00002060 },
235b6837619SAndrew Halaney };
236b6837619SAndrew Halaney 
237b6837619SAndrew Halaney static const struct ethqos_emac_driver_data emac_v3_0_0_data = {
238b6837619SAndrew Halaney 	.por = emac_v3_0_0_por,
239b6837619SAndrew Halaney 	.num_por = ARRAY_SIZE(emac_v3_0_0_por),
240b6837619SAndrew Halaney 	.rgmii_config_loopback_en = false,
2418c4d92e8SBartosz Golaszewski 	.has_emac_ge_3 = true,
2428c4d92e8SBartosz Golaszewski 	.dwmac4_addrs = {
2438c4d92e8SBartosz Golaszewski 		.dma_chan = 0x00008100,
2448c4d92e8SBartosz Golaszewski 		.dma_chan_offset = 0x1000,
2458c4d92e8SBartosz Golaszewski 		.mtl_chan = 0x00008000,
2468c4d92e8SBartosz Golaszewski 		.mtl_chan_offset = 0x1000,
2478c4d92e8SBartosz Golaszewski 		.mtl_ets_ctrl = 0x00008010,
2488c4d92e8SBartosz Golaszewski 		.mtl_ets_ctrl_offset = 0x1000,
2498c4d92e8SBartosz Golaszewski 		.mtl_txq_weight = 0x00008018,
2508c4d92e8SBartosz Golaszewski 		.mtl_txq_weight_offset = 0x1000,
2518c4d92e8SBartosz Golaszewski 		.mtl_send_slp_cred = 0x0000801c,
2528c4d92e8SBartosz Golaszewski 		.mtl_send_slp_cred_offset = 0x1000,
2538c4d92e8SBartosz Golaszewski 		.mtl_high_cred = 0x00008020,
2548c4d92e8SBartosz Golaszewski 		.mtl_high_cred_offset = 0x1000,
2558c4d92e8SBartosz Golaszewski 		.mtl_low_cred = 0x00008024,
2568c4d92e8SBartosz Golaszewski 		.mtl_low_cred_offset = 0x1000,
2578c4d92e8SBartosz Golaszewski 	},
2588c4d92e8SBartosz Golaszewski };
2598c4d92e8SBartosz Golaszewski 
2608c4d92e8SBartosz Golaszewski static const struct ethqos_emac_por emac_v4_0_0_por[] = {
2618c4d92e8SBartosz Golaszewski 	{ .offset = RGMII_IO_MACRO_CONFIG,	.value = 0x40c01343 },
2628c4d92e8SBartosz Golaszewski 	{ .offset = SDCC_HC_REG_DLL_CONFIG,	.value = 0x2004642c },
2638c4d92e8SBartosz Golaszewski 	{ .offset = SDCC_HC_REG_DDR_CONFIG,	.value = 0x80040800 },
2648c4d92e8SBartosz Golaszewski 	{ .offset = SDCC_HC_REG_DLL_CONFIG2,	.value = 0x00200000 },
2658c4d92e8SBartosz Golaszewski 	{ .offset = SDCC_USR_CTL,		.value = 0x00010800 },
2668c4d92e8SBartosz Golaszewski 	{ .offset = RGMII_IO_MACRO_CONFIG2,	.value = 0x00002060 },
2678c4d92e8SBartosz Golaszewski };
2688c4d92e8SBartosz Golaszewski 
2698c4d92e8SBartosz Golaszewski static const struct ethqos_emac_driver_data emac_v4_0_0_data = {
2708c4d92e8SBartosz Golaszewski 	.por = emac_v4_0_0_por,
2718c4d92e8SBartosz Golaszewski 	.num_por = ARRAY_SIZE(emac_v3_0_0_por),
2728c4d92e8SBartosz Golaszewski 	.rgmii_config_loopback_en = false,
2738c4d92e8SBartosz Golaszewski 	.has_emac_ge_3 = true,
2748c4d92e8SBartosz Golaszewski 	.link_clk_name = "phyaux",
2758c4d92e8SBartosz Golaszewski 	.has_integrated_pcs = true,
276f100031fSSagar Cheluvegowda 	.dma_addr_width = 36,
277b6837619SAndrew Halaney 	.dwmac4_addrs = {
278b6837619SAndrew Halaney 		.dma_chan = 0x00008100,
279b6837619SAndrew Halaney 		.dma_chan_offset = 0x1000,
280b6837619SAndrew Halaney 		.mtl_chan = 0x00008000,
281b6837619SAndrew Halaney 		.mtl_chan_offset = 0x1000,
282b6837619SAndrew Halaney 		.mtl_ets_ctrl = 0x00008010,
283b6837619SAndrew Halaney 		.mtl_ets_ctrl_offset = 0x1000,
284b6837619SAndrew Halaney 		.mtl_txq_weight = 0x00008018,
285b6837619SAndrew Halaney 		.mtl_txq_weight_offset = 0x1000,
286b6837619SAndrew Halaney 		.mtl_send_slp_cred = 0x0000801c,
287b6837619SAndrew Halaney 		.mtl_send_slp_cred_offset = 0x1000,
288b6837619SAndrew Halaney 		.mtl_high_cred = 0x00008020,
289b6837619SAndrew Halaney 		.mtl_high_cred_offset = 0x1000,
290b6837619SAndrew Halaney 		.mtl_low_cred = 0x00008024,
291b6837619SAndrew Halaney 		.mtl_low_cred_offset = 0x1000,
292b6837619SAndrew Halaney 	},
293d90b3120SVinod Koul };
294d90b3120SVinod Koul 
ethqos_dll_configure(struct qcom_ethqos * ethqos)295a7c30e62SVinod Koul static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
296a7c30e62SVinod Koul {
297302555a0SBartosz Golaszewski 	struct device *dev = &ethqos->pdev->dev;
298a7c30e62SVinod Koul 	unsigned int val;
299a7c30e62SVinod Koul 	int retry = 1000;
300a7c30e62SVinod Koul 
301a7c30e62SVinod Koul 	/* Set CDR_EN */
302a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN,
303a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_CDR_EN, SDCC_HC_REG_DLL_CONFIG);
304a7c30e62SVinod Koul 
305a7c30e62SVinod Koul 	/* Set CDR_EXT_EN */
306a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EXT_EN,
307a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_CDR_EXT_EN, SDCC_HC_REG_DLL_CONFIG);
308a7c30e62SVinod Koul 
309a7c30e62SVinod Koul 	/* Clear CK_OUT_EN */
310a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
311a7c30e62SVinod Koul 		      0, SDCC_HC_REG_DLL_CONFIG);
312a7c30e62SVinod Koul 
313a7c30e62SVinod Koul 	/* Set DLL_EN */
314a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
315a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
316a7c30e62SVinod Koul 
3178c4d92e8SBartosz Golaszewski 	if (!ethqos->has_emac_ge_3) {
318a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN,
319a7c30e62SVinod Koul 			      0, SDCC_HC_REG_DLL_CONFIG);
320a7c30e62SVinod Koul 
321a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE,
322a7c30e62SVinod Koul 			      0, SDCC_HC_REG_DLL_CONFIG);
323b6837619SAndrew Halaney 	}
324a7c30e62SVinod Koul 
325a7c30e62SVinod Koul 	/* Wait for CK_OUT_EN clear */
326a7c30e62SVinod Koul 	do {
327a7c30e62SVinod Koul 		val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG);
328a7c30e62SVinod Koul 		val &= SDCC_DLL_CONFIG_CK_OUT_EN;
329a7c30e62SVinod Koul 		if (!val)
330a7c30e62SVinod Koul 			break;
331a7c30e62SVinod Koul 		mdelay(1);
332a7c30e62SVinod Koul 		retry--;
333a7c30e62SVinod Koul 	} while (retry > 0);
334a7c30e62SVinod Koul 	if (!retry)
335302555a0SBartosz Golaszewski 		dev_err(dev, "Clear CK_OUT_EN timedout\n");
336a7c30e62SVinod Koul 
337a7c30e62SVinod Koul 	/* Set CK_OUT_EN */
338a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
339a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_CK_OUT_EN, SDCC_HC_REG_DLL_CONFIG);
340a7c30e62SVinod Koul 
341a7c30e62SVinod Koul 	/* Wait for CK_OUT_EN set */
342a7c30e62SVinod Koul 	retry = 1000;
343a7c30e62SVinod Koul 	do {
344a7c30e62SVinod Koul 		val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG);
345a7c30e62SVinod Koul 		val &= SDCC_DLL_CONFIG_CK_OUT_EN;
346a7c30e62SVinod Koul 		if (val)
347a7c30e62SVinod Koul 			break;
348a7c30e62SVinod Koul 		mdelay(1);
349a7c30e62SVinod Koul 		retry--;
350a7c30e62SVinod Koul 	} while (retry > 0);
351a7c30e62SVinod Koul 	if (!retry)
352302555a0SBartosz Golaszewski 		dev_err(dev, "Set CK_OUT_EN timedout\n");
353a7c30e62SVinod Koul 
354a7c30e62SVinod Koul 	/* Set DDR_CAL_EN */
355a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN,
356a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2);
357a7c30e62SVinod Koul 
3588c4d92e8SBartosz Golaszewski 	if (!ethqos->has_emac_ge_3) {
359a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS,
360a7c30e62SVinod Koul 			      0, SDCC_HC_REG_DLL_CONFIG2);
361a7c30e62SVinod Koul 
362a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC,
363a7c30e62SVinod Koul 			      0x1A << 10, SDCC_HC_REG_DLL_CONFIG2);
364a7c30e62SVinod Koul 
365a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL,
366a7c30e62SVinod Koul 			      BIT(2), SDCC_HC_REG_DLL_CONFIG2);
367a7c30e62SVinod Koul 
368a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
369a7c30e62SVinod Koul 			      SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
370a7c30e62SVinod Koul 			      SDCC_HC_REG_DLL_CONFIG2);
371b6837619SAndrew Halaney 	}
372a7c30e62SVinod Koul 
373a7c30e62SVinod Koul 	return 0;
374a7c30e62SVinod Koul }
375a7c30e62SVinod Koul 
ethqos_rgmii_macro_init(struct qcom_ethqos * ethqos)376a7c30e62SVinod Koul static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
377a7c30e62SVinod Koul {
378302555a0SBartosz Golaszewski 	struct device *dev = &ethqos->pdev->dev;
379164a9ebeSAndrew Halaney 	int phase_shift;
380030f1d59SAndrew Halaney 	int loopback;
381164a9ebeSAndrew Halaney 
382164a9ebeSAndrew Halaney 	/* Determine if the PHY adds a 2 ns TX delay or the MAC handles it */
38325c4a076SBartosz Golaszewski 	if (ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_ID ||
38425c4a076SBartosz Golaszewski 	    ethqos->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID)
385164a9ebeSAndrew Halaney 		phase_shift = 0;
386164a9ebeSAndrew Halaney 	else
387164a9ebeSAndrew Halaney 		phase_shift = RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN;
388164a9ebeSAndrew Halaney 
389a7c30e62SVinod Koul 	/* Disable loopback mode */
390a7c30e62SVinod Koul 	rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN,
391a7c30e62SVinod Koul 		      0, RGMII_IO_MACRO_CONFIG2);
392a7c30e62SVinod Koul 
393030f1d59SAndrew Halaney 	/* Determine if this platform wants loopback enabled after programming */
394030f1d59SAndrew Halaney 	if (ethqos->rgmii_config_loopback_en)
395030f1d59SAndrew Halaney 		loopback = RGMII_CONFIG_LOOPBACK_EN;
396030f1d59SAndrew Halaney 	else
397030f1d59SAndrew Halaney 		loopback = 0;
398030f1d59SAndrew Halaney 
399a7c30e62SVinod Koul 	/* Select RGMII, write 0 to interface select */
400a7c30e62SVinod Koul 	rgmii_updatel(ethqos, RGMII_CONFIG_INTF_SEL,
401a7c30e62SVinod Koul 		      0, RGMII_IO_MACRO_CONFIG);
402a7c30e62SVinod Koul 
403a7c30e62SVinod Koul 	switch (ethqos->speed) {
404a7c30e62SVinod Koul 	case SPEED_1000:
405a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
406a7c30e62SVinod Koul 			      RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
407a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
408a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
409a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
410a7c30e62SVinod Koul 			      RGMII_CONFIG_POS_NEG_DATA_SEL,
411a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG);
412a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
413a7c30e62SVinod Koul 			      RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG);
414a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
415a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
416164a9ebeSAndrew Halaney 
417a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
418164a9ebeSAndrew Halaney 			      phase_shift, RGMII_IO_MACRO_CONFIG2);
419a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
420a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
421a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
422a7c30e62SVinod Koul 			      RGMII_CONFIG2_RX_PROG_SWAP,
423a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG2);
424a7c30e62SVinod Koul 
425b6837619SAndrew Halaney 		/* PRG_RCLK_DLY = TCXO period * TCXO_CYCLES_CNT / 2 * RX delay ns,
426b6837619SAndrew Halaney 		 * in practice this becomes PRG_RCLK_DLY = 52 * 4 / 2 * RX delay ns
427b6837619SAndrew Halaney 		 */
4288c4d92e8SBartosz Golaszewski 		if (ethqos->has_emac_ge_3) {
429b6837619SAndrew Halaney 			/* 0.9 ns */
430b6837619SAndrew Halaney 			rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
431b6837619SAndrew Halaney 				      115, SDCC_HC_REG_DDR_CONFIG);
432b6837619SAndrew Halaney 		} else {
433b6837619SAndrew Halaney 			/* 1.8 ns */
434a7c30e62SVinod Koul 			rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
435a7c30e62SVinod Koul 				      57, SDCC_HC_REG_DDR_CONFIG);
436b6837619SAndrew Halaney 		}
437a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN,
438a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_PRG_DLY_EN,
439a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
440a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
441030f1d59SAndrew Halaney 			      loopback, RGMII_IO_MACRO_CONFIG);
442a7c30e62SVinod Koul 		break;
443a7c30e62SVinod Koul 
444a7c30e62SVinod Koul 	case SPEED_100:
445a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
446a7c30e62SVinod Koul 			      RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
447a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
448a7c30e62SVinod Koul 			      RGMII_CONFIG_BYPASS_TX_ID_EN,
449a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG);
450a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
451a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
452a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
453a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
454a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
455a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
456a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
457164a9ebeSAndrew Halaney 			      phase_shift, RGMII_IO_MACRO_CONFIG2);
458a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2,
459a7c30e62SVinod Koul 			      BIT(6), RGMII_IO_MACRO_CONFIG);
460a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
461a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
462b6837619SAndrew Halaney 
4638c4d92e8SBartosz Golaszewski 		if (ethqos->has_emac_ge_3)
464b6837619SAndrew Halaney 			rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
465b6837619SAndrew Halaney 				      RGMII_CONFIG2_RX_PROG_SWAP,
466b6837619SAndrew Halaney 				      RGMII_IO_MACRO_CONFIG2);
467b6837619SAndrew Halaney 		else
468a7c30e62SVinod Koul 			rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
469a7c30e62SVinod Koul 				      0, RGMII_IO_MACRO_CONFIG2);
470b6837619SAndrew Halaney 
471a7c30e62SVinod Koul 		/* Write 0x5 to PRG_RCLK_DLY_CODE */
472a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
473a7c30e62SVinod Koul 			      (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
474a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
475a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
476a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
477a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
478a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
479a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
480a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
481030f1d59SAndrew Halaney 			      loopback, RGMII_IO_MACRO_CONFIG);
482a7c30e62SVinod Koul 		break;
483a7c30e62SVinod Koul 
484a7c30e62SVinod Koul 	case SPEED_10:
485a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
486a7c30e62SVinod Koul 			      RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
487a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
488a7c30e62SVinod Koul 			      RGMII_CONFIG_BYPASS_TX_ID_EN,
489a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG);
490a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
491a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
492a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
493a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG);
494a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
495a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
496a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
497164a9ebeSAndrew Halaney 			      phase_shift, RGMII_IO_MACRO_CONFIG2);
498a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9,
499a7c30e62SVinod Koul 			      BIT(12) | GENMASK(9, 8),
500a7c30e62SVinod Koul 			      RGMII_IO_MACRO_CONFIG);
501a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
502a7c30e62SVinod Koul 			      0, RGMII_IO_MACRO_CONFIG2);
5038c4d92e8SBartosz Golaszewski 		if (ethqos->has_emac_ge_3)
504b6837619SAndrew Halaney 			rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
505b6837619SAndrew Halaney 				      RGMII_CONFIG2_RX_PROG_SWAP,
506b6837619SAndrew Halaney 				      RGMII_IO_MACRO_CONFIG2);
507b6837619SAndrew Halaney 		else
508a7c30e62SVinod Koul 			rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
509a7c30e62SVinod Koul 				      0, RGMII_IO_MACRO_CONFIG2);
510a7c30e62SVinod Koul 		/* Write 0x5 to PRG_RCLK_DLY_CODE */
511a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
512a7c30e62SVinod Koul 			      (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
513a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
514a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
515a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
516a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
517a7c30e62SVinod Koul 			      SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
518a7c30e62SVinod Koul 			      SDCC_HC_REG_DDR_CONFIG);
519a7c30e62SVinod Koul 		rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
520030f1d59SAndrew Halaney 			      loopback, RGMII_IO_MACRO_CONFIG);
521a7c30e62SVinod Koul 		break;
522a7c30e62SVinod Koul 	default:
523302555a0SBartosz Golaszewski 		dev_err(dev, "Invalid speed %d\n", ethqos->speed);
524a7c30e62SVinod Koul 		return -EINVAL;
525a7c30e62SVinod Koul 	}
526a7c30e62SVinod Koul 
527a7c30e62SVinod Koul 	return 0;
528a7c30e62SVinod Koul }
529a7c30e62SVinod Koul 
ethqos_configure_rgmii(struct qcom_ethqos * ethqos)53025c4a076SBartosz Golaszewski static int ethqos_configure_rgmii(struct qcom_ethqos *ethqos)
531a7c30e62SVinod Koul {
532302555a0SBartosz Golaszewski 	struct device *dev = &ethqos->pdev->dev;
533a7c30e62SVinod Koul 	volatile unsigned int dll_lock;
534a7c30e62SVinod Koul 	unsigned int i, retry = 1000;
535a7c30e62SVinod Koul 
536a7c30e62SVinod Koul 	/* Reset to POR values and enable clk */
537a7c30e62SVinod Koul 	for (i = 0; i < ethqos->num_por; i++)
538a7c30e62SVinod Koul 		rgmii_writel(ethqos, ethqos->por[i].value,
539a7c30e62SVinod Koul 			     ethqos->por[i].offset);
540a7c30e62SVinod Koul 	ethqos_set_func_clk_en(ethqos);
541a7c30e62SVinod Koul 
542a7c30e62SVinod Koul 	/* Initialize the DLL first */
543a7c30e62SVinod Koul 
544a7c30e62SVinod Koul 	/* Set DLL_RST */
545a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST,
546a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_DLL_RST, SDCC_HC_REG_DLL_CONFIG);
547a7c30e62SVinod Koul 
548a7c30e62SVinod Koul 	/* Set PDN */
549a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN,
550a7c30e62SVinod Koul 		      SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG);
551a7c30e62SVinod Koul 
5528c4d92e8SBartosz Golaszewski 	if (ethqos->has_emac_ge_3) {
553b6837619SAndrew Halaney 		if (ethqos->speed == SPEED_1000) {
554b6837619SAndrew Halaney 			rgmii_writel(ethqos, 0x1800000, SDCC_TEST_CTL);
555b6837619SAndrew Halaney 			rgmii_writel(ethqos, 0x2C010800, SDCC_USR_CTL);
556b6837619SAndrew Halaney 			rgmii_writel(ethqos, 0xA001, SDCC_HC_REG_DLL_CONFIG2);
557b6837619SAndrew Halaney 		} else {
558b6837619SAndrew Halaney 			rgmii_writel(ethqos, 0x40010800, SDCC_USR_CTL);
559b6837619SAndrew Halaney 			rgmii_writel(ethqos, 0xA001, SDCC_HC_REG_DLL_CONFIG2);
560b6837619SAndrew Halaney 		}
561b6837619SAndrew Halaney 	}
562b6837619SAndrew Halaney 
563a7c30e62SVinod Koul 	/* Clear DLL_RST */
564a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, 0,
565a7c30e62SVinod Koul 		      SDCC_HC_REG_DLL_CONFIG);
566a7c30e62SVinod Koul 
567a7c30e62SVinod Koul 	/* Clear PDN */
568a7c30e62SVinod Koul 	rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, 0,
569a7c30e62SVinod Koul 		      SDCC_HC_REG_DLL_CONFIG);
570a7c30e62SVinod Koul 
571a7c30e62SVinod Koul 	if (ethqos->speed != SPEED_100 && ethqos->speed != SPEED_10) {
572a7c30e62SVinod Koul 		/* Set DLL_EN */
573a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
574a7c30e62SVinod Koul 			      SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
575a7c30e62SVinod Koul 
576a7c30e62SVinod Koul 		/* Set CK_OUT_EN */
577a7c30e62SVinod Koul 		rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
578a7c30e62SVinod Koul 			      SDCC_DLL_CONFIG_CK_OUT_EN,
579a7c30e62SVinod Koul 			      SDCC_HC_REG_DLL_CONFIG);
580a7c30e62SVinod Koul 
581a7c30e62SVinod Koul 		/* Set USR_CTL bit 26 with mask of 3 bits */
5828c4d92e8SBartosz Golaszewski 		if (!ethqos->has_emac_ge_3)
583b6837619SAndrew Halaney 			rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26),
584b6837619SAndrew Halaney 				      SDCC_USR_CTL);
585a7c30e62SVinod Koul 
586a7c30e62SVinod Koul 		/* wait for DLL LOCK */
587a7c30e62SVinod Koul 		do {
588a7c30e62SVinod Koul 			mdelay(1);
589a7c30e62SVinod Koul 			dll_lock = rgmii_readl(ethqos, SDC4_STATUS);
590a7c30e62SVinod Koul 			if (dll_lock & SDC4_STATUS_DLL_LOCK)
591a7c30e62SVinod Koul 				break;
5927d10f077SDejin Zheng 			retry--;
593a7c30e62SVinod Koul 		} while (retry > 0);
594a7c30e62SVinod Koul 		if (!retry)
595302555a0SBartosz Golaszewski 			dev_err(dev, "Timeout while waiting for DLL lock\n");
596a7c30e62SVinod Koul 	}
597a7c30e62SVinod Koul 
598a7c30e62SVinod Koul 	if (ethqos->speed == SPEED_1000)
599a7c30e62SVinod Koul 		ethqos_dll_configure(ethqos);
600a7c30e62SVinod Koul 
601a7c30e62SVinod Koul 	ethqos_rgmii_macro_init(ethqos);
602a7c30e62SVinod Koul 
603a7c30e62SVinod Koul 	return 0;
604a7c30e62SVinod Koul }
605a7c30e62SVinod Koul 
606ad531dfcSSneh Shah /* On interface toggle MAC registers gets reset.
607ad531dfcSSneh Shah  * Configure MAC block for SGMII on ethernet phy link up
608ad531dfcSSneh Shah  */
ethqos_configure_sgmii(struct qcom_ethqos * ethqos)609463120c3SBartosz Golaszewski static int ethqos_configure_sgmii(struct qcom_ethqos *ethqos)
610463120c3SBartosz Golaszewski {
611463120c3SBartosz Golaszewski 	int val;
612463120c3SBartosz Golaszewski 
613463120c3SBartosz Golaszewski 	val = readl(ethqos->mac_base + MAC_CTRL_REG);
614463120c3SBartosz Golaszewski 
615463120c3SBartosz Golaszewski 	switch (ethqos->speed) {
616463120c3SBartosz Golaszewski 	case SPEED_1000:
617463120c3SBartosz Golaszewski 		val &= ~ETHQOS_MAC_CTRL_PORT_SEL;
618463120c3SBartosz Golaszewski 		rgmii_updatel(ethqos, RGMII_CONFIG2_RGMII_CLK_SEL_CFG,
619463120c3SBartosz Golaszewski 			      RGMII_CONFIG2_RGMII_CLK_SEL_CFG,
620463120c3SBartosz Golaszewski 			      RGMII_IO_MACRO_CONFIG2);
621463120c3SBartosz Golaszewski 		break;
622463120c3SBartosz Golaszewski 	case SPEED_100:
623463120c3SBartosz Golaszewski 		val |= ETHQOS_MAC_CTRL_PORT_SEL | ETHQOS_MAC_CTRL_SPEED_MODE;
624463120c3SBartosz Golaszewski 		break;
625463120c3SBartosz Golaszewski 	case SPEED_10:
626463120c3SBartosz Golaszewski 		val |= ETHQOS_MAC_CTRL_PORT_SEL;
627463120c3SBartosz Golaszewski 		val &= ~ETHQOS_MAC_CTRL_SPEED_MODE;
628ad531dfcSSneh Shah 		rgmii_updatel(ethqos, RGMII_CONFIG_SGMII_CLK_DVDR,
629ad531dfcSSneh Shah 			      FIELD_PREP(RGMII_CONFIG_SGMII_CLK_DVDR,
630ad531dfcSSneh Shah 					 SGMII_10M_RX_CLK_DVDR),
631ad531dfcSSneh Shah 			      RGMII_IO_MACRO_CONFIG);
632463120c3SBartosz Golaszewski 		break;
633463120c3SBartosz Golaszewski 	}
634463120c3SBartosz Golaszewski 
635463120c3SBartosz Golaszewski 	writel(val, ethqos->mac_base + MAC_CTRL_REG);
636463120c3SBartosz Golaszewski 
637463120c3SBartosz Golaszewski 	return val;
638463120c3SBartosz Golaszewski }
639463120c3SBartosz Golaszewski 
ethqos_configure(struct qcom_ethqos * ethqos)64025c4a076SBartosz Golaszewski static int ethqos_configure(struct qcom_ethqos *ethqos)
64125c4a076SBartosz Golaszewski {
64225c4a076SBartosz Golaszewski 	return ethqos->configure_func(ethqos);
64325c4a076SBartosz Golaszewski }
64425c4a076SBartosz Golaszewski 
ethqos_fix_mac_speed(void * priv,unsigned int speed,unsigned int mode)6451fc04a0bSShenwei Wang static void ethqos_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode)
646a7c30e62SVinod Koul {
647a7c30e62SVinod Koul 	struct qcom_ethqos *ethqos = priv;
648a7c30e62SVinod Koul 
649a7c30e62SVinod Koul 	ethqos->speed = speed;
650feeb2716SBartosz Golaszewski 	ethqos_update_link_clk(ethqos, speed);
651a7c30e62SVinod Koul 	ethqos_configure(ethqos);
652a7c30e62SVinod Koul }
653a7c30e62SVinod Koul 
qcom_ethqos_serdes_powerup(struct net_device * ndev,void * priv)6540dec3b48SBartosz Golaszewski static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv)
6550dec3b48SBartosz Golaszewski {
6560dec3b48SBartosz Golaszewski 	struct qcom_ethqos *ethqos = priv;
6570dec3b48SBartosz Golaszewski 	int ret;
6580dec3b48SBartosz Golaszewski 
6590dec3b48SBartosz Golaszewski 	ret = phy_init(ethqos->serdes_phy);
6600dec3b48SBartosz Golaszewski 	if (ret)
6610dec3b48SBartosz Golaszewski 		return ret;
6620dec3b48SBartosz Golaszewski 
6630dec3b48SBartosz Golaszewski 	ret = phy_power_on(ethqos->serdes_phy);
6640dec3b48SBartosz Golaszewski 	if (ret)
6650dec3b48SBartosz Golaszewski 		return ret;
6660dec3b48SBartosz Golaszewski 
6670dec3b48SBartosz Golaszewski 	return phy_set_speed(ethqos->serdes_phy, ethqos->speed);
6680dec3b48SBartosz Golaszewski }
6690dec3b48SBartosz Golaszewski 
qcom_ethqos_serdes_powerdown(struct net_device * ndev,void * priv)6700dec3b48SBartosz Golaszewski static void qcom_ethqos_serdes_powerdown(struct net_device *ndev, void *priv)
6710dec3b48SBartosz Golaszewski {
6720dec3b48SBartosz Golaszewski 	struct qcom_ethqos *ethqos = priv;
6730dec3b48SBartosz Golaszewski 
6740dec3b48SBartosz Golaszewski 	phy_power_off(ethqos->serdes_phy);
6750dec3b48SBartosz Golaszewski 	phy_exit(ethqos->serdes_phy);
6760dec3b48SBartosz Golaszewski }
6770dec3b48SBartosz Golaszewski 
ethqos_clks_config(void * priv,bool enabled)6786c950ca7SBhupesh Sharma static int ethqos_clks_config(void *priv, bool enabled)
6796c950ca7SBhupesh Sharma {
6806c950ca7SBhupesh Sharma 	struct qcom_ethqos *ethqos = priv;
6816c950ca7SBhupesh Sharma 	int ret = 0;
6826c950ca7SBhupesh Sharma 
6836c950ca7SBhupesh Sharma 	if (enabled) {
684feeb2716SBartosz Golaszewski 		ret = clk_prepare_enable(ethqos->link_clk);
6856c950ca7SBhupesh Sharma 		if (ret) {
686feeb2716SBartosz Golaszewski 			dev_err(&ethqos->pdev->dev, "link_clk enable failed\n");
6876c950ca7SBhupesh Sharma 			return ret;
6886c950ca7SBhupesh Sharma 		}
689ffba2123SBjorn Andersson 
690ffba2123SBjorn Andersson 		/* Enable functional clock to prevent DMA reset to timeout due
691ffba2123SBjorn Andersson 		 * to lacking PHY clock after the hardware block has been power
692ffba2123SBjorn Andersson 		 * cycled. The actual configuration will be adjusted once
693ffba2123SBjorn Andersson 		 * ethqos_fix_mac_speed() is invoked.
694ffba2123SBjorn Andersson 		 */
695ffba2123SBjorn Andersson 		ethqos_set_func_clk_en(ethqos);
6966c950ca7SBhupesh Sharma 	} else {
697feeb2716SBartosz Golaszewski 		clk_disable_unprepare(ethqos->link_clk);
6986c950ca7SBhupesh Sharma 	}
6996c950ca7SBhupesh Sharma 
7006c950ca7SBhupesh Sharma 	return ret;
7016c950ca7SBhupesh Sharma }
7026c950ca7SBhupesh Sharma 
ethqos_clks_disable(void * data)7039fc68f23SBartosz Golaszewski static void ethqos_clks_disable(void *data)
7049fc68f23SBartosz Golaszewski {
7059fc68f23SBartosz Golaszewski 	ethqos_clks_config(data, false);
7069fc68f23SBartosz Golaszewski }
7079fc68f23SBartosz Golaszewski 
ethqos_ptp_clk_freq_config(struct stmmac_priv * priv)708db845b9bSAndrew Halaney static void ethqos_ptp_clk_freq_config(struct stmmac_priv *priv)
709db845b9bSAndrew Halaney {
710db845b9bSAndrew Halaney 	struct plat_stmmacenet_data *plat_dat = priv->plat;
711db845b9bSAndrew Halaney 	int err;
712db845b9bSAndrew Halaney 
713db845b9bSAndrew Halaney 	if (!plat_dat->clk_ptp_ref)
714db845b9bSAndrew Halaney 		return;
715db845b9bSAndrew Halaney 
716db845b9bSAndrew Halaney 	/* Max the PTP ref clock out to get the best resolution possible */
717db845b9bSAndrew Halaney 	err = clk_set_rate(plat_dat->clk_ptp_ref, ULONG_MAX);
718db845b9bSAndrew Halaney 	if (err)
719db845b9bSAndrew Halaney 		netdev_err(priv->dev, "Failed to max out clk_ptp_ref: %d\n", err);
720db845b9bSAndrew Halaney 	plat_dat->clk_ptp_rate = clk_get_rate(plat_dat->clk_ptp_ref);
721db845b9bSAndrew Halaney 
722db845b9bSAndrew Halaney 	netdev_dbg(priv->dev, "PTP rate %d\n", plat_dat->clk_ptp_rate);
723db845b9bSAndrew Halaney }
724db845b9bSAndrew Halaney 
qcom_ethqos_probe(struct platform_device * pdev)725a7c30e62SVinod Koul static int qcom_ethqos_probe(struct platform_device *pdev)
726a7c30e62SVinod Koul {
727a7c30e62SVinod Koul 	struct device_node *np = pdev->dev.of_node;
7287b5e64a9SBartosz Golaszewski 	const struct ethqos_emac_driver_data *data;
729a7c30e62SVinod Koul 	struct plat_stmmacenet_data *plat_dat;
730a7c30e62SVinod Koul 	struct stmmac_resources stmmac_res;
731302555a0SBartosz Golaszewski 	struct device *dev = &pdev->dev;
732a7c30e62SVinod Koul 	struct qcom_ethqos *ethqos;
733a7c30e62SVinod Koul 	int ret;
734a7c30e62SVinod Koul 
735a7c30e62SVinod Koul 	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
736a7c30e62SVinod Koul 	if (ret)
73727381e72SAndrew Halaney 		return dev_err_probe(dev, ret,
73827381e72SAndrew Halaney 				     "Failed to get platform resources\n");
739a7c30e62SVinod Koul 
740061425d9SBartosz Golaszewski 	plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
741a7c30e62SVinod Koul 	if (IS_ERR(plat_dat)) {
742b2f3d915SAndrew Halaney 		return dev_err_probe(dev, PTR_ERR(plat_dat),
743b2f3d915SAndrew Halaney 				     "dt configuration failed\n");
744a7c30e62SVinod Koul 	}
745a7c30e62SVinod Koul 
7466c950ca7SBhupesh Sharma 	plat_dat->clks_config = ethqos_clks_config;
7476c950ca7SBhupesh Sharma 
748302555a0SBartosz Golaszewski 	ethqos = devm_kzalloc(dev, sizeof(*ethqos), GFP_KERNEL);
749061425d9SBartosz Golaszewski 	if (!ethqos)
750061425d9SBartosz Golaszewski 		return -ENOMEM;
751a7c30e62SVinod Koul 
752a8aa20a6SAndrew Halaney 	ret = of_get_phy_mode(np, &ethqos->phy_mode);
753a8aa20a6SAndrew Halaney 	if (ret)
754a8aa20a6SAndrew Halaney 		return dev_err_probe(dev, ret, "Failed to get phy mode\n");
75525c4a076SBartosz Golaszewski 	switch (ethqos->phy_mode) {
75625c4a076SBartosz Golaszewski 	case PHY_INTERFACE_MODE_RGMII:
75725c4a076SBartosz Golaszewski 	case PHY_INTERFACE_MODE_RGMII_ID:
75825c4a076SBartosz Golaszewski 	case PHY_INTERFACE_MODE_RGMII_RXID:
75925c4a076SBartosz Golaszewski 	case PHY_INTERFACE_MODE_RGMII_TXID:
76025c4a076SBartosz Golaszewski 		ethqos->configure_func = ethqos_configure_rgmii;
76125c4a076SBartosz Golaszewski 		break;
762463120c3SBartosz Golaszewski 	case PHY_INTERFACE_MODE_SGMII:
763463120c3SBartosz Golaszewski 		ethqos->configure_func = ethqos_configure_sgmii;
764463120c3SBartosz Golaszewski 		break;
76525c4a076SBartosz Golaszewski 	default:
76627381e72SAndrew Halaney 		dev_err(dev, "Unsupported phy mode %s\n",
76727381e72SAndrew Halaney 			phy_modes(ethqos->phy_mode));
768061425d9SBartosz Golaszewski 		return -EINVAL;
76925c4a076SBartosz Golaszewski 	}
77025c4a076SBartosz Golaszewski 
771a7c30e62SVinod Koul 	ethqos->pdev = pdev;
7723a5a32b5SYang Yingliang 	ethqos->rgmii_base = devm_platform_ioremap_resource_byname(pdev, "rgmii");
773061425d9SBartosz Golaszewski 	if (IS_ERR(ethqos->rgmii_base))
77427381e72SAndrew Halaney 		return dev_err_probe(dev, PTR_ERR(ethqos->rgmii_base),
77527381e72SAndrew Halaney 				     "Failed to map rgmii resource\n");
776a7c30e62SVinod Koul 
777463120c3SBartosz Golaszewski 	ethqos->mac_base = stmmac_res.addr;
778463120c3SBartosz Golaszewski 
779302555a0SBartosz Golaszewski 	data = of_device_get_match_data(dev);
780fd4a5177SVinod Koul 	ethqos->por = data->por;
781fd4a5177SVinod Koul 	ethqos->num_por = data->num_por;
782030f1d59SAndrew Halaney 	ethqos->rgmii_config_loopback_en = data->rgmii_config_loopback_en;
7838c4d92e8SBartosz Golaszewski 	ethqos->has_emac_ge_3 = data->has_emac_ge_3;
784a7c30e62SVinod Koul 
785feeb2716SBartosz Golaszewski 	ethqos->link_clk = devm_clk_get(dev, data->link_clk_name ?: "rgmii");
786061425d9SBartosz Golaszewski 	if (IS_ERR(ethqos->link_clk))
78727381e72SAndrew Halaney 		return dev_err_probe(dev, PTR_ERR(ethqos->link_clk),
78827381e72SAndrew Halaney 				     "Failed to get link_clk\n");
789a7c30e62SVinod Koul 
7906c950ca7SBhupesh Sharma 	ret = ethqos_clks_config(ethqos, true);
791a7c30e62SVinod Koul 	if (ret)
792061425d9SBartosz Golaszewski 		return ret;
793a7c30e62SVinod Koul 
794302555a0SBartosz Golaszewski 	ret = devm_add_action_or_reset(dev, ethqos_clks_disable, ethqos);
7959fc68f23SBartosz Golaszewski 	if (ret)
796061425d9SBartosz Golaszewski 		return ret;
7979fc68f23SBartosz Golaszewski 
7980dec3b48SBartosz Golaszewski 	ethqos->serdes_phy = devm_phy_optional_get(dev, "serdes");
799061425d9SBartosz Golaszewski 	if (IS_ERR(ethqos->serdes_phy))
80027381e72SAndrew Halaney 		return dev_err_probe(dev, PTR_ERR(ethqos->serdes_phy),
80127381e72SAndrew Halaney 				     "Failed to get serdes phy\n");
8020dec3b48SBartosz Golaszewski 
803a7c30e62SVinod Koul 	ethqos->speed = SPEED_1000;
804feeb2716SBartosz Golaszewski 	ethqos_update_link_clk(ethqos, SPEED_1000);
805a7c30e62SVinod Koul 	ethqos_set_func_clk_en(ethqos);
806a7c30e62SVinod Koul 
807a7c30e62SVinod Koul 	plat_dat->bsp_priv = ethqos;
808a7c30e62SVinod Koul 	plat_dat->fix_mac_speed = ethqos_fix_mac_speed;
8094047b9dbSBhupesh Sharma 	plat_dat->dump_debug_regs = rgmii_dump;
810db845b9bSAndrew Halaney 	plat_dat->ptp_clk_freq_config = ethqos_ptp_clk_freq_config;
811a7c30e62SVinod Koul 	plat_dat->has_gmac4 = 1;
8128c4d92e8SBartosz Golaszewski 	if (ethqos->has_emac_ge_3)
813b6837619SAndrew Halaney 		plat_dat->dwmac4_addrs = &data->dwmac4_addrs;
814a7c30e62SVinod Koul 	plat_dat->pmt = 1;
81568861a3bSBartosz Golaszewski 	if (of_property_read_bool(np, "snps,tso"))
81668861a3bSBartosz Golaszewski 		plat_dat->flags |= STMMAC_FLAG_TSO_EN;
81754aa39a5SAndrey Konovalov 	if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
818743dd1dbSBartosz Golaszewski 		plat_dat->flags |= STMMAC_FLAG_RX_CLK_RUNS_IN_LPI;
819d26979f1SBartosz Golaszewski 	if (data->has_integrated_pcs)
820d26979f1SBartosz Golaszewski 		plat_dat->flags |= STMMAC_FLAG_HAS_INTEGRATED_PCS;
821f100031fSSagar Cheluvegowda 	if (data->dma_addr_width)
822f100031fSSagar Cheluvegowda 		plat_dat->host_dma_width = data->dma_addr_width;
823a7c30e62SVinod Koul 
8240dec3b48SBartosz Golaszewski 	if (ethqos->serdes_phy) {
8250dec3b48SBartosz Golaszewski 		plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup;
8260dec3b48SBartosz Golaszewski 		plat_dat->serdes_powerdown  = qcom_ethqos_serdes_powerdown;
8270dec3b48SBartosz Golaszewski 	}
8280dec3b48SBartosz Golaszewski 
8294194f32aSBartosz Golaszewski 	return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
830a7c30e62SVinod Koul }
831a7c30e62SVinod Koul 
832a7c30e62SVinod Koul static const struct of_device_id qcom_ethqos_match[] = {
833fd4a5177SVinod Koul 	{ .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data},
8348c4d92e8SBartosz Golaszewski 	{ .compatible = "qcom,sa8775p-ethqos", .data = &emac_v4_0_0_data},
835b6837619SAndrew Halaney 	{ .compatible = "qcom,sc8280xp-ethqos", .data = &emac_v3_0_0_data},
836d90b3120SVinod Koul 	{ .compatible = "qcom,sm8150-ethqos", .data = &emac_v2_1_0_data},
837a7c30e62SVinod Koul 	{ }
838a7c30e62SVinod Koul };
839a7c30e62SVinod Koul MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
840a7c30e62SVinod Koul 
841a7c30e62SVinod Koul static struct platform_driver qcom_ethqos_driver = {
842a7c30e62SVinod Koul 	.probe  = qcom_ethqos_probe,
843a7c30e62SVinod Koul 	.driver = {
844a7c30e62SVinod Koul 		.name           = "qcom-ethqos",
845a7c30e62SVinod Koul 		.pm		= &stmmac_pltfr_pm_ops,
846dc54e450SKrzysztof Kozlowski 		.of_match_table = qcom_ethqos_match,
847a7c30e62SVinod Koul 	},
848a7c30e62SVinod Koul };
849a7c30e62SVinod Koul module_platform_driver(qcom_ethqos_driver);
850a7c30e62SVinod Koul 
851a7c30e62SVinod Koul MODULE_DESCRIPTION("Qualcomm ETHQOS driver");
852a7c30e62SVinod Koul MODULE_LICENSE("GPL v2");
853