19dc8ba19STed Chen /* 29dc8ba19STed Chen * Copyright (c) 2015 Realtek Semiconductor Corp. All rights reserved. 39dc8ba19STed Chen * 49dc8ba19STed Chen * SPDX-License-Identifier: GPL-2.0 59dc8ba19STed Chen * 69dc8ba19STed Chen */ 79dc8ba19STed Chen 89dc8ba19STed Chen #include <common.h> 96688452aSStefan Roese #include <dm.h> 109dc8ba19STed Chen #include <errno.h> 119dc8ba19STed Chen #include <malloc.h> 12*c7ac1538SStefan Roese #include <memalign.h> 139dc8ba19STed Chen #include <usb.h> 149dc8ba19STed Chen #include <usb/lin_gadget_compat.h> 159dc8ba19STed Chen #include <linux/mii.h> 169dc8ba19STed Chen #include <linux/bitops.h> 179dc8ba19STed Chen #include "usb_ether.h" 189dc8ba19STed Chen #include "r8152.h" 199dc8ba19STed Chen 206688452aSStefan Roese #ifndef CONFIG_DM_ETH 219dc8ba19STed Chen /* local vars */ 229dc8ba19STed Chen static int curr_eth_dev; /* index for name of next device detected */ 239dc8ba19STed Chen 249dc8ba19STed Chen struct r8152_dongle { 259dc8ba19STed Chen unsigned short vendor; 269dc8ba19STed Chen unsigned short product; 279dc8ba19STed Chen }; 289dc8ba19STed Chen 299dc8ba19STed Chen static const struct r8152_dongle const r8152_dongles[] = { 309dc8ba19STed Chen /* Realtek */ 319dc8ba19STed Chen { 0x0bda, 0x8050 }, 329dc8ba19STed Chen { 0x0bda, 0x8152 }, 339dc8ba19STed Chen { 0x0bda, 0x8153 }, 349dc8ba19STed Chen 359dc8ba19STed Chen /* Samsung */ 369dc8ba19STed Chen { 0x04e8, 0xa101 }, 379dc8ba19STed Chen 389dc8ba19STed Chen /* Lenovo */ 399dc8ba19STed Chen { 0x17ef, 0x304f }, 409dc8ba19STed Chen { 0x17ef, 0x3052 }, 419dc8ba19STed Chen { 0x17ef, 0x3054 }, 429dc8ba19STed Chen { 0x17ef, 0x3057 }, 439dc8ba19STed Chen { 0x17ef, 0x7205 }, 449dc8ba19STed Chen { 0x17ef, 0x720a }, 459dc8ba19STed Chen { 0x17ef, 0x720b }, 469dc8ba19STed Chen { 0x17ef, 0x720c }, 479dc8ba19STed Chen 489dc8ba19STed Chen /* TP-LINK */ 499dc8ba19STed Chen { 0x2357, 0x0601 }, 509dc8ba19STed Chen 519dc8ba19STed Chen /* Nvidia */ 529dc8ba19STed Chen { 0x0955, 0x09ff }, 539dc8ba19STed Chen }; 546688452aSStefan Roese #endif 556688452aSStefan Roese 566688452aSStefan Roese struct r8152_version { 576688452aSStefan Roese unsigned short tcr; 586688452aSStefan Roese unsigned short version; 596688452aSStefan Roese bool gmii; 606688452aSStefan Roese }; 619dc8ba19STed Chen 629dc8ba19STed Chen static const struct r8152_version const r8152_versions[] = { 639dc8ba19STed Chen { 0x4c00, RTL_VER_01, 0 }, 649dc8ba19STed Chen { 0x4c10, RTL_VER_02, 0 }, 659dc8ba19STed Chen { 0x5c00, RTL_VER_03, 1 }, 669dc8ba19STed Chen { 0x5c10, RTL_VER_04, 1 }, 679dc8ba19STed Chen { 0x5c20, RTL_VER_05, 1 }, 689dc8ba19STed Chen { 0x5c30, RTL_VER_06, 1 }, 699dc8ba19STed Chen { 0x4800, RTL_VER_07, 0 }, 709dc8ba19STed Chen }; 719dc8ba19STed Chen 729dc8ba19STed Chen static 739dc8ba19STed Chen int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) 749dc8ba19STed Chen { 75*c7ac1538SStefan Roese ALLOC_CACHE_ALIGN_BUFFER(void *, tmp, size); 76*c7ac1538SStefan Roese int ret; 77*c7ac1538SStefan Roese 78*c7ac1538SStefan Roese ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0), 799dc8ba19STed Chen RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, 80*c7ac1538SStefan Roese value, index, tmp, size, 500); 81*c7ac1538SStefan Roese memcpy(data, tmp, size); 82*c7ac1538SStefan Roese return ret; 839dc8ba19STed Chen } 849dc8ba19STed Chen 859dc8ba19STed Chen static 869dc8ba19STed Chen int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) 879dc8ba19STed Chen { 88*c7ac1538SStefan Roese ALLOC_CACHE_ALIGN_BUFFER(void *, tmp, size); 89*c7ac1538SStefan Roese 90*c7ac1538SStefan Roese memcpy(tmp, data, size); 919dc8ba19STed Chen return usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0), 929dc8ba19STed Chen RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, 93*c7ac1538SStefan Roese value, index, tmp, size, 500); 949dc8ba19STed Chen } 959dc8ba19STed Chen 969dc8ba19STed Chen int generic_ocp_read(struct r8152 *tp, u16 index, u16 size, 979dc8ba19STed Chen void *data, u16 type) 989dc8ba19STed Chen { 999dc8ba19STed Chen u16 burst_size = 64; 1009dc8ba19STed Chen int ret; 1019dc8ba19STed Chen int txsize; 1029dc8ba19STed Chen 1039dc8ba19STed Chen /* both size and index must be 4 bytes align */ 1049dc8ba19STed Chen if ((size & 3) || !size || (index & 3) || !data) 1059dc8ba19STed Chen return -EINVAL; 1069dc8ba19STed Chen 1079dc8ba19STed Chen if (index + size > 0xffff) 1089dc8ba19STed Chen return -EINVAL; 1099dc8ba19STed Chen 1109dc8ba19STed Chen while (size) { 1119dc8ba19STed Chen txsize = min(size, burst_size); 1129dc8ba19STed Chen ret = get_registers(tp, index, type, txsize, data); 1139dc8ba19STed Chen if (ret < 0) 1149dc8ba19STed Chen break; 1159dc8ba19STed Chen 1169dc8ba19STed Chen index += txsize; 1179dc8ba19STed Chen data += txsize; 1189dc8ba19STed Chen size -= txsize; 1199dc8ba19STed Chen } 1209dc8ba19STed Chen 1219dc8ba19STed Chen return ret; 1229dc8ba19STed Chen } 1239dc8ba19STed Chen 1249dc8ba19STed Chen int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen, 1259dc8ba19STed Chen u16 size, void *data, u16 type) 1269dc8ba19STed Chen { 1279dc8ba19STed Chen int ret; 1289dc8ba19STed Chen u16 byteen_start, byteen_end, byte_en_to_hw; 1299dc8ba19STed Chen u16 burst_size = 512; 1309dc8ba19STed Chen int txsize; 1319dc8ba19STed Chen 1329dc8ba19STed Chen /* both size and index must be 4 bytes align */ 1339dc8ba19STed Chen if ((size & 3) || !size || (index & 3) || !data) 1349dc8ba19STed Chen return -EINVAL; 1359dc8ba19STed Chen 1369dc8ba19STed Chen if (index + size > 0xffff) 1379dc8ba19STed Chen return -EINVAL; 1389dc8ba19STed Chen 1399dc8ba19STed Chen byteen_start = byteen & BYTE_EN_START_MASK; 1409dc8ba19STed Chen byteen_end = byteen & BYTE_EN_END_MASK; 1419dc8ba19STed Chen 1429dc8ba19STed Chen byte_en_to_hw = byteen_start | (byteen_start << 4); 1439dc8ba19STed Chen ret = set_registers(tp, index, type | byte_en_to_hw, 4, data); 1449dc8ba19STed Chen if (ret < 0) 1459dc8ba19STed Chen return ret; 1469dc8ba19STed Chen 1479dc8ba19STed Chen index += 4; 1489dc8ba19STed Chen data += 4; 1499dc8ba19STed Chen size -= 4; 1509dc8ba19STed Chen 1519dc8ba19STed Chen if (size) { 1529dc8ba19STed Chen size -= 4; 1539dc8ba19STed Chen 1549dc8ba19STed Chen while (size) { 1559dc8ba19STed Chen txsize = min(size, burst_size); 1569dc8ba19STed Chen 1579dc8ba19STed Chen ret = set_registers(tp, index, 1589dc8ba19STed Chen type | BYTE_EN_DWORD, 1599dc8ba19STed Chen txsize, data); 1609dc8ba19STed Chen if (ret < 0) 1619dc8ba19STed Chen return ret; 1629dc8ba19STed Chen 1639dc8ba19STed Chen index += txsize; 1649dc8ba19STed Chen data += txsize; 1659dc8ba19STed Chen size -= txsize; 1669dc8ba19STed Chen } 1679dc8ba19STed Chen 1689dc8ba19STed Chen byte_en_to_hw = byteen_end | (byteen_end >> 4); 1699dc8ba19STed Chen ret = set_registers(tp, index, type | byte_en_to_hw, 4, data); 1709dc8ba19STed Chen if (ret < 0) 1719dc8ba19STed Chen return ret; 1729dc8ba19STed Chen } 1739dc8ba19STed Chen 1749dc8ba19STed Chen return ret; 1759dc8ba19STed Chen } 1769dc8ba19STed Chen 1779dc8ba19STed Chen int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data) 1789dc8ba19STed Chen { 1799dc8ba19STed Chen return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA); 1809dc8ba19STed Chen } 1819dc8ba19STed Chen 1829dc8ba19STed Chen int pla_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data) 1839dc8ba19STed Chen { 1849dc8ba19STed Chen return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_PLA); 1859dc8ba19STed Chen } 1869dc8ba19STed Chen 1879dc8ba19STed Chen int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data) 1889dc8ba19STed Chen { 1899dc8ba19STed Chen return generic_ocp_read(tp, index, size, data, MCU_TYPE_USB); 1909dc8ba19STed Chen } 1919dc8ba19STed Chen 1929dc8ba19STed Chen int usb_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data) 1939dc8ba19STed Chen { 1949dc8ba19STed Chen return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_USB); 1959dc8ba19STed Chen } 1969dc8ba19STed Chen 1979dc8ba19STed Chen u32 ocp_read_dword(struct r8152 *tp, u16 type, u16 index) 1989dc8ba19STed Chen { 1999dc8ba19STed Chen __le32 data; 2009dc8ba19STed Chen 2019dc8ba19STed Chen generic_ocp_read(tp, index, sizeof(data), &data, type); 2029dc8ba19STed Chen 2039dc8ba19STed Chen return __le32_to_cpu(data); 2049dc8ba19STed Chen } 2059dc8ba19STed Chen 2069dc8ba19STed Chen void ocp_write_dword(struct r8152 *tp, u16 type, u16 index, u32 data) 2079dc8ba19STed Chen { 2089dc8ba19STed Chen __le32 tmp = __cpu_to_le32(data); 2099dc8ba19STed Chen 2109dc8ba19STed Chen generic_ocp_write(tp, index, BYTE_EN_DWORD, sizeof(tmp), &tmp, type); 2119dc8ba19STed Chen } 2129dc8ba19STed Chen 2139dc8ba19STed Chen u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index) 2149dc8ba19STed Chen { 2159dc8ba19STed Chen u32 data; 2169dc8ba19STed Chen __le32 tmp; 2179dc8ba19STed Chen u8 shift = index & 2; 2189dc8ba19STed Chen 2199dc8ba19STed Chen index &= ~3; 2209dc8ba19STed Chen 2219dc8ba19STed Chen generic_ocp_read(tp, index, sizeof(tmp), &tmp, type); 2229dc8ba19STed Chen 2239dc8ba19STed Chen data = __le32_to_cpu(tmp); 2249dc8ba19STed Chen data >>= (shift * 8); 2259dc8ba19STed Chen data &= 0xffff; 2269dc8ba19STed Chen 2279dc8ba19STed Chen return data; 2289dc8ba19STed Chen } 2299dc8ba19STed Chen 2309dc8ba19STed Chen void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data) 2319dc8ba19STed Chen { 2329dc8ba19STed Chen u32 mask = 0xffff; 2339dc8ba19STed Chen __le32 tmp; 2349dc8ba19STed Chen u16 byen = BYTE_EN_WORD; 2359dc8ba19STed Chen u8 shift = index & 2; 2369dc8ba19STed Chen 2379dc8ba19STed Chen data &= mask; 2389dc8ba19STed Chen 2399dc8ba19STed Chen if (index & 2) { 2409dc8ba19STed Chen byen <<= shift; 2419dc8ba19STed Chen mask <<= (shift * 8); 2429dc8ba19STed Chen data <<= (shift * 8); 2439dc8ba19STed Chen index &= ~3; 2449dc8ba19STed Chen } 2459dc8ba19STed Chen 2469dc8ba19STed Chen tmp = __cpu_to_le32(data); 2479dc8ba19STed Chen 2489dc8ba19STed Chen generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type); 2499dc8ba19STed Chen } 2509dc8ba19STed Chen 2519dc8ba19STed Chen u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index) 2529dc8ba19STed Chen { 2539dc8ba19STed Chen u32 data; 2549dc8ba19STed Chen __le32 tmp; 2559dc8ba19STed Chen u8 shift = index & 3; 2569dc8ba19STed Chen 2579dc8ba19STed Chen index &= ~3; 2589dc8ba19STed Chen 2599dc8ba19STed Chen generic_ocp_read(tp, index, sizeof(tmp), &tmp, type); 2609dc8ba19STed Chen 2619dc8ba19STed Chen data = __le32_to_cpu(tmp); 2629dc8ba19STed Chen data >>= (shift * 8); 2639dc8ba19STed Chen data &= 0xff; 2649dc8ba19STed Chen 2659dc8ba19STed Chen return data; 2669dc8ba19STed Chen } 2679dc8ba19STed Chen 2689dc8ba19STed Chen void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data) 2699dc8ba19STed Chen { 2709dc8ba19STed Chen u32 mask = 0xff; 2719dc8ba19STed Chen __le32 tmp; 2729dc8ba19STed Chen u16 byen = BYTE_EN_BYTE; 2739dc8ba19STed Chen u8 shift = index & 3; 2749dc8ba19STed Chen 2759dc8ba19STed Chen data &= mask; 2769dc8ba19STed Chen 2779dc8ba19STed Chen if (index & 3) { 2789dc8ba19STed Chen byen <<= shift; 2799dc8ba19STed Chen mask <<= (shift * 8); 2809dc8ba19STed Chen data <<= (shift * 8); 2819dc8ba19STed Chen index &= ~3; 2829dc8ba19STed Chen } 2839dc8ba19STed Chen 2849dc8ba19STed Chen tmp = __cpu_to_le32(data); 2859dc8ba19STed Chen 2869dc8ba19STed Chen generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type); 2879dc8ba19STed Chen } 2889dc8ba19STed Chen 2899dc8ba19STed Chen u16 ocp_reg_read(struct r8152 *tp, u16 addr) 2909dc8ba19STed Chen { 2919dc8ba19STed Chen u16 ocp_base, ocp_index; 2929dc8ba19STed Chen 2939dc8ba19STed Chen ocp_base = addr & 0xf000; 2949dc8ba19STed Chen if (ocp_base != tp->ocp_base) { 2959dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base); 2969dc8ba19STed Chen tp->ocp_base = ocp_base; 2979dc8ba19STed Chen } 2989dc8ba19STed Chen 2999dc8ba19STed Chen ocp_index = (addr & 0x0fff) | 0xb000; 3009dc8ba19STed Chen return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index); 3019dc8ba19STed Chen } 3029dc8ba19STed Chen 3039dc8ba19STed Chen void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data) 3049dc8ba19STed Chen { 3059dc8ba19STed Chen u16 ocp_base, ocp_index; 3069dc8ba19STed Chen 3079dc8ba19STed Chen ocp_base = addr & 0xf000; 3089dc8ba19STed Chen if (ocp_base != tp->ocp_base) { 3099dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base); 3109dc8ba19STed Chen tp->ocp_base = ocp_base; 3119dc8ba19STed Chen } 3129dc8ba19STed Chen 3139dc8ba19STed Chen ocp_index = (addr & 0x0fff) | 0xb000; 3149dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data); 3159dc8ba19STed Chen } 3169dc8ba19STed Chen 3179dc8ba19STed Chen static void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value) 3189dc8ba19STed Chen { 3199dc8ba19STed Chen ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value); 3209dc8ba19STed Chen } 3219dc8ba19STed Chen 3229dc8ba19STed Chen static int r8152_mdio_read(struct r8152 *tp, u32 reg_addr) 3239dc8ba19STed Chen { 3249dc8ba19STed Chen return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2); 3259dc8ba19STed Chen } 3269dc8ba19STed Chen 3279dc8ba19STed Chen void sram_write(struct r8152 *tp, u16 addr, u16 data) 3289dc8ba19STed Chen { 3299dc8ba19STed Chen ocp_reg_write(tp, OCP_SRAM_ADDR, addr); 3309dc8ba19STed Chen ocp_reg_write(tp, OCP_SRAM_DATA, data); 3319dc8ba19STed Chen } 3329dc8ba19STed Chen 3339dc8ba19STed Chen int r8152_wait_for_bit(struct r8152 *tp, bool ocp_reg, u16 type, u16 index, 3349dc8ba19STed Chen const u32 mask, bool set, unsigned int timeout) 3359dc8ba19STed Chen { 3369dc8ba19STed Chen u32 val; 3379dc8ba19STed Chen 3389dc8ba19STed Chen while (--timeout) { 3399dc8ba19STed Chen if (ocp_reg) 3409dc8ba19STed Chen val = ocp_reg_read(tp, index); 3419dc8ba19STed Chen else 3429dc8ba19STed Chen val = ocp_read_dword(tp, type, index); 3439dc8ba19STed Chen 3449dc8ba19STed Chen if (!set) 3459dc8ba19STed Chen val = ~val; 3469dc8ba19STed Chen 3479dc8ba19STed Chen if ((val & mask) == mask) 3489dc8ba19STed Chen return 0; 3499dc8ba19STed Chen 3509dc8ba19STed Chen mdelay(1); 3519dc8ba19STed Chen } 3529dc8ba19STed Chen 3539dc8ba19STed Chen debug("%s: Timeout (index=%04x mask=%08x timeout=%d)\n", 3549dc8ba19STed Chen __func__, index, mask, timeout); 3559dc8ba19STed Chen 3569dc8ba19STed Chen return -ETIMEDOUT; 3579dc8ba19STed Chen } 3589dc8ba19STed Chen 3599dc8ba19STed Chen static void r8152b_reset_packet_filter(struct r8152 *tp) 3609dc8ba19STed Chen { 3619dc8ba19STed Chen u32 ocp_data; 3629dc8ba19STed Chen 3639dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC); 3649dc8ba19STed Chen ocp_data &= ~FMC_FCR_MCU_EN; 3659dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data); 3669dc8ba19STed Chen ocp_data |= FMC_FCR_MCU_EN; 3679dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data); 3689dc8ba19STed Chen } 3699dc8ba19STed Chen 3709dc8ba19STed Chen static void rtl8152_wait_fifo_empty(struct r8152 *tp) 3719dc8ba19STed Chen { 3729dc8ba19STed Chen int ret; 3739dc8ba19STed Chen 3749dc8ba19STed Chen ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR, 3759dc8ba19STed Chen PLA_PHY_PWR_TXEMP, 1, R8152_WAIT_TIMEOUT); 3769dc8ba19STed Chen if (ret) 3779dc8ba19STed Chen debug("Timeout waiting for FIFO empty\n"); 3789dc8ba19STed Chen 3799dc8ba19STed Chen ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_TCR0, 3809dc8ba19STed Chen TCR0_TX_EMPTY, 1, R8152_WAIT_TIMEOUT); 3819dc8ba19STed Chen if (ret) 3829dc8ba19STed Chen debug("Timeout waiting for TX empty\n"); 3839dc8ba19STed Chen } 3849dc8ba19STed Chen 3859dc8ba19STed Chen static void rtl8152_nic_reset(struct r8152 *tp) 3869dc8ba19STed Chen { 3879dc8ba19STed Chen int ret; 3889dc8ba19STed Chen u32 ocp_data; 3899dc8ba19STed Chen 3909dc8ba19STed Chen ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, BIST_CTRL); 3919dc8ba19STed Chen ocp_data |= BIST_CTRL_SW_RESET; 3929dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, BIST_CTRL, ocp_data); 3939dc8ba19STed Chen 3949dc8ba19STed Chen ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, BIST_CTRL, 3959dc8ba19STed Chen BIST_CTRL_SW_RESET, 0, R8152_WAIT_TIMEOUT); 3969dc8ba19STed Chen if (ret) 3979dc8ba19STed Chen debug("Timeout waiting for NIC reset\n"); 3989dc8ba19STed Chen } 3999dc8ba19STed Chen 4009dc8ba19STed Chen static u8 rtl8152_get_speed(struct r8152 *tp) 4019dc8ba19STed Chen { 4029dc8ba19STed Chen return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); 4039dc8ba19STed Chen } 4049dc8ba19STed Chen 4059dc8ba19STed Chen static void rtl_set_eee_plus(struct r8152 *tp) 4069dc8ba19STed Chen { 4079dc8ba19STed Chen u32 ocp_data; 4089dc8ba19STed Chen 4099dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); 4109dc8ba19STed Chen ocp_data &= ~EEEP_CR_EEEP_TX; 4119dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data); 4129dc8ba19STed Chen } 4139dc8ba19STed Chen 4149dc8ba19STed Chen static void rxdy_gated_en(struct r8152 *tp, bool enable) 4159dc8ba19STed Chen { 4169dc8ba19STed Chen u32 ocp_data; 4179dc8ba19STed Chen 4189dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1); 4199dc8ba19STed Chen if (enable) 4209dc8ba19STed Chen ocp_data |= RXDY_GATED_EN; 4219dc8ba19STed Chen else 4229dc8ba19STed Chen ocp_data &= ~RXDY_GATED_EN; 4239dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data); 4249dc8ba19STed Chen } 4259dc8ba19STed Chen 4269dc8ba19STed Chen static void rtl8152_set_rx_mode(struct r8152 *tp) 4279dc8ba19STed Chen { 4289dc8ba19STed Chen u32 ocp_data; 4299dc8ba19STed Chen __le32 tmp[2]; 4309dc8ba19STed Chen 4319dc8ba19STed Chen tmp[0] = 0xffffffff; 4329dc8ba19STed Chen tmp[1] = 0xffffffff; 4339dc8ba19STed Chen 4349dc8ba19STed Chen pla_ocp_write(tp, PLA_MAR, BYTE_EN_DWORD, sizeof(tmp), tmp); 4359dc8ba19STed Chen 4369dc8ba19STed Chen ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); 4379dc8ba19STed Chen ocp_data |= RCR_APM | RCR_AM | RCR_AB; 4389dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); 4399dc8ba19STed Chen } 4409dc8ba19STed Chen 4419dc8ba19STed Chen static int rtl_enable(struct r8152 *tp) 4429dc8ba19STed Chen { 4439dc8ba19STed Chen u32 ocp_data; 4449dc8ba19STed Chen 4459dc8ba19STed Chen r8152b_reset_packet_filter(tp); 4469dc8ba19STed Chen 4479dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR); 4489dc8ba19STed Chen ocp_data |= PLA_CR_RE | PLA_CR_TE; 4499dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data); 4509dc8ba19STed Chen 4519dc8ba19STed Chen rxdy_gated_en(tp, false); 4529dc8ba19STed Chen 4539dc8ba19STed Chen rtl8152_set_rx_mode(tp); 4549dc8ba19STed Chen 4559dc8ba19STed Chen return 0; 4569dc8ba19STed Chen } 4579dc8ba19STed Chen 4589dc8ba19STed Chen static int rtl8152_enable(struct r8152 *tp) 4599dc8ba19STed Chen { 4609dc8ba19STed Chen rtl_set_eee_plus(tp); 4619dc8ba19STed Chen 4629dc8ba19STed Chen return rtl_enable(tp); 4639dc8ba19STed Chen } 4649dc8ba19STed Chen 4659dc8ba19STed Chen static void r8153_set_rx_early_timeout(struct r8152 *tp) 4669dc8ba19STed Chen { 4679dc8ba19STed Chen u32 ocp_data = tp->coalesce / 8; 4689dc8ba19STed Chen 4699dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT, ocp_data); 4709dc8ba19STed Chen } 4719dc8ba19STed Chen 4729dc8ba19STed Chen static void r8153_set_rx_early_size(struct r8152 *tp) 4739dc8ba19STed Chen { 4749dc8ba19STed Chen u32 ocp_data = (RTL8152_AGG_BUF_SZ - RTL8153_RMS) / 4; 4759dc8ba19STed Chen 4769dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, ocp_data); 4779dc8ba19STed Chen } 4789dc8ba19STed Chen 4799dc8ba19STed Chen static int rtl8153_enable(struct r8152 *tp) 4809dc8ba19STed Chen { 4819dc8ba19STed Chen rtl_set_eee_plus(tp); 4829dc8ba19STed Chen r8153_set_rx_early_timeout(tp); 4839dc8ba19STed Chen r8153_set_rx_early_size(tp); 4849dc8ba19STed Chen 4859dc8ba19STed Chen return rtl_enable(tp); 4869dc8ba19STed Chen } 4879dc8ba19STed Chen 4889dc8ba19STed Chen static void rtl_disable(struct r8152 *tp) 4899dc8ba19STed Chen { 4909dc8ba19STed Chen u32 ocp_data; 4919dc8ba19STed Chen 4929dc8ba19STed Chen ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); 4939dc8ba19STed Chen ocp_data &= ~RCR_ACPT_ALL; 4949dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); 4959dc8ba19STed Chen 4969dc8ba19STed Chen rxdy_gated_en(tp, true); 4979dc8ba19STed Chen 4989dc8ba19STed Chen rtl8152_wait_fifo_empty(tp); 4999dc8ba19STed Chen rtl8152_nic_reset(tp); 5009dc8ba19STed Chen } 5019dc8ba19STed Chen 5029dc8ba19STed Chen static void r8152_power_cut_en(struct r8152 *tp, bool enable) 5039dc8ba19STed Chen { 5049dc8ba19STed Chen u32 ocp_data; 5059dc8ba19STed Chen 5069dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL); 5079dc8ba19STed Chen if (enable) 5089dc8ba19STed Chen ocp_data |= POWER_CUT; 5099dc8ba19STed Chen else 5109dc8ba19STed Chen ocp_data &= ~POWER_CUT; 5119dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data); 5129dc8ba19STed Chen 5139dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS); 5149dc8ba19STed Chen ocp_data &= ~RESUME_INDICATE; 5159dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data); 5169dc8ba19STed Chen } 5179dc8ba19STed Chen 5189dc8ba19STed Chen static void rtl_rx_vlan_en(struct r8152 *tp, bool enable) 5199dc8ba19STed Chen { 5209dc8ba19STed Chen u32 ocp_data; 5219dc8ba19STed Chen 5229dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR); 5239dc8ba19STed Chen if (enable) 5249dc8ba19STed Chen ocp_data |= CPCR_RX_VLAN; 5259dc8ba19STed Chen else 5269dc8ba19STed Chen ocp_data &= ~CPCR_RX_VLAN; 5279dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data); 5289dc8ba19STed Chen } 5299dc8ba19STed Chen 5309dc8ba19STed Chen static void r8153_u1u2en(struct r8152 *tp, bool enable) 5319dc8ba19STed Chen { 5329dc8ba19STed Chen u8 u1u2[8]; 5339dc8ba19STed Chen 5349dc8ba19STed Chen if (enable) 5359dc8ba19STed Chen memset(u1u2, 0xff, sizeof(u1u2)); 5369dc8ba19STed Chen else 5379dc8ba19STed Chen memset(u1u2, 0x00, sizeof(u1u2)); 5389dc8ba19STed Chen 5399dc8ba19STed Chen usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2); 5409dc8ba19STed Chen } 5419dc8ba19STed Chen 5429dc8ba19STed Chen static void r8153_u2p3en(struct r8152 *tp, bool enable) 5439dc8ba19STed Chen { 5449dc8ba19STed Chen u32 ocp_data; 5459dc8ba19STed Chen 5469dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL); 5479dc8ba19STed Chen if (enable && tp->version != RTL_VER_03 && tp->version != RTL_VER_04) 5489dc8ba19STed Chen ocp_data |= U2P3_ENABLE; 5499dc8ba19STed Chen else 5509dc8ba19STed Chen ocp_data &= ~U2P3_ENABLE; 5519dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data); 5529dc8ba19STed Chen } 5539dc8ba19STed Chen 5549dc8ba19STed Chen static void r8153_power_cut_en(struct r8152 *tp, bool enable) 5559dc8ba19STed Chen { 5569dc8ba19STed Chen u32 ocp_data; 5579dc8ba19STed Chen 5589dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT); 5599dc8ba19STed Chen if (enable) 5609dc8ba19STed Chen ocp_data |= PWR_EN | PHASE2_EN; 5619dc8ba19STed Chen else 5629dc8ba19STed Chen ocp_data &= ~(PWR_EN | PHASE2_EN); 5639dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data); 5649dc8ba19STed Chen 5659dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0); 5669dc8ba19STed Chen ocp_data &= ~PCUT_STATUS; 5679dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data); 5689dc8ba19STed Chen } 5699dc8ba19STed Chen 5709dc8ba19STed Chen static int r8152_read_mac(struct r8152 *tp, unsigned char *macaddr) 5719dc8ba19STed Chen { 5729dc8ba19STed Chen int ret; 5739dc8ba19STed Chen unsigned char enetaddr[8] = {0}; 5749dc8ba19STed Chen 5759dc8ba19STed Chen ret = pla_ocp_read(tp, PLA_IDR, 8, enetaddr); 5769dc8ba19STed Chen if (ret < 0) 5779dc8ba19STed Chen return ret; 5789dc8ba19STed Chen 5799dc8ba19STed Chen memcpy(macaddr, enetaddr, ETH_ALEN); 5809dc8ba19STed Chen return 0; 5819dc8ba19STed Chen } 5829dc8ba19STed Chen 5839dc8ba19STed Chen static void r8152b_disable_aldps(struct r8152 *tp) 5849dc8ba19STed Chen { 5859dc8ba19STed Chen ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE); 5869dc8ba19STed Chen mdelay(20); 5879dc8ba19STed Chen } 5889dc8ba19STed Chen 5899dc8ba19STed Chen static void r8152b_enable_aldps(struct r8152 *tp) 5909dc8ba19STed Chen { 5919dc8ba19STed Chen ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS | 5929dc8ba19STed Chen LINKENA | DIS_SDSAVE); 5939dc8ba19STed Chen } 5949dc8ba19STed Chen 5959dc8ba19STed Chen static void rtl8152_disable(struct r8152 *tp) 5969dc8ba19STed Chen { 5979dc8ba19STed Chen r8152b_disable_aldps(tp); 5989dc8ba19STed Chen rtl_disable(tp); 5999dc8ba19STed Chen r8152b_enable_aldps(tp); 6009dc8ba19STed Chen } 6019dc8ba19STed Chen 6029dc8ba19STed Chen static void r8152b_hw_phy_cfg(struct r8152 *tp) 6039dc8ba19STed Chen { 6049dc8ba19STed Chen u16 data; 6059dc8ba19STed Chen 6069dc8ba19STed Chen data = r8152_mdio_read(tp, MII_BMCR); 6079dc8ba19STed Chen if (data & BMCR_PDOWN) { 6089dc8ba19STed Chen data &= ~BMCR_PDOWN; 6099dc8ba19STed Chen r8152_mdio_write(tp, MII_BMCR, data); 6109dc8ba19STed Chen } 6119dc8ba19STed Chen 6129dc8ba19STed Chen r8152b_firmware(tp); 6139dc8ba19STed Chen } 6149dc8ba19STed Chen 6159dc8ba19STed Chen static void rtl8152_reinit_ll(struct r8152 *tp) 6169dc8ba19STed Chen { 6179dc8ba19STed Chen u32 ocp_data; 6189dc8ba19STed Chen int ret; 6199dc8ba19STed Chen 6209dc8ba19STed Chen ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR, 6219dc8ba19STed Chen PLA_PHY_PWR_LLR, 1, R8152_WAIT_TIMEOUT); 6229dc8ba19STed Chen if (ret) 6239dc8ba19STed Chen debug("Timeout waiting for link list ready\n"); 6249dc8ba19STed Chen 6259dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); 6269dc8ba19STed Chen ocp_data |= RE_INIT_LL; 6279dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); 6289dc8ba19STed Chen 6299dc8ba19STed Chen ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR, 6309dc8ba19STed Chen PLA_PHY_PWR_LLR, 1, R8152_WAIT_TIMEOUT); 6319dc8ba19STed Chen if (ret) 6329dc8ba19STed Chen debug("Timeout waiting for link list ready\n"); 6339dc8ba19STed Chen } 6349dc8ba19STed Chen 6359dc8ba19STed Chen static void r8152b_exit_oob(struct r8152 *tp) 6369dc8ba19STed Chen { 6379dc8ba19STed Chen u32 ocp_data; 6389dc8ba19STed Chen 6399dc8ba19STed Chen ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); 6409dc8ba19STed Chen ocp_data &= ~RCR_ACPT_ALL; 6419dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); 6429dc8ba19STed Chen 6439dc8ba19STed Chen rxdy_gated_en(tp, true); 6449dc8ba19STed Chen r8152b_hw_phy_cfg(tp); 6459dc8ba19STed Chen 6469dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); 6479dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, 0x00); 6489dc8ba19STed Chen 6499dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); 6509dc8ba19STed Chen ocp_data &= ~NOW_IS_OOB; 6519dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); 6529dc8ba19STed Chen 6539dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); 6549dc8ba19STed Chen ocp_data &= ~MCU_BORW_EN; 6559dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); 6569dc8ba19STed Chen 6579dc8ba19STed Chen rtl8152_reinit_ll(tp); 6589dc8ba19STed Chen rtl8152_nic_reset(tp); 6599dc8ba19STed Chen 6609dc8ba19STed Chen /* rx share fifo credit full threshold */ 6619dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL); 6629dc8ba19STed Chen 6639dc8ba19STed Chen if (tp->udev->speed == USB_SPEED_FULL || 6649dc8ba19STed Chen tp->udev->speed == USB_SPEED_LOW) { 6659dc8ba19STed Chen /* rx share fifo credit near full threshold */ 6669dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, 6679dc8ba19STed Chen RXFIFO_THR2_FULL); 6689dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, 6699dc8ba19STed Chen RXFIFO_THR3_FULL); 6709dc8ba19STed Chen } else { 6719dc8ba19STed Chen /* rx share fifo credit near full threshold */ 6729dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, 6739dc8ba19STed Chen RXFIFO_THR2_HIGH); 6749dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, 6759dc8ba19STed Chen RXFIFO_THR3_HIGH); 6769dc8ba19STed Chen } 6779dc8ba19STed Chen 6789dc8ba19STed Chen /* TX share fifo free credit full threshold */ 6799dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL); 6809dc8ba19STed Chen 6819dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD); 6829dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH); 6839dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_USB, USB_TX_DMA, 6849dc8ba19STed Chen TEST_MODE_DISABLE | TX_SIZE_ADJUST1); 6859dc8ba19STed Chen 6869dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); 6879dc8ba19STed Chen 6889dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); 6899dc8ba19STed Chen ocp_data |= TCR0_AUTO_FIFO; 6909dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data); 6919dc8ba19STed Chen } 6929dc8ba19STed Chen 6939dc8ba19STed Chen static void r8152b_enter_oob(struct r8152 *tp) 6949dc8ba19STed Chen { 6959dc8ba19STed Chen u32 ocp_data; 6969dc8ba19STed Chen 6979dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); 6989dc8ba19STed Chen ocp_data &= ~NOW_IS_OOB; 6999dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); 7009dc8ba19STed Chen 7019dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_OOB); 7029dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB); 7039dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB); 7049dc8ba19STed Chen 7059dc8ba19STed Chen rtl_disable(tp); 7069dc8ba19STed Chen 7079dc8ba19STed Chen rtl8152_reinit_ll(tp); 7089dc8ba19STed Chen 7099dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS); 7109dc8ba19STed Chen 7119dc8ba19STed Chen rtl_rx_vlan_en(tp, false); 7129dc8ba19STed Chen 7139dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR); 7149dc8ba19STed Chen ocp_data |= ALDPS_PROXY_MODE; 7159dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data); 7169dc8ba19STed Chen 7179dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); 7189dc8ba19STed Chen ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB; 7199dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); 7209dc8ba19STed Chen 7219dc8ba19STed Chen rxdy_gated_en(tp, false); 7229dc8ba19STed Chen 7239dc8ba19STed Chen ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); 7249dc8ba19STed Chen ocp_data |= RCR_APM | RCR_AM | RCR_AB; 7259dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); 7269dc8ba19STed Chen } 7279dc8ba19STed Chen 7289dc8ba19STed Chen static void r8153_hw_phy_cfg(struct r8152 *tp) 7299dc8ba19STed Chen { 7309dc8ba19STed Chen u32 ocp_data; 7319dc8ba19STed Chen u16 data; 7329dc8ba19STed Chen 7339dc8ba19STed Chen if (tp->version == RTL_VER_03 || tp->version == RTL_VER_04 || 7349dc8ba19STed Chen tp->version == RTL_VER_05) 7359dc8ba19STed Chen ocp_reg_write(tp, OCP_ADC_CFG, CKADSEL_L | ADC_EN | EN_EMI_L); 7369dc8ba19STed Chen 7379dc8ba19STed Chen data = r8152_mdio_read(tp, MII_BMCR); 7389dc8ba19STed Chen if (data & BMCR_PDOWN) { 7399dc8ba19STed Chen data &= ~BMCR_PDOWN; 7409dc8ba19STed Chen r8152_mdio_write(tp, MII_BMCR, data); 7419dc8ba19STed Chen } 7429dc8ba19STed Chen 7439dc8ba19STed Chen r8153_firmware(tp); 7449dc8ba19STed Chen 7459dc8ba19STed Chen if (tp->version == RTL_VER_03) { 7469dc8ba19STed Chen data = ocp_reg_read(tp, OCP_EEE_CFG); 7479dc8ba19STed Chen data &= ~CTAP_SHORT_EN; 7489dc8ba19STed Chen ocp_reg_write(tp, OCP_EEE_CFG, data); 7499dc8ba19STed Chen } 7509dc8ba19STed Chen 7519dc8ba19STed Chen data = ocp_reg_read(tp, OCP_POWER_CFG); 7529dc8ba19STed Chen data |= EEE_CLKDIV_EN; 7539dc8ba19STed Chen ocp_reg_write(tp, OCP_POWER_CFG, data); 7549dc8ba19STed Chen 7559dc8ba19STed Chen data = ocp_reg_read(tp, OCP_DOWN_SPEED); 7569dc8ba19STed Chen data |= EN_10M_BGOFF; 7579dc8ba19STed Chen ocp_reg_write(tp, OCP_DOWN_SPEED, data); 7589dc8ba19STed Chen data = ocp_reg_read(tp, OCP_POWER_CFG); 7599dc8ba19STed Chen data |= EN_10M_PLLOFF; 7609dc8ba19STed Chen ocp_reg_write(tp, OCP_POWER_CFG, data); 7619dc8ba19STed Chen sram_write(tp, SRAM_IMPEDANCE, 0x0b13); 7629dc8ba19STed Chen 7639dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); 7649dc8ba19STed Chen ocp_data |= PFM_PWM_SWITCH; 7659dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); 7669dc8ba19STed Chen 7679dc8ba19STed Chen /* Enable LPF corner auto tune */ 7689dc8ba19STed Chen sram_write(tp, SRAM_LPF_CFG, 0xf70f); 7699dc8ba19STed Chen 7709dc8ba19STed Chen /* Adjust 10M Amplitude */ 7719dc8ba19STed Chen sram_write(tp, SRAM_10M_AMP1, 0x00af); 7729dc8ba19STed Chen sram_write(tp, SRAM_10M_AMP2, 0x0208); 7739dc8ba19STed Chen } 7749dc8ba19STed Chen 7759dc8ba19STed Chen static void r8153_first_init(struct r8152 *tp) 7769dc8ba19STed Chen { 7779dc8ba19STed Chen u32 ocp_data; 7789dc8ba19STed Chen 7799dc8ba19STed Chen rxdy_gated_en(tp, true); 7809dc8ba19STed Chen 7819dc8ba19STed Chen ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); 7829dc8ba19STed Chen ocp_data &= ~RCR_ACPT_ALL; 7839dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); 7849dc8ba19STed Chen 7859dc8ba19STed Chen r8153_hw_phy_cfg(tp); 7869dc8ba19STed Chen 7879dc8ba19STed Chen rtl8152_nic_reset(tp); 7889dc8ba19STed Chen 7899dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); 7909dc8ba19STed Chen ocp_data &= ~NOW_IS_OOB; 7919dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); 7929dc8ba19STed Chen 7939dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7); 7949dc8ba19STed Chen ocp_data &= ~MCU_BORW_EN; 7959dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data); 7969dc8ba19STed Chen 7979dc8ba19STed Chen rtl8152_reinit_ll(tp); 7989dc8ba19STed Chen 7999dc8ba19STed Chen rtl_rx_vlan_en(tp, false); 8009dc8ba19STed Chen 8019dc8ba19STed Chen ocp_data = RTL8153_RMS; 8029dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); 8039dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO); 8049dc8ba19STed Chen 8059dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0); 8069dc8ba19STed Chen ocp_data |= TCR0_AUTO_FIFO; 8079dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data); 8089dc8ba19STed Chen 8099dc8ba19STed Chen rtl8152_nic_reset(tp); 8109dc8ba19STed Chen 8119dc8ba19STed Chen /* rx share fifo credit full threshold */ 8129dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL); 8139dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_NORMAL); 8149dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL); 8159dc8ba19STed Chen /* TX share fifo free credit full threshold */ 8169dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2); 8179dc8ba19STed Chen 8189dc8ba19STed Chen /* rx aggregation */ 8199dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); 8209dc8ba19STed Chen 8219dc8ba19STed Chen ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); 8229dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); 8239dc8ba19STed Chen } 8249dc8ba19STed Chen 8259dc8ba19STed Chen static void r8153_enter_oob(struct r8152 *tp) 8269dc8ba19STed Chen { 8279dc8ba19STed Chen u32 ocp_data; 8289dc8ba19STed Chen 8299dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); 8309dc8ba19STed Chen ocp_data &= ~NOW_IS_OOB; 8319dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); 8329dc8ba19STed Chen 8339dc8ba19STed Chen rtl_disable(tp); 8349dc8ba19STed Chen 8359dc8ba19STed Chen rtl8152_reinit_ll(tp); 8369dc8ba19STed Chen 8379dc8ba19STed Chen ocp_data = RTL8153_RMS; 8389dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data); 8399dc8ba19STed Chen 8409dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG); 8419dc8ba19STed Chen ocp_data &= ~TEREDO_WAKE_MASK; 8429dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data); 8439dc8ba19STed Chen 8449dc8ba19STed Chen rtl_rx_vlan_en(tp, false); 8459dc8ba19STed Chen 8469dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR); 8479dc8ba19STed Chen ocp_data |= ALDPS_PROXY_MODE; 8489dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data); 8499dc8ba19STed Chen 8509dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); 8519dc8ba19STed Chen ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB; 8529dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); 8539dc8ba19STed Chen 8549dc8ba19STed Chen rxdy_gated_en(tp, false); 8559dc8ba19STed Chen 8569dc8ba19STed Chen ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); 8579dc8ba19STed Chen ocp_data |= RCR_APM | RCR_AM | RCR_AB; 8589dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); 8599dc8ba19STed Chen } 8609dc8ba19STed Chen 8619dc8ba19STed Chen static void r8153_disable_aldps(struct r8152 *tp) 8629dc8ba19STed Chen { 8639dc8ba19STed Chen u16 data; 8649dc8ba19STed Chen 8659dc8ba19STed Chen data = ocp_reg_read(tp, OCP_POWER_CFG); 8669dc8ba19STed Chen data &= ~EN_ALDPS; 8679dc8ba19STed Chen ocp_reg_write(tp, OCP_POWER_CFG, data); 8689dc8ba19STed Chen mdelay(20); 8699dc8ba19STed Chen } 8709dc8ba19STed Chen 8719dc8ba19STed Chen static void rtl8153_disable(struct r8152 *tp) 8729dc8ba19STed Chen { 8739dc8ba19STed Chen r8153_disable_aldps(tp); 8749dc8ba19STed Chen rtl_disable(tp); 8759dc8ba19STed Chen } 8769dc8ba19STed Chen 8779dc8ba19STed Chen static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex) 8789dc8ba19STed Chen { 8799dc8ba19STed Chen u16 bmcr, anar, gbcr; 8809dc8ba19STed Chen 8819dc8ba19STed Chen anar = r8152_mdio_read(tp, MII_ADVERTISE); 8829dc8ba19STed Chen anar &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | 8839dc8ba19STed Chen ADVERTISE_100HALF | ADVERTISE_100FULL); 8849dc8ba19STed Chen if (tp->supports_gmii) { 8859dc8ba19STed Chen gbcr = r8152_mdio_read(tp, MII_CTRL1000); 8869dc8ba19STed Chen gbcr &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); 8879dc8ba19STed Chen } else { 8889dc8ba19STed Chen gbcr = 0; 8899dc8ba19STed Chen } 8909dc8ba19STed Chen 8919dc8ba19STed Chen if (autoneg == AUTONEG_DISABLE) { 8929dc8ba19STed Chen if (speed == SPEED_10) { 8939dc8ba19STed Chen bmcr = 0; 8949dc8ba19STed Chen anar |= ADVERTISE_10HALF | ADVERTISE_10FULL; 8959dc8ba19STed Chen } else if (speed == SPEED_100) { 8969dc8ba19STed Chen bmcr = BMCR_SPEED100; 8979dc8ba19STed Chen anar |= ADVERTISE_100HALF | ADVERTISE_100FULL; 8989dc8ba19STed Chen } else if (speed == SPEED_1000 && tp->supports_gmii) { 8999dc8ba19STed Chen bmcr = BMCR_SPEED1000; 9009dc8ba19STed Chen gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; 9019dc8ba19STed Chen } else { 9029dc8ba19STed Chen return -EINVAL; 9039dc8ba19STed Chen } 9049dc8ba19STed Chen 9059dc8ba19STed Chen if (duplex == DUPLEX_FULL) 9069dc8ba19STed Chen bmcr |= BMCR_FULLDPLX; 9079dc8ba19STed Chen } else { 9089dc8ba19STed Chen if (speed == SPEED_10) { 9099dc8ba19STed Chen if (duplex == DUPLEX_FULL) 9109dc8ba19STed Chen anar |= ADVERTISE_10HALF | ADVERTISE_10FULL; 9119dc8ba19STed Chen else 9129dc8ba19STed Chen anar |= ADVERTISE_10HALF; 9139dc8ba19STed Chen } else if (speed == SPEED_100) { 9149dc8ba19STed Chen if (duplex == DUPLEX_FULL) { 9159dc8ba19STed Chen anar |= ADVERTISE_10HALF | ADVERTISE_10FULL; 9169dc8ba19STed Chen anar |= ADVERTISE_100HALF | ADVERTISE_100FULL; 9179dc8ba19STed Chen } else { 9189dc8ba19STed Chen anar |= ADVERTISE_10HALF; 9199dc8ba19STed Chen anar |= ADVERTISE_100HALF; 9209dc8ba19STed Chen } 9219dc8ba19STed Chen } else if (speed == SPEED_1000 && tp->supports_gmii) { 9229dc8ba19STed Chen if (duplex == DUPLEX_FULL) { 9239dc8ba19STed Chen anar |= ADVERTISE_10HALF | ADVERTISE_10FULL; 9249dc8ba19STed Chen anar |= ADVERTISE_100HALF | ADVERTISE_100FULL; 9259dc8ba19STed Chen gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF; 9269dc8ba19STed Chen } else { 9279dc8ba19STed Chen anar |= ADVERTISE_10HALF; 9289dc8ba19STed Chen anar |= ADVERTISE_100HALF; 9299dc8ba19STed Chen gbcr |= ADVERTISE_1000HALF; 9309dc8ba19STed Chen } 9319dc8ba19STed Chen } else { 9329dc8ba19STed Chen return -EINVAL; 9339dc8ba19STed Chen } 9349dc8ba19STed Chen 9359dc8ba19STed Chen bmcr = BMCR_ANENABLE | BMCR_ANRESTART; 9369dc8ba19STed Chen } 9379dc8ba19STed Chen 9389dc8ba19STed Chen if (tp->supports_gmii) 9399dc8ba19STed Chen r8152_mdio_write(tp, MII_CTRL1000, gbcr); 9409dc8ba19STed Chen 9419dc8ba19STed Chen r8152_mdio_write(tp, MII_ADVERTISE, anar); 9429dc8ba19STed Chen r8152_mdio_write(tp, MII_BMCR, bmcr); 9439dc8ba19STed Chen 9449dc8ba19STed Chen return 0; 9459dc8ba19STed Chen } 9469dc8ba19STed Chen 9479dc8ba19STed Chen static void rtl8152_up(struct r8152 *tp) 9489dc8ba19STed Chen { 9499dc8ba19STed Chen r8152b_disable_aldps(tp); 9509dc8ba19STed Chen r8152b_exit_oob(tp); 9519dc8ba19STed Chen r8152b_enable_aldps(tp); 9529dc8ba19STed Chen } 9539dc8ba19STed Chen 9549dc8ba19STed Chen static void rtl8152_down(struct r8152 *tp) 9559dc8ba19STed Chen { 9569dc8ba19STed Chen r8152_power_cut_en(tp, false); 9579dc8ba19STed Chen r8152b_disable_aldps(tp); 9589dc8ba19STed Chen r8152b_enter_oob(tp); 9599dc8ba19STed Chen r8152b_enable_aldps(tp); 9609dc8ba19STed Chen } 9619dc8ba19STed Chen 9629dc8ba19STed Chen static void rtl8153_up(struct r8152 *tp) 9639dc8ba19STed Chen { 9649dc8ba19STed Chen r8153_u1u2en(tp, false); 9659dc8ba19STed Chen r8153_disable_aldps(tp); 9669dc8ba19STed Chen r8153_first_init(tp); 9679dc8ba19STed Chen r8153_u2p3en(tp, false); 9689dc8ba19STed Chen } 9699dc8ba19STed Chen 9709dc8ba19STed Chen static void rtl8153_down(struct r8152 *tp) 9719dc8ba19STed Chen { 9729dc8ba19STed Chen r8153_u1u2en(tp, false); 9739dc8ba19STed Chen r8153_u2p3en(tp, false); 9749dc8ba19STed Chen r8153_power_cut_en(tp, false); 9759dc8ba19STed Chen r8153_disable_aldps(tp); 9769dc8ba19STed Chen r8153_enter_oob(tp); 9779dc8ba19STed Chen } 9789dc8ba19STed Chen 9799dc8ba19STed Chen static void r8152b_get_version(struct r8152 *tp) 9809dc8ba19STed Chen { 9819dc8ba19STed Chen u32 ocp_data; 9829dc8ba19STed Chen u16 tcr; 9839dc8ba19STed Chen int i; 9849dc8ba19STed Chen 9859dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR1); 9869dc8ba19STed Chen tcr = (u16)(ocp_data & VERSION_MASK); 9879dc8ba19STed Chen 9889dc8ba19STed Chen for (i = 0; i < ARRAY_SIZE(r8152_versions); i++) { 9899dc8ba19STed Chen if (tcr == r8152_versions[i].tcr) { 9909dc8ba19STed Chen /* Found a supported version */ 9919dc8ba19STed Chen tp->version = r8152_versions[i].version; 9929dc8ba19STed Chen tp->supports_gmii = r8152_versions[i].gmii; 9939dc8ba19STed Chen break; 9949dc8ba19STed Chen } 9959dc8ba19STed Chen } 9969dc8ba19STed Chen 9979dc8ba19STed Chen if (tp->version == RTL_VER_UNKNOWN) 9989dc8ba19STed Chen debug("r8152 Unknown tcr version 0x%04x\n", tcr); 9999dc8ba19STed Chen } 10009dc8ba19STed Chen 10019dc8ba19STed Chen static void r8152b_enable_fc(struct r8152 *tp) 10029dc8ba19STed Chen { 10039dc8ba19STed Chen u16 anar; 10049dc8ba19STed Chen anar = r8152_mdio_read(tp, MII_ADVERTISE); 10059dc8ba19STed Chen anar |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; 10069dc8ba19STed Chen r8152_mdio_write(tp, MII_ADVERTISE, anar); 10079dc8ba19STed Chen } 10089dc8ba19STed Chen 10099dc8ba19STed Chen static void rtl_tally_reset(struct r8152 *tp) 10109dc8ba19STed Chen { 10119dc8ba19STed Chen u32 ocp_data; 10129dc8ba19STed Chen 10139dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY); 10149dc8ba19STed Chen ocp_data |= TALLY_RESET; 10159dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data); 10169dc8ba19STed Chen } 10179dc8ba19STed Chen 10189dc8ba19STed Chen static void r8152b_init(struct r8152 *tp) 10199dc8ba19STed Chen { 10209dc8ba19STed Chen u32 ocp_data; 10219dc8ba19STed Chen 10229dc8ba19STed Chen r8152b_disable_aldps(tp); 10239dc8ba19STed Chen 10249dc8ba19STed Chen if (tp->version == RTL_VER_01) { 10259dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE); 10269dc8ba19STed Chen ocp_data &= ~LED_MODE_MASK; 10279dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data); 10289dc8ba19STed Chen } 10299dc8ba19STed Chen 10309dc8ba19STed Chen r8152_power_cut_en(tp, false); 10319dc8ba19STed Chen 10329dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR); 10339dc8ba19STed Chen ocp_data |= TX_10M_IDLE_EN | PFM_PWM_SWITCH; 10349dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data); 10359dc8ba19STed Chen ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL); 10369dc8ba19STed Chen ocp_data &= ~MCU_CLK_RATIO_MASK; 10379dc8ba19STed Chen ocp_data |= MCU_CLK_RATIO | D3_CLK_GATED_EN; 10389dc8ba19STed Chen ocp_write_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ocp_data); 10399dc8ba19STed Chen ocp_data = GPHY_STS_MSK | SPEED_DOWN_MSK | 10409dc8ba19STed Chen SPDWN_RXDV_MSK | SPDWN_LINKCHG_MSK; 10419dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data); 10429dc8ba19STed Chen 10439dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_TIMER); 10449dc8ba19STed Chen ocp_data |= BIT(15); 10459dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_USB_TIMER, ocp_data); 10469dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, 0xcbfc, 0x03e8); 10479dc8ba19STed Chen ocp_data &= ~BIT(15); 10489dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_USB_TIMER, ocp_data); 10499dc8ba19STed Chen 10509dc8ba19STed Chen r8152b_enable_fc(tp); 10519dc8ba19STed Chen rtl_tally_reset(tp); 10529dc8ba19STed Chen 10539dc8ba19STed Chen /* enable rx aggregation */ 10549dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL); 10559dc8ba19STed Chen 10569dc8ba19STed Chen ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN); 10579dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data); 10589dc8ba19STed Chen } 10599dc8ba19STed Chen 10609dc8ba19STed Chen static void r8153_init(struct r8152 *tp) 10619dc8ba19STed Chen { 10629dc8ba19STed Chen int i; 10639dc8ba19STed Chen u32 ocp_data; 10649dc8ba19STed Chen 10659dc8ba19STed Chen r8153_disable_aldps(tp); 10669dc8ba19STed Chen r8153_u1u2en(tp, false); 10679dc8ba19STed Chen 10689dc8ba19STed Chen r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_BOOT_CTRL, 10699dc8ba19STed Chen AUTOLOAD_DONE, 1, R8152_WAIT_TIMEOUT); 10709dc8ba19STed Chen 10719dc8ba19STed Chen for (i = 0; i < R8152_WAIT_TIMEOUT; i++) { 10729dc8ba19STed Chen ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK; 10739dc8ba19STed Chen if (ocp_data == PHY_STAT_LAN_ON || ocp_data == PHY_STAT_PWRDN) 10749dc8ba19STed Chen break; 10759dc8ba19STed Chen 10769dc8ba19STed Chen mdelay(1); 10779dc8ba19STed Chen } 10789dc8ba19STed Chen 10799dc8ba19STed Chen r8153_u2p3en(tp, false); 10809dc8ba19STed Chen 10819dc8ba19STed Chen if (tp->version == RTL_VER_04) { 10829dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2); 10839dc8ba19STed Chen ocp_data &= ~pwd_dn_scale_mask; 10849dc8ba19STed Chen ocp_data |= pwd_dn_scale(96); 10859dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2, ocp_data); 10869dc8ba19STed Chen 10879dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_USB2PHY); 10889dc8ba19STed Chen ocp_data |= USB2PHY_L1 | USB2PHY_SUSPEND; 10899dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_USB, USB_USB2PHY, ocp_data); 10909dc8ba19STed Chen } else if (tp->version == RTL_VER_05) { 10919dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0); 10929dc8ba19STed Chen ocp_data &= ~ECM_ALDPS; 10939dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0, ocp_data); 10949dc8ba19STed Chen 10959dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1); 10969dc8ba19STed Chen if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0) 10979dc8ba19STed Chen ocp_data &= ~DYNAMIC_BURST; 10989dc8ba19STed Chen else 10999dc8ba19STed Chen ocp_data |= DYNAMIC_BURST; 11009dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data); 11019dc8ba19STed Chen } else if (tp->version == RTL_VER_06) { 11029dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1); 11039dc8ba19STed Chen if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0) 11049dc8ba19STed Chen ocp_data &= ~DYNAMIC_BURST; 11059dc8ba19STed Chen else 11069dc8ba19STed Chen ocp_data |= DYNAMIC_BURST; 11079dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data); 11089dc8ba19STed Chen } 11099dc8ba19STed Chen 11109dc8ba19STed Chen ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2); 11119dc8ba19STed Chen ocp_data |= EP4_FULL_FC; 11129dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2, ocp_data); 11139dc8ba19STed Chen 11149dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL); 11159dc8ba19STed Chen ocp_data &= ~TIMER11_EN; 11169dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data); 11179dc8ba19STed Chen 11189dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE); 11199dc8ba19STed Chen ocp_data &= ~LED_MODE_MASK; 11209dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data); 11219dc8ba19STed Chen 11229dc8ba19STed Chen ocp_data = FIFO_EMPTY_1FB | ROK_EXIT_LPM; 11239dc8ba19STed Chen if (tp->version == RTL_VER_04 && tp->udev->speed != USB_SPEED_SUPER) 11249dc8ba19STed Chen ocp_data |= LPM_TIMER_500MS; 11259dc8ba19STed Chen else 11269dc8ba19STed Chen ocp_data |= LPM_TIMER_500US; 11279dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL, ocp_data); 11289dc8ba19STed Chen 11299dc8ba19STed Chen ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2); 11309dc8ba19STed Chen ocp_data &= ~SEN_VAL_MASK; 11319dc8ba19STed Chen ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE; 11329dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data); 11339dc8ba19STed Chen 11349dc8ba19STed Chen ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001); 11359dc8ba19STed Chen 11369dc8ba19STed Chen r8153_power_cut_en(tp, false); 11379dc8ba19STed Chen 11389dc8ba19STed Chen r8152b_enable_fc(tp); 11399dc8ba19STed Chen rtl_tally_reset(tp); 11409dc8ba19STed Chen } 11419dc8ba19STed Chen 11429dc8ba19STed Chen static void rtl8152_unload(struct r8152 *tp) 11439dc8ba19STed Chen { 11449dc8ba19STed Chen if (tp->version != RTL_VER_01) 11459dc8ba19STed Chen r8152_power_cut_en(tp, true); 11469dc8ba19STed Chen } 11479dc8ba19STed Chen 11489dc8ba19STed Chen static void rtl8153_unload(struct r8152 *tp) 11499dc8ba19STed Chen { 11509dc8ba19STed Chen r8153_power_cut_en(tp, false); 11519dc8ba19STed Chen } 11529dc8ba19STed Chen 11539dc8ba19STed Chen static int rtl_ops_init(struct r8152 *tp) 11549dc8ba19STed Chen { 11559dc8ba19STed Chen struct rtl_ops *ops = &tp->rtl_ops; 11569dc8ba19STed Chen int ret = 0; 11579dc8ba19STed Chen 11589dc8ba19STed Chen switch (tp->version) { 11599dc8ba19STed Chen case RTL_VER_01: 11609dc8ba19STed Chen case RTL_VER_02: 11619dc8ba19STed Chen case RTL_VER_07: 11629dc8ba19STed Chen ops->init = r8152b_init; 11639dc8ba19STed Chen ops->enable = rtl8152_enable; 11649dc8ba19STed Chen ops->disable = rtl8152_disable; 11659dc8ba19STed Chen ops->up = rtl8152_up; 11669dc8ba19STed Chen ops->down = rtl8152_down; 11679dc8ba19STed Chen ops->unload = rtl8152_unload; 11689dc8ba19STed Chen break; 11699dc8ba19STed Chen 11709dc8ba19STed Chen case RTL_VER_03: 11719dc8ba19STed Chen case RTL_VER_04: 11729dc8ba19STed Chen case RTL_VER_05: 11739dc8ba19STed Chen case RTL_VER_06: 11749dc8ba19STed Chen ops->init = r8153_init; 11759dc8ba19STed Chen ops->enable = rtl8153_enable; 11769dc8ba19STed Chen ops->disable = rtl8153_disable; 11779dc8ba19STed Chen ops->up = rtl8153_up; 11789dc8ba19STed Chen ops->down = rtl8153_down; 11799dc8ba19STed Chen ops->unload = rtl8153_unload; 11809dc8ba19STed Chen break; 11819dc8ba19STed Chen 11829dc8ba19STed Chen default: 11839dc8ba19STed Chen ret = -ENODEV; 11849dc8ba19STed Chen printf("r8152 Unknown Device\n"); 11859dc8ba19STed Chen break; 11869dc8ba19STed Chen } 11879dc8ba19STed Chen 11889dc8ba19STed Chen return ret; 11899dc8ba19STed Chen } 11909dc8ba19STed Chen 11916688452aSStefan Roese static int r8152_init_common(struct r8152 *tp) 11929dc8ba19STed Chen { 11939dc8ba19STed Chen u8 speed; 11949dc8ba19STed Chen int timeout = 0; 11959dc8ba19STed Chen int link_detected; 11969dc8ba19STed Chen 11979dc8ba19STed Chen debug("** %s()\n", __func__); 11989dc8ba19STed Chen 11999dc8ba19STed Chen do { 12009dc8ba19STed Chen speed = rtl8152_get_speed(tp); 12019dc8ba19STed Chen 12029dc8ba19STed Chen link_detected = speed & LINK_STATUS; 12039dc8ba19STed Chen if (!link_detected) { 12049dc8ba19STed Chen if (timeout == 0) 12059dc8ba19STed Chen printf("Waiting for Ethernet connection... "); 12069dc8ba19STed Chen mdelay(TIMEOUT_RESOLUTION); 12079dc8ba19STed Chen timeout += TIMEOUT_RESOLUTION; 12089dc8ba19STed Chen } 12099dc8ba19STed Chen } while (!link_detected && timeout < PHY_CONNECT_TIMEOUT); 12109dc8ba19STed Chen if (link_detected) { 12119dc8ba19STed Chen tp->rtl_ops.enable(tp); 12129dc8ba19STed Chen 12139dc8ba19STed Chen if (timeout != 0) 12149dc8ba19STed Chen printf("done.\n"); 12159dc8ba19STed Chen } else { 12169dc8ba19STed Chen printf("unable to connect.\n"); 12179dc8ba19STed Chen } 12189dc8ba19STed Chen 12199dc8ba19STed Chen return 0; 12209dc8ba19STed Chen } 12219dc8ba19STed Chen 12226688452aSStefan Roese static int r8152_send_common(struct ueth_data *ueth, void *packet, int length) 12239dc8ba19STed Chen { 12246688452aSStefan Roese struct usb_device *udev = ueth->pusb_dev; 12259dc8ba19STed Chen u32 opts1, opts2 = 0; 12269dc8ba19STed Chen int err; 12279dc8ba19STed Chen int actual_len; 1228*c7ac1538SStefan Roese ALLOC_CACHE_ALIGN_BUFFER(uint8_t, msg, 1229*c7ac1538SStefan Roese PKTSIZE + sizeof(struct tx_desc)); 12309dc8ba19STed Chen struct tx_desc *tx_desc = (struct tx_desc *)msg; 12319dc8ba19STed Chen 12329dc8ba19STed Chen debug("** %s(), len %d\n", __func__, length); 12339dc8ba19STed Chen 12349dc8ba19STed Chen opts1 = length | TX_FS | TX_LS; 12359dc8ba19STed Chen 12369dc8ba19STed Chen tx_desc->opts2 = cpu_to_le32(opts2); 12379dc8ba19STed Chen tx_desc->opts1 = cpu_to_le32(opts1); 12389dc8ba19STed Chen 12399dc8ba19STed Chen memcpy(msg + sizeof(struct tx_desc), (void *)packet, length); 12409dc8ba19STed Chen 12416688452aSStefan Roese err = usb_bulk_msg(udev, usb_sndbulkpipe(udev, ueth->ep_out), 12426688452aSStefan Roese (void *)msg, length + sizeof(struct tx_desc), 12436688452aSStefan Roese &actual_len, USB_BULK_SEND_TIMEOUT); 12449dc8ba19STed Chen debug("Tx: len = %zu, actual = %u, err = %d\n", 12459dc8ba19STed Chen length + sizeof(struct tx_desc), actual_len, err); 12469dc8ba19STed Chen 12479dc8ba19STed Chen return err; 12489dc8ba19STed Chen } 12499dc8ba19STed Chen 12506688452aSStefan Roese #ifndef CONFIG_DM_ETH 12516688452aSStefan Roese static int r8152_init(struct eth_device *eth, bd_t *bd) 12526688452aSStefan Roese { 12536688452aSStefan Roese struct ueth_data *dev = (struct ueth_data *)eth->priv; 12546688452aSStefan Roese struct r8152 *tp = (struct r8152 *)dev->dev_priv; 12556688452aSStefan Roese 12566688452aSStefan Roese return r8152_init_common(tp); 12576688452aSStefan Roese } 12586688452aSStefan Roese 12596688452aSStefan Roese static int r8152_send(struct eth_device *eth, void *packet, int length) 12606688452aSStefan Roese { 12616688452aSStefan Roese struct ueth_data *dev = (struct ueth_data *)eth->priv; 12626688452aSStefan Roese 12636688452aSStefan Roese return r8152_send_common(dev, packet, length); 12646688452aSStefan Roese } 12656688452aSStefan Roese 12669dc8ba19STed Chen static int r8152_recv(struct eth_device *eth) 12679dc8ba19STed Chen { 12689dc8ba19STed Chen struct ueth_data *dev = (struct ueth_data *)eth->priv; 12699dc8ba19STed Chen 1270*c7ac1538SStefan Roese ALLOC_CACHE_ALIGN_BUFFER(uint8_t, recv_buf, RTL8152_AGG_BUF_SZ); 12719dc8ba19STed Chen unsigned char *pkt_ptr; 12729dc8ba19STed Chen int err; 12739dc8ba19STed Chen int actual_len; 12749dc8ba19STed Chen u16 packet_len; 12759dc8ba19STed Chen 12769dc8ba19STed Chen u32 bytes_process = 0; 12779dc8ba19STed Chen struct rx_desc *rx_desc; 12789dc8ba19STed Chen 12799dc8ba19STed Chen debug("** %s()\n", __func__); 12809dc8ba19STed Chen 12819dc8ba19STed Chen err = usb_bulk_msg(dev->pusb_dev, 12829dc8ba19STed Chen usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in), 12839dc8ba19STed Chen (void *)recv_buf, 12849dc8ba19STed Chen RTL8152_AGG_BUF_SZ, 12859dc8ba19STed Chen &actual_len, 12869dc8ba19STed Chen USB_BULK_RECV_TIMEOUT); 12879dc8ba19STed Chen debug("Rx: len = %u, actual = %u, err = %d\n", RTL8152_AGG_BUF_SZ, 12889dc8ba19STed Chen actual_len, err); 12899dc8ba19STed Chen if (err != 0) { 12909dc8ba19STed Chen debug("Rx: failed to receive\n"); 12919dc8ba19STed Chen return -1; 12929dc8ba19STed Chen } 12939dc8ba19STed Chen if (actual_len > RTL8152_AGG_BUF_SZ) { 12949dc8ba19STed Chen debug("Rx: received too many bytes %d\n", actual_len); 12959dc8ba19STed Chen return -1; 12969dc8ba19STed Chen } 12979dc8ba19STed Chen 12989dc8ba19STed Chen while (bytes_process < actual_len) { 12999dc8ba19STed Chen rx_desc = (struct rx_desc *)(recv_buf + bytes_process); 13009dc8ba19STed Chen pkt_ptr = recv_buf + sizeof(struct rx_desc) + bytes_process; 13019dc8ba19STed Chen 13029dc8ba19STed Chen packet_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; 13039dc8ba19STed Chen packet_len -= CRC_SIZE; 13049dc8ba19STed Chen 13059dc8ba19STed Chen net_process_received_packet(pkt_ptr, packet_len); 13069dc8ba19STed Chen 13079dc8ba19STed Chen bytes_process += 13089dc8ba19STed Chen (packet_len + sizeof(struct rx_desc) + CRC_SIZE); 13099dc8ba19STed Chen 13109dc8ba19STed Chen if (bytes_process % 8) 13119dc8ba19STed Chen bytes_process = bytes_process + 8 - (bytes_process % 8); 13129dc8ba19STed Chen } 13139dc8ba19STed Chen 13149dc8ba19STed Chen return 0; 13159dc8ba19STed Chen } 13169dc8ba19STed Chen 13179dc8ba19STed Chen static void r8152_halt(struct eth_device *eth) 13189dc8ba19STed Chen { 13199dc8ba19STed Chen struct ueth_data *dev = (struct ueth_data *)eth->priv; 13209dc8ba19STed Chen struct r8152 *tp = (struct r8152 *)dev->dev_priv; 13219dc8ba19STed Chen 13229dc8ba19STed Chen debug("** %s()\n", __func__); 13239dc8ba19STed Chen 13249dc8ba19STed Chen tp->rtl_ops.disable(tp); 13259dc8ba19STed Chen } 13269dc8ba19STed Chen 13279dc8ba19STed Chen static int r8152_write_hwaddr(struct eth_device *eth) 13289dc8ba19STed Chen { 13299dc8ba19STed Chen struct ueth_data *dev = (struct ueth_data *)eth->priv; 13309dc8ba19STed Chen struct r8152 *tp = (struct r8152 *)dev->dev_priv; 13319dc8ba19STed Chen 13329dc8ba19STed Chen unsigned char enetaddr[8] = {0}; 13339dc8ba19STed Chen 13349dc8ba19STed Chen memcpy(enetaddr, eth->enetaddr, ETH_ALEN); 13359dc8ba19STed Chen 13369dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); 13379dc8ba19STed Chen pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, enetaddr); 13389dc8ba19STed Chen ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); 13399dc8ba19STed Chen 13409dc8ba19STed Chen debug("MAC %pM\n", eth->enetaddr); 13419dc8ba19STed Chen return 0; 13429dc8ba19STed Chen } 13439dc8ba19STed Chen 13449dc8ba19STed Chen void r8152_eth_before_probe(void) 13459dc8ba19STed Chen { 13469dc8ba19STed Chen curr_eth_dev = 0; 13479dc8ba19STed Chen } 13489dc8ba19STed Chen 13499dc8ba19STed Chen /* Probe to see if a new device is actually an realtek device */ 13509dc8ba19STed Chen int r8152_eth_probe(struct usb_device *dev, unsigned int ifnum, 13519dc8ba19STed Chen struct ueth_data *ss) 13529dc8ba19STed Chen { 13539dc8ba19STed Chen struct usb_interface *iface; 13549dc8ba19STed Chen struct usb_interface_descriptor *iface_desc; 13559dc8ba19STed Chen int ep_in_found = 0, ep_out_found = 0; 13569dc8ba19STed Chen int i; 13579dc8ba19STed Chen 13589dc8ba19STed Chen struct r8152 *tp; 13599dc8ba19STed Chen 13609dc8ba19STed Chen /* let's examine the device now */ 13619dc8ba19STed Chen iface = &dev->config.if_desc[ifnum]; 13629dc8ba19STed Chen iface_desc = &dev->config.if_desc[ifnum].desc; 13639dc8ba19STed Chen 13649dc8ba19STed Chen for (i = 0; i < ARRAY_SIZE(r8152_dongles); i++) { 13659dc8ba19STed Chen if (dev->descriptor.idVendor == r8152_dongles[i].vendor && 13669dc8ba19STed Chen dev->descriptor.idProduct == r8152_dongles[i].product) 13679dc8ba19STed Chen /* Found a supported dongle */ 13689dc8ba19STed Chen break; 13699dc8ba19STed Chen } 13709dc8ba19STed Chen 13719dc8ba19STed Chen if (i == ARRAY_SIZE(r8152_dongles)) 13729dc8ba19STed Chen return 0; 13739dc8ba19STed Chen 13749dc8ba19STed Chen memset(ss, 0, sizeof(struct ueth_data)); 13759dc8ba19STed Chen 13769dc8ba19STed Chen /* At this point, we know we've got a live one */ 13779dc8ba19STed Chen debug("\n\nUSB Ethernet device detected: %#04x:%#04x\n", 13789dc8ba19STed Chen dev->descriptor.idVendor, dev->descriptor.idProduct); 13799dc8ba19STed Chen 13809dc8ba19STed Chen /* Initialize the ueth_data structure with some useful info */ 13819dc8ba19STed Chen ss->ifnum = ifnum; 13829dc8ba19STed Chen ss->pusb_dev = dev; 13839dc8ba19STed Chen ss->subclass = iface_desc->bInterfaceSubClass; 13849dc8ba19STed Chen ss->protocol = iface_desc->bInterfaceProtocol; 13859dc8ba19STed Chen 13869dc8ba19STed Chen /* alloc driver private */ 13879dc8ba19STed Chen ss->dev_priv = calloc(1, sizeof(struct r8152)); 13889dc8ba19STed Chen 13899dc8ba19STed Chen if (!ss->dev_priv) 13909dc8ba19STed Chen return 0; 13919dc8ba19STed Chen 13929dc8ba19STed Chen /* 13939dc8ba19STed Chen * We are expecting a minimum of 3 endpoints - in, out (bulk), and 13949dc8ba19STed Chen * int. We will ignore any others. 13959dc8ba19STed Chen */ 13969dc8ba19STed Chen for (i = 0; i < iface_desc->bNumEndpoints; i++) { 13979dc8ba19STed Chen /* is it an BULK endpoint? */ 13989dc8ba19STed Chen if ((iface->ep_desc[i].bmAttributes & 13999dc8ba19STed Chen USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { 14009dc8ba19STed Chen u8 ep_addr = iface->ep_desc[i].bEndpointAddress; 14019dc8ba19STed Chen if ((ep_addr & USB_DIR_IN) && !ep_in_found) { 14029dc8ba19STed Chen ss->ep_in = ep_addr & 14039dc8ba19STed Chen USB_ENDPOINT_NUMBER_MASK; 14049dc8ba19STed Chen ep_in_found = 1; 14059dc8ba19STed Chen } else { 14069dc8ba19STed Chen if (!ep_out_found) { 14079dc8ba19STed Chen ss->ep_out = ep_addr & 14089dc8ba19STed Chen USB_ENDPOINT_NUMBER_MASK; 14099dc8ba19STed Chen ep_out_found = 1; 14109dc8ba19STed Chen } 14119dc8ba19STed Chen } 14129dc8ba19STed Chen } 14139dc8ba19STed Chen 14149dc8ba19STed Chen /* is it an interrupt endpoint? */ 14159dc8ba19STed Chen if ((iface->ep_desc[i].bmAttributes & 14169dc8ba19STed Chen USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { 14179dc8ba19STed Chen ss->ep_int = iface->ep_desc[i].bEndpointAddress & 14189dc8ba19STed Chen USB_ENDPOINT_NUMBER_MASK; 14199dc8ba19STed Chen ss->irqinterval = iface->ep_desc[i].bInterval; 14209dc8ba19STed Chen } 14219dc8ba19STed Chen } 14229dc8ba19STed Chen 14239dc8ba19STed Chen debug("Endpoints In %d Out %d Int %d\n", 14249dc8ba19STed Chen ss->ep_in, ss->ep_out, ss->ep_int); 14259dc8ba19STed Chen 14269dc8ba19STed Chen /* Do some basic sanity checks, and bail if we find a problem */ 14279dc8ba19STed Chen if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) || 14289dc8ba19STed Chen !ss->ep_in || !ss->ep_out || !ss->ep_int) { 14299dc8ba19STed Chen debug("Problems with device\n"); 14309dc8ba19STed Chen return 0; 14319dc8ba19STed Chen } 14329dc8ba19STed Chen 14339dc8ba19STed Chen dev->privptr = (void *)ss; 14349dc8ba19STed Chen 14359dc8ba19STed Chen tp = ss->dev_priv; 14369dc8ba19STed Chen tp->udev = dev; 14379dc8ba19STed Chen tp->intf = iface; 14389dc8ba19STed Chen 14399dc8ba19STed Chen r8152b_get_version(tp); 14409dc8ba19STed Chen 14419dc8ba19STed Chen if (rtl_ops_init(tp)) 14429dc8ba19STed Chen return 0; 14439dc8ba19STed Chen 14449dc8ba19STed Chen tp->rtl_ops.init(tp); 14459dc8ba19STed Chen tp->rtl_ops.up(tp); 14469dc8ba19STed Chen 14479dc8ba19STed Chen rtl8152_set_speed(tp, AUTONEG_ENABLE, 14489dc8ba19STed Chen tp->supports_gmii ? SPEED_1000 : SPEED_100, 14499dc8ba19STed Chen DUPLEX_FULL); 14509dc8ba19STed Chen 14519dc8ba19STed Chen return 1; 14529dc8ba19STed Chen } 14539dc8ba19STed Chen 14549dc8ba19STed Chen int r8152_eth_get_info(struct usb_device *dev, struct ueth_data *ss, 14559dc8ba19STed Chen struct eth_device *eth) 14569dc8ba19STed Chen { 14579dc8ba19STed Chen if (!eth) { 14589dc8ba19STed Chen debug("%s: missing parameter.\n", __func__); 14599dc8ba19STed Chen return 0; 14609dc8ba19STed Chen } 14619dc8ba19STed Chen 14629dc8ba19STed Chen sprintf(eth->name, "%s#%d", R8152_BASE_NAME, curr_eth_dev++); 14639dc8ba19STed Chen eth->init = r8152_init; 14649dc8ba19STed Chen eth->send = r8152_send; 14659dc8ba19STed Chen eth->recv = r8152_recv; 14669dc8ba19STed Chen eth->halt = r8152_halt; 14679dc8ba19STed Chen eth->write_hwaddr = r8152_write_hwaddr; 14689dc8ba19STed Chen eth->priv = ss; 14699dc8ba19STed Chen 14709dc8ba19STed Chen /* Get the MAC address */ 14719dc8ba19STed Chen if (r8152_read_mac(ss->dev_priv, eth->enetaddr) < 0) 14729dc8ba19STed Chen return 0; 14739dc8ba19STed Chen 14749dc8ba19STed Chen debug("MAC %pM\n", eth->enetaddr); 14759dc8ba19STed Chen return 1; 14769dc8ba19STed Chen } 14776688452aSStefan Roese #endif /* !CONFIG_DM_ETH */ 14786688452aSStefan Roese 14796688452aSStefan Roese #ifdef CONFIG_DM_ETH 14806688452aSStefan Roese static int r8152_eth_start(struct udevice *dev) 14816688452aSStefan Roese { 14826688452aSStefan Roese struct r8152 *tp = dev_get_priv(dev); 14836688452aSStefan Roese 14846688452aSStefan Roese debug("** %s (%d)\n", __func__, __LINE__); 14856688452aSStefan Roese 14866688452aSStefan Roese return r8152_init_common(tp); 14876688452aSStefan Roese } 14886688452aSStefan Roese 14896688452aSStefan Roese void r8152_eth_stop(struct udevice *dev) 14906688452aSStefan Roese { 14916688452aSStefan Roese struct r8152 *tp = dev_get_priv(dev); 14926688452aSStefan Roese 14936688452aSStefan Roese debug("** %s (%d)\n", __func__, __LINE__); 14946688452aSStefan Roese 14956688452aSStefan Roese tp->rtl_ops.disable(tp); 14966688452aSStefan Roese } 14976688452aSStefan Roese 14986688452aSStefan Roese int r8152_eth_send(struct udevice *dev, void *packet, int length) 14996688452aSStefan Roese { 15006688452aSStefan Roese struct r8152 *tp = dev_get_priv(dev); 15016688452aSStefan Roese 15026688452aSStefan Roese return r8152_send_common(&tp->ueth, packet, length); 15036688452aSStefan Roese } 15046688452aSStefan Roese 15056688452aSStefan Roese int r8152_eth_recv(struct udevice *dev, int flags, uchar **packetp) 15066688452aSStefan Roese { 15076688452aSStefan Roese struct r8152 *tp = dev_get_priv(dev); 15086688452aSStefan Roese struct ueth_data *ueth = &tp->ueth; 15096688452aSStefan Roese uint8_t *ptr; 15106688452aSStefan Roese int ret, len; 15116688452aSStefan Roese struct rx_desc *rx_desc; 15126688452aSStefan Roese u16 packet_len; 15136688452aSStefan Roese 15146688452aSStefan Roese len = usb_ether_get_rx_bytes(ueth, &ptr); 15156688452aSStefan Roese debug("%s: first try, len=%d\n", __func__, len); 15166688452aSStefan Roese if (!len) { 15176688452aSStefan Roese if (!(flags & ETH_RECV_CHECK_DEVICE)) 15186688452aSStefan Roese return -EAGAIN; 15196688452aSStefan Roese ret = usb_ether_receive(ueth, RTL8152_AGG_BUF_SZ); 15206688452aSStefan Roese if (ret) 15216688452aSStefan Roese return ret; 15226688452aSStefan Roese 15236688452aSStefan Roese len = usb_ether_get_rx_bytes(ueth, &ptr); 15246688452aSStefan Roese debug("%s: second try, len=%d\n", __func__, len); 15256688452aSStefan Roese } 15266688452aSStefan Roese 15276688452aSStefan Roese rx_desc = (struct rx_desc *)ptr; 15286688452aSStefan Roese packet_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; 15296688452aSStefan Roese packet_len -= CRC_SIZE; 15306688452aSStefan Roese 15316688452aSStefan Roese if (packet_len > len - (sizeof(struct rx_desc) + CRC_SIZE)) { 15326688452aSStefan Roese debug("Rx: too large packet: %d\n", packet_len); 15336688452aSStefan Roese goto err; 15346688452aSStefan Roese } 15356688452aSStefan Roese 15366688452aSStefan Roese *packetp = ptr + sizeof(struct rx_desc); 15376688452aSStefan Roese return packet_len; 15386688452aSStefan Roese 15396688452aSStefan Roese err: 15406688452aSStefan Roese usb_ether_advance_rxbuf(ueth, -1); 15416688452aSStefan Roese return -ENOSPC; 15426688452aSStefan Roese } 15436688452aSStefan Roese 15446688452aSStefan Roese static int r8152_free_pkt(struct udevice *dev, uchar *packet, int packet_len) 15456688452aSStefan Roese { 15466688452aSStefan Roese struct r8152 *tp = dev_get_priv(dev); 15476688452aSStefan Roese 15486688452aSStefan Roese packet_len += sizeof(struct rx_desc) + CRC_SIZE; 15496688452aSStefan Roese packet_len = ALIGN(packet_len, 8); 15506688452aSStefan Roese usb_ether_advance_rxbuf(&tp->ueth, packet_len); 15516688452aSStefan Roese 15526688452aSStefan Roese return 0; 15536688452aSStefan Roese } 15546688452aSStefan Roese 15556688452aSStefan Roese static int r8152_write_hwaddr(struct udevice *dev) 15566688452aSStefan Roese { 15576688452aSStefan Roese struct eth_pdata *pdata = dev_get_platdata(dev); 15586688452aSStefan Roese struct r8152 *tp = dev_get_priv(dev); 15596688452aSStefan Roese 15606688452aSStefan Roese unsigned char enetaddr[8] = { 0 }; 15616688452aSStefan Roese 15626688452aSStefan Roese debug("** %s (%d)\n", __func__, __LINE__); 15636688452aSStefan Roese memcpy(enetaddr, pdata->enetaddr, ETH_ALEN); 15646688452aSStefan Roese 15656688452aSStefan Roese ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG); 15666688452aSStefan Roese pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, enetaddr); 15676688452aSStefan Roese ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML); 15686688452aSStefan Roese 15696688452aSStefan Roese debug("MAC %pM\n", pdata->enetaddr); 15706688452aSStefan Roese return 0; 15716688452aSStefan Roese } 15726688452aSStefan Roese 15736688452aSStefan Roese int r8152_read_rom_hwaddr(struct udevice *dev) 15746688452aSStefan Roese { 15756688452aSStefan Roese struct eth_pdata *pdata = dev_get_platdata(dev); 15766688452aSStefan Roese struct r8152 *tp = dev_get_priv(dev); 15776688452aSStefan Roese 15786688452aSStefan Roese debug("** %s (%d)\n", __func__, __LINE__); 15796688452aSStefan Roese r8152_read_mac(tp, pdata->enetaddr); 15806688452aSStefan Roese return 0; 15816688452aSStefan Roese } 15826688452aSStefan Roese 15836688452aSStefan Roese static int r8152_eth_probe(struct udevice *dev) 15846688452aSStefan Roese { 15856688452aSStefan Roese struct usb_device *udev = dev_get_parent_priv(dev); 15866688452aSStefan Roese struct eth_pdata *pdata = dev_get_platdata(dev); 15876688452aSStefan Roese struct r8152 *tp = dev_get_priv(dev); 15886688452aSStefan Roese struct ueth_data *ueth = &tp->ueth; 15896688452aSStefan Roese int ret; 15906688452aSStefan Roese 15916688452aSStefan Roese tp->udev = udev; 15926688452aSStefan Roese r8152_read_mac(tp, pdata->enetaddr); 15936688452aSStefan Roese 15946688452aSStefan Roese r8152b_get_version(tp); 15956688452aSStefan Roese 15966688452aSStefan Roese ret = rtl_ops_init(tp); 15976688452aSStefan Roese if (ret) 15986688452aSStefan Roese return ret; 15996688452aSStefan Roese 16006688452aSStefan Roese tp->rtl_ops.init(tp); 16016688452aSStefan Roese tp->rtl_ops.up(tp); 16026688452aSStefan Roese 16036688452aSStefan Roese rtl8152_set_speed(tp, AUTONEG_ENABLE, 16046688452aSStefan Roese tp->supports_gmii ? SPEED_1000 : SPEED_100, 16056688452aSStefan Roese DUPLEX_FULL); 16066688452aSStefan Roese 16076688452aSStefan Roese return usb_ether_register(dev, ueth, RTL8152_AGG_BUF_SZ); 16086688452aSStefan Roese } 16096688452aSStefan Roese 16106688452aSStefan Roese static const struct eth_ops r8152_eth_ops = { 16116688452aSStefan Roese .start = r8152_eth_start, 16126688452aSStefan Roese .send = r8152_eth_send, 16136688452aSStefan Roese .recv = r8152_eth_recv, 16146688452aSStefan Roese .free_pkt = r8152_free_pkt, 16156688452aSStefan Roese .stop = r8152_eth_stop, 16166688452aSStefan Roese .write_hwaddr = r8152_write_hwaddr, 16176688452aSStefan Roese .read_rom_hwaddr = r8152_read_rom_hwaddr, 16186688452aSStefan Roese }; 16196688452aSStefan Roese 16206688452aSStefan Roese U_BOOT_DRIVER(r8152_eth) = { 16216688452aSStefan Roese .name = "r8152_eth", 16226688452aSStefan Roese .id = UCLASS_ETH, 16236688452aSStefan Roese .probe = r8152_eth_probe, 16246688452aSStefan Roese .ops = &r8152_eth_ops, 16256688452aSStefan Roese .priv_auto_alloc_size = sizeof(struct r8152), 16266688452aSStefan Roese .platdata_auto_alloc_size = sizeof(struct eth_pdata), 16276688452aSStefan Roese }; 16286688452aSStefan Roese 16296688452aSStefan Roese static const struct usb_device_id r8152_eth_id_table[] = { 16306688452aSStefan Roese /* Realtek */ 16316688452aSStefan Roese { USB_DEVICE(0x0bda, 0x8050) }, 16326688452aSStefan Roese { USB_DEVICE(0x0bda, 0x8152) }, 16336688452aSStefan Roese { USB_DEVICE(0x0bda, 0x8153) }, 16346688452aSStefan Roese 16356688452aSStefan Roese /* Samsung */ 16366688452aSStefan Roese { USB_DEVICE(0x04e8, 0xa101) }, 16376688452aSStefan Roese 16386688452aSStefan Roese /* Lenovo */ 16396688452aSStefan Roese { USB_DEVICE(0x17ef, 0x304f) }, 16406688452aSStefan Roese { USB_DEVICE(0x17ef, 0x3052) }, 16416688452aSStefan Roese { USB_DEVICE(0x17ef, 0x3054) }, 16426688452aSStefan Roese { USB_DEVICE(0x17ef, 0x3057) }, 16436688452aSStefan Roese { USB_DEVICE(0x17ef, 0x7205) }, 16446688452aSStefan Roese { USB_DEVICE(0x17ef, 0x720a) }, 16456688452aSStefan Roese { USB_DEVICE(0x17ef, 0x720b) }, 16466688452aSStefan Roese { USB_DEVICE(0x17ef, 0x720c) }, 16476688452aSStefan Roese 16486688452aSStefan Roese /* TP-LINK */ 16496688452aSStefan Roese { USB_DEVICE(0x2357, 0x0601) }, 16506688452aSStefan Roese 16516688452aSStefan Roese /* Nvidia */ 16526688452aSStefan Roese { USB_DEVICE(0x0955, 0x09ff) }, 16536688452aSStefan Roese 16546688452aSStefan Roese { } /* Terminating entry */ 16556688452aSStefan Roese }; 16566688452aSStefan Roese 16576688452aSStefan Roese U_BOOT_USB_DEVICE(r8152_eth, r8152_eth_id_table); 16586688452aSStefan Roese #endif /* CONFIG_DM_ETH */ 16596688452aSStefan Roese 1660