14
14
#include <linux/clk.h>
15
15
#include <linux/clk-provider.h>
16
16
#include <linux/device.h>
17
+ #include <linux/gpio/consumer.h>
17
18
#include <linux/ethtool.h>
18
19
#include <linux/io.h>
20
+ #include <linux/iopoll.h>
19
21
#include <linux/ioport.h>
20
22
#include <linux/module.h>
21
23
#include <linux/of_device.h>
22
24
#include <linux/of_net.h>
23
25
#include <linux/mfd/syscon.h>
24
26
#include <linux/platform_device.h>
27
+ #include <linux/reset.h>
25
28
#include <linux/stmmac.h>
26
29
27
30
#include "stmmac_platform.h"
31
+ #include "dwmac4.h"
32
+
33
+ struct tegra_eqos {
34
+ struct device * dev ;
35
+ void __iomem * regs ;
36
+
37
+ struct reset_control * rst ;
38
+ struct clk * clk_master ;
39
+ struct clk * clk_slave ;
40
+ struct clk * clk_tx ;
41
+ struct clk * clk_rx ;
42
+
43
+ struct gpio_desc * reset ;
44
+ };
28
45
29
46
static int dwc_eth_dwmac_config_dt (struct platform_device * pdev ,
30
47
struct plat_stmmacenet_data * plat_dat )
@@ -158,6 +175,230 @@ static int dwc_qos_remove(struct platform_device *pdev)
158
175
return 0 ;
159
176
}
160
177
178
+ #define SDMEMCOMPPADCTRL 0x8800
179
+ #define SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31)
180
+
181
+ #define AUTO_CAL_CONFIG 0x8804
182
+ #define AUTO_CAL_CONFIG_START BIT(31)
183
+ #define AUTO_CAL_CONFIG_ENABLE BIT(29)
184
+
185
+ #define AUTO_CAL_STATUS 0x880c
186
+ #define AUTO_CAL_STATUS_ACTIVE BIT(31)
187
+
188
+ static void tegra_eqos_fix_speed (void * priv , unsigned int speed )
189
+ {
190
+ struct tegra_eqos * eqos = priv ;
191
+ unsigned long rate = 125000000 ;
192
+ bool needs_calibration = false;
193
+ u32 value ;
194
+ int err ;
195
+
196
+ switch (speed ) {
197
+ case SPEED_1000 :
198
+ needs_calibration = true;
199
+ rate = 125000000 ;
200
+ break ;
201
+
202
+ case SPEED_100 :
203
+ needs_calibration = true;
204
+ rate = 25000000 ;
205
+ break ;
206
+
207
+ case SPEED_10 :
208
+ rate = 2500000 ;
209
+ break ;
210
+
211
+ default :
212
+ dev_err (eqos -> dev , "invalid speed %u\n" , speed );
213
+ break ;
214
+ }
215
+
216
+ if (needs_calibration ) {
217
+ /* calibrate */
218
+ value = readl (eqos -> regs + SDMEMCOMPPADCTRL );
219
+ value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD ;
220
+ writel (value , eqos -> regs + SDMEMCOMPPADCTRL );
221
+
222
+ udelay (1 );
223
+
224
+ value = readl (eqos -> regs + AUTO_CAL_CONFIG );
225
+ value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE ;
226
+ writel (value , eqos -> regs + AUTO_CAL_CONFIG );
227
+
228
+ err = readl_poll_timeout_atomic (eqos -> regs + AUTO_CAL_STATUS ,
229
+ value ,
230
+ value & AUTO_CAL_STATUS_ACTIVE ,
231
+ 1 , 10 );
232
+ if (err < 0 ) {
233
+ dev_err (eqos -> dev , "calibration did not start\n" );
234
+ goto failed ;
235
+ }
236
+
237
+ err = readl_poll_timeout_atomic (eqos -> regs + AUTO_CAL_STATUS ,
238
+ value ,
239
+ (value & AUTO_CAL_STATUS_ACTIVE ) == 0 ,
240
+ 20 , 200 );
241
+ if (err < 0 ) {
242
+ dev_err (eqos -> dev , "calibration didn't finish\n" );
243
+ goto failed ;
244
+ }
245
+
246
+ failed :
247
+ value = readl (eqos -> regs + SDMEMCOMPPADCTRL );
248
+ value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD ;
249
+ writel (value , eqos -> regs + SDMEMCOMPPADCTRL );
250
+ } else {
251
+ value = readl (eqos -> regs + AUTO_CAL_CONFIG );
252
+ value &= ~AUTO_CAL_CONFIG_ENABLE ;
253
+ writel (value , eqos -> regs + AUTO_CAL_CONFIG );
254
+ }
255
+
256
+ err = clk_set_rate (eqos -> clk_tx , rate );
257
+ if (err < 0 )
258
+ dev_err (eqos -> dev , "failed to set TX rate: %d\n" , err );
259
+ }
260
+
261
+ static int tegra_eqos_init (struct platform_device * pdev , void * priv )
262
+ {
263
+ struct tegra_eqos * eqos = priv ;
264
+ unsigned long rate ;
265
+ u32 value ;
266
+
267
+ rate = clk_get_rate (eqos -> clk_slave );
268
+
269
+ value = (rate / 1000000 ) - 1 ;
270
+ writel (value , eqos -> regs + GMAC_1US_TIC_COUNTER );
271
+
272
+ return 0 ;
273
+ }
274
+
275
+ static void * tegra_eqos_probe (struct platform_device * pdev ,
276
+ struct plat_stmmacenet_data * data ,
277
+ struct stmmac_resources * res )
278
+ {
279
+ struct tegra_eqos * eqos ;
280
+ int err ;
281
+
282
+ eqos = devm_kzalloc (& pdev -> dev , sizeof (* eqos ), GFP_KERNEL );
283
+ if (!eqos ) {
284
+ err = - ENOMEM ;
285
+ goto error ;
286
+ }
287
+
288
+ eqos -> dev = & pdev -> dev ;
289
+ eqos -> regs = res -> addr ;
290
+
291
+ eqos -> clk_master = devm_clk_get (& pdev -> dev , "master_bus" );
292
+ if (IS_ERR (eqos -> clk_master )) {
293
+ err = PTR_ERR (eqos -> clk_master );
294
+ goto error ;
295
+ }
296
+
297
+ err = clk_prepare_enable (eqos -> clk_master );
298
+ if (err < 0 )
299
+ goto error ;
300
+
301
+ eqos -> clk_slave = devm_clk_get (& pdev -> dev , "slave_bus" );
302
+ if (IS_ERR (eqos -> clk_slave )) {
303
+ err = PTR_ERR (eqos -> clk_slave );
304
+ goto disable_master ;
305
+ }
306
+
307
+ data -> stmmac_clk = eqos -> clk_slave ;
308
+
309
+ err = clk_prepare_enable (eqos -> clk_slave );
310
+ if (err < 0 )
311
+ goto disable_master ;
312
+
313
+ eqos -> clk_rx = devm_clk_get (& pdev -> dev , "rx" );
314
+ if (IS_ERR (eqos -> clk_rx )) {
315
+ err = PTR_ERR (eqos -> clk_rx );
316
+ goto disable_slave ;
317
+ }
318
+
319
+ err = clk_prepare_enable (eqos -> clk_rx );
320
+ if (err < 0 )
321
+ goto disable_slave ;
322
+
323
+ eqos -> clk_tx = devm_clk_get (& pdev -> dev , "tx" );
324
+ if (IS_ERR (eqos -> clk_tx )) {
325
+ err = PTR_ERR (eqos -> clk_tx );
326
+ goto disable_rx ;
327
+ }
328
+
329
+ err = clk_prepare_enable (eqos -> clk_tx );
330
+ if (err < 0 )
331
+ goto disable_rx ;
332
+
333
+ eqos -> reset = devm_gpiod_get (& pdev -> dev , "phy-reset" , GPIOD_OUT_HIGH );
334
+ if (IS_ERR (eqos -> reset )) {
335
+ err = PTR_ERR (eqos -> reset );
336
+ goto disable_tx ;
337
+ }
338
+
339
+ usleep_range (2000 , 4000 );
340
+ gpiod_set_value (eqos -> reset , 0 );
341
+
342
+ eqos -> rst = devm_reset_control_get (& pdev -> dev , "eqos" );
343
+ if (IS_ERR (eqos -> rst )) {
344
+ err = PTR_ERR (eqos -> rst );
345
+ goto reset_phy ;
346
+ }
347
+
348
+ err = reset_control_assert (eqos -> rst );
349
+ if (err < 0 )
350
+ goto reset_phy ;
351
+
352
+ usleep_range (2000 , 4000 );
353
+
354
+ err = reset_control_deassert (eqos -> rst );
355
+ if (err < 0 )
356
+ goto reset_phy ;
357
+
358
+ usleep_range (2000 , 4000 );
359
+
360
+ data -> fix_mac_speed = tegra_eqos_fix_speed ;
361
+ data -> init = tegra_eqos_init ;
362
+ data -> bsp_priv = eqos ;
363
+
364
+ err = tegra_eqos_init (pdev , eqos );
365
+ if (err < 0 )
366
+ goto reset ;
367
+
368
+ out :
369
+ return eqos ;
370
+
371
+ reset :
372
+ reset_control_assert (eqos -> rst );
373
+ reset_phy :
374
+ gpiod_set_value (eqos -> reset , 1 );
375
+ disable_tx :
376
+ clk_disable_unprepare (eqos -> clk_tx );
377
+ disable_rx :
378
+ clk_disable_unprepare (eqos -> clk_rx );
379
+ disable_slave :
380
+ clk_disable_unprepare (eqos -> clk_slave );
381
+ disable_master :
382
+ clk_disable_unprepare (eqos -> clk_master );
383
+ error :
384
+ eqos = ERR_PTR (err );
385
+ goto out ;
386
+ }
387
+
388
+ static int tegra_eqos_remove (struct platform_device * pdev )
389
+ {
390
+ struct tegra_eqos * eqos = get_stmmac_bsp_priv (& pdev -> dev );
391
+
392
+ reset_control_assert (eqos -> rst );
393
+ gpiod_set_value (eqos -> reset , 1 );
394
+ clk_disable_unprepare (eqos -> clk_tx );
395
+ clk_disable_unprepare (eqos -> clk_rx );
396
+ clk_disable_unprepare (eqos -> clk_slave );
397
+ clk_disable_unprepare (eqos -> clk_master );
398
+
399
+ return 0 ;
400
+ }
401
+
161
402
struct dwc_eth_dwmac_data {
162
403
void * (* probe )(struct platform_device * pdev ,
163
404
struct plat_stmmacenet_data * data ,
@@ -170,6 +411,11 @@ static const struct dwc_eth_dwmac_data dwc_qos_data = {
170
411
.remove = dwc_qos_remove ,
171
412
};
172
413
414
+ static const struct dwc_eth_dwmac_data tegra_eqos_data = {
415
+ .probe = tegra_eqos_probe ,
416
+ .remove = tegra_eqos_remove ,
417
+ };
418
+
173
419
static int dwc_eth_dwmac_probe (struct platform_device * pdev )
174
420
{
175
421
const struct dwc_eth_dwmac_data * data ;
@@ -255,6 +501,7 @@ static int dwc_eth_dwmac_remove(struct platform_device *pdev)
255
501
256
502
static const struct of_device_id dwc_eth_dwmac_match [] = {
257
503
{ .compatible = "snps,dwc-qos-ethernet-4.10" , .data = & dwc_qos_data },
504
+ { .compatible = "nvidia,tegra186-eqos" , .data = & tegra_eqos_data },
258
505
{ }
259
506
};
260
507
MODULE_DEVICE_TABLE (of , dwc_eth_dwmac_match );
0 commit comments