1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright (c) 2018-19, Linaro Limited
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include <linux/module.h>
5*4882a593Smuzhiyun #include <linux/of.h>
6*4882a593Smuzhiyun #include <linux/of_device.h>
7*4882a593Smuzhiyun #include <linux/platform_device.h>
8*4882a593Smuzhiyun #include <linux/phy.h>
9*4882a593Smuzhiyun #include "stmmac.h"
10*4882a593Smuzhiyun #include "stmmac_platform.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #define RGMII_IO_MACRO_CONFIG 0x0
13*4882a593Smuzhiyun #define SDCC_HC_REG_DLL_CONFIG 0x4
14*4882a593Smuzhiyun #define SDCC_HC_REG_DDR_CONFIG 0xC
15*4882a593Smuzhiyun #define SDCC_HC_REG_DLL_CONFIG2 0x10
16*4882a593Smuzhiyun #define SDC4_STATUS 0x14
17*4882a593Smuzhiyun #define SDCC_USR_CTL 0x18
18*4882a593Smuzhiyun #define RGMII_IO_MACRO_CONFIG2 0x1C
19*4882a593Smuzhiyun #define RGMII_IO_MACRO_DEBUG1 0x20
20*4882a593Smuzhiyun #define EMAC_SYSTEM_LOW_POWER_DEBUG 0x28
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /* RGMII_IO_MACRO_CONFIG fields */
23*4882a593Smuzhiyun #define RGMII_CONFIG_FUNC_CLK_EN BIT(30)
24*4882a593Smuzhiyun #define RGMII_CONFIG_POS_NEG_DATA_SEL BIT(23)
25*4882a593Smuzhiyun #define RGMII_CONFIG_GPIO_CFG_RX_INT GENMASK(21, 20)
26*4882a593Smuzhiyun #define RGMII_CONFIG_GPIO_CFG_TX_INT GENMASK(19, 17)
27*4882a593Smuzhiyun #define RGMII_CONFIG_MAX_SPD_PRG_9 GENMASK(16, 8)
28*4882a593Smuzhiyun #define RGMII_CONFIG_MAX_SPD_PRG_2 GENMASK(7, 6)
29*4882a593Smuzhiyun #define RGMII_CONFIG_INTF_SEL GENMASK(5, 4)
30*4882a593Smuzhiyun #define RGMII_CONFIG_BYPASS_TX_ID_EN BIT(3)
31*4882a593Smuzhiyun #define RGMII_CONFIG_LOOPBACK_EN BIT(2)
32*4882a593Smuzhiyun #define RGMII_CONFIG_PROG_SWAP BIT(1)
33*4882a593Smuzhiyun #define RGMII_CONFIG_DDR_MODE BIT(0)
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /* SDCC_HC_REG_DLL_CONFIG fields */
36*4882a593Smuzhiyun #define SDCC_DLL_CONFIG_DLL_RST BIT(30)
37*4882a593Smuzhiyun #define SDCC_DLL_CONFIG_PDN BIT(29)
38*4882a593Smuzhiyun #define SDCC_DLL_CONFIG_MCLK_FREQ GENMASK(26, 24)
39*4882a593Smuzhiyun #define SDCC_DLL_CONFIG_CDR_SELEXT GENMASK(23, 20)
40*4882a593Smuzhiyun #define SDCC_DLL_CONFIG_CDR_EXT_EN BIT(19)
41*4882a593Smuzhiyun #define SDCC_DLL_CONFIG_CK_OUT_EN BIT(18)
42*4882a593Smuzhiyun #define SDCC_DLL_CONFIG_CDR_EN BIT(17)
43*4882a593Smuzhiyun #define SDCC_DLL_CONFIG_DLL_EN BIT(16)
44*4882a593Smuzhiyun #define SDCC_DLL_MCLK_GATING_EN BIT(5)
45*4882a593Smuzhiyun #define SDCC_DLL_CDR_FINE_PHASE GENMASK(3, 2)
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* SDCC_HC_REG_DDR_CONFIG fields */
48*4882a593Smuzhiyun #define SDCC_DDR_CONFIG_PRG_DLY_EN BIT(31)
49*4882a593Smuzhiyun #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY GENMASK(26, 21)
50*4882a593Smuzhiyun #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE GENMASK(29, 27)
51*4882a593Smuzhiyun #define SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN BIT(30)
52*4882a593Smuzhiyun #define SDCC_DDR_CONFIG_PRG_RCLK_DLY GENMASK(8, 0)
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* SDCC_HC_REG_DLL_CONFIG2 fields */
55*4882a593Smuzhiyun #define SDCC_DLL_CONFIG2_DLL_CLOCK_DIS BIT(21)
56*4882a593Smuzhiyun #define SDCC_DLL_CONFIG2_MCLK_FREQ_CALC GENMASK(17, 10)
57*4882a593Smuzhiyun #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL GENMASK(3, 2)
58*4882a593Smuzhiyun #define SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW BIT(1)
59*4882a593Smuzhiyun #define SDCC_DLL_CONFIG2_DDR_CAL_EN BIT(0)
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* SDC4_STATUS bits */
62*4882a593Smuzhiyun #define SDC4_STATUS_DLL_LOCK BIT(7)
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /* RGMII_IO_MACRO_CONFIG2 fields */
65*4882a593Smuzhiyun #define RGMII_CONFIG2_RSVD_CONFIG15 GENMASK(31, 17)
66*4882a593Smuzhiyun #define RGMII_CONFIG2_RGMII_CLK_SEL_CFG BIT(16)
67*4882a593Smuzhiyun #define RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN BIT(13)
68*4882a593Smuzhiyun #define RGMII_CONFIG2_CLK_DIVIDE_SEL BIT(12)
69*4882a593Smuzhiyun #define RGMII_CONFIG2_RX_PROG_SWAP BIT(7)
70*4882a593Smuzhiyun #define RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL BIT(6)
71*4882a593Smuzhiyun #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5)
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun struct ethqos_emac_por {
74*4882a593Smuzhiyun unsigned int offset;
75*4882a593Smuzhiyun unsigned int value;
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun struct ethqos_emac_driver_data {
79*4882a593Smuzhiyun const struct ethqos_emac_por *por;
80*4882a593Smuzhiyun unsigned int num_por;
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun struct qcom_ethqos {
84*4882a593Smuzhiyun struct platform_device *pdev;
85*4882a593Smuzhiyun void __iomem *rgmii_base;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun unsigned int rgmii_clk_rate;
88*4882a593Smuzhiyun struct clk *rgmii_clk;
89*4882a593Smuzhiyun unsigned int speed;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun const struct ethqos_emac_por *por;
92*4882a593Smuzhiyun unsigned int num_por;
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun
rgmii_readl(struct qcom_ethqos * ethqos,unsigned int offset)95*4882a593Smuzhiyun static int rgmii_readl(struct qcom_ethqos *ethqos, unsigned int offset)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun return readl(ethqos->rgmii_base + offset);
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
rgmii_writel(struct qcom_ethqos * ethqos,int value,unsigned int offset)100*4882a593Smuzhiyun static void rgmii_writel(struct qcom_ethqos *ethqos,
101*4882a593Smuzhiyun int value, unsigned int offset)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun writel(value, ethqos->rgmii_base + offset);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
rgmii_updatel(struct qcom_ethqos * ethqos,int mask,int val,unsigned int offset)106*4882a593Smuzhiyun static void rgmii_updatel(struct qcom_ethqos *ethqos,
107*4882a593Smuzhiyun int mask, int val, unsigned int offset)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun unsigned int temp;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun temp = rgmii_readl(ethqos, offset);
112*4882a593Smuzhiyun temp = (temp & ~(mask)) | val;
113*4882a593Smuzhiyun rgmii_writel(ethqos, temp, offset);
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
rgmii_dump(struct qcom_ethqos * ethqos)116*4882a593Smuzhiyun static void rgmii_dump(struct qcom_ethqos *ethqos)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "Rgmii register dump\n");
119*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG: %x\n",
120*4882a593Smuzhiyun rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG));
121*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG: %x\n",
122*4882a593Smuzhiyun rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG));
123*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DDR_CONFIG: %x\n",
124*4882a593Smuzhiyun rgmii_readl(ethqos, SDCC_HC_REG_DDR_CONFIG));
125*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "SDCC_HC_REG_DLL_CONFIG2: %x\n",
126*4882a593Smuzhiyun rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG2));
127*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "SDC4_STATUS: %x\n",
128*4882a593Smuzhiyun rgmii_readl(ethqos, SDC4_STATUS));
129*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "SDCC_USR_CTL: %x\n",
130*4882a593Smuzhiyun rgmii_readl(ethqos, SDCC_USR_CTL));
131*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_CONFIG2: %x\n",
132*4882a593Smuzhiyun rgmii_readl(ethqos, RGMII_IO_MACRO_CONFIG2));
133*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "RGMII_IO_MACRO_DEBUG1: %x\n",
134*4882a593Smuzhiyun rgmii_readl(ethqos, RGMII_IO_MACRO_DEBUG1));
135*4882a593Smuzhiyun dev_dbg(ðqos->pdev->dev, "EMAC_SYSTEM_LOW_POWER_DEBUG: %x\n",
136*4882a593Smuzhiyun rgmii_readl(ethqos, EMAC_SYSTEM_LOW_POWER_DEBUG));
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* Clock rates */
140*4882a593Smuzhiyun #define RGMII_1000_NOM_CLK_FREQ (250 * 1000 * 1000UL)
141*4882a593Smuzhiyun #define RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ (50 * 1000 * 1000UL)
142*4882a593Smuzhiyun #define RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ (5 * 1000 * 1000UL)
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun static void
ethqos_update_rgmii_clk(struct qcom_ethqos * ethqos,unsigned int speed)145*4882a593Smuzhiyun ethqos_update_rgmii_clk(struct qcom_ethqos *ethqos, unsigned int speed)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun switch (speed) {
148*4882a593Smuzhiyun case SPEED_1000:
149*4882a593Smuzhiyun ethqos->rgmii_clk_rate = RGMII_1000_NOM_CLK_FREQ;
150*4882a593Smuzhiyun break;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun case SPEED_100:
153*4882a593Smuzhiyun ethqos->rgmii_clk_rate = RGMII_ID_MODE_100_LOW_SVS_CLK_FREQ;
154*4882a593Smuzhiyun break;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun case SPEED_10:
157*4882a593Smuzhiyun ethqos->rgmii_clk_rate = RGMII_ID_MODE_10_LOW_SVS_CLK_FREQ;
158*4882a593Smuzhiyun break;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun clk_set_rate(ethqos->rgmii_clk, ethqos->rgmii_clk_rate);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
ethqos_set_func_clk_en(struct qcom_ethqos * ethqos)164*4882a593Smuzhiyun static void ethqos_set_func_clk_en(struct qcom_ethqos *ethqos)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_FUNC_CLK_EN,
167*4882a593Smuzhiyun RGMII_CONFIG_FUNC_CLK_EN, RGMII_IO_MACRO_CONFIG);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun static const struct ethqos_emac_por emac_v2_3_0_por[] = {
171*4882a593Smuzhiyun { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x00C01343 },
172*4882a593Smuzhiyun { .offset = SDCC_HC_REG_DLL_CONFIG, .value = 0x2004642C },
173*4882a593Smuzhiyun { .offset = SDCC_HC_REG_DDR_CONFIG, .value = 0x00000000 },
174*4882a593Smuzhiyun { .offset = SDCC_HC_REG_DLL_CONFIG2, .value = 0x00200000 },
175*4882a593Smuzhiyun { .offset = SDCC_USR_CTL, .value = 0x00010800 },
176*4882a593Smuzhiyun { .offset = RGMII_IO_MACRO_CONFIG2, .value = 0x00002060 },
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun static const struct ethqos_emac_driver_data emac_v2_3_0_data = {
180*4882a593Smuzhiyun .por = emac_v2_3_0_por,
181*4882a593Smuzhiyun .num_por = ARRAY_SIZE(emac_v2_3_0_por),
182*4882a593Smuzhiyun };
183*4882a593Smuzhiyun
ethqos_dll_configure(struct qcom_ethqos * ethqos)184*4882a593Smuzhiyun static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun unsigned int val;
187*4882a593Smuzhiyun int retry = 1000;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun /* Set CDR_EN */
190*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EN,
191*4882a593Smuzhiyun SDCC_DLL_CONFIG_CDR_EN, SDCC_HC_REG_DLL_CONFIG);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /* Set CDR_EXT_EN */
194*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CDR_EXT_EN,
195*4882a593Smuzhiyun SDCC_DLL_CONFIG_CDR_EXT_EN, SDCC_HC_REG_DLL_CONFIG);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* Clear CK_OUT_EN */
198*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
199*4882a593Smuzhiyun 0, SDCC_HC_REG_DLL_CONFIG);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /* Set DLL_EN */
202*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
203*4882a593Smuzhiyun SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_MCLK_GATING_EN,
206*4882a593Smuzhiyun 0, SDCC_HC_REG_DLL_CONFIG);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CDR_FINE_PHASE,
209*4882a593Smuzhiyun 0, SDCC_HC_REG_DLL_CONFIG);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /* Wait for CK_OUT_EN clear */
212*4882a593Smuzhiyun do {
213*4882a593Smuzhiyun val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG);
214*4882a593Smuzhiyun val &= SDCC_DLL_CONFIG_CK_OUT_EN;
215*4882a593Smuzhiyun if (!val)
216*4882a593Smuzhiyun break;
217*4882a593Smuzhiyun mdelay(1);
218*4882a593Smuzhiyun retry--;
219*4882a593Smuzhiyun } while (retry > 0);
220*4882a593Smuzhiyun if (!retry)
221*4882a593Smuzhiyun dev_err(ðqos->pdev->dev, "Clear CK_OUT_EN timedout\n");
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /* Set CK_OUT_EN */
224*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
225*4882a593Smuzhiyun SDCC_DLL_CONFIG_CK_OUT_EN, SDCC_HC_REG_DLL_CONFIG);
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /* Wait for CK_OUT_EN set */
228*4882a593Smuzhiyun retry = 1000;
229*4882a593Smuzhiyun do {
230*4882a593Smuzhiyun val = rgmii_readl(ethqos, SDCC_HC_REG_DLL_CONFIG);
231*4882a593Smuzhiyun val &= SDCC_DLL_CONFIG_CK_OUT_EN;
232*4882a593Smuzhiyun if (val)
233*4882a593Smuzhiyun break;
234*4882a593Smuzhiyun mdelay(1);
235*4882a593Smuzhiyun retry--;
236*4882a593Smuzhiyun } while (retry > 0);
237*4882a593Smuzhiyun if (!retry)
238*4882a593Smuzhiyun dev_err(ðqos->pdev->dev, "Set CK_OUT_EN timedout\n");
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /* Set DDR_CAL_EN */
241*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_CAL_EN,
242*4882a593Smuzhiyun SDCC_DLL_CONFIG2_DDR_CAL_EN, SDCC_HC_REG_DLL_CONFIG2);
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DLL_CLOCK_DIS,
245*4882a593Smuzhiyun 0, SDCC_HC_REG_DLL_CONFIG2);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_MCLK_FREQ_CALC,
248*4882a593Smuzhiyun 0x1A << 10, SDCC_HC_REG_DLL_CONFIG2);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SEL,
251*4882a593Smuzhiyun BIT(2), SDCC_HC_REG_DLL_CONFIG2);
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
254*4882a593Smuzhiyun SDCC_DLL_CONFIG2_DDR_TRAFFIC_INIT_SW,
255*4882a593Smuzhiyun SDCC_HC_REG_DLL_CONFIG2);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun return 0;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
ethqos_rgmii_macro_init(struct qcom_ethqos * ethqos)260*4882a593Smuzhiyun static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun /* Disable loopback mode */
263*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN,
264*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /* Select RGMII, write 0 to interface select */
267*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_INTF_SEL,
268*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG);
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun switch (ethqos->speed) {
271*4882a593Smuzhiyun case SPEED_1000:
272*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
273*4882a593Smuzhiyun RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
274*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
275*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG);
276*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
277*4882a593Smuzhiyun RGMII_CONFIG_POS_NEG_DATA_SEL,
278*4882a593Smuzhiyun RGMII_IO_MACRO_CONFIG);
279*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
280*4882a593Smuzhiyun RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG);
281*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
282*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
283*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
284*4882a593Smuzhiyun RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
285*4882a593Smuzhiyun RGMII_IO_MACRO_CONFIG2);
286*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
287*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
288*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
289*4882a593Smuzhiyun RGMII_CONFIG2_RX_PROG_SWAP,
290*4882a593Smuzhiyun RGMII_IO_MACRO_CONFIG2);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun /* Set PRG_RCLK_DLY to 57 for 1.8 ns delay */
293*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY,
294*4882a593Smuzhiyun 57, SDCC_HC_REG_DDR_CONFIG);
295*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN,
296*4882a593Smuzhiyun SDCC_DDR_CONFIG_PRG_DLY_EN,
297*4882a593Smuzhiyun SDCC_HC_REG_DDR_CONFIG);
298*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
299*4882a593Smuzhiyun RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
300*4882a593Smuzhiyun break;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun case SPEED_100:
303*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
304*4882a593Smuzhiyun RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
305*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
306*4882a593Smuzhiyun RGMII_CONFIG_BYPASS_TX_ID_EN,
307*4882a593Smuzhiyun RGMII_IO_MACRO_CONFIG);
308*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
309*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG);
310*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
311*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG);
312*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
313*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
314*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
315*4882a593Smuzhiyun RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
316*4882a593Smuzhiyun RGMII_IO_MACRO_CONFIG2);
317*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2,
318*4882a593Smuzhiyun BIT(6), RGMII_IO_MACRO_CONFIG);
319*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
320*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
321*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
322*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
323*4882a593Smuzhiyun /* Write 0x5 to PRG_RCLK_DLY_CODE */
324*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
325*4882a593Smuzhiyun (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
326*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
327*4882a593Smuzhiyun SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
328*4882a593Smuzhiyun SDCC_HC_REG_DDR_CONFIG);
329*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
330*4882a593Smuzhiyun SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
331*4882a593Smuzhiyun SDCC_HC_REG_DDR_CONFIG);
332*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
333*4882a593Smuzhiyun RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
334*4882a593Smuzhiyun break;
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun case SPEED_10:
337*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE,
338*4882a593Smuzhiyun RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG);
339*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN,
340*4882a593Smuzhiyun RGMII_CONFIG_BYPASS_TX_ID_EN,
341*4882a593Smuzhiyun RGMII_IO_MACRO_CONFIG);
342*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL,
343*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG);
344*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP,
345*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG);
346*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL,
347*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
348*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN,
349*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
350*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9,
351*4882a593Smuzhiyun BIT(12) | GENMASK(9, 8),
352*4882a593Smuzhiyun RGMII_IO_MACRO_CONFIG);
353*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15,
354*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
355*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP,
356*4882a593Smuzhiyun 0, RGMII_IO_MACRO_CONFIG2);
357*4882a593Smuzhiyun /* Write 0x5 to PRG_RCLK_DLY_CODE */
358*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE,
359*4882a593Smuzhiyun (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG);
360*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
361*4882a593Smuzhiyun SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY,
362*4882a593Smuzhiyun SDCC_HC_REG_DDR_CONFIG);
363*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
364*4882a593Smuzhiyun SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN,
365*4882a593Smuzhiyun SDCC_HC_REG_DDR_CONFIG);
366*4882a593Smuzhiyun rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN,
367*4882a593Smuzhiyun RGMII_CONFIG_LOOPBACK_EN, RGMII_IO_MACRO_CONFIG);
368*4882a593Smuzhiyun break;
369*4882a593Smuzhiyun default:
370*4882a593Smuzhiyun dev_err(ðqos->pdev->dev,
371*4882a593Smuzhiyun "Invalid speed %d\n", ethqos->speed);
372*4882a593Smuzhiyun return -EINVAL;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun return 0;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
ethqos_configure(struct qcom_ethqos * ethqos)378*4882a593Smuzhiyun static int ethqos_configure(struct qcom_ethqos *ethqos)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun volatile unsigned int dll_lock;
381*4882a593Smuzhiyun unsigned int i, retry = 1000;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun /* Reset to POR values and enable clk */
384*4882a593Smuzhiyun for (i = 0; i < ethqos->num_por; i++)
385*4882a593Smuzhiyun rgmii_writel(ethqos, ethqos->por[i].value,
386*4882a593Smuzhiyun ethqos->por[i].offset);
387*4882a593Smuzhiyun ethqos_set_func_clk_en(ethqos);
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun /* Initialize the DLL first */
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* Set DLL_RST */
392*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST,
393*4882a593Smuzhiyun SDCC_DLL_CONFIG_DLL_RST, SDCC_HC_REG_DLL_CONFIG);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun /* Set PDN */
396*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN,
397*4882a593Smuzhiyun SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* Clear DLL_RST */
400*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, 0,
401*4882a593Smuzhiyun SDCC_HC_REG_DLL_CONFIG);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun /* Clear PDN */
404*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, 0,
405*4882a593Smuzhiyun SDCC_HC_REG_DLL_CONFIG);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun if (ethqos->speed != SPEED_100 && ethqos->speed != SPEED_10) {
408*4882a593Smuzhiyun /* Set DLL_EN */
409*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_EN,
410*4882a593Smuzhiyun SDCC_DLL_CONFIG_DLL_EN, SDCC_HC_REG_DLL_CONFIG);
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* Set CK_OUT_EN */
413*4882a593Smuzhiyun rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN,
414*4882a593Smuzhiyun SDCC_DLL_CONFIG_CK_OUT_EN,
415*4882a593Smuzhiyun SDCC_HC_REG_DLL_CONFIG);
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /* Set USR_CTL bit 26 with mask of 3 bits */
418*4882a593Smuzhiyun rgmii_updatel(ethqos, GENMASK(26, 24), BIT(26), SDCC_USR_CTL);
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun /* wait for DLL LOCK */
421*4882a593Smuzhiyun do {
422*4882a593Smuzhiyun mdelay(1);
423*4882a593Smuzhiyun dll_lock = rgmii_readl(ethqos, SDC4_STATUS);
424*4882a593Smuzhiyun if (dll_lock & SDC4_STATUS_DLL_LOCK)
425*4882a593Smuzhiyun break;
426*4882a593Smuzhiyun retry--;
427*4882a593Smuzhiyun } while (retry > 0);
428*4882a593Smuzhiyun if (!retry)
429*4882a593Smuzhiyun dev_err(ðqos->pdev->dev,
430*4882a593Smuzhiyun "Timeout while waiting for DLL lock\n");
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun if (ethqos->speed == SPEED_1000)
434*4882a593Smuzhiyun ethqos_dll_configure(ethqos);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun ethqos_rgmii_macro_init(ethqos);
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun return 0;
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun
ethqos_fix_mac_speed(void * priv,unsigned int speed)441*4882a593Smuzhiyun static void ethqos_fix_mac_speed(void *priv, unsigned int speed)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun struct qcom_ethqos *ethqos = priv;
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun ethqos->speed = speed;
446*4882a593Smuzhiyun ethqos_update_rgmii_clk(ethqos, speed);
447*4882a593Smuzhiyun ethqos_configure(ethqos);
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun
qcom_ethqos_probe(struct platform_device * pdev)450*4882a593Smuzhiyun static int qcom_ethqos_probe(struct platform_device *pdev)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun struct device_node *np = pdev->dev.of_node;
453*4882a593Smuzhiyun struct plat_stmmacenet_data *plat_dat;
454*4882a593Smuzhiyun struct stmmac_resources stmmac_res;
455*4882a593Smuzhiyun const struct ethqos_emac_driver_data *data;
456*4882a593Smuzhiyun struct qcom_ethqos *ethqos;
457*4882a593Smuzhiyun struct resource *res;
458*4882a593Smuzhiyun int ret;
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun ret = stmmac_get_platform_resources(pdev, &stmmac_res);
461*4882a593Smuzhiyun if (ret)
462*4882a593Smuzhiyun return ret;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
465*4882a593Smuzhiyun if (IS_ERR(plat_dat)) {
466*4882a593Smuzhiyun dev_err(&pdev->dev, "dt configuration failed\n");
467*4882a593Smuzhiyun return PTR_ERR(plat_dat);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun ethqos = devm_kzalloc(&pdev->dev, sizeof(*ethqos), GFP_KERNEL);
471*4882a593Smuzhiyun if (!ethqos) {
472*4882a593Smuzhiyun ret = -ENOMEM;
473*4882a593Smuzhiyun goto err_mem;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun ethqos->pdev = pdev;
477*4882a593Smuzhiyun res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rgmii");
478*4882a593Smuzhiyun ethqos->rgmii_base = devm_ioremap_resource(&pdev->dev, res);
479*4882a593Smuzhiyun if (IS_ERR(ethqos->rgmii_base)) {
480*4882a593Smuzhiyun dev_err(&pdev->dev, "Can't get rgmii base\n");
481*4882a593Smuzhiyun ret = PTR_ERR(ethqos->rgmii_base);
482*4882a593Smuzhiyun goto err_mem;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun data = of_device_get_match_data(&pdev->dev);
486*4882a593Smuzhiyun ethqos->por = data->por;
487*4882a593Smuzhiyun ethqos->num_por = data->num_por;
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
490*4882a593Smuzhiyun if (IS_ERR(ethqos->rgmii_clk)) {
491*4882a593Smuzhiyun ret = PTR_ERR(ethqos->rgmii_clk);
492*4882a593Smuzhiyun goto err_mem;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun ret = clk_prepare_enable(ethqos->rgmii_clk);
496*4882a593Smuzhiyun if (ret)
497*4882a593Smuzhiyun goto err_mem;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun ethqos->speed = SPEED_1000;
500*4882a593Smuzhiyun ethqos_update_rgmii_clk(ethqos, SPEED_1000);
501*4882a593Smuzhiyun ethqos_set_func_clk_en(ethqos);
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun plat_dat->bsp_priv = ethqos;
504*4882a593Smuzhiyun plat_dat->fix_mac_speed = ethqos_fix_mac_speed;
505*4882a593Smuzhiyun plat_dat->has_gmac4 = 1;
506*4882a593Smuzhiyun plat_dat->pmt = 1;
507*4882a593Smuzhiyun plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
510*4882a593Smuzhiyun if (ret)
511*4882a593Smuzhiyun goto err_clk;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun rgmii_dump(ethqos);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun return ret;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun err_clk:
518*4882a593Smuzhiyun clk_disable_unprepare(ethqos->rgmii_clk);
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun err_mem:
521*4882a593Smuzhiyun stmmac_remove_config_dt(pdev, plat_dat);
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun return ret;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun
qcom_ethqos_remove(struct platform_device * pdev)526*4882a593Smuzhiyun static int qcom_ethqos_remove(struct platform_device *pdev)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun struct qcom_ethqos *ethqos;
529*4882a593Smuzhiyun int ret;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun ethqos = get_stmmac_bsp_priv(&pdev->dev);
532*4882a593Smuzhiyun if (!ethqos)
533*4882a593Smuzhiyun return -ENODEV;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun ret = stmmac_pltfr_remove(pdev);
536*4882a593Smuzhiyun clk_disable_unprepare(ethqos->rgmii_clk);
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun return ret;
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun static const struct of_device_id qcom_ethqos_match[] = {
542*4882a593Smuzhiyun { .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data},
543*4882a593Smuzhiyun { }
544*4882a593Smuzhiyun };
545*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun static struct platform_driver qcom_ethqos_driver = {
548*4882a593Smuzhiyun .probe = qcom_ethqos_probe,
549*4882a593Smuzhiyun .remove = qcom_ethqos_remove,
550*4882a593Smuzhiyun .driver = {
551*4882a593Smuzhiyun .name = "qcom-ethqos",
552*4882a593Smuzhiyun .pm = &stmmac_pltfr_pm_ops,
553*4882a593Smuzhiyun .of_match_table = of_match_ptr(qcom_ethqos_match),
554*4882a593Smuzhiyun },
555*4882a593Smuzhiyun };
556*4882a593Smuzhiyun module_platform_driver(qcom_ethqos_driver);
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun MODULE_DESCRIPTION("Qualcomm ETHQOS driver");
559*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
560