]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0 |
9dc8ba19 TC |
2 | /* |
3 | * Copyright (c) 2015 Realtek Semiconductor Corp. All rights reserved. | |
4 | * | |
6688452a | 5 | */ |
9dc8ba19 TC |
6 | |
7 | #include <common.h> | |
6688452a | 8 | #include <dm.h> |
9dc8ba19 | 9 | #include <errno.h> |
f7ae49fc | 10 | #include <log.h> |
9dc8ba19 | 11 | #include <malloc.h> |
c7ac1538 | 12 | #include <memalign.h> |
90526e9f | 13 | #include <net.h> |
9dc8ba19 | 14 | #include <usb.h> |
c05ed00a | 15 | #include <linux/delay.h> |
9dc8ba19 TC |
16 | #include <linux/mii.h> |
17 | #include <linux/bitops.h> | |
18 | #include "usb_ether.h" | |
19 | #include "r8152.h" | |
20 | ||
6688452a | 21 | #ifndef CONFIG_DM_ETH |
9dc8ba19 TC |
22 | /* local vars */ |
23 | static int curr_eth_dev; /* index for name of next device detected */ | |
24 | ||
25 | struct r8152_dongle { | |
26 | unsigned short vendor; | |
27 | unsigned short product; | |
28 | }; | |
29 | ||
734f9abd | 30 | static const struct r8152_dongle r8152_dongles[] = { |
9dc8ba19 TC |
31 | /* Realtek */ |
32 | { 0x0bda, 0x8050 }, | |
33 | { 0x0bda, 0x8152 }, | |
34 | { 0x0bda, 0x8153 }, | |
35 | ||
36 | /* Samsung */ | |
37 | { 0x04e8, 0xa101 }, | |
38 | ||
39 | /* Lenovo */ | |
40 | { 0x17ef, 0x304f }, | |
41 | { 0x17ef, 0x3052 }, | |
42 | { 0x17ef, 0x3054 }, | |
43 | { 0x17ef, 0x3057 }, | |
44 | { 0x17ef, 0x7205 }, | |
45 | { 0x17ef, 0x720a }, | |
46 | { 0x17ef, 0x720b }, | |
47 | { 0x17ef, 0x720c }, | |
48 | ||
49 | /* TP-LINK */ | |
50 | { 0x2357, 0x0601 }, | |
51 | ||
52 | /* Nvidia */ | |
53 | { 0x0955, 0x09ff }, | |
54 | }; | |
6688452a SR |
55 | #endif |
56 | ||
57 | struct r8152_version { | |
58 | unsigned short tcr; | |
59 | unsigned short version; | |
60 | bool gmii; | |
61 | }; | |
9dc8ba19 | 62 | |
734f9abd | 63 | static const struct r8152_version r8152_versions[] = { |
9dc8ba19 TC |
64 | { 0x4c00, RTL_VER_01, 0 }, |
65 | { 0x4c10, RTL_VER_02, 0 }, | |
66 | { 0x5c00, RTL_VER_03, 1 }, | |
67 | { 0x5c10, RTL_VER_04, 1 }, | |
68 | { 0x5c20, RTL_VER_05, 1 }, | |
69 | { 0x5c30, RTL_VER_06, 1 }, | |
70 | { 0x4800, RTL_VER_07, 0 }, | |
3a41086f HW |
71 | { 0x6000, RTL_VER_08, 1 }, |
72 | { 0x6010, RTL_VER_09, 1 }, | |
9dc8ba19 TC |
73 | }; |
74 | ||
75 | static | |
76 | int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) | |
77 | { | |
c7ac1538 SR |
78 | ALLOC_CACHE_ALIGN_BUFFER(void *, tmp, size); |
79 | int ret; | |
80 | ||
81 | ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0), | |
82 | RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, | |
83 | value, index, tmp, size, 500); | |
84 | memcpy(data, tmp, size); | |
85 | return ret; | |
9dc8ba19 TC |
86 | } |
87 | ||
88 | static | |
89 | int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) | |
90 | { | |
c7ac1538 SR |
91 | ALLOC_CACHE_ALIGN_BUFFER(void *, tmp, size); |
92 | ||
93 | memcpy(tmp, data, size); | |
9dc8ba19 TC |
94 | return usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0), |
95 | RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, | |
c7ac1538 | 96 | value, index, tmp, size, 500); |
9dc8ba19 TC |
97 | } |
98 | ||
99 | int generic_ocp_read(struct r8152 *tp, u16 index, u16 size, | |
100 | void *data, u16 type) | |
101 | { | |
102 | u16 burst_size = 64; | |
103 | int ret; | |
104 | int txsize; | |
105 | ||
106 | /* both size and index must be 4 bytes align */ | |
107 | if ((size & 3) || !size || (index & 3) || !data) | |
108 | return -EINVAL; | |
109 | ||
110 | if (index + size > 0xffff) | |
111 | return -EINVAL; | |
112 | ||
113 | while (size) { | |
114 | txsize = min(size, burst_size); | |
115 | ret = get_registers(tp, index, type, txsize, data); | |
116 | if (ret < 0) | |
117 | break; | |
118 | ||
119 | index += txsize; | |
120 | data += txsize; | |
121 | size -= txsize; | |
122 | } | |
123 | ||
124 | return ret; | |
125 | } | |
126 | ||
127 | int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen, | |
128 | u16 size, void *data, u16 type) | |
129 | { | |
130 | int ret; | |
131 | u16 byteen_start, byteen_end, byte_en_to_hw; | |
132 | u16 burst_size = 512; | |
133 | int txsize; | |
134 | ||
135 | /* both size and index must be 4 bytes align */ | |
136 | if ((size & 3) || !size || (index & 3) || !data) | |
137 | return -EINVAL; | |
138 | ||
139 | if (index + size > 0xffff) | |
140 | return -EINVAL; | |
141 | ||
142 | byteen_start = byteen & BYTE_EN_START_MASK; | |
143 | byteen_end = byteen & BYTE_EN_END_MASK; | |
144 | ||
145 | byte_en_to_hw = byteen_start | (byteen_start << 4); | |
146 | ret = set_registers(tp, index, type | byte_en_to_hw, 4, data); | |
147 | if (ret < 0) | |
148 | return ret; | |
149 | ||
150 | index += 4; | |
151 | data += 4; | |
152 | size -= 4; | |
153 | ||
154 | if (size) { | |
155 | size -= 4; | |
156 | ||
157 | while (size) { | |
158 | txsize = min(size, burst_size); | |
159 | ||
160 | ret = set_registers(tp, index, | |
161 | type | BYTE_EN_DWORD, | |
162 | txsize, data); | |
163 | if (ret < 0) | |
164 | return ret; | |
165 | ||
166 | index += txsize; | |
167 | data += txsize; | |
168 | size -= txsize; | |
169 | } | |
170 | ||
171 | byte_en_to_hw = byteen_end | (byteen_end >> 4); | |
172 | ret = set_registers(tp, index, type | byte_en_to_hw, 4, data); | |
173 | if (ret < 0) | |
174 | return ret; | |
175 | } | |
176 | ||
177 | return ret; | |
178 | } | |
179 | ||
180 | int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data) | |
181 | { | |
182 | return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA); | |
183 | } | |
184 | ||
185 | int pla_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data) | |
186 | { | |
187 | return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_PLA); | |
188 | } | |
189 | ||
190 | int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data) | |
191 | { | |
192 | return generic_ocp_read(tp, index, size, data, MCU_TYPE_USB); | |
193 | } | |
194 | ||
195 | int usb_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data) | |
196 | { | |
197 | return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_USB); | |
198 | } | |
199 | ||
200 | u32 ocp_read_dword(struct r8152 *tp, u16 type, u16 index) | |
201 | { | |
202 | __le32 data; | |
203 | ||
204 | generic_ocp_read(tp, index, sizeof(data), &data, type); | |
205 | ||
206 | return __le32_to_cpu(data); | |
207 | } | |
208 | ||
209 | void ocp_write_dword(struct r8152 *tp, u16 type, u16 index, u32 data) | |
210 | { | |
211 | __le32 tmp = __cpu_to_le32(data); | |
212 | ||
213 | generic_ocp_write(tp, index, BYTE_EN_DWORD, sizeof(tmp), &tmp, type); | |
214 | } | |
215 | ||
216 | u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index) | |
217 | { | |
218 | u32 data; | |
219 | __le32 tmp; | |
220 | u8 shift = index & 2; | |
221 | ||
222 | index &= ~3; | |
223 | ||
224 | generic_ocp_read(tp, index, sizeof(tmp), &tmp, type); | |
225 | ||
226 | data = __le32_to_cpu(tmp); | |
227 | data >>= (shift * 8); | |
228 | data &= 0xffff; | |
229 | ||
230 | return data; | |
231 | } | |
232 | ||
233 | void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data) | |
234 | { | |
235 | u32 mask = 0xffff; | |
236 | __le32 tmp; | |
237 | u16 byen = BYTE_EN_WORD; | |
238 | u8 shift = index & 2; | |
239 | ||
240 | data &= mask; | |
241 | ||
242 | if (index & 2) { | |
243 | byen <<= shift; | |
244 | mask <<= (shift * 8); | |
245 | data <<= (shift * 8); | |
246 | index &= ~3; | |
247 | } | |
248 | ||
249 | tmp = __cpu_to_le32(data); | |
250 | ||
251 | generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type); | |
252 | } | |
253 | ||
254 | u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index) | |
255 | { | |
256 | u32 data; | |
257 | __le32 tmp; | |
258 | u8 shift = index & 3; | |
259 | ||
260 | index &= ~3; | |
261 | ||
262 | generic_ocp_read(tp, index, sizeof(tmp), &tmp, type); | |
263 | ||
264 | data = __le32_to_cpu(tmp); | |
265 | data >>= (shift * 8); | |
266 | data &= 0xff; | |
267 | ||
268 | return data; | |
269 | } | |
270 | ||
271 | void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data) | |
272 | { | |
273 | u32 mask = 0xff; | |
274 | __le32 tmp; | |
275 | u16 byen = BYTE_EN_BYTE; | |
276 | u8 shift = index & 3; | |
277 | ||
278 | data &= mask; | |
279 | ||
280 | if (index & 3) { | |
281 | byen <<= shift; | |
282 | mask <<= (shift * 8); | |
283 | data <<= (shift * 8); | |
284 | index &= ~3; | |
285 | } | |
286 | ||
287 | tmp = __cpu_to_le32(data); | |
288 | ||
289 | generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type); | |
290 | } | |
291 | ||
292 | u16 ocp_reg_read(struct r8152 *tp, u16 addr) | |
293 | { | |
294 | u16 ocp_base, ocp_index; | |
295 | ||
296 | ocp_base = addr & 0xf000; | |
297 | if (ocp_base != tp->ocp_base) { | |
298 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base); | |
299 | tp->ocp_base = ocp_base; | |
300 | } | |
301 | ||
302 | ocp_index = (addr & 0x0fff) | 0xb000; | |
303 | return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index); | |
304 | } | |
305 | ||
306 | void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data) | |
307 | { | |
308 | u16 ocp_base, ocp_index; | |
309 | ||
310 | ocp_base = addr & 0xf000; | |
311 | if (ocp_base != tp->ocp_base) { | |
312 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base); | |
313 | tp->ocp_base = ocp_base; | |
314 | } | |
315 | ||
316 | ocp_index = (addr & 0x0fff) | 0xb000; | |
317 | ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data); | |
318 | } | |
319 | ||
320 | static void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value) | |
321 | { | |
322 | ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value); | |
323 | } | |
324 | ||
325 | static int r8152_mdio_read(struct r8152 *tp, u32 reg_addr) | |
326 | { | |
327 | return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2); | |
328 | } | |
329 | ||
330 | void sram_write(struct r8152 *tp, u16 addr, u16 data) | |
331 | { | |
332 | ocp_reg_write(tp, OCP_SRAM_ADDR, addr); | |
333 | ocp_reg_write(tp, OCP_SRAM_DATA, data); | |
334 | } | |
335 | ||
3a41086f HW |
336 | static u16 sram_read(struct r8152 *tp, u16 addr) |
337 | { | |
338 | ocp_reg_write(tp, OCP_SRAM_ADDR, addr); | |
339 | return ocp_reg_read(tp, OCP_SRAM_DATA); | |
340 | } | |
341 | ||
9dc8ba19 TC |
342 | int r8152_wait_for_bit(struct r8152 *tp, bool ocp_reg, u16 type, u16 index, |
343 | const u32 mask, bool set, unsigned int timeout) | |
344 | { | |
345 | u32 val; | |
346 | ||
347 | while (--timeout) { | |
348 | if (ocp_reg) | |
349 | val = ocp_reg_read(tp, index); | |
350 | else | |
351 | val = ocp_read_dword(tp, type, index); | |
352 | ||
353 | if (!set) | |
354 | val = ~val; | |
355 | ||
356 | if ((val & mask) == mask) | |
357 | return 0; | |
358 | ||
359 | mdelay(1); | |
360 | } | |
361 | ||
362 | debug("%s: Timeout (index=%04x mask=%08x timeout=%d)\n", | |
363 | __func__, index, mask, timeout); | |
364 | ||
365 | return -ETIMEDOUT; | |
366 | } | |
367 | ||
368 | static void r8152b_reset_packet_filter(struct r8152 *tp) | |
369 | { | |
370 | u32 ocp_data; | |
371 | ||
372 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC); | |
373 | ocp_data &= ~FMC_FCR_MCU_EN; | |
374 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data); | |
375 | ocp_data |= FMC_FCR_MCU_EN; | |
376 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data); | |
377 | } | |
378 | ||
379 | static void rtl8152_wait_fifo_empty(struct r8152 *tp) | |
380 | { | |
381 | int ret; | |
382 | ||
383 | ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR, | |
384 | PLA_PHY_PWR_TXEMP, 1, R8152_WAIT_TIMEOUT); | |
385 | if (ret) | |
386 | debug("Timeout waiting for FIFO empty\n"); | |
387 | ||
388 | ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_TCR0, | |
389 | TCR0_TX_EMPTY, 1, R8152_WAIT_TIMEOUT); | |
390 | if (ret) | |
391 | debug("Timeout waiting for TX empty\n"); | |
392 | } | |
393 | ||
394 | static void rtl8152_nic_reset(struct r8152 *tp) | |
395 | { | |
396 | int ret; | |
397 | u32 ocp_data; | |
398 | ||
399 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, BIST_CTRL); | |
400 | ocp_data |= BIST_CTRL_SW_RESET; | |
401 | ocp_write_dword(tp, MCU_TYPE_PLA, BIST_CTRL, ocp_data); | |
402 | ||
403 | ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, BIST_CTRL, | |
404 | BIST_CTRL_SW_RESET, 0, R8152_WAIT_TIMEOUT); | |
405 | if (ret) | |
406 | debug("Timeout waiting for NIC reset\n"); | |
407 | } | |
408 | ||
409 | static u8 rtl8152_get_speed(struct r8152 *tp) | |
410 | { | |
411 | return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); | |
412 | } | |
413 | ||
414 | static void rtl_set_eee_plus(struct r8152 *tp) | |
415 | { | |
416 | u32 ocp_data; | |
417 | ||
418 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); | |
419 | ocp_data &= ~EEEP_CR_EEEP_TX; | |
420 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); | |
421 | } | |
422 | ||
423 | static void rxdy_gated_en(struct r8152 *tp, bool enable) | |
424 | { | |
425 | u32 ocp_data; | |
426 | ||
427 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1); | |
428 | if (enable) | |
429 | ocp_data |= RXDY_GATED_EN; | |
430 | else | |
431 | ocp_data &= ~RXDY_GATED_EN; | |
432 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data); | |
433 | } | |
434 | ||
435 | static void rtl8152_set_rx_mode(struct r8152 *tp) | |
436 | { | |
437 | u32 ocp_data; | |
438 | __le32 tmp[2]; | |
439 | ||
440 | tmp[0] = 0xffffffff; | |
441 | tmp[1] = 0xffffffff; | |
442 | ||
443 | pla_ocp_write(tp, PLA_MAR, BYTE_EN_DWORD, sizeof(tmp), tmp); | |
444 | ||
445 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); | |
446 | ocp_data |= RCR_APM | RCR_AM | RCR_AB; | |
447 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); | |
448 | } | |
449 | ||
72294407 HW |
450 | static inline void r8153b_rx_agg_chg_indicate(struct r8152 *tp) |
451 | { | |
452 | ocp_write_byte(tp, MCU_TYPE_USB, USB_UPT_RXDMA_OWN, | |
453 | OWN_UPDATE | OWN_CLEAR); | |
454 | } | |
455 | ||
9dc8ba19 TC |
456 | static int rtl_enable(struct r8152 *tp) |
457 | { | |
458 | u32 ocp_data; | |
459 | ||
460 | r8152b_reset_packet_filter(tp); | |
461 | ||
462 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR); | |
463 | ocp_data |= PLA_CR_RE | PLA_CR_TE; | |
464 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data); | |
465 | ||
72294407 HW |
466 | switch (tp->version) { |
467 | case RTL_VER_08: | |
468 | case RTL_VER_09: | |
469 | r8153b_rx_agg_chg_indicate(tp); | |
470 | break; | |
471 | default: | |
472 | break; | |
473 | } | |
474 | ||
9dc8ba19 TC |
475 | rxdy_gated_en(tp, false); |
476 | ||
477 | rtl8152_set_rx_mode(tp); | |
478 | ||
479 | return 0; | |
480 | } | |
481 | ||
482 | static int rtl8152_enable(struct r8152 *tp) | |
483 | { | |
484 | rtl_set_eee_plus(tp); | |
485 | ||
486 | return rtl_enable(tp); | |
487 | } | |
488 | ||
489 | static void r8153_set_rx_early_timeout(struct r8152 *tp) | |
490 | { | |
491 | u32 ocp_data = tp->coalesce / 8; | |
492 | ||
3a41086f HW |
493 | switch (tp->version) { |
494 | case RTL_VER_03: | |
495 | case RTL_VER_04: | |
496 | case RTL_VER_05: | |
497 | case RTL_VER_06: | |
498 | ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT, | |
499 | ocp_data); | |
500 | break; | |
501 | ||
502 | case RTL_VER_08: | |
503 | case RTL_VER_09: | |
504 | /* The RTL8153B uses USB_RX_EXTRA_AGGR_TMR for rx timeout | |
505 | * primarily. For USB_RX_EARLY_TIMEOUT, we fix it to 1264ns. | |
506 | */ | |
507 | ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT, | |
508 | RX_AUXILIARY_TIMER / 8); | |
509 | ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EXTRA_AGGR_TMR, | |
510 | ocp_data); | |
511 | break; | |
512 | ||
513 | default: | |
514 | debug("** %s Invalid Device\n", __func__); | |
515 | break; | |
516 | } | |
9dc8ba19 TC |
517 | } |
518 | ||
519 | static void r8153_set_rx_early_size(struct r8152 *tp) | |
520 | { | |
3a41086f HW |
521 | u32 ocp_data = (RTL8152_AGG_BUF_SZ - RTL8153_RMS - |
522 | sizeof(struct rx_desc)); | |
523 | ||
524 | switch (tp->version) { | |
525 | case RTL_VER_03: | |
526 | case RTL_VER_04: | |
527 | case RTL_VER_05: | |
528 | case RTL_VER_06: | |
529 | ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, | |
530 | ocp_data / 4); | |
531 | break; | |
532 | ||
533 | case RTL_VER_08: | |
534 | case RTL_VER_09: | |
535 | ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, | |
536 | ocp_data / 8); | |
537 | break; | |
538 | ||
539 | default: | |
540 | debug("** %s Invalid Device\n", __func__); | |
541 | break; | |
542 | } | |
9dc8ba19 TC |
543 | } |
544 | ||
545 | static int rtl8153_enable(struct r8152 *tp) | |
546 | { | |
547 | rtl_set_eee_plus(tp); | |
548 | r8153_set_rx_early_timeout(tp); | |
549 | r8153_set_rx_early_size(tp); | |
550 | ||
551 | return rtl_enable(tp); | |
552 | } | |
553 | ||
554 | static void rtl_disable(struct r8152 *tp) | |
555 | { | |
556 | u32 ocp_data; | |
557 | ||
558 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); | |
559 | ocp_data &= ~RCR_ACPT_ALL; | |
560 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); | |
561 | ||
562 | rxdy_gated_en(tp, true); | |
563 | ||
564 | rtl8152_wait_fifo_empty(tp); | |
565 | rtl8152_nic_reset(tp); | |
566 | } | |
567 | ||
568 | static void r8152_power_cut_en(struct r8152 *tp, bool enable) | |
569 | { | |
570 | u32 ocp_data; | |
571 | ||
572 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL); | |
573 | if (enable) | |
574 | ocp_data |= POWER_CUT; | |
575 | else | |
576 | ocp_data &= ~POWER_CUT; | |
577 | ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data); | |
578 | ||
579 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS); | |
580 | ocp_data &= ~RESUME_INDICATE; | |
581 | ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data); | |
582 | } | |
583 | ||
584 | static void rtl_rx_vlan_en(struct r8152 *tp, bool enable) | |
585 | { | |
586 | u32 ocp_data; | |
587 | ||
588 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); | |
589 | if (enable) | |
590 | ocp_data |= CPCR_RX_VLAN; | |
591 | else | |
592 | ocp_data &= ~CPCR_RX_VLAN; | |
593 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); | |
594 | } | |
595 | ||
596 | static void r8153_u1u2en(struct r8152 *tp, bool enable) | |
597 | { | |
598 | u8 u1u2[8]; | |
599 | ||
600 | if (enable) | |
601 | memset(u1u2, 0xff, sizeof(u1u2)); | |
602 | else | |
603 | memset(u1u2, 0x00, sizeof(u1u2)); | |
604 | ||
605 | usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2); | |
606 | } | |
607 | ||
3a41086f HW |
608 | static void r8153b_u1u2en(struct r8152 *tp, bool enable) |
609 | { | |
610 | u16 ocp_data; | |
611 | ||
612 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_LPM_CONFIG); | |
613 | if (enable) | |
614 | ocp_data |= LPM_U1U2_EN; | |
615 | else | |
616 | ocp_data &= ~LPM_U1U2_EN; | |
617 | ||
618 | ocp_write_word(tp, MCU_TYPE_USB, USB_LPM_CONFIG, ocp_data); | |
619 | } | |
620 | ||
9dc8ba19 TC |
621 | static void r8153_u2p3en(struct r8152 *tp, bool enable) |
622 | { | |
623 | u32 ocp_data; | |
624 | ||
625 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL); | |
626 | if (enable && tp->version != RTL_VER_03 && tp->version != RTL_VER_04) | |
627 | ocp_data |= U2P3_ENABLE; | |
628 | else | |
629 | ocp_data &= ~U2P3_ENABLE; | |
630 | ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data); | |
631 | } | |
632 | ||
633 | static void r8153_power_cut_en(struct r8152 *tp, bool enable) | |
634 | { | |
635 | u32 ocp_data; | |
636 | ||
637 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT); | |
638 | if (enable) | |
639 | ocp_data |= PWR_EN | PHASE2_EN; | |
640 | else | |
641 | ocp_data &= ~(PWR_EN | PHASE2_EN); | |
642 | ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); | |
643 | ||
644 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); | |
645 | ocp_data &= ~PCUT_STATUS; | |
646 | ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); | |
647 | } | |
648 | ||
d74a7623 HW |
649 | static void rtl_reset_bmu(struct r8152 *tp) |
650 | { | |
651 | u8 ocp_data; | |
652 | ||
653 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_BMU_RESET); | |
654 | ocp_data &= ~(BMU_RESET_EP_IN | BMU_RESET_EP_OUT); | |
655 | ocp_write_byte(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data); | |
656 | ocp_data |= BMU_RESET_EP_IN | BMU_RESET_EP_OUT; | |
657 | ocp_write_byte(tp, MCU_TYPE_USB, USB_BMU_RESET, ocp_data); | |
658 | } | |
659 | ||
9dc8ba19 TC |
660 | static int r8152_read_mac(struct r8152 *tp, unsigned char *macaddr) |
661 | { | |
662 | int ret; | |
663 | unsigned char enetaddr[8] = {0}; | |
664 | ||
665 | ret = pla_ocp_read(tp, PLA_IDR, 8, enetaddr); | |
666 | if (ret < 0) | |
667 | return ret; | |
668 | ||
669 | memcpy(macaddr, enetaddr, ETH_ALEN); | |
670 | return 0; | |
671 | } | |
672 | ||
673 | static void r8152b_disable_aldps(struct r8152 *tp) | |
674 | { | |
675 | ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE); | |
676 | mdelay(20); | |
677 | } | |
678 | ||
679 | static void r8152b_enable_aldps(struct r8152 *tp) | |
680 | { | |
681 | ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS | | |
682 | LINKENA | DIS_SDSAVE); | |
683 | } | |
684 | ||
685 | static void rtl8152_disable(struct r8152 *tp) | |
686 | { | |
687 | r8152b_disable_aldps(tp); | |
688 | rtl_disable(tp); | |
689 | r8152b_enable_aldps(tp); | |
690 | } | |
691 | ||
692 | static void r8152b_hw_phy_cfg(struct r8152 *tp) | |
693 | { | |
694 | u16 data; | |
695 | ||
696 | data = r8152_mdio_read(tp, MII_BMCR); | |
697 | if (data & BMCR_PDOWN) { | |
698 | data &= ~BMCR_PDOWN; | |
699 | r8152_mdio_write(tp, MII_BMCR, data); | |
700 | } | |
701 | ||
702 | r8152b_firmware(tp); | |
703 | } | |
704 | ||
705 | static void rtl8152_reinit_ll(struct r8152 *tp) | |
706 | { | |
707 | u32 ocp_data; | |
708 | int ret; | |
709 | ||
710 | ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR, | |
711 | PLA_PHY_PWR_LLR, 1, R8152_WAIT_TIMEOUT); | |
712 | if (ret) | |
713 | debug("Timeout waiting for link list ready\n"); | |
714 | ||
715 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); | |
716 | ocp_data |= RE_INIT_LL; | |
717 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); | |
718 | ||
719 | ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR, | |
720 | PLA_PHY_PWR_LLR, 1, R8152_WAIT_TIMEOUT); | |
721 | if (ret) | |
722 | debug("Timeout waiting for link list ready\n"); | |
723 | } | |
724 | ||
725 | static void r8152b_exit_oob(struct r8152 *tp) | |
726 | { | |
727 | u32 ocp_data; | |
728 | ||
729 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); | |
730 | ocp_data &= ~RCR_ACPT_ALL; | |
731 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); | |
732 | ||
733 | rxdy_gated_en(tp, true); | |
734 | r8152b_hw_phy_cfg(tp); | |
735 | ||
736 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); | |
737 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, 0x00); | |
738 | ||
739 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); | |
740 | ocp_data &= ~NOW_IS_OOB; | |
741 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); | |
742 | ||
743 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); | |
744 | ocp_data &= ~MCU_BORW_EN; | |
745 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); | |
746 | ||
747 | rtl8152_reinit_ll(tp); | |
748 | rtl8152_nic_reset(tp); | |
749 | ||
750 | /* rx share fifo credit full threshold */ | |
751 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL); | |
752 | ||
753 | if (tp->udev->speed == USB_SPEED_FULL || | |
754 | tp->udev->speed == USB_SPEED_LOW) { | |
755 | /* rx share fifo credit near full threshold */ | |
756 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, | |
757 | RXFIFO_THR2_FULL); | |
758 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, | |
759 | RXFIFO_THR3_FULL); | |
760 | } else { | |
761 | /* rx share fifo credit near full threshold */ | |
762 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, | |
763 | RXFIFO_THR2_HIGH); | |
764 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, | |
765 | RXFIFO_THR3_HIGH); | |
766 | } | |
767 | ||
768 | /* TX share fifo free credit full threshold */ | |
769 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL); | |
770 | ||
771 | ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD); | |
772 | ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH); | |
773 | ocp_write_dword(tp, MCU_TYPE_USB, USB_TX_DMA, | |
774 | TEST_MODE_DISABLE | TX_SIZE_ADJUST1); | |
775 | ||
776 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); | |
777 | ||
778 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); | |
779 | ocp_data |= TCR0_AUTO_FIFO; | |
780 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data); | |
781 | } | |
782 | ||
783 | static void r8152b_enter_oob(struct r8152 *tp) | |
784 | { | |
785 | u32 ocp_data; | |
786 | ||
787 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); | |
788 | ocp_data &= ~NOW_IS_OOB; | |
789 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); | |
790 | ||
791 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_OOB); | |
792 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB); | |
793 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB); | |
794 | ||
795 | rtl_disable(tp); | |
796 | ||
797 | rtl8152_reinit_ll(tp); | |
798 | ||
799 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); | |
800 | ||
801 | rtl_rx_vlan_en(tp, false); | |
802 | ||
2cff87f7 | 803 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR); |
9dc8ba19 | 804 | ocp_data |= ALDPS_PROXY_MODE; |
2cff87f7 | 805 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data); |
9dc8ba19 TC |
806 | |
807 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); | |
808 | ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB; | |
809 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); | |
810 | ||
811 | rxdy_gated_en(tp, false); | |
812 | ||
813 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); | |
814 | ocp_data |= RCR_APM | RCR_AM | RCR_AB; | |
815 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); | |
816 | } | |
817 | ||
818 | static void r8153_hw_phy_cfg(struct r8152 *tp) | |
819 | { | |
820 | u32 ocp_data; | |
821 | u16 data; | |
822 | ||
823 | if (tp->version == RTL_VER_03 || tp->version == RTL_VER_04 || | |
824 | tp->version == RTL_VER_05) | |
825 | ocp_reg_write(tp, OCP_ADC_CFG, CKADSEL_L | ADC_EN | EN_EMI_L); | |
826 | ||
827 | data = r8152_mdio_read(tp, MII_BMCR); | |
828 | if (data & BMCR_PDOWN) { | |
829 | data &= ~BMCR_PDOWN; | |
830 | r8152_mdio_write(tp, MII_BMCR, data); | |
831 | } | |
832 | ||
833 | r8153_firmware(tp); | |
834 | ||
835 | if (tp->version == RTL_VER_03) { | |
836 | data = ocp_reg_read(tp, OCP_EEE_CFG); | |
837 | data &= ~CTAP_SHORT_EN; | |
838 | ocp_reg_write(tp, OCP_EEE_CFG, data); | |
839 | } | |
840 | ||
841 | data = ocp_reg_read(tp, OCP_POWER_CFG); | |
842 | data |= EEE_CLKDIV_EN; | |
843 | ocp_reg_write(tp, OCP_POWER_CFG, data); | |
844 | ||
845 | data = ocp_reg_read(tp, OCP_DOWN_SPEED); | |
846 | data |= EN_10M_BGOFF; | |
847 | ocp_reg_write(tp, OCP_DOWN_SPEED, data); | |
848 | data = ocp_reg_read(tp, OCP_POWER_CFG); | |
849 | data |= EN_10M_PLLOFF; | |
850 | ocp_reg_write(tp, OCP_POWER_CFG, data); | |
851 | sram_write(tp, SRAM_IMPEDANCE, 0x0b13); | |
852 | ||
853 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); | |
854 | ocp_data |= PFM_PWM_SWITCH; | |
855 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); | |
856 | ||
857 | /* Enable LPF corner auto tune */ | |
858 | sram_write(tp, SRAM_LPF_CFG, 0xf70f); | |
859 | ||
860 | /* Adjust 10M Amplitude */ | |
861 | sram_write(tp, SRAM_10M_AMP1, 0x00af); | |
862 | sram_write(tp, SRAM_10M_AMP2, 0x0208); | |
863 | } | |
864 | ||
3a41086f HW |
865 | static u32 r8152_efuse_read(struct r8152 *tp, u8 addr) |
866 | { | |
867 | u32 ocp_data; | |
868 | ||
869 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_EFUSE_CMD, EFUSE_READ_CMD | addr); | |
870 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EFUSE_CMD); | |
871 | ocp_data = (ocp_data & EFUSE_DATA_BIT16) << 9; /* data of bit16 */ | |
872 | ocp_data |= ocp_read_word(tp, MCU_TYPE_PLA, PLA_EFUSE_DATA); | |
873 | ||
874 | return ocp_data; | |
875 | } | |
876 | ||
877 | static void r8153b_hw_phy_cfg(struct r8152 *tp) | |
878 | { | |
879 | u32 ocp_data; | |
880 | u16 data; | |
881 | ||
882 | data = r8152_mdio_read(tp, MII_BMCR); | |
883 | if (data & BMCR_PDOWN) { | |
884 | data &= ~BMCR_PDOWN; | |
885 | r8152_mdio_write(tp, MII_BMCR, data); | |
886 | } | |
887 | ||
888 | /* U1/U2/L1 idle timer. 500 us */ | |
889 | ocp_write_word(tp, MCU_TYPE_USB, USB_U1U2_TIMER, 500); | |
890 | ||
891 | r8153b_firmware(tp); | |
892 | ||
893 | data = sram_read(tp, SRAM_GREEN_CFG); | |
894 | data |= R_TUNE_EN; | |
895 | sram_write(tp, SRAM_GREEN_CFG, data); | |
896 | data = ocp_reg_read(tp, OCP_NCTL_CFG); | |
897 | data |= PGA_RETURN_EN; | |
898 | ocp_reg_write(tp, OCP_NCTL_CFG, data); | |
899 | ||
900 | /* ADC Bias Calibration: | |
901 | * read efuse offset 0x7d to get a 17-bit data. Remove the dummy/fake | |
902 | * bit (bit3) to rebuild the real 16-bit data. Write the data to the | |
903 | * ADC ioffset. | |
904 | */ | |
905 | ocp_data = r8152_efuse_read(tp, 0x7d); | |
906 | ocp_data = ((ocp_data & 0x1fff0) >> 1) | (ocp_data & 0x7); | |
907 | if (ocp_data != 0xffff) | |
908 | ocp_reg_write(tp, OCP_ADC_IOFFSET, ocp_data); | |
909 | ||
910 | /* ups mode tx-link-pulse timing adjustment: | |
911 | * rg_saw_cnt = OCP reg 0xC426 Bit[13:0] | |
912 | * swr_cnt_1ms_ini = 16000000 / rg_saw_cnt | |
913 | */ | |
914 | ocp_data = ocp_reg_read(tp, 0xc426); | |
915 | ocp_data &= 0x3fff; | |
916 | if (ocp_data) { | |
917 | u32 swr_cnt_1ms_ini; | |
918 | ||
919 | swr_cnt_1ms_ini = (16000000 / ocp_data) & SAW_CNT_1MS_MASK; | |
920 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG); | |
921 | ocp_data = (ocp_data & ~SAW_CNT_1MS_MASK) | swr_cnt_1ms_ini; | |
922 | ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CFG, ocp_data); | |
923 | } | |
924 | ||
925 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); | |
926 | ocp_data |= PFM_PWM_SWITCH; | |
927 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); | |
928 | } | |
929 | ||
9dc8ba19 TC |
930 | static void r8153_first_init(struct r8152 *tp) |
931 | { | |
932 | u32 ocp_data; | |
933 | ||
934 | rxdy_gated_en(tp, true); | |
935 | ||
936 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); | |
937 | ocp_data &= ~RCR_ACPT_ALL; | |
938 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); | |
939 | ||
940 | r8153_hw_phy_cfg(tp); | |
941 | ||
942 | rtl8152_nic_reset(tp); | |
d74a7623 | 943 | rtl_reset_bmu(tp); |
9dc8ba19 TC |
944 | |
945 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); | |
946 | ocp_data &= ~NOW_IS_OOB; | |
947 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); | |
948 | ||
949 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); | |
950 | ocp_data &= ~MCU_BORW_EN; | |
951 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); | |
952 | ||
953 | rtl8152_reinit_ll(tp); | |
954 | ||
955 | rtl_rx_vlan_en(tp, false); | |
956 | ||
957 | ocp_data = RTL8153_RMS; | |
958 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); | |
959 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); | |
960 | ||
961 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); | |
962 | ocp_data |= TCR0_AUTO_FIFO; | |
963 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data); | |
964 | ||
965 | rtl8152_nic_reset(tp); | |
966 | ||
967 | /* rx share fifo credit full threshold */ | |
968 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL); | |
969 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_NORMAL); | |
970 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL); | |
971 | /* TX share fifo free credit full threshold */ | |
972 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2); | |
973 | ||
974 | /* rx aggregation */ | |
975 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); | |
976 | ||
977 | ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); | |
978 | ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); | |
979 | } | |
980 | ||
981 | static void r8153_enter_oob(struct r8152 *tp) | |
982 | { | |
983 | u32 ocp_data; | |
984 | ||
985 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); | |
986 | ocp_data &= ~NOW_IS_OOB; | |
987 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); | |
988 | ||
989 | rtl_disable(tp); | |
d74a7623 | 990 | rtl_reset_bmu(tp); |
9dc8ba19 TC |
991 | |
992 | rtl8152_reinit_ll(tp); | |
993 | ||
994 | ocp_data = RTL8153_RMS; | |
995 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); | |
996 | ||
997 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG); | |
998 | ocp_data &= ~TEREDO_WAKE_MASK; | |
999 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data); | |
1000 | ||
1001 | rtl_rx_vlan_en(tp, false); | |
1002 | ||
2cff87f7 | 1003 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_BDC_CR); |
9dc8ba19 | 1004 | ocp_data |= ALDPS_PROXY_MODE; |
2cff87f7 | 1005 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_BDC_CR, ocp_data); |
9dc8ba19 TC |
1006 | |
1007 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); | |
1008 | ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB; | |
1009 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); | |
1010 | ||
1011 | rxdy_gated_en(tp, false); | |
1012 | ||
1013 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); | |
1014 | ocp_data |= RCR_APM | RCR_AM | RCR_AB; | |
1015 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); | |
1016 | } | |
1017 | ||
1018 | static void r8153_disable_aldps(struct r8152 *tp) | |
1019 | { | |
1020 | u16 data; | |
1021 | ||
1022 | data = ocp_reg_read(tp, OCP_POWER_CFG); | |
1023 | data &= ~EN_ALDPS; | |
1024 | ocp_reg_write(tp, OCP_POWER_CFG, data); | |
1025 | mdelay(20); | |
1026 | } | |
1027 | ||
1028 | static void rtl8153_disable(struct r8152 *tp) | |
1029 | { | |
1030 | r8153_disable_aldps(tp); | |
1031 | rtl_disable(tp); | |
d74a7623 | 1032 | rtl_reset_bmu(tp); |
9dc8ba19 TC |
1033 | } |
1034 | ||
1035 | static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex) | |
1036 | { | |
1037 | u16 bmcr, anar, gbcr; | |
1038 | ||
1039 | anar = r8152_mdio_read(tp, MII_ADVERTISE); | |
1040 | anar &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | | |
1041 | ADVERTISE_100HALF | ADVERTISE_100FULL); | |
1042 | if (tp->supports_gmii) { | |
1043 | gbcr = r8152_mdio_read(tp, MII_CTRL1000); | |
1044 | gbcr &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); | |
1045 | } else { | |
1046 | gbcr = 0; | |
1047 | } | |
1048 | ||
1049 | if (autoneg == AUTONEG_DISABLE) { | |
1050 | if (speed == SPEED_10) { | |
1051 | bmcr = 0; | |
1052 | anar |= ADVERTISE_10HALF | ADVERTISE_10FULL; | |
1053 | } else if (speed == SPEED_100) { | |
1054 | bmcr = BMCR_SPEED100; | |
1055 | anar |= ADVERTISE_100HALF | ADVERTISE_100FULL; | |
1056 | } else if (speed == SPEED_1000 && tp->supports_gmii) { | |
1057 | bmcr = BMCR_SPEED1000; | |
1058 | gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; | |
1059 | } else { | |
1060 | return -EINVAL; | |
1061 | } | |
1062 | ||
1063 | if (duplex == DUPLEX_FULL) | |
1064 | bmcr |= BMCR_FULLDPLX; | |
1065 | } else { | |
1066 | if (speed == SPEED_10) { | |
1067 | if (duplex == DUPLEX_FULL) | |
1068 | anar |= ADVERTISE_10HALF | ADVERTISE_10FULL; | |
1069 | else | |
1070 | anar |= ADVERTISE_10HALF; | |
1071 | } else if (speed == SPEED_100) { | |
1072 | if (duplex == DUPLEX_FULL) { | |
1073 | anar |= ADVERTISE_10HALF | ADVERTISE_10FULL; | |
1074 | anar |= ADVERTISE_100HALF | ADVERTISE_100FULL; | |
1075 | } else { | |
1076 | anar |= ADVERTISE_10HALF; | |
1077 | anar |= ADVERTISE_100HALF; | |
1078 | } | |
1079 | } else if (speed == SPEED_1000 && tp->supports_gmii) { | |
1080 | if (duplex == DUPLEX_FULL) { | |
1081 | anar |= ADVERTISE_10HALF | ADVERTISE_10FULL; | |
1082 | anar |= ADVERTISE_100HALF | ADVERTISE_100FULL; | |
1083 | gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; | |
1084 | } else { | |
1085 | anar |= ADVERTISE_10HALF; | |
1086 | anar |= ADVERTISE_100HALF; | |
1087 | gbcr |= ADVERTISE_1000HALF; | |
1088 | } | |
1089 | } else { | |
1090 | return -EINVAL; | |
1091 | } | |
1092 | ||
16b9417b | 1093 | bmcr = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET; |
9dc8ba19 TC |
1094 | } |
1095 | ||
1096 | if (tp->supports_gmii) | |
1097 | r8152_mdio_write(tp, MII_CTRL1000, gbcr); | |
1098 | ||
1099 | r8152_mdio_write(tp, MII_ADVERTISE, anar); | |
1100 | r8152_mdio_write(tp, MII_BMCR, bmcr); | |
1101 | ||
1102 | return 0; | |
1103 | } | |
1104 | ||
1105 | static void rtl8152_up(struct r8152 *tp) | |
1106 | { | |
1107 | r8152b_disable_aldps(tp); | |
1108 | r8152b_exit_oob(tp); | |
1109 | r8152b_enable_aldps(tp); | |
1110 | } | |
1111 | ||
1112 | static void rtl8152_down(struct r8152 *tp) | |
1113 | { | |
1114 | r8152_power_cut_en(tp, false); | |
1115 | r8152b_disable_aldps(tp); | |
1116 | r8152b_enter_oob(tp); | |
1117 | r8152b_enable_aldps(tp); | |
1118 | } | |
1119 | ||
1120 | static void rtl8153_up(struct r8152 *tp) | |
1121 | { | |
1122 | r8153_u1u2en(tp, false); | |
1123 | r8153_disable_aldps(tp); | |
1124 | r8153_first_init(tp); | |
1125 | r8153_u2p3en(tp, false); | |
1126 | } | |
1127 | ||
1128 | static void rtl8153_down(struct r8152 *tp) | |
1129 | { | |
1130 | r8153_u1u2en(tp, false); | |
1131 | r8153_u2p3en(tp, false); | |
1132 | r8153_power_cut_en(tp, false); | |
1133 | r8153_disable_aldps(tp); | |
1134 | r8153_enter_oob(tp); | |
1135 | } | |
1136 | ||
3a41086f HW |
1137 | static void rtl8153b_up(struct r8152 *tp) |
1138 | { | |
1139 | r8153_first_init(tp); | |
1140 | } | |
1141 | ||
1142 | static void rtl8153b_down(struct r8152 *tp) | |
1143 | { | |
1144 | r8153_enter_oob(tp); | |
1145 | } | |
1146 | ||
9dc8ba19 TC |
1147 | static void r8152b_get_version(struct r8152 *tp) |
1148 | { | |
1149 | u32 ocp_data; | |
1150 | u16 tcr; | |
1151 | int i; | |
1152 | ||
1153 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR1); | |
1154 | tcr = (u16)(ocp_data & VERSION_MASK); | |
1155 | ||
1156 | for (i = 0; i < ARRAY_SIZE(r8152_versions); i++) { | |
1157 | if (tcr == r8152_versions[i].tcr) { | |
1158 | /* Found a supported version */ | |
1159 | tp->version = r8152_versions[i].version; | |
1160 | tp->supports_gmii = r8152_versions[i].gmii; | |
1161 | break; | |
1162 | } | |
1163 | } | |
1164 | ||
1165 | if (tp->version == RTL_VER_UNKNOWN) | |
1166 | debug("r8152 Unknown tcr version 0x%04x\n", tcr); | |
1167 | } | |
1168 | ||
1169 | static void r8152b_enable_fc(struct r8152 *tp) | |
1170 | { | |
1171 | u16 anar; | |
1172 | anar = r8152_mdio_read(tp, MII_ADVERTISE); | |
1173 | anar |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; | |
1174 | r8152_mdio_write(tp, MII_ADVERTISE, anar); | |
1175 | } | |
1176 | ||
1177 | static void rtl_tally_reset(struct r8152 *tp) | |
1178 | { | |
1179 | u32 ocp_data; | |
1180 | ||
1181 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY); | |
1182 | ocp_data |= TALLY_RESET; | |
1183 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data); | |
1184 | } | |
1185 | ||
1186 | static void r8152b_init(struct r8152 *tp) | |
1187 | { | |
1188 | u32 ocp_data; | |
1189 | ||
1190 | r8152b_disable_aldps(tp); | |
1191 | ||
1192 | if (tp->version == RTL_VER_01) { | |
1193 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE); | |
1194 | ocp_data &= ~LED_MODE_MASK; | |
1195 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data); | |
1196 | } | |
1197 | ||
1198 | r8152_power_cut_en(tp, false); | |
1199 | ||
1200 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); | |
1201 | ocp_data |= TX_10M_IDLE_EN | PFM_PWM_SWITCH; | |
1202 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); | |
1203 | ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL); | |
1204 | ocp_data &= ~MCU_CLK_RATIO_MASK; | |
1205 | ocp_data |= MCU_CLK_RATIO | D3_CLK_GATED_EN; | |
1206 | ocp_write_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ocp_data); | |
1207 | ocp_data = GPHY_STS_MSK | SPEED_DOWN_MSK | | |
1208 | SPDWN_RXDV_MSK | SPDWN_LINKCHG_MSK; | |
1209 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data); | |
1210 | ||
1211 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_TIMER); | |
1212 | ocp_data |= BIT(15); | |
1213 | ocp_write_word(tp, MCU_TYPE_USB, USB_USB_TIMER, ocp_data); | |
1214 | ocp_write_word(tp, MCU_TYPE_USB, 0xcbfc, 0x03e8); | |
1215 | ocp_data &= ~BIT(15); | |
1216 | ocp_write_word(tp, MCU_TYPE_USB, USB_USB_TIMER, ocp_data); | |
1217 | ||
1218 | r8152b_enable_fc(tp); | |
1219 | rtl_tally_reset(tp); | |
1220 | ||
1221 | /* enable rx aggregation */ | |
1222 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); | |
1223 | ||
1224 | ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); | |
1225 | ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); | |
1226 | } | |
1227 | ||
1228 | static void r8153_init(struct r8152 *tp) | |
1229 | { | |
1230 | int i; | |
1231 | u32 ocp_data; | |
1232 | ||
1233 | r8153_disable_aldps(tp); | |
1234 | r8153_u1u2en(tp, false); | |
1235 | ||
1236 | r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_BOOT_CTRL, | |
1237 | AUTOLOAD_DONE, 1, R8152_WAIT_TIMEOUT); | |
1238 | ||
1239 | for (i = 0; i < R8152_WAIT_TIMEOUT; i++) { | |
1240 | ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK; | |
1241 | if (ocp_data == PHY_STAT_LAN_ON || ocp_data == PHY_STAT_PWRDN) | |
1242 | break; | |
1243 | ||
1244 | mdelay(1); | |
1245 | } | |
1246 | ||
1247 | r8153_u2p3en(tp, false); | |
1248 | ||
1249 | if (tp->version == RTL_VER_04) { | |
1250 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2); | |
1251 | ocp_data &= ~pwd_dn_scale_mask; | |
1252 | ocp_data |= pwd_dn_scale(96); | |
1253 | ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2, ocp_data); | |
1254 | ||
1255 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_USB2PHY); | |
1256 | ocp_data |= USB2PHY_L1 | USB2PHY_SUSPEND; | |
1257 | ocp_write_byte(tp, MCU_TYPE_USB, USB_USB2PHY, ocp_data); | |
1258 | } else if (tp->version == RTL_VER_05) { | |
1259 | ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0); | |
1260 | ocp_data &= ~ECM_ALDPS; | |
1261 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0, ocp_data); | |
1262 | ||
1263 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1); | |
1264 | if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0) | |
1265 | ocp_data &= ~DYNAMIC_BURST; | |
1266 | else | |
1267 | ocp_data |= DYNAMIC_BURST; | |
1268 | ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data); | |
1269 | } else if (tp->version == RTL_VER_06) { | |
1270 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1); | |
1271 | if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0) | |
1272 | ocp_data &= ~DYNAMIC_BURST; | |
1273 | else | |
1274 | ocp_data |= DYNAMIC_BURST; | |
1275 | ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data); | |
1276 | } | |
1277 | ||
1278 | ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2); | |
1279 | ocp_data |= EP4_FULL_FC; | |
1280 | ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2, ocp_data); | |
1281 | ||
1282 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL); | |
1283 | ocp_data &= ~TIMER11_EN; | |
1284 | ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data); | |
1285 | ||
1286 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE); | |
1287 | ocp_data &= ~LED_MODE_MASK; | |
1288 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data); | |
1289 | ||
1290 | ocp_data = FIFO_EMPTY_1FB | ROK_EXIT_LPM; | |
1291 | if (tp->version == RTL_VER_04 && tp->udev->speed != USB_SPEED_SUPER) | |
1292 | ocp_data |= LPM_TIMER_500MS; | |
1293 | else | |
1294 | ocp_data |= LPM_TIMER_500US; | |
1295 | ocp_write_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL, ocp_data); | |
1296 | ||
1297 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2); | |
1298 | ocp_data &= ~SEN_VAL_MASK; | |
1299 | ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE; | |
1300 | ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data); | |
1301 | ||
1302 | ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001); | |
1303 | ||
1304 | r8153_power_cut_en(tp, false); | |
1305 | ||
1306 | r8152b_enable_fc(tp); | |
1307 | rtl_tally_reset(tp); | |
1308 | } | |
1309 | ||
3a41086f HW |
1310 | static void r8153b_init(struct r8152 *tp) |
1311 | { | |
1312 | u32 ocp_data; | |
1313 | int i; | |
1314 | ||
1315 | r8153_disable_aldps(tp); | |
1316 | r8153b_u1u2en(tp, false); | |
1317 | ||
1318 | r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_BOOT_CTRL, | |
1319 | AUTOLOAD_DONE, 1, R8152_WAIT_TIMEOUT); | |
1320 | ||
1321 | for (i = 0; i < R8152_WAIT_TIMEOUT; i++) { | |
1322 | ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK; | |
1323 | if (ocp_data == PHY_STAT_LAN_ON || ocp_data == PHY_STAT_PWRDN) | |
1324 | break; | |
1325 | ||
1326 | mdelay(1); | |
1327 | } | |
1328 | ||
1329 | r8153_u2p3en(tp, false); | |
1330 | ||
1331 | /* MSC timer = 0xfff * 8ms = 32760 ms */ | |
1332 | ocp_write_word(tp, MCU_TYPE_USB, USB_MSC_TIMER, 0x0fff); | |
1333 | ||
1334 | r8153_power_cut_en(tp, false); | |
1335 | ||
1336 | /* MAC clock speed down */ | |
1337 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2); | |
1338 | ocp_data |= MAC_CLK_SPDWN_EN; | |
1339 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data); | |
1340 | ||
1341 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3); | |
1342 | ocp_data &= ~PLA_MCU_SPDWN_EN; | |
1343 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data); | |
1344 | ||
1345 | if (tp->version == RTL_VER_09) { | |
1346 | /* Disable Test IO for 32QFN */ | |
1347 | if (ocp_read_byte(tp, MCU_TYPE_PLA, 0xdc00) & BIT(5)) { | |
1348 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); | |
1349 | ocp_data |= TEST_IO_OFF; | |
1350 | ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); | |
1351 | } | |
1352 | } | |
1353 | ||
1354 | /* rx aggregation */ | |
1355 | ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); | |
1356 | ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); | |
1357 | ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); | |
1358 | ||
1359 | rtl_tally_reset(tp); | |
1360 | r8153b_hw_phy_cfg(tp); | |
1361 | r8152b_enable_fc(tp); | |
1362 | } | |
1363 | ||
9dc8ba19 TC |
1364 | static void rtl8152_unload(struct r8152 *tp) |
1365 | { | |
1366 | if (tp->version != RTL_VER_01) | |
1367 | r8152_power_cut_en(tp, true); | |
1368 | } | |
1369 | ||
1370 | static void rtl8153_unload(struct r8152 *tp) | |
1371 | { | |
1372 | r8153_power_cut_en(tp, false); | |
1373 | } | |
1374 | ||
1375 | static int rtl_ops_init(struct r8152 *tp) | |
1376 | { | |
1377 | struct rtl_ops *ops = &tp->rtl_ops; | |
1378 | int ret = 0; | |
1379 | ||
1380 | switch (tp->version) { | |
1381 | case RTL_VER_01: | |
1382 | case RTL_VER_02: | |
1383 | case RTL_VER_07: | |
1384 | ops->init = r8152b_init; | |
1385 | ops->enable = rtl8152_enable; | |
1386 | ops->disable = rtl8152_disable; | |
1387 | ops->up = rtl8152_up; | |
1388 | ops->down = rtl8152_down; | |
1389 | ops->unload = rtl8152_unload; | |
1390 | break; | |
1391 | ||
1392 | case RTL_VER_03: | |
1393 | case RTL_VER_04: | |
1394 | case RTL_VER_05: | |
1395 | case RTL_VER_06: | |
1396 | ops->init = r8153_init; | |
1397 | ops->enable = rtl8153_enable; | |
1398 | ops->disable = rtl8153_disable; | |
1399 | ops->up = rtl8153_up; | |
1400 | ops->down = rtl8153_down; | |
1401 | ops->unload = rtl8153_unload; | |
1402 | break; | |
1403 | ||
3a41086f HW |
1404 | case RTL_VER_08: |
1405 | case RTL_VER_09: | |
1406 | ops->init = r8153b_init; | |
1407 | ops->enable = rtl8153_enable; | |
1408 | ops->disable = rtl8153_disable; | |
1409 | ops->up = rtl8153b_up; | |
1410 | ops->down = rtl8153b_down; | |
1411 | break; | |
1412 | ||
9dc8ba19 TC |
1413 | default: |
1414 | ret = -ENODEV; | |
1415 | printf("r8152 Unknown Device\n"); | |
1416 | break; | |
1417 | } | |
1418 | ||
1419 | return ret; | |
1420 | } | |
1421 | ||
6688452a | 1422 | static int r8152_init_common(struct r8152 *tp) |
9dc8ba19 | 1423 | { |
9dc8ba19 TC |
1424 | u8 speed; |
1425 | int timeout = 0; | |
1426 | int link_detected; | |
1427 | ||
1428 | debug("** %s()\n", __func__); | |
1429 | ||
1430 | do { | |
1431 | speed = rtl8152_get_speed(tp); | |
1432 | ||
1433 | link_detected = speed & LINK_STATUS; | |
1434 | if (!link_detected) { | |
1435 | if (timeout == 0) | |
1436 | printf("Waiting for Ethernet connection... "); | |
1437 | mdelay(TIMEOUT_RESOLUTION); | |
1438 | timeout += TIMEOUT_RESOLUTION; | |
1439 | } | |
1440 | } while (!link_detected && timeout < PHY_CONNECT_TIMEOUT); | |
1441 | if (link_detected) { | |
1442 | tp->rtl_ops.enable(tp); | |
1443 | ||
1444 | if (timeout != 0) | |
1445 | printf("done.\n"); | |
1446 | } else { | |
1447 | printf("unable to connect.\n"); | |
1448 | } | |
1449 | ||
1450 | return 0; | |
1451 | } | |
1452 | ||
6688452a | 1453 | static int r8152_send_common(struct ueth_data *ueth, void *packet, int length) |
9dc8ba19 | 1454 | { |
6688452a | 1455 | struct usb_device *udev = ueth->pusb_dev; |
9dc8ba19 | 1456 | u32 opts1, opts2 = 0; |
9dc8ba19 | 1457 | int err; |
9dc8ba19 | 1458 | int actual_len; |
c7ac1538 SR |
1459 | ALLOC_CACHE_ALIGN_BUFFER(uint8_t, msg, |
1460 | PKTSIZE + sizeof(struct tx_desc)); | |
9dc8ba19 TC |
1461 | struct tx_desc *tx_desc = (struct tx_desc *)msg; |
1462 | ||
1463 | debug("** %s(), len %d\n", __func__, length); | |
1464 | ||
1465 | opts1 = length | TX_FS | TX_LS; | |
1466 | ||
1467 | tx_desc->opts2 = cpu_to_le32(opts2); | |
1468 | tx_desc->opts1 = cpu_to_le32(opts1); | |
1469 | ||
1470 | memcpy(msg + sizeof(struct tx_desc), (void *)packet, length); | |
1471 | ||
6688452a SR |
1472 | err = usb_bulk_msg(udev, usb_sndbulkpipe(udev, ueth->ep_out), |
1473 | (void *)msg, length + sizeof(struct tx_desc), | |
1474 | &actual_len, USB_BULK_SEND_TIMEOUT); | |
9dc8ba19 TC |
1475 | debug("Tx: len = %zu, actual = %u, err = %d\n", |
1476 | length + sizeof(struct tx_desc), actual_len, err); | |
1477 | ||
1478 | return err; | |
1479 | } | |
1480 | ||
6688452a | 1481 | #ifndef CONFIG_DM_ETH |
b75d8dc5 | 1482 | static int r8152_init(struct eth_device *eth, struct bd_info *bd) |
6688452a SR |
1483 | { |
1484 | struct ueth_data *dev = (struct ueth_data *)eth->priv; | |
1485 | struct r8152 *tp = (struct r8152 *)dev->dev_priv; | |
1486 | ||
1487 | return r8152_init_common(tp); | |
1488 | } | |
1489 | ||
1490 | static int r8152_send(struct eth_device *eth, void *packet, int length) | |
1491 | { | |
1492 | struct ueth_data *dev = (struct ueth_data *)eth->priv; | |
1493 | ||
1494 | return r8152_send_common(dev, packet, length); | |
1495 | } | |
1496 | ||
9dc8ba19 TC |
1497 | static int r8152_recv(struct eth_device *eth) |
1498 | { | |
1499 | struct ueth_data *dev = (struct ueth_data *)eth->priv; | |
1500 | ||
c7ac1538 | 1501 | ALLOC_CACHE_ALIGN_BUFFER(uint8_t, recv_buf, RTL8152_AGG_BUF_SZ); |
9dc8ba19 TC |
1502 | unsigned char *pkt_ptr; |
1503 | int err; | |
1504 | int actual_len; | |
1505 | u16 packet_len; | |
1506 | ||
1507 | u32 bytes_process = 0; | |
1508 | struct rx_desc *rx_desc; | |
1509 | ||
1510 | debug("** %s()\n", __func__); | |
1511 | ||
1512 | err = usb_bulk_msg(dev->pusb_dev, | |
1513 | usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in), | |
1514 | (void *)recv_buf, | |
1515 | RTL8152_AGG_BUF_SZ, | |
1516 | &actual_len, | |
1517 | USB_BULK_RECV_TIMEOUT); | |
1518 | debug("Rx: len = %u, actual = %u, err = %d\n", RTL8152_AGG_BUF_SZ, | |
1519 | actual_len, err); | |
1520 | if (err != 0) { | |
1521 | debug("Rx: failed to receive\n"); | |
1522 | return -1; | |
1523 | } | |
1524 | if (actual_len > RTL8152_AGG_BUF_SZ) { | |
1525 | debug("Rx: received too many bytes %d\n", actual_len); | |
1526 | return -1; | |
1527 | } | |
1528 | ||
1529 | while (bytes_process < actual_len) { | |
1530 | rx_desc = (struct rx_desc *)(recv_buf + bytes_process); | |
1531 | pkt_ptr = recv_buf + sizeof(struct rx_desc) + bytes_process; | |
1532 | ||
1533 | packet_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; | |
1534 | packet_len -= CRC_SIZE; | |
1535 | ||
1536 | net_process_received_packet(pkt_ptr, packet_len); | |
1537 | ||
1538 | bytes_process += | |
1539 | (packet_len + sizeof(struct rx_desc) + CRC_SIZE); | |
1540 | ||
1541 | if (bytes_process % 8) | |
1542 | bytes_process = bytes_process + 8 - (bytes_process % 8); | |
1543 | } | |
1544 | ||
1545 | return 0; | |
1546 | } | |
1547 | ||
1548 | static void r8152_halt(struct eth_device *eth) | |
1549 | { | |
1550 | struct ueth_data *dev = (struct ueth_data *)eth->priv; | |
1551 | struct r8152 *tp = (struct r8152 *)dev->dev_priv; | |
1552 | ||
1553 | debug("** %s()\n", __func__); | |
1554 | ||
1555 | tp->rtl_ops.disable(tp); | |
1556 | } | |
1557 | ||
1558 | static int r8152_write_hwaddr(struct eth_device *eth) | |
1559 | { | |
1560 | struct ueth_data *dev = (struct ueth_data *)eth->priv; | |
1561 | struct r8152 *tp = (struct r8152 *)dev->dev_priv; | |
1562 | ||
1563 | unsigned char enetaddr[8] = {0}; | |
1564 | ||
1565 | memcpy(enetaddr, eth->enetaddr, ETH_ALEN); | |
1566 | ||
1567 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); | |
1568 | pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, enetaddr); | |
1569 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); | |
1570 | ||
1571 | debug("MAC %pM\n", eth->enetaddr); | |
1572 | return 0; | |
1573 | } | |
1574 | ||
1575 | void r8152_eth_before_probe(void) | |
1576 | { | |
1577 | curr_eth_dev = 0; | |
1578 | } | |
1579 | ||
1580 | /* Probe to see if a new device is actually an realtek device */ | |
1581 | int r8152_eth_probe(struct usb_device *dev, unsigned int ifnum, | |
1582 | struct ueth_data *ss) | |
1583 | { | |
1584 | struct usb_interface *iface; | |
1585 | struct usb_interface_descriptor *iface_desc; | |
1586 | int ep_in_found = 0, ep_out_found = 0; | |
9dc8ba19 | 1587 | struct r8152 *tp; |
3da0291b | 1588 | int i; |
9dc8ba19 TC |
1589 | |
1590 | /* let's examine the device now */ | |
1591 | iface = &dev->config.if_desc[ifnum]; | |
1592 | iface_desc = &dev->config.if_desc[ifnum].desc; | |
1593 | ||
1594 | for (i = 0; i < ARRAY_SIZE(r8152_dongles); i++) { | |
1595 | if (dev->descriptor.idVendor == r8152_dongles[i].vendor && | |
1596 | dev->descriptor.idProduct == r8152_dongles[i].product) | |
1597 | /* Found a supported dongle */ | |
1598 | break; | |
1599 | } | |
1600 | ||
1601 | if (i == ARRAY_SIZE(r8152_dongles)) | |
1602 | return 0; | |
1603 | ||
1604 | memset(ss, 0, sizeof(struct ueth_data)); | |
1605 | ||
1606 | /* At this point, we know we've got a live one */ | |
1607 | debug("\n\nUSB Ethernet device detected: %#04x:%#04x\n", | |
1608 | dev->descriptor.idVendor, dev->descriptor.idProduct); | |
1609 | ||
1610 | /* Initialize the ueth_data structure with some useful info */ | |
1611 | ss->ifnum = ifnum; | |
1612 | ss->pusb_dev = dev; | |
1613 | ss->subclass = iface_desc->bInterfaceSubClass; | |
1614 | ss->protocol = iface_desc->bInterfaceProtocol; | |
1615 | ||
1616 | /* alloc driver private */ | |
1617 | ss->dev_priv = calloc(1, sizeof(struct r8152)); | |
1618 | ||
1619 | if (!ss->dev_priv) | |
1620 | return 0; | |
1621 | ||
1622 | /* | |
1623 | * We are expecting a minimum of 3 endpoints - in, out (bulk), and | |
1624 | * int. We will ignore any others. | |
1625 | */ | |
1626 | for (i = 0; i < iface_desc->bNumEndpoints; i++) { | |
1627 | /* is it an BULK endpoint? */ | |
1628 | if ((iface->ep_desc[i].bmAttributes & | |
1629 | USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { | |
1630 | u8 ep_addr = iface->ep_desc[i].bEndpointAddress; | |
3da0291b HW |
1631 | |
1632 | if (ep_addr & USB_DIR_IN) { | |
1633 | if (!ep_in_found) { | |
1634 | ss->ep_in = ep_addr & | |
1635 | USB_ENDPOINT_NUMBER_MASK; | |
1636 | ep_in_found = 1; | |
1637 | } | |
9dc8ba19 TC |
1638 | } else { |
1639 | if (!ep_out_found) { | |
1640 | ss->ep_out = ep_addr & | |
1641 | USB_ENDPOINT_NUMBER_MASK; | |
1642 | ep_out_found = 1; | |
1643 | } | |
1644 | } | |
1645 | } | |
1646 | ||
1647 | /* is it an interrupt endpoint? */ | |
1648 | if ((iface->ep_desc[i].bmAttributes & | |
1649 | USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { | |
1650 | ss->ep_int = iface->ep_desc[i].bEndpointAddress & | |
1651 | USB_ENDPOINT_NUMBER_MASK; | |
1652 | ss->irqinterval = iface->ep_desc[i].bInterval; | |
1653 | } | |
1654 | } | |
1655 | ||
1656 | debug("Endpoints In %d Out %d Int %d\n", | |
1657 | ss->ep_in, ss->ep_out, ss->ep_int); | |
1658 | ||
1659 | /* Do some basic sanity checks, and bail if we find a problem */ | |
1660 | if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) || | |
1661 | !ss->ep_in || !ss->ep_out || !ss->ep_int) { | |
1662 | debug("Problems with device\n"); | |
17d5a461 | 1663 | goto error; |
9dc8ba19 TC |
1664 | } |
1665 | ||
1666 | dev->privptr = (void *)ss; | |
1667 | ||
1668 | tp = ss->dev_priv; | |
1669 | tp->udev = dev; | |
1670 | tp->intf = iface; | |
1671 | ||
1672 | r8152b_get_version(tp); | |
1673 | ||
1674 | if (rtl_ops_init(tp)) | |
17d5a461 | 1675 | goto error; |
9dc8ba19 TC |
1676 | |
1677 | tp->rtl_ops.init(tp); | |
1678 | tp->rtl_ops.up(tp); | |
1679 | ||
1680 | rtl8152_set_speed(tp, AUTONEG_ENABLE, | |
1681 | tp->supports_gmii ? SPEED_1000 : SPEED_100, | |
1682 | DUPLEX_FULL); | |
1683 | ||
1684 | return 1; | |
17d5a461 HW |
1685 | |
1686 | error: | |
1687 | cfree(ss->dev_priv); | |
1688 | ss->dev_priv = 0; | |
1689 | return 0; | |
9dc8ba19 TC |
1690 | } |
1691 | ||
1692 | int r8152_eth_get_info(struct usb_device *dev, struct ueth_data *ss, | |
1693 | struct eth_device *eth) | |
1694 | { | |
1695 | if (!eth) { | |
1696 | debug("%s: missing parameter.\n", __func__); | |
1697 | return 0; | |
1698 | } | |
1699 | ||
1700 | sprintf(eth->name, "%s#%d", R8152_BASE_NAME, curr_eth_dev++); | |
1701 | eth->init = r8152_init; | |
1702 | eth->send = r8152_send; | |
1703 | eth->recv = r8152_recv; | |
1704 | eth->halt = r8152_halt; | |
1705 | eth->write_hwaddr = r8152_write_hwaddr; | |
1706 | eth->priv = ss; | |
1707 | ||
1708 | /* Get the MAC address */ | |
1709 | if (r8152_read_mac(ss->dev_priv, eth->enetaddr) < 0) | |
1710 | return 0; | |
1711 | ||
1712 | debug("MAC %pM\n", eth->enetaddr); | |
1713 | return 1; | |
1714 | } | |
6688452a SR |
1715 | #endif /* !CONFIG_DM_ETH */ |
1716 | ||
1717 | #ifdef CONFIG_DM_ETH | |
1718 | static int r8152_eth_start(struct udevice *dev) | |
1719 | { | |
1720 | struct r8152 *tp = dev_get_priv(dev); | |
1721 | ||
1722 | debug("** %s (%d)\n", __func__, __LINE__); | |
1723 | ||
1724 | return r8152_init_common(tp); | |
1725 | } | |
1726 | ||
1727 | void r8152_eth_stop(struct udevice *dev) | |
1728 | { | |
1729 | struct r8152 *tp = dev_get_priv(dev); | |
1730 | ||
1731 | debug("** %s (%d)\n", __func__, __LINE__); | |
1732 | ||
1733 | tp->rtl_ops.disable(tp); | |
1734 | } | |
1735 | ||
1736 | int r8152_eth_send(struct udevice *dev, void *packet, int length) | |
1737 | { | |
1738 | struct r8152 *tp = dev_get_priv(dev); | |
1739 | ||
1740 | return r8152_send_common(&tp->ueth, packet, length); | |
1741 | } | |
1742 | ||
1743 | int r8152_eth_recv(struct udevice *dev, int flags, uchar **packetp) | |
1744 | { | |
1745 | struct r8152 *tp = dev_get_priv(dev); | |
1746 | struct ueth_data *ueth = &tp->ueth; | |
1747 | uint8_t *ptr; | |
1748 | int ret, len; | |
1749 | struct rx_desc *rx_desc; | |
1750 | u16 packet_len; | |
1751 | ||
1752 | len = usb_ether_get_rx_bytes(ueth, &ptr); | |
1753 | debug("%s: first try, len=%d\n", __func__, len); | |
1754 | if (!len) { | |
1755 | if (!(flags & ETH_RECV_CHECK_DEVICE)) | |
1756 | return -EAGAIN; | |
1757 | ret = usb_ether_receive(ueth, RTL8152_AGG_BUF_SZ); | |
1758 | if (ret) | |
1759 | return ret; | |
1760 | ||
1761 | len = usb_ether_get_rx_bytes(ueth, &ptr); | |
1762 | debug("%s: second try, len=%d\n", __func__, len); | |
1763 | } | |
1764 | ||
1765 | rx_desc = (struct rx_desc *)ptr; | |
1766 | packet_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; | |
1767 | packet_len -= CRC_SIZE; | |
1768 | ||
1769 | if (packet_len > len - (sizeof(struct rx_desc) + CRC_SIZE)) { | |
1770 | debug("Rx: too large packet: %d\n", packet_len); | |
1771 | goto err; | |
1772 | } | |
1773 | ||
1774 | *packetp = ptr + sizeof(struct rx_desc); | |
1775 | return packet_len; | |
1776 | ||
1777 | err: | |
1778 | usb_ether_advance_rxbuf(ueth, -1); | |
1779 | return -ENOSPC; | |
1780 | } | |
1781 | ||
1782 | static int r8152_free_pkt(struct udevice *dev, uchar *packet, int packet_len) | |
1783 | { | |
1784 | struct r8152 *tp = dev_get_priv(dev); | |
1785 | ||
1786 | packet_len += sizeof(struct rx_desc) + CRC_SIZE; | |
1787 | packet_len = ALIGN(packet_len, 8); | |
1788 | usb_ether_advance_rxbuf(&tp->ueth, packet_len); | |
1789 | ||
1790 | return 0; | |
1791 | } | |
1792 | ||
1793 | static int r8152_write_hwaddr(struct udevice *dev) | |
1794 | { | |
c69cda25 | 1795 | struct eth_pdata *pdata = dev_get_plat(dev); |
6688452a SR |
1796 | struct r8152 *tp = dev_get_priv(dev); |
1797 | ||
1798 | unsigned char enetaddr[8] = { 0 }; | |
1799 | ||
1800 | debug("** %s (%d)\n", __func__, __LINE__); | |
1801 | memcpy(enetaddr, pdata->enetaddr, ETH_ALEN); | |
1802 | ||
1803 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); | |
1804 | pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, enetaddr); | |
1805 | ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); | |
1806 | ||
1807 | debug("MAC %pM\n", pdata->enetaddr); | |
1808 | return 0; | |
1809 | } | |
1810 | ||
1811 | int r8152_read_rom_hwaddr(struct udevice *dev) | |
1812 | { | |
c69cda25 | 1813 | struct eth_pdata *pdata = dev_get_plat(dev); |
6688452a SR |
1814 | struct r8152 *tp = dev_get_priv(dev); |
1815 | ||
1816 | debug("** %s (%d)\n", __func__, __LINE__); | |
1817 | r8152_read_mac(tp, pdata->enetaddr); | |
1818 | return 0; | |
1819 | } | |
1820 | ||
1821 | static int r8152_eth_probe(struct udevice *dev) | |
1822 | { | |
1823 | struct usb_device *udev = dev_get_parent_priv(dev); | |
c69cda25 | 1824 | struct eth_pdata *pdata = dev_get_plat(dev); |
6688452a SR |
1825 | struct r8152 *tp = dev_get_priv(dev); |
1826 | struct ueth_data *ueth = &tp->ueth; | |
1827 | int ret; | |
1828 | ||
1829 | tp->udev = udev; | |
1830 | r8152_read_mac(tp, pdata->enetaddr); | |
1831 | ||
1832 | r8152b_get_version(tp); | |
1833 | ||
1834 | ret = rtl_ops_init(tp); | |
1835 | if (ret) | |
1836 | return ret; | |
1837 | ||
1838 | tp->rtl_ops.init(tp); | |
1839 | tp->rtl_ops.up(tp); | |
1840 | ||
1841 | rtl8152_set_speed(tp, AUTONEG_ENABLE, | |
1842 | tp->supports_gmii ? SPEED_1000 : SPEED_100, | |
1843 | DUPLEX_FULL); | |
1844 | ||
1845 | return usb_ether_register(dev, ueth, RTL8152_AGG_BUF_SZ); | |
1846 | } | |
1847 | ||
1848 | static const struct eth_ops r8152_eth_ops = { | |
1849 | .start = r8152_eth_start, | |
1850 | .send = r8152_eth_send, | |
1851 | .recv = r8152_eth_recv, | |
1852 | .free_pkt = r8152_free_pkt, | |
1853 | .stop = r8152_eth_stop, | |
1854 | .write_hwaddr = r8152_write_hwaddr, | |
1855 | .read_rom_hwaddr = r8152_read_rom_hwaddr, | |
1856 | }; | |
1857 | ||
1858 | U_BOOT_DRIVER(r8152_eth) = { | |
1859 | .name = "r8152_eth", | |
1860 | .id = UCLASS_ETH, | |
1861 | .probe = r8152_eth_probe, | |
1862 | .ops = &r8152_eth_ops, | |
41575d8e | 1863 | .priv_auto = sizeof(struct r8152), |
caa4daa2 | 1864 | .plat_auto = sizeof(struct eth_pdata), |
6688452a SR |
1865 | }; |
1866 | ||
1867 | static const struct usb_device_id r8152_eth_id_table[] = { | |
1868 | /* Realtek */ | |
1869 | { USB_DEVICE(0x0bda, 0x8050) }, | |
1870 | { USB_DEVICE(0x0bda, 0x8152) }, | |
1871 | { USB_DEVICE(0x0bda, 0x8153) }, | |
1872 | ||
1873 | /* Samsung */ | |
1874 | { USB_DEVICE(0x04e8, 0xa101) }, | |
1875 | ||
1876 | /* Lenovo */ | |
1877 | { USB_DEVICE(0x17ef, 0x304f) }, | |
1878 | { USB_DEVICE(0x17ef, 0x3052) }, | |
1879 | { USB_DEVICE(0x17ef, 0x3054) }, | |
1880 | { USB_DEVICE(0x17ef, 0x3057) }, | |
1881 | { USB_DEVICE(0x17ef, 0x7205) }, | |
1882 | { USB_DEVICE(0x17ef, 0x720a) }, | |
1883 | { USB_DEVICE(0x17ef, 0x720b) }, | |
1884 | { USB_DEVICE(0x17ef, 0x720c) }, | |
1885 | ||
1886 | /* TP-LINK */ | |
1887 | { USB_DEVICE(0x2357, 0x0601) }, | |
1888 | ||
1889 | /* Nvidia */ | |
1890 | { USB_DEVICE(0x0955, 0x09ff) }, | |
1891 | ||
1892 | { } /* Terminating entry */ | |
1893 | }; | |
1894 | ||
1895 | U_BOOT_USB_DEVICE(r8152_eth, r8152_eth_id_table); | |
1896 | #endif /* CONFIG_DM_ETH */ |