`HI
I have ordered this chip for our project. I could find only the attached file in the website. But this file needs various other support files (.h files).
Can you please provide example code for interfacing this chip with microcontroller using RMII interface?
Kindly let me know for clarifications if any.
Thanks
Priya
CGit
Gitweb
gitprojects / ti-analog-linux-kernel / dmurphy-analog.git / blob
commit
? search:
re
summary | shortlog | log | commit | commitdiff | tree
history | raw | HEAD
net: phy: dp83td510: Add support for the DP83td510 Ethernet PHY
[ti-analog-linux-kernel/dmurphy-analog.git] / drivers / net / phy / dp83td510.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Driver for the Texas Instruments DP83TD510 PHY
3 * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/
4 */
5
6 #include <linux/ethtool.h>
7 #include <linux/etherdevice.h>
8 #include <linux/kernel.h>
9 #include <linux/mii.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/phy.h>
13 #include <linux/netdevice.h>
14
15 #define DP83TD510E_PHY_ID 0x20000180
16 #define DP83TD510_DEVADDR_AN 0x7
17 #define DP83TD510_DEVADDR 0x1f
18
19 #define DP83TD510_MII_REG 0x0
20 #define DP83TD510_PHY_STAT 0x10
21 #define DP83TD510_GEN_CFG 0x11
22 #define DP83TD510_INT_REG1 0x12
23 #define DP83TD510_INT_REG2 0x13
24 #define DP83TD510_MAC_CFG_1 0x17
25
26 #define DP83TD510_SOR_1 0x467
27
28 #define DP83TD510_HW_RESET BIT(15)
29 #define DP83TD510_SW_RESET BIT(14)
30
31 /* GEN CFG bits */
32 #define DP83TD510_INT_OE BIT(0)
33 #define DP83TD510_INT_EN BIT(1)
34
35 /* INT REG 1 bits */
36 #define DP83TD510_INT1_ESD_EN BIT(3)
37 #define DP83TD510_INT1_LINK_EN BIT(5)
38 #define DP83TD510_INT1_RHF_EN BIT(7)
39 #define DP83TD510_INT1_ESD BIT(11)
40 #define DP83TD510_INT1_LINK BIT(13)
41 #define DP83TD510_INT1_RHF BIT(15)
42
43 /* INT REG 2 bits */
44 #define DP83TD510_INT2_POR_EN BIT(0)
45 #define DP83TD510_INT2_POL_EN BIT(1)
46 #define DP83TD510_INT2_PAGE_EN BIT(5)
47 #define DP83TD510_INT2_POR BIT(8)
48 #define DP83TD510_INT2_POL BIT(9)
49 #define DP83TD510_INT2_PAGE BIT(13)
50
51 /* MAC CFG bits */
52 #define DP83TD510_RX_CLK_SHIFT BIT(12)
53 #define DP83TD510_TX_CLK_SHIFT BIT(11)
54
55 #define DP83TD510_MASTER_MODE BIT(2)
56 #define DP83TD510_2_4V BIT(7)
57 #define DP83TD510_RGMII BIT(8)
58
59 #define DP83TD510_FIFO_DEPTH_MASK GENMASK(6, 5)
60 #define DP83TD510_FIFO_DEPTH_4_B_NIB 0
61 #define DP83TD510_FIFO_DEPTH_5_B_NIB BIT(5)
62 #define DP83TD510_FIFO_DEPTH_6_B_NIB BIT(6)
63 #define DP83TD510_FIFO_DEPTH_8_B_NIB (BIT(5) | BIT(6))
64
65 enum dp83td510_mode_config {
66 DP83TD510_AUTO_NEG = 0,
67 DP83TD510_MASTER_1 = 1,
68 DP83TD510_MASTER_24 = 2,
69 DP83TD510_SLAVE_1 = 3,
70 DP83TD510_SLAVE_24 = 4,
71 };
72
73 struct dp83td510_private {
74 u32 forced_mode;
75 u32 tx_fifo_depth;
76 u32 rgmii_delay;
77 bool is_rgmii;
78 };
79
80 struct dp83td510_init_reg {
81 int reg;
82 int val;
83 };
84
85 static struct dp83td510_init_reg dp83td510_master_1_0[] = {
86 { 0x000d, 0x0007 }, /* disable auto-neg */
87 { 0x000e, 0x0200 },
88 { 0x000d, 0x4007 },
89 { 0x000e, 0x0000 },
90 { 0x000d, 0x0001 }, /* force master mode */
91 { 0x000e, 0x0834 },
92 { 0x000d, 0x4001 },
93 { 0x000e, 0x4000 },
94 { 0x000d, 0x0001 }, /* force 1.0v swing */
95 { 0x000e, 0x08f6 },
96 { 0x000d, 0x4001 },
97 { 0x000e, 0x0000 },
98 { 0x0608, 0x003b }, /* disable_0_transition */
99 { 0x0862, 0x39f8 }, /* AGC Gain during Autoneg */
100 { 0x081a, 0x67c0 }, /* deq offset for 1V swing */
101 { 0x081c, 0xfb62 }, /* deq offset for 2.4V swing */
102 { 0x0830, 0x05a3 }, /* Enable energy lost fallback */
103 { 0x0855, 0x1b55 }, /* MSE Threshold change */
104 { 0x0831, 0x0403 }, /* energy detect threshold */
105 { 0x0856, 0x1800 }, /* good1 MSE threshold change */
106 { 0x0857, 0x8fa0 }, /* Enable fallback to phase 1 on watchdog trigger */
107 { 0x0871, 0x000c }, /* TED input changed to slicer_in without FFE */
108 { 0x0883, 0x022e }, /* Enable Rx Filter, Change PGA threshold for Short Cable detection */
109 { 0x0402, 0x1800 }, /* Adjusr LD swing */
110 { 0x0878, 0x2248 }, /* Change PI up/down polarity */
111 { 0x010c, 0x0008 }, /* tx filter coefficient */
112 { 0x0112, 0x1212 }, /* tx filter scaling factor */
113 { 0x0809, 0x5c80 }, /* AGC retrain */
114 { 0x0803, 0x1529 }, /* Master Ph1 Back-off */
115 { 0x0804, 0x1a33 }, /* Master Ph1 Back-off */
116 { 0x0805, 0x1f3d }, /* Master Ph1 Back-off */
117 { 0x0850, 0x045b }, /* hybrid gain & delay */
118 { 0x0874, 0x6967 }, /* kp step 0 for master */
119 { 0x0852, 0x7800 }, /* FAGC init gain */
120 { 0x0806, 0x1e1e }, /* Master/Slave Ph2 Back-off */
121 { 0x0807, 0x2525 }, /* Master/Slave Ph2 Back-off */
122 { 0x0808, 0x2c2c }, /* Master/Slave Ph2 Back-off */
123 { 0x0850, 0x0590 }, /* Hybrid Gain/Delay Code */
124 { 0x0827, 0x4000 }, /* Echo Fixed Delay */
125 { 0x0849, 0x0fe4 }, /* Hybrid Cal enable */
126 { 0x084b, 0x04b5 }, /* Echo Score Sel */
127 { 0x0018, 0x0043 }, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */
128 };
129
130 static struct dp83td510_init_reg dp83td510_slave_1_0[] = {
131 { 0x000d, 0x0007 }, /* disable auto-neg */
132 { 0x000e, 0x0200 },
133 { 0x000d, 0x4007 },
134 { 0x000e, 0x0000 },
135 { 0x000d, 0x0001 }, /* force slave mode */
136 { 0x000e, 0x0834 },
137 { 0x000d, 0x4001 },
138 { 0x000e, 0x0000 },
139 { 0x000d, 0x0001 }, /* force 1.0v swing */
140 { 0x000d, 0x4001 },
141 { 0x000e, 0x0000 },
142 { 0x0608, 0x003b }, /* disable_0_transition */
143 { 0x0862, 0x39f8 }, /* AGC Gain during Autoneg */
144 { 0x081a, 0x67c0 }, /* deq offset for 1V swing */
145 { 0x081c, 0xfb62 }, /* deq offset for 2.4V swing */
146 { 0x0830, 0x05a3 }, /* Enable energy lost fallback */
147 { 0x0855, 0x1b55 }, /* MSE Threshold change */
148 { 0x0831, 0x0403 }, /* energy detect threshold */
149 { 0x0856, 0x1800 }, /* good1 MSE threshold change */
150 { 0x0857, 0x8fa0 }, /* Enable fallback to phase 1 on watchdog trigger */
151 { 0x0871, 0x000c }, /* TED input changed to slicer_in without FFE */
152 { 0x0883, 0x022e }, /* Enable Rx Filter, PGA threshold for Short Cable detection */
153 { 0x0402, 0x1800 }, /* Adjusr LD swing */
154 { 0x0878, 0x2248 }, /* Change PI up/down polarity */
155 { 0x010c, 0x0008 }, /* tx filter coefficient */
156 { 0x0112, 0x1212 }, /* tx filter scaling factor */
157 { 0x0809, 0x5c80 }, /* AGC retrain */
158 { 0x0803, 0x1529 }, /* Master Ph1 Back-off */
159 { 0x0804, 0x1a33 }, /* Master Ph1 Back-off */
160 { 0x0805, 0x1f3d }, /* Master Ph1 Back-off */
161 { 0x0850, 0x045b }, /* hybrid gain & delay */
162 { 0x0874, 0x6967 }, /* kp step 0 for master */
163 { 0x0852, 0x7800 }, /* FAGC init gain */
164 { 0x0806, 0x1e1e }, /* Master/Slave Ph2 Back-off */
165 { 0x0807, 0x2525 }, /* Master/Slave Ph2 Back-off */
166 { 0x0808, 0x2c2c }, /* Master/Slave Ph2 Back-off */
167 { 0x0850, 0x0590 }, /* Hybrid Gain/Delay Code */
168 { 0x0827, 0x4000 }, /* Echo Fixed Delay */
169 { 0x0849, 0x0fe4 }, /* Hybrid Cal enable */
170 { 0x084b, 0x04b5 }, /* Echo Score Sel */
171 { 0x0018, 0x0043 }, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */
172 };
173
174 static struct dp83td510_init_reg dp83td510_master_2_4[] = {
175 { 0x000d, 0x0007 }, /* disable auto-neg */
176 { 0x000e, 0x0200 },
177 { 0x000d, 0x4007 },
178 { 0x000e, 0x0000 },
179 { 0x000d, 0x0001 }, /* force Master mode */
180 { 0x000e, 0x0834 },
181 { 0x000d, 0x4001 },
182 { 0x000e, 0x4000 },
183 { 0x000d, 0x0001 }, /* force 2.4v swing */
184 { 0x000e, 0x08f6 },
185 { 0x000d, 0x4001 },
186 { 0x000e, 0x1000 },
187 { 0x0608, 0x003b }, /* disable_0_transition */
188 { 0x0862, 0x39f8 }, /* AGC Gain during Autoneg */
189 { 0x081a, 0x67c0 }, /* deq offset for 1V swing */
190 { 0x081c, 0xfb62 }, /* deq offset for 2.4V swing */
191 { 0x0830, 0x05a3 }, /* Enable energy lost fallback */
192 { 0x0855, 0x1b55 }, /* MSE Threshold change */
193 { 0x0831, 0x0403 }, /* energy detect threshold */
194 { 0x0856, 0x1800 }, /* good1 MSE threshold change */
195 { 0x0857, 0x8fa0 }, /* Enable fallback to phase 1 on watchdog trigger */
196 { 0x0871, 0x000c }, /* TED input changed to slicer_in without FFE */
197 { 0x0883, 0x022e }, /* Enable Rx Filter, Change PGA threshold for Short Cable detection */
198 { 0x0402, 0x1800 }, /* Adjusr LD swing */
199 { 0x0878, 0x2248 }, /* Change PI up/down polarity */
200 { 0x010c, 0x0008 }, /* tx filter coefficient */
201 { 0x0112, 0x1212 }, /* tx filter scaling factor */
202 { 0x0809, 0x5c80 }, /* AGC retrain */
203 { 0x0803, 0x1529 }, /* Master Ph1 Back-off */
204 { 0x0804, 0x1a33 }, /* Master Ph1 Back-off */
205 { 0x0805, 0x1f3d }, /* Master Ph1 Back-off */
206 { 0x0850, 0x045b }, /* hybrid gain & delay */
207 { 0x0874, 0x6967 }, /* kp step 0 for master */
208 { 0x0852, 0x7800 }, /* FAGC init gain */
209 { 0x0806, 0x1e1e }, /* Master/Slave Ph2 Back-off */
210 { 0x0807, 0x2525 }, /* Master/Slave Ph2 Back-off */
211 { 0x0808, 0x2c2c }, /* Master/Slave Ph2 Back-off */
212 { 0x0850, 0x0590 }, /* Hybrid Gain/Delay Code */
213 { 0x0827, 0x4000 }, /* Echo Fixed Delay */
214 { 0x0849, 0x0fe4 }, /* Hybrid Cal enable */
215 { 0x084b, 0x04b5 }, /* Echo Score Sel */
216 { 0x0018, 0x0043 }, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */
217 };
218
219 static struct dp83td510_init_reg dp83td510_slave_2_4[] = {
220 { 0x000d, 0x0007}, /* disable auto-neg */
221 { 0x000e, 0x0200},
222 { 0x000d, 0x4007},
223 { 0x000e, 0x0000},
224 { 0x000d, 0x0001}, /* force slave mode */
225 { 0x000e, 0x0834},
226 { 0x000d, 0x4001},
227 { 0x000e, 0x0000},
228 { 0x000d, 0x0001}, /* force 2.4v swing */
229 { 0x000e, 0x08f6},
230 { 0x000d, 0x4001},
231 { 0x000e, 0x1000},
232 { 0x0608, 0x003b}, /* disable_0_transition */
233 { 0x0862, 0x39f8}, /* AGC Gain during Autoneg */
234 { 0x081a, 0x67c0}, /* deq offset for 1V swing */
235 { 0x081c, 0xfb62}, /* deq offset for 2.4V swing */
236 { 0x0830, 0x05a3}, /* Enable energy lost fallback */
237 { 0x0855, 0x1b55}, /* MSE Threshold change */
238 { 0x0831, 0x0403}, /* energy detect threshold */
239 { 0x0856, 0x1800}, /* good1 MSE threshold change */
240 { 0x0857, 0x8fa0}, /* Enable fallback to phase 1 on watchdog trigger */
241 { 0x0871, 0x000c}, /* TED input changed to slicer_in without FFE */
242 { 0x0883, 0x022e}, /* Enable Rx Filter, Change PGA threshold for Short Cable detection */
243 { 0x0402, 0x1800}, /* Adjusr LD swing */
244 { 0x0878, 0x2248}, /* Change PI up/down polarity */
245 { 0x010c, 0x0008}, /* tx filter coefficient */
246 { 0x0112, 0x1212}, /* tx filter scaling factor */
247 { 0x0809, 0x5c80}, /* AGC retrain */
248 { 0x0803, 0x1529}, /* Master Ph1 Back-off */
249 { 0x0804, 0x1a33}, /* Master Ph1 Back-off */
250 { 0x0805, 0x1f3d}, /* Master Ph1 Back-off */
251 { 0x0850, 0x045b}, /* hybrid gain & delay */
252 { 0x0874, 0x6967}, /* kp step 0 for master */
253 { 0x0852, 0x7800}, /* FAGC init gain */
254 { 0x0806, 0x1e1e}, /* Master/Slave Ph2 Back-off */
255 { 0x0807, 0x2525}, /* Master/Slave Ph2 Back-off */
256 { 0x0808, 0x2c2c}, /* Master/Slave Ph2 Back-off */
257 { 0x0850, 0x0590}, /* Hybrid Gain/Delay Code */
258 { 0x0827, 0x4000}, /* Echo Fixed Delay */
259 { 0x0849, 0x0fe4}, /* Hybrid Cal enable */
260 { 0x084b, 0x04b5}, /* Echo Score Sel */
261 { 0x0018, 0x0043}, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */
262 };
263
264 static struct dp83td510_init_reg dp83td510_auto_neg[] = {
265 { 0x608, 0x003b }, /* disable_0_transition */
266 { 0x862, 0x39f8 }, /* AGC Gain during Autoneg */
267 { 0x81a, 0x67c0 }, /* deq offset for 1V swing */
268 { 0x81c, 0xfb62 }, /* deq offset for 2.4V swing */
269 { 0x830, 0x05a3 }, /* Enable energy lost fallback */
270 { 0x855, 0x1b55 }, /* MSE Threshold change */
271 { 0x831, 0x0403 }, /* energy detect threshold */
272 { 0x856, 0x1800 }, /* good1 MSE threshold change */
273 { 0x857, 0x8fa0 }, /* Enable fallback to phase 1 on watchdog trigger */
274 { 0x871, 0x000c }, /* TED input changed to slicer_in without FFE */
275 { 0x883, 0x022e }, /* Enable Rx Filter Change PGA threshold for Short Cable detection */
276 { 0x402, 0x1800 }, /* Adjusr LD swing */
277 { 0x878, 0x2248 }, /* Change PI up/down polarity */
278 { 0x10c, 0x0008 }, /* tx filter coefficient */
279 { 0x112, 0x1212 }, /* tx filter scaling factor */
280 { 0x809, 0x5c80 }, /* AGC retrain */
281 { 0x803, 0x1529 }, /* Master Ph1 Back-off */
282 { 0x804, 0x1a33 }, /* Master Ph1 Back-off */
283 { 0x805, 0x1f3d }, /* Master Ph1 Back-off */
284 { 0x850, 0x045b }, /* hybrid gain & delay */
285 { 0x874, 0x6967 }, /* kp step 0 for master */
286 { 0x852, 0x7800 }, /* FAGC init gain */
287 { 0x806, 0x1e1e }, /* Master/Slave Ph2 Back-off */
288 { 0x807, 0x2525 }, /* Master/Slave Ph2 Back-off */
289 { 0x808, 0x2c2c }, /* Master/Slave Ph2 Back-off */
290 { 0x850, 0x0590 }, /* Hybrid Gain/Delay Code */
291 { 0x827, 0x4000 }, /* Echo Fixed Delay */
292 { 0x849, 0x0fe4 }, /* Hybrid Cal enable */
293 { 0x84b, 0x04b5 }, /* Echo Score Sel */
294 { 0x018, 0x0043 }, /* Set CRS/RX_DV pin as RX_DV for RMII repeater mode */
295 };
296
297 static int dp83td510_ack_interrupt(struct phy_device *phydev)
298 {
299 int ret;
300
301 ret = phy_read(phydev, DP83TD510_INT_REG1);
302 if (ret < 0)
303 return ret;
304
305 ret = phy_read(phydev, DP83TD510_INT_REG2);
306 if (ret < 0)
307 return ret;
308
309 return 0;
310 }
311
312 static int dp83td510_config_intr(struct phy_device *phydev)
313 {
314 int int_status;
315 int gen_cfg_val;
316 int ret;
317
318 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
319 int_status = phy_read(phydev, DP83TD510_INT_REG1);
320 if (int_status < 0)
321 return int_status;
322
323 int_status = (DP83TD510_INT1_ESD_EN | DP83TD510_INT1_LINK_EN |
324 DP83TD510_INT1_RHF_EN);
325
326 ret = phy_write(phydev, DP83TD510_INT_REG1, int_status);
327 if (ret)
328 return ret;
329
330 int_status = phy_read(phydev, DP83TD510_INT_REG2);
331 if (int_status < 0)
332 return int_status;
333
334 int_status = (DP83TD510_INT2_POR | DP83TD510_INT2_POL |
335 DP83TD510_INT2_PAGE);
336
337 ret = phy_write(phydev, DP83TD510_INT_REG2, int_status);
338 if (ret)
339 return ret;
340
341 gen_cfg_val = phy_read(phydev, DP83TD510_GEN_CFG);
342 if (gen_cfg_val < 0)
343 return gen_cfg_val;
344
345 gen_cfg_val |= DP83TD510_INT_OE | DP83TD510_INT_EN;
346
347 } else {
348 ret = phy_write(phydev, DP83TD510_INT_REG1, 0);
349 if (ret)
350 return ret;
351
352 ret = phy_write(phydev, DP83TD510_INT_REG2, 0);
353 if (ret)
354 return ret;
355
356 gen_cfg_val = phy_read(phydev, DP83TD510_GEN_CFG);
357 if (gen_cfg_val < 0)
358 return gen_cfg_val;
359
360 gen_cfg_val &= ~DP83TD510_INT_EN;
361 }
362
363 return phy_write(phydev, DP83TD510_GEN_CFG, gen_cfg_val);
364 }
365
366 static int dp83td510_configure_mode(struct phy_device *phydev)
367 {
368 struct dp83td510_private *dp83td510 = phydev->priv;
369 struct dp83td510_init_reg *init_data;
370 int size;
371 int ret;
372 int i;
373
374 ret = phy_set_bits(phydev, DP83TD510_MII_REG, DP83TD510_HW_RESET);
375 if (ret < 0)
376 return ret;
377
378 switch (dp83td510->forced_mode) {
379 case DP83TD510_MASTER_1:
380 size = ARRAY_SIZE(dp83td510_master_1_0);
381 init_data = dp83td510_master_1_0;
382 break;
383 case DP83TD510_MASTER_24:
384 size = ARRAY_SIZE(dp83td510_master_2_4);
385 init_data = dp83td510_master_2_4;
386 break;
387 case DP83TD510_SLAVE_1:
388 size = ARRAY_SIZE(dp83td510_slave_1_0);
389 init_data = dp83td510_slave_1_0;
390 break;
391 case DP83TD510_SLAVE_24:
392 size = ARRAY_SIZE(dp83td510_slave_2_4);
393 init_data = dp83td510_slave_2_4;
394 break;
395 case DP83TD510_AUTO_NEG:
396 default:
397 size = ARRAY_SIZE(dp83td510_auto_neg);
398 init_data = dp83td510_auto_neg;
399 break;
400 };
401
402 for (i = 0; i < size; i++) {
403 ret = phy_write_mmd(phydev, DP83TD510_DEVADDR, init_data[i].reg,
404 init_data[i].val);
405 if (ret)
406 return ret;
407 }
408
409 return phy_set_bits(phydev, DP83TD510_MII_REG, DP83TD510_SW_RESET);
410 }
411
412 static int dp83td510_config_init(struct phy_device *phydev)
413 {
414 struct dp83td510_private *dp83td510 = phydev->priv;
415 int ret = 0;
416
417 if (phy_interface_is_rgmii(phydev)) {
418 if (dp83td510->rgmii_delay) {
419 ret = phy_set_bits_mmd(phydev, DP83TD510_DEVADDR,
420 DP83TD510_MAC_CFG_1, dp83td510->rgmii_delay);
421 if (ret)
422 return ret;
423 }
424 }
425
426 if (phydev->interface == PHY_INTERFACE_MODE_RMII)
427 ret = phy_modify(phydev, DP83TD510_GEN_CFG,
428 DP83TD510_FIFO_DEPTH_MASK,
429 dp83td510->tx_fifo_depth);
430
431 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->advertising);
432 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phydev->supported);
433 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->advertising);
434 linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported);
435 linkmode_clear_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->advertising);
436 linkmode_clear_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->supported);
437
438 return dp83td510_configure_mode(phydev);
439 }
440
441 static int dp83td510_phy_reset(struct phy_device *phydev)
442 {
443 int ret;
444
445 ret = phy_set_bits(phydev, DP83TD510_MII_REG, DP83TD510_SW_RESET);
446 if (ret < 0)
447 return ret;
448
449 usleep_range(10, 20);
450
451 return dp83td510_config_init(phydev);
452 }
453
454 static int dp83td510_read_straps(struct phy_device *phydev)
455 {
456 struct dp83td510_private *dp83td510 = phydev->priv;
457 int strap;
458
459 strap = phy_read_mmd(phydev, DP83TD510_DEVADDR, DP83TD510_SOR_1);
460 if (strap < 0)
461 return strap;
462
463 if (strap & DP83TD510_RGMII)
464 dp83td510->is_rgmii = true;
465
466 return 0;
467 };
468
469 #if IS_ENABLED(CONFIG_OF_MDIO)
470 static int dp83td510_of_init(struct phy_device *phydev)
471 {
472 struct dp83td510_private *dp83td510 = phydev->priv;
473 struct device *dev = &phydev->mdio.dev;
474 struct device_node *of_node = dev->of_node;
475 s32 rx_int_delay;
476 s32 tx_int_delay;
477 int ret;
478
479 if (!of_node)
480 return -ENODEV;
481
482 ret = dp83td510_read_straps(phydev);
483 if (ret)
484 return ret;
485
486 ret = device_property_read_u32(&phydev->mdio.dev, "ti,master-slave-mode",
487 &dp83td510->forced_mode);
488 if (ret)
489 dp83td510->forced_mode = DP83TD510_AUTO_NEG;
490
491 if (dp83td510->forced_mode < DP83TD510_AUTO_NEG ||
492 dp83td510->forced_mode > DP83TD510_SLAVE_24)
493 return -EINVAL;
494
495 if (device_property_read_u32(&phydev->mdio.dev, "tx-fifo-depth",
496 &dp83td510->tx_fifo_depth))
497 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_5_B_NIB;
498
499 switch (dp83td510->tx_fifo_depth) {
500 case 4:
501 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_4_B_NIB;
502 break;
503 case 5:
504 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_5_B_NIB;
505 break;
506 case 6:
507 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_6_B_NIB;
508 break;
509 case 8:
510 dp83td510->tx_fifo_depth = DP83TD510_FIFO_DEPTH_8_B_NIB;
511 break;
512 default:
513 return -EINVAL;
514 }
515
516 rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0, true);
517 if (rx_int_delay <= 0)
518 dp83td510->rgmii_delay = DP83TD510_RX_CLK_SHIFT;
519 else
520 dp83td510->rgmii_delay = 0;
521
522 tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0, false);
523 if (tx_int_delay <= 0)
524 dp83td510->rgmii_delay |= DP83TD510_TX_CLK_SHIFT;
525 else
526 dp83td510->rgmii_delay &= ~DP83TD510_TX_CLK_SHIFT;
527
528 return ret;
529 }
530 #else
531 static int dp83869_of_init(struct phy_device *phydev)
532 {
533 return dp83td510_read_straps(phydev);
534 }
535 #endif /* CONFIG_OF_MDIO */
536
537 static int dp83td510_probe(struct phy_device *phydev)
538 {
539 struct dp83td510_private *dp83td510;
540 int ret;
541
542 dp83td510 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83td510), GFP_KERNEL);
543 if (!dp83td510)
544 return -ENOMEM;
545
546 phydev->priv = dp83td510;
547
548 ret = dp83td510_of_init(phydev);
549 if (ret)
550 return ret;
551
552 return dp83td510_config_init(phydev);
553 }
554
555 static struct phy_driver dp83td510_driver[] = {
556 {
557 PHY_ID_MATCH_MODEL(DP83TD510E_PHY_ID),
558 .name = "TI DP83TD510E",
559 .probe = dp83td510_probe,
560 .config_init = dp83td510_config_init,
561 .soft_reset = dp83td510_phy_reset,
562 .features = PHY_BASIC_FEATURES,
563
564 /* IRQ related */
565 .ack_interrupt = dp83td510_ack_interrupt,
566 .config_intr = dp83td510_config_intr,
567
568 .suspend = genphy_suspend,
569 .resume = genphy_resume,
570 },
571 };
572 module_phy_driver(dp83td510_driver);
573
574 static struct mdio_device_id __maybe_unused dp83td510_tbl[] = {
575 { PHY_ID_MATCH_MODEL(DP83TD510E_PHY_ID) },
576 { }
577 };
578 MODULE_DEVICE_TABLE(mdio, dp83td510_tbl);
579
580 MODULE_DESCRIPTION("Texas Instruments DP83TD510E PHY driver");
581 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
582 MODULE_LICENSE("GPL v2");
583
Repository for all dmurphy work for analog device drivers.RSSAtom
© Copyright 1995-2020 Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy policy | Terms of use | Terms of sale