18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Shlomi Gridish <gridish@freescale.com> 68c2ecf20Sopenharmony_ci * Li Yang <leoli@freescale.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Description: 98c2ecf20Sopenharmony_ci * QE UCC Gigabit Ethernet Driver 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/errno.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/stddef.h> 198c2ecf20Sopenharmony_ci#include <linux/module.h> 208c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 218c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 228c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 238c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 248c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 258c2ecf20Sopenharmony_ci#include <linux/mm.h> 268c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 278c2ecf20Sopenharmony_ci#include <linux/mii.h> 288c2ecf20Sopenharmony_ci#include <linux/phy.h> 298c2ecf20Sopenharmony_ci#include <linux/phy_fixed.h> 308c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 318c2ecf20Sopenharmony_ci#include <linux/of_address.h> 328c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 338c2ecf20Sopenharmony_ci#include <linux/of_mdio.h> 348c2ecf20Sopenharmony_ci#include <linux/of_net.h> 358c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 388c2ecf20Sopenharmony_ci#include <asm/irq.h> 398c2ecf20Sopenharmony_ci#include <asm/io.h> 408c2ecf20Sopenharmony_ci#include <soc/fsl/qe/immap_qe.h> 418c2ecf20Sopenharmony_ci#include <soc/fsl/qe/qe.h> 428c2ecf20Sopenharmony_ci#include <soc/fsl/qe/ucc.h> 438c2ecf20Sopenharmony_ci#include <soc/fsl/qe/ucc_fast.h> 448c2ecf20Sopenharmony_ci#include <asm/machdep.h> 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#include "ucc_geth.h" 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#undef DEBUG 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define ugeth_printk(level, format, arg...) \ 518c2ecf20Sopenharmony_ci printk(level format "\n", ## arg) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define ugeth_dbg(format, arg...) \ 548c2ecf20Sopenharmony_ci ugeth_printk(KERN_DEBUG , format , ## arg) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#ifdef UGETH_VERBOSE_DEBUG 578c2ecf20Sopenharmony_ci#define ugeth_vdbg ugeth_dbg 588c2ecf20Sopenharmony_ci#else 598c2ecf20Sopenharmony_ci#define ugeth_vdbg(fmt, args...) do { } while (0) 608c2ecf20Sopenharmony_ci#endif /* UGETH_VERBOSE_DEBUG */ 618c2ecf20Sopenharmony_ci#define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(ugeth_lock); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic struct { 678c2ecf20Sopenharmony_ci u32 msg_enable; 688c2ecf20Sopenharmony_ci} debug = { -1 }; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cimodule_param_named(debug, debug.msg_enable, int, 0); 718c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 0xffff=all)"); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic struct ucc_geth_info ugeth_primary_info = { 748c2ecf20Sopenharmony_ci .uf_info = { 758c2ecf20Sopenharmony_ci .bd_mem_part = MEM_PART_SYSTEM, 768c2ecf20Sopenharmony_ci .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES, 778c2ecf20Sopenharmony_ci .max_rx_buf_length = 1536, 788c2ecf20Sopenharmony_ci /* adjusted at startup if max-speed 1000 */ 798c2ecf20Sopenharmony_ci .urfs = UCC_GETH_URFS_INIT, 808c2ecf20Sopenharmony_ci .urfet = UCC_GETH_URFET_INIT, 818c2ecf20Sopenharmony_ci .urfset = UCC_GETH_URFSET_INIT, 828c2ecf20Sopenharmony_ci .utfs = UCC_GETH_UTFS_INIT, 838c2ecf20Sopenharmony_ci .utfet = UCC_GETH_UTFET_INIT, 848c2ecf20Sopenharmony_ci .utftt = UCC_GETH_UTFTT_INIT, 858c2ecf20Sopenharmony_ci .ufpt = 256, 868c2ecf20Sopenharmony_ci .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET, 878c2ecf20Sopenharmony_ci .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL, 888c2ecf20Sopenharmony_ci .tenc = UCC_FAST_TX_ENCODING_NRZ, 898c2ecf20Sopenharmony_ci .renc = UCC_FAST_RX_ENCODING_NRZ, 908c2ecf20Sopenharmony_ci .tcrc = UCC_FAST_16_BIT_CRC, 918c2ecf20Sopenharmony_ci .synl = UCC_FAST_SYNC_LEN_NOT_USED, 928c2ecf20Sopenharmony_ci }, 938c2ecf20Sopenharmony_ci .numQueuesTx = 1, 948c2ecf20Sopenharmony_ci .numQueuesRx = 1, 958c2ecf20Sopenharmony_ci .extendedFilteringChainPointer = ((uint32_t) NULL), 968c2ecf20Sopenharmony_ci .typeorlen = 3072 /*1536 */ , 978c2ecf20Sopenharmony_ci .nonBackToBackIfgPart1 = 0x40, 988c2ecf20Sopenharmony_ci .nonBackToBackIfgPart2 = 0x60, 998c2ecf20Sopenharmony_ci .miminumInterFrameGapEnforcement = 0x50, 1008c2ecf20Sopenharmony_ci .backToBackInterFrameGap = 0x60, 1018c2ecf20Sopenharmony_ci .mblinterval = 128, 1028c2ecf20Sopenharmony_ci .nortsrbytetime = 5, 1038c2ecf20Sopenharmony_ci .fracsiz = 1, 1048c2ecf20Sopenharmony_ci .strictpriorityq = 0xff, 1058c2ecf20Sopenharmony_ci .altBebTruncation = 0xa, 1068c2ecf20Sopenharmony_ci .excessDefer = 1, 1078c2ecf20Sopenharmony_ci .maxRetransmission = 0xf, 1088c2ecf20Sopenharmony_ci .collisionWindow = 0x37, 1098c2ecf20Sopenharmony_ci .receiveFlowControl = 1, 1108c2ecf20Sopenharmony_ci .transmitFlowControl = 1, 1118c2ecf20Sopenharmony_ci .maxGroupAddrInHash = 4, 1128c2ecf20Sopenharmony_ci .maxIndAddrInHash = 4, 1138c2ecf20Sopenharmony_ci .prel = 7, 1148c2ecf20Sopenharmony_ci .maxFrameLength = 1518+16, /* Add extra bytes for VLANs etc. */ 1158c2ecf20Sopenharmony_ci .minFrameLength = 64, 1168c2ecf20Sopenharmony_ci .maxD1Length = 1520+16, /* Add extra bytes for VLANs etc. */ 1178c2ecf20Sopenharmony_ci .maxD2Length = 1520+16, /* Add extra bytes for VLANs etc. */ 1188c2ecf20Sopenharmony_ci .vlantype = 0x8100, 1198c2ecf20Sopenharmony_ci .ecamptr = ((uint32_t) NULL), 1208c2ecf20Sopenharmony_ci .eventRegMask = UCCE_OTHER, 1218c2ecf20Sopenharmony_ci .pausePeriod = 0xf000, 1228c2ecf20Sopenharmony_ci .interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1}, 1238c2ecf20Sopenharmony_ci .bdRingLenTx = { 1248c2ecf20Sopenharmony_ci TX_BD_RING_LEN, 1258c2ecf20Sopenharmony_ci TX_BD_RING_LEN, 1268c2ecf20Sopenharmony_ci TX_BD_RING_LEN, 1278c2ecf20Sopenharmony_ci TX_BD_RING_LEN, 1288c2ecf20Sopenharmony_ci TX_BD_RING_LEN, 1298c2ecf20Sopenharmony_ci TX_BD_RING_LEN, 1308c2ecf20Sopenharmony_ci TX_BD_RING_LEN, 1318c2ecf20Sopenharmony_ci TX_BD_RING_LEN}, 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci .bdRingLenRx = { 1348c2ecf20Sopenharmony_ci RX_BD_RING_LEN, 1358c2ecf20Sopenharmony_ci RX_BD_RING_LEN, 1368c2ecf20Sopenharmony_ci RX_BD_RING_LEN, 1378c2ecf20Sopenharmony_ci RX_BD_RING_LEN, 1388c2ecf20Sopenharmony_ci RX_BD_RING_LEN, 1398c2ecf20Sopenharmony_ci RX_BD_RING_LEN, 1408c2ecf20Sopenharmony_ci RX_BD_RING_LEN, 1418c2ecf20Sopenharmony_ci RX_BD_RING_LEN}, 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1, 1448c2ecf20Sopenharmony_ci .largestexternallookupkeysize = 1458c2ecf20Sopenharmony_ci QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE, 1468c2ecf20Sopenharmony_ci .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE | 1478c2ecf20Sopenharmony_ci UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX | 1488c2ecf20Sopenharmony_ci UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX, 1498c2ecf20Sopenharmony_ci .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP, 1508c2ecf20Sopenharmony_ci .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP, 1518c2ecf20Sopenharmony_ci .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT, 1528c2ecf20Sopenharmony_ci .aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE, 1538c2ecf20Sopenharmony_ci .padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC, 1548c2ecf20Sopenharmony_ci .numThreadsTx = UCC_GETH_NUM_OF_THREADS_1, 1558c2ecf20Sopenharmony_ci .numThreadsRx = UCC_GETH_NUM_OF_THREADS_1, 1568c2ecf20Sopenharmony_ci .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, 1578c2ecf20Sopenharmony_ci .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, 1588c2ecf20Sopenharmony_ci}; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic struct ucc_geth_info ugeth_info[8]; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci#ifdef DEBUG 1638c2ecf20Sopenharmony_cistatic void mem_disp(u8 *addr, int size) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci u8 *i; 1668c2ecf20Sopenharmony_ci int size16Aling = (size >> 4) << 4; 1678c2ecf20Sopenharmony_ci int size4Aling = (size >> 2) << 2; 1688c2ecf20Sopenharmony_ci int notAlign = 0; 1698c2ecf20Sopenharmony_ci if (size % 16) 1708c2ecf20Sopenharmony_ci notAlign = 1; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16) 1738c2ecf20Sopenharmony_ci printk("0x%08x: %08x %08x %08x %08x\r\n", 1748c2ecf20Sopenharmony_ci (u32) i, 1758c2ecf20Sopenharmony_ci *((u32 *) (i)), 1768c2ecf20Sopenharmony_ci *((u32 *) (i + 4)), 1778c2ecf20Sopenharmony_ci *((u32 *) (i + 8)), *((u32 *) (i + 12))); 1788c2ecf20Sopenharmony_ci if (notAlign == 1) 1798c2ecf20Sopenharmony_ci printk("0x%08x: ", (u32) i); 1808c2ecf20Sopenharmony_ci for (; (u32) i < (u32) addr + size4Aling; i += 4) 1818c2ecf20Sopenharmony_ci printk("%08x ", *((u32 *) (i))); 1828c2ecf20Sopenharmony_ci for (; (u32) i < (u32) addr + size; i++) 1838c2ecf20Sopenharmony_ci printk("%02x", *((i))); 1848c2ecf20Sopenharmony_ci if (notAlign == 1) 1858c2ecf20Sopenharmony_ci printk("\r\n"); 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci#endif /* DEBUG */ 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic struct list_head *dequeue(struct list_head *lh) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci unsigned long flags; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci spin_lock_irqsave(&ugeth_lock, flags); 1948c2ecf20Sopenharmony_ci if (!list_empty(lh)) { 1958c2ecf20Sopenharmony_ci struct list_head *node = lh->next; 1968c2ecf20Sopenharmony_ci list_del(node); 1978c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ugeth_lock, flags); 1988c2ecf20Sopenharmony_ci return node; 1998c2ecf20Sopenharmony_ci } else { 2008c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ugeth_lock, flags); 2018c2ecf20Sopenharmony_ci return NULL; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci} 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_cistatic struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, 2068c2ecf20Sopenharmony_ci u8 __iomem *bd) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci struct sk_buff *skb; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci skb = netdev_alloc_skb(ugeth->ndev, 2118c2ecf20Sopenharmony_ci ugeth->ug_info->uf_info.max_rx_buf_length + 2128c2ecf20Sopenharmony_ci UCC_GETH_RX_DATA_BUF_ALIGNMENT); 2138c2ecf20Sopenharmony_ci if (!skb) 2148c2ecf20Sopenharmony_ci return NULL; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* We need the data buffer to be aligned properly. We will reserve 2178c2ecf20Sopenharmony_ci * as many bytes as needed to align the data properly 2188c2ecf20Sopenharmony_ci */ 2198c2ecf20Sopenharmony_ci skb_reserve(skb, 2208c2ecf20Sopenharmony_ci UCC_GETH_RX_DATA_BUF_ALIGNMENT - 2218c2ecf20Sopenharmony_ci (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT - 2228c2ecf20Sopenharmony_ci 1))); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci out_be32(&((struct qe_bd __iomem *)bd)->buf, 2258c2ecf20Sopenharmony_ci dma_map_single(ugeth->dev, 2268c2ecf20Sopenharmony_ci skb->data, 2278c2ecf20Sopenharmony_ci ugeth->ug_info->uf_info.max_rx_buf_length + 2288c2ecf20Sopenharmony_ci UCC_GETH_RX_DATA_BUF_ALIGNMENT, 2298c2ecf20Sopenharmony_ci DMA_FROM_DEVICE)); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci out_be32((u32 __iomem *)bd, 2328c2ecf20Sopenharmony_ci (R_E | R_I | (in_be32((u32 __iomem*)bd) & R_W))); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci return skb; 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic int rx_bd_buffer_set(struct ucc_geth_private *ugeth, u8 rxQ) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci u8 __iomem *bd; 2408c2ecf20Sopenharmony_ci u32 bd_status; 2418c2ecf20Sopenharmony_ci struct sk_buff *skb; 2428c2ecf20Sopenharmony_ci int i; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci bd = ugeth->p_rx_bd_ring[rxQ]; 2458c2ecf20Sopenharmony_ci i = 0; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci do { 2488c2ecf20Sopenharmony_ci bd_status = in_be32((u32 __iomem *)bd); 2498c2ecf20Sopenharmony_ci skb = get_new_skb(ugeth, bd); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (!skb) /* If can not allocate data buffer, 2528c2ecf20Sopenharmony_ci abort. Cleanup will be elsewhere */ 2538c2ecf20Sopenharmony_ci return -ENOMEM; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci ugeth->rx_skbuff[rxQ][i] = skb; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* advance the BD pointer */ 2588c2ecf20Sopenharmony_ci bd += sizeof(struct qe_bd); 2598c2ecf20Sopenharmony_ci i++; 2608c2ecf20Sopenharmony_ci } while (!(bd_status & R_W)); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci return 0; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_cistatic int fill_init_enet_entries(struct ucc_geth_private *ugeth, 2668c2ecf20Sopenharmony_ci u32 *p_start, 2678c2ecf20Sopenharmony_ci u8 num_entries, 2688c2ecf20Sopenharmony_ci u32 thread_size, 2698c2ecf20Sopenharmony_ci u32 thread_alignment, 2708c2ecf20Sopenharmony_ci unsigned int risc, 2718c2ecf20Sopenharmony_ci int skip_page_for_first_entry) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci u32 init_enet_offset; 2748c2ecf20Sopenharmony_ci u8 i; 2758c2ecf20Sopenharmony_ci int snum; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci for (i = 0; i < num_entries; i++) { 2788c2ecf20Sopenharmony_ci if ((snum = qe_get_snum()) < 0) { 2798c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 2808c2ecf20Sopenharmony_ci pr_err("Can not get SNUM\n"); 2818c2ecf20Sopenharmony_ci return snum; 2828c2ecf20Sopenharmony_ci } 2838c2ecf20Sopenharmony_ci if ((i == 0) && skip_page_for_first_entry) 2848c2ecf20Sopenharmony_ci /* First entry of Rx does not have page */ 2858c2ecf20Sopenharmony_ci init_enet_offset = 0; 2868c2ecf20Sopenharmony_ci else { 2878c2ecf20Sopenharmony_ci init_enet_offset = 2888c2ecf20Sopenharmony_ci qe_muram_alloc(thread_size, thread_alignment); 2898c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(init_enet_offset)) { 2908c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 2918c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory\n"); 2928c2ecf20Sopenharmony_ci qe_put_snum((u8) snum); 2938c2ecf20Sopenharmony_ci return -ENOMEM; 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci *(p_start++) = 2978c2ecf20Sopenharmony_ci ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset 2988c2ecf20Sopenharmony_ci | risc; 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci return 0; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int return_init_enet_entries(struct ucc_geth_private *ugeth, 3058c2ecf20Sopenharmony_ci u32 *p_start, 3068c2ecf20Sopenharmony_ci u8 num_entries, 3078c2ecf20Sopenharmony_ci unsigned int risc, 3088c2ecf20Sopenharmony_ci int skip_page_for_first_entry) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci u32 init_enet_offset; 3118c2ecf20Sopenharmony_ci u8 i; 3128c2ecf20Sopenharmony_ci int snum; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci for (i = 0; i < num_entries; i++) { 3158c2ecf20Sopenharmony_ci u32 val = *p_start; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci /* Check that this entry was actually valid -- 3188c2ecf20Sopenharmony_ci needed in case failed in allocations */ 3198c2ecf20Sopenharmony_ci if ((val & ENET_INIT_PARAM_RISC_MASK) == risc) { 3208c2ecf20Sopenharmony_ci snum = 3218c2ecf20Sopenharmony_ci (u32) (val & ENET_INIT_PARAM_SNUM_MASK) >> 3228c2ecf20Sopenharmony_ci ENET_INIT_PARAM_SNUM_SHIFT; 3238c2ecf20Sopenharmony_ci qe_put_snum((u8) snum); 3248c2ecf20Sopenharmony_ci if (!((i == 0) && skip_page_for_first_entry)) { 3258c2ecf20Sopenharmony_ci /* First entry of Rx does not have page */ 3268c2ecf20Sopenharmony_ci init_enet_offset = 3278c2ecf20Sopenharmony_ci (val & ENET_INIT_PARAM_PTR_MASK); 3288c2ecf20Sopenharmony_ci qe_muram_free(init_enet_offset); 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci *p_start++ = 0; 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci return 0; 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci#ifdef DEBUG 3388c2ecf20Sopenharmony_cistatic int dump_init_enet_entries(struct ucc_geth_private *ugeth, 3398c2ecf20Sopenharmony_ci u32 __iomem *p_start, 3408c2ecf20Sopenharmony_ci u8 num_entries, 3418c2ecf20Sopenharmony_ci u32 thread_size, 3428c2ecf20Sopenharmony_ci unsigned int risc, 3438c2ecf20Sopenharmony_ci int skip_page_for_first_entry) 3448c2ecf20Sopenharmony_ci{ 3458c2ecf20Sopenharmony_ci u32 init_enet_offset; 3468c2ecf20Sopenharmony_ci u8 i; 3478c2ecf20Sopenharmony_ci int snum; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci for (i = 0; i < num_entries; i++) { 3508c2ecf20Sopenharmony_ci u32 val = in_be32(p_start); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci /* Check that this entry was actually valid -- 3538c2ecf20Sopenharmony_ci needed in case failed in allocations */ 3548c2ecf20Sopenharmony_ci if ((val & ENET_INIT_PARAM_RISC_MASK) == risc) { 3558c2ecf20Sopenharmony_ci snum = 3568c2ecf20Sopenharmony_ci (u32) (val & ENET_INIT_PARAM_SNUM_MASK) >> 3578c2ecf20Sopenharmony_ci ENET_INIT_PARAM_SNUM_SHIFT; 3588c2ecf20Sopenharmony_ci qe_put_snum((u8) snum); 3598c2ecf20Sopenharmony_ci if (!((i == 0) && skip_page_for_first_entry)) { 3608c2ecf20Sopenharmony_ci /* First entry of Rx does not have page */ 3618c2ecf20Sopenharmony_ci init_enet_offset = 3628c2ecf20Sopenharmony_ci (in_be32(p_start) & 3638c2ecf20Sopenharmony_ci ENET_INIT_PARAM_PTR_MASK); 3648c2ecf20Sopenharmony_ci pr_info("Init enet entry %d:\n", i); 3658c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 3668c2ecf20Sopenharmony_ci (u32)qe_muram_addr(init_enet_offset)); 3678c2ecf20Sopenharmony_ci mem_disp(qe_muram_addr(init_enet_offset), 3688c2ecf20Sopenharmony_ci thread_size); 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci p_start++; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci return 0; 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci#endif 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic void put_enet_addr_container(struct enet_addr_container *enet_addr_cont) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci kfree(enet_addr_cont); 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_cistatic void set_mac_addr(__be16 __iomem *reg, u8 *mac) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci out_be16(®[0], ((u16)mac[5] << 8) | mac[4]); 3868c2ecf20Sopenharmony_ci out_be16(®[1], ((u16)mac[3] << 8) | mac[2]); 3878c2ecf20Sopenharmony_ci out_be16(®[2], ((u16)mac[1] << 8) | mac[0]); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci if (paddr_num >= NUM_OF_PADDRS) { 3958c2ecf20Sopenharmony_ci pr_warn("%s: Invalid paddr_num: %u\n", __func__, paddr_num); 3968c2ecf20Sopenharmony_ci return -EINVAL; 3978c2ecf20Sopenharmony_ci } 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci p_82xx_addr_filt = 4008c2ecf20Sopenharmony_ci (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->p_rx_glbl_pram-> 4018c2ecf20Sopenharmony_ci addressfiltering; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci /* Writing address ff.ff.ff.ff.ff.ff disables address 4048c2ecf20Sopenharmony_ci recognition for this register */ 4058c2ecf20Sopenharmony_ci out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff); 4068c2ecf20Sopenharmony_ci out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff); 4078c2ecf20Sopenharmony_ci out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci return 0; 4108c2ecf20Sopenharmony_ci} 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistatic void hw_add_addr_in_hash(struct ucc_geth_private *ugeth, 4138c2ecf20Sopenharmony_ci u8 *p_enet_addr) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; 4168c2ecf20Sopenharmony_ci u32 cecr_subblock; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci p_82xx_addr_filt = 4198c2ecf20Sopenharmony_ci (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->p_rx_glbl_pram-> 4208c2ecf20Sopenharmony_ci addressfiltering; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci cecr_subblock = 4238c2ecf20Sopenharmony_ci ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci /* Ethernet frames are defined in Little Endian mode, 4268c2ecf20Sopenharmony_ci therefore to insert */ 4278c2ecf20Sopenharmony_ci /* the address to the hash (Big Endian mode), we reverse the bytes.*/ 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci set_mac_addr(&p_82xx_addr_filt->taddr.h, p_enet_addr); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock, 4328c2ecf20Sopenharmony_ci QE_CR_PROTOCOL_ETHERNET, 0); 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci#ifdef DEBUG 4368c2ecf20Sopenharmony_cistatic void get_statistics(struct ucc_geth_private *ugeth, 4378c2ecf20Sopenharmony_ci struct ucc_geth_tx_firmware_statistics * 4388c2ecf20Sopenharmony_ci tx_firmware_statistics, 4398c2ecf20Sopenharmony_ci struct ucc_geth_rx_firmware_statistics * 4408c2ecf20Sopenharmony_ci rx_firmware_statistics, 4418c2ecf20Sopenharmony_ci struct ucc_geth_hardware_statistics *hardware_statistics) 4428c2ecf20Sopenharmony_ci{ 4438c2ecf20Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 4448c2ecf20Sopenharmony_ci struct ucc_geth __iomem *ug_regs; 4458c2ecf20Sopenharmony_ci struct ucc_geth_tx_firmware_statistics_pram *p_tx_fw_statistics_pram; 4468c2ecf20Sopenharmony_ci struct ucc_geth_rx_firmware_statistics_pram *p_rx_fw_statistics_pram; 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci ug_regs = ugeth->ug_regs; 4498c2ecf20Sopenharmony_ci uf_regs = (struct ucc_fast __iomem *) ug_regs; 4508c2ecf20Sopenharmony_ci p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram; 4518c2ecf20Sopenharmony_ci p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci /* Tx firmware only if user handed pointer and driver actually 4548c2ecf20Sopenharmony_ci gathers Tx firmware statistics */ 4558c2ecf20Sopenharmony_ci if (tx_firmware_statistics && p_tx_fw_statistics_pram) { 4568c2ecf20Sopenharmony_ci tx_firmware_statistics->sicoltx = 4578c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->sicoltx); 4588c2ecf20Sopenharmony_ci tx_firmware_statistics->mulcoltx = 4598c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->mulcoltx); 4608c2ecf20Sopenharmony_ci tx_firmware_statistics->latecoltxfr = 4618c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->latecoltxfr); 4628c2ecf20Sopenharmony_ci tx_firmware_statistics->frabortduecol = 4638c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->frabortduecol); 4648c2ecf20Sopenharmony_ci tx_firmware_statistics->frlostinmactxer = 4658c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->frlostinmactxer); 4668c2ecf20Sopenharmony_ci tx_firmware_statistics->carriersenseertx = 4678c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->carriersenseertx); 4688c2ecf20Sopenharmony_ci tx_firmware_statistics->frtxok = 4698c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->frtxok); 4708c2ecf20Sopenharmony_ci tx_firmware_statistics->txfrexcessivedefer = 4718c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer); 4728c2ecf20Sopenharmony_ci tx_firmware_statistics->txpkts256 = 4738c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->txpkts256); 4748c2ecf20Sopenharmony_ci tx_firmware_statistics->txpkts512 = 4758c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->txpkts512); 4768c2ecf20Sopenharmony_ci tx_firmware_statistics->txpkts1024 = 4778c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->txpkts1024); 4788c2ecf20Sopenharmony_ci tx_firmware_statistics->txpktsjumbo = 4798c2ecf20Sopenharmony_ci in_be32(&p_tx_fw_statistics_pram->txpktsjumbo); 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /* Rx firmware only if user handed pointer and driver actually 4838c2ecf20Sopenharmony_ci * gathers Rx firmware statistics */ 4848c2ecf20Sopenharmony_ci if (rx_firmware_statistics && p_rx_fw_statistics_pram) { 4858c2ecf20Sopenharmony_ci int i; 4868c2ecf20Sopenharmony_ci rx_firmware_statistics->frrxfcser = 4878c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->frrxfcser); 4888c2ecf20Sopenharmony_ci rx_firmware_statistics->fraligner = 4898c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->fraligner); 4908c2ecf20Sopenharmony_ci rx_firmware_statistics->inrangelenrxer = 4918c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->inrangelenrxer); 4928c2ecf20Sopenharmony_ci rx_firmware_statistics->outrangelenrxer = 4938c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->outrangelenrxer); 4948c2ecf20Sopenharmony_ci rx_firmware_statistics->frtoolong = 4958c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->frtoolong); 4968c2ecf20Sopenharmony_ci rx_firmware_statistics->runt = 4978c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->runt); 4988c2ecf20Sopenharmony_ci rx_firmware_statistics->verylongevent = 4998c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->verylongevent); 5008c2ecf20Sopenharmony_ci rx_firmware_statistics->symbolerror = 5018c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->symbolerror); 5028c2ecf20Sopenharmony_ci rx_firmware_statistics->dropbsy = 5038c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->dropbsy); 5048c2ecf20Sopenharmony_ci for (i = 0; i < 0x8; i++) 5058c2ecf20Sopenharmony_ci rx_firmware_statistics->res0[i] = 5068c2ecf20Sopenharmony_ci p_rx_fw_statistics_pram->res0[i]; 5078c2ecf20Sopenharmony_ci rx_firmware_statistics->mismatchdrop = 5088c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->mismatchdrop); 5098c2ecf20Sopenharmony_ci rx_firmware_statistics->underpkts = 5108c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->underpkts); 5118c2ecf20Sopenharmony_ci rx_firmware_statistics->pkts256 = 5128c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->pkts256); 5138c2ecf20Sopenharmony_ci rx_firmware_statistics->pkts512 = 5148c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->pkts512); 5158c2ecf20Sopenharmony_ci rx_firmware_statistics->pkts1024 = 5168c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->pkts1024); 5178c2ecf20Sopenharmony_ci rx_firmware_statistics->pktsjumbo = 5188c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->pktsjumbo); 5198c2ecf20Sopenharmony_ci rx_firmware_statistics->frlossinmacer = 5208c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->frlossinmacer); 5218c2ecf20Sopenharmony_ci rx_firmware_statistics->pausefr = 5228c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->pausefr); 5238c2ecf20Sopenharmony_ci for (i = 0; i < 0x4; i++) 5248c2ecf20Sopenharmony_ci rx_firmware_statistics->res1[i] = 5258c2ecf20Sopenharmony_ci p_rx_fw_statistics_pram->res1[i]; 5268c2ecf20Sopenharmony_ci rx_firmware_statistics->removevlan = 5278c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->removevlan); 5288c2ecf20Sopenharmony_ci rx_firmware_statistics->replacevlan = 5298c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->replacevlan); 5308c2ecf20Sopenharmony_ci rx_firmware_statistics->insertvlan = 5318c2ecf20Sopenharmony_ci in_be32(&p_rx_fw_statistics_pram->insertvlan); 5328c2ecf20Sopenharmony_ci } 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci /* Hardware only if user handed pointer and driver actually 5358c2ecf20Sopenharmony_ci gathers hardware statistics */ 5368c2ecf20Sopenharmony_ci if (hardware_statistics && 5378c2ecf20Sopenharmony_ci (in_be32(&uf_regs->upsmr) & UCC_GETH_UPSMR_HSE)) { 5388c2ecf20Sopenharmony_ci hardware_statistics->tx64 = in_be32(&ug_regs->tx64); 5398c2ecf20Sopenharmony_ci hardware_statistics->tx127 = in_be32(&ug_regs->tx127); 5408c2ecf20Sopenharmony_ci hardware_statistics->tx255 = in_be32(&ug_regs->tx255); 5418c2ecf20Sopenharmony_ci hardware_statistics->rx64 = in_be32(&ug_regs->rx64); 5428c2ecf20Sopenharmony_ci hardware_statistics->rx127 = in_be32(&ug_regs->rx127); 5438c2ecf20Sopenharmony_ci hardware_statistics->rx255 = in_be32(&ug_regs->rx255); 5448c2ecf20Sopenharmony_ci hardware_statistics->txok = in_be32(&ug_regs->txok); 5458c2ecf20Sopenharmony_ci hardware_statistics->txcf = in_be16(&ug_regs->txcf); 5468c2ecf20Sopenharmony_ci hardware_statistics->tmca = in_be32(&ug_regs->tmca); 5478c2ecf20Sopenharmony_ci hardware_statistics->tbca = in_be32(&ug_regs->tbca); 5488c2ecf20Sopenharmony_ci hardware_statistics->rxfok = in_be32(&ug_regs->rxfok); 5498c2ecf20Sopenharmony_ci hardware_statistics->rxbok = in_be32(&ug_regs->rxbok); 5508c2ecf20Sopenharmony_ci hardware_statistics->rbyt = in_be32(&ug_regs->rbyt); 5518c2ecf20Sopenharmony_ci hardware_statistics->rmca = in_be32(&ug_regs->rmca); 5528c2ecf20Sopenharmony_ci hardware_statistics->rbca = in_be32(&ug_regs->rbca); 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_cistatic void dump_bds(struct ucc_geth_private *ugeth) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci int i; 5598c2ecf20Sopenharmony_ci int length; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { 5628c2ecf20Sopenharmony_ci if (ugeth->p_tx_bd_ring[i]) { 5638c2ecf20Sopenharmony_ci length = 5648c2ecf20Sopenharmony_ci (ugeth->ug_info->bdRingLenTx[i] * 5658c2ecf20Sopenharmony_ci sizeof(struct qe_bd)); 5668c2ecf20Sopenharmony_ci pr_info("TX BDs[%d]\n", i); 5678c2ecf20Sopenharmony_ci mem_disp(ugeth->p_tx_bd_ring[i], length); 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { 5718c2ecf20Sopenharmony_ci if (ugeth->p_rx_bd_ring[i]) { 5728c2ecf20Sopenharmony_ci length = 5738c2ecf20Sopenharmony_ci (ugeth->ug_info->bdRingLenRx[i] * 5748c2ecf20Sopenharmony_ci sizeof(struct qe_bd)); 5758c2ecf20Sopenharmony_ci pr_info("RX BDs[%d]\n", i); 5768c2ecf20Sopenharmony_ci mem_disp(ugeth->p_rx_bd_ring[i], length); 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci} 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_cistatic void dump_regs(struct ucc_geth_private *ugeth) 5828c2ecf20Sopenharmony_ci{ 5838c2ecf20Sopenharmony_ci int i; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci pr_info("UCC%d Geth registers:\n", ugeth->ug_info->uf_info.ucc_num + 1); 5868c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", (u32)ugeth->ug_regs); 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci pr_info("maccfg1 : addr - 0x%08x, val - 0x%08x\n", 5898c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->maccfg1, 5908c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->maccfg1)); 5918c2ecf20Sopenharmony_ci pr_info("maccfg2 : addr - 0x%08x, val - 0x%08x\n", 5928c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->maccfg2, 5938c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->maccfg2)); 5948c2ecf20Sopenharmony_ci pr_info("ipgifg : addr - 0x%08x, val - 0x%08x\n", 5958c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->ipgifg, 5968c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->ipgifg)); 5978c2ecf20Sopenharmony_ci pr_info("hafdup : addr - 0x%08x, val - 0x%08x\n", 5988c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->hafdup, 5998c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->hafdup)); 6008c2ecf20Sopenharmony_ci pr_info("ifctl : addr - 0x%08x, val - 0x%08x\n", 6018c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->ifctl, 6028c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->ifctl)); 6038c2ecf20Sopenharmony_ci pr_info("ifstat : addr - 0x%08x, val - 0x%08x\n", 6048c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->ifstat, 6058c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->ifstat)); 6068c2ecf20Sopenharmony_ci pr_info("macstnaddr1: addr - 0x%08x, val - 0x%08x\n", 6078c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->macstnaddr1, 6088c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->macstnaddr1)); 6098c2ecf20Sopenharmony_ci pr_info("macstnaddr2: addr - 0x%08x, val - 0x%08x\n", 6108c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->macstnaddr2, 6118c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->macstnaddr2)); 6128c2ecf20Sopenharmony_ci pr_info("uempr : addr - 0x%08x, val - 0x%08x\n", 6138c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->uempr, 6148c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->uempr)); 6158c2ecf20Sopenharmony_ci pr_info("utbipar : addr - 0x%08x, val - 0x%08x\n", 6168c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->utbipar, 6178c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->utbipar)); 6188c2ecf20Sopenharmony_ci pr_info("uescr : addr - 0x%08x, val - 0x%04x\n", 6198c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->uescr, 6208c2ecf20Sopenharmony_ci in_be16(&ugeth->ug_regs->uescr)); 6218c2ecf20Sopenharmony_ci pr_info("tx64 : addr - 0x%08x, val - 0x%08x\n", 6228c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->tx64, 6238c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->tx64)); 6248c2ecf20Sopenharmony_ci pr_info("tx127 : addr - 0x%08x, val - 0x%08x\n", 6258c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->tx127, 6268c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->tx127)); 6278c2ecf20Sopenharmony_ci pr_info("tx255 : addr - 0x%08x, val - 0x%08x\n", 6288c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->tx255, 6298c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->tx255)); 6308c2ecf20Sopenharmony_ci pr_info("rx64 : addr - 0x%08x, val - 0x%08x\n", 6318c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->rx64, 6328c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->rx64)); 6338c2ecf20Sopenharmony_ci pr_info("rx127 : addr - 0x%08x, val - 0x%08x\n", 6348c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->rx127, 6358c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->rx127)); 6368c2ecf20Sopenharmony_ci pr_info("rx255 : addr - 0x%08x, val - 0x%08x\n", 6378c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->rx255, 6388c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->rx255)); 6398c2ecf20Sopenharmony_ci pr_info("txok : addr - 0x%08x, val - 0x%08x\n", 6408c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->txok, 6418c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->txok)); 6428c2ecf20Sopenharmony_ci pr_info("txcf : addr - 0x%08x, val - 0x%04x\n", 6438c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->txcf, 6448c2ecf20Sopenharmony_ci in_be16(&ugeth->ug_regs->txcf)); 6458c2ecf20Sopenharmony_ci pr_info("tmca : addr - 0x%08x, val - 0x%08x\n", 6468c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->tmca, 6478c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->tmca)); 6488c2ecf20Sopenharmony_ci pr_info("tbca : addr - 0x%08x, val - 0x%08x\n", 6498c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->tbca, 6508c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->tbca)); 6518c2ecf20Sopenharmony_ci pr_info("rxfok : addr - 0x%08x, val - 0x%08x\n", 6528c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->rxfok, 6538c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->rxfok)); 6548c2ecf20Sopenharmony_ci pr_info("rxbok : addr - 0x%08x, val - 0x%08x\n", 6558c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->rxbok, 6568c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->rxbok)); 6578c2ecf20Sopenharmony_ci pr_info("rbyt : addr - 0x%08x, val - 0x%08x\n", 6588c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->rbyt, 6598c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->rbyt)); 6608c2ecf20Sopenharmony_ci pr_info("rmca : addr - 0x%08x, val - 0x%08x\n", 6618c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->rmca, 6628c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->rmca)); 6638c2ecf20Sopenharmony_ci pr_info("rbca : addr - 0x%08x, val - 0x%08x\n", 6648c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->rbca, 6658c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->rbca)); 6668c2ecf20Sopenharmony_ci pr_info("scar : addr - 0x%08x, val - 0x%08x\n", 6678c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->scar, 6688c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->scar)); 6698c2ecf20Sopenharmony_ci pr_info("scam : addr - 0x%08x, val - 0x%08x\n", 6708c2ecf20Sopenharmony_ci (u32)&ugeth->ug_regs->scam, 6718c2ecf20Sopenharmony_ci in_be32(&ugeth->ug_regs->scam)); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci if (ugeth->p_thread_data_tx) { 6748c2ecf20Sopenharmony_ci int numThreadsTxNumerical; 6758c2ecf20Sopenharmony_ci switch (ugeth->ug_info->numThreadsTx) { 6768c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_1: 6778c2ecf20Sopenharmony_ci numThreadsTxNumerical = 1; 6788c2ecf20Sopenharmony_ci break; 6798c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_2: 6808c2ecf20Sopenharmony_ci numThreadsTxNumerical = 2; 6818c2ecf20Sopenharmony_ci break; 6828c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_4: 6838c2ecf20Sopenharmony_ci numThreadsTxNumerical = 4; 6848c2ecf20Sopenharmony_ci break; 6858c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_6: 6868c2ecf20Sopenharmony_ci numThreadsTxNumerical = 6; 6878c2ecf20Sopenharmony_ci break; 6888c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_8: 6898c2ecf20Sopenharmony_ci numThreadsTxNumerical = 8; 6908c2ecf20Sopenharmony_ci break; 6918c2ecf20Sopenharmony_ci default: 6928c2ecf20Sopenharmony_ci numThreadsTxNumerical = 0; 6938c2ecf20Sopenharmony_ci break; 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci pr_info("Thread data TXs:\n"); 6978c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 6988c2ecf20Sopenharmony_ci (u32)ugeth->p_thread_data_tx); 6998c2ecf20Sopenharmony_ci for (i = 0; i < numThreadsTxNumerical; i++) { 7008c2ecf20Sopenharmony_ci pr_info("Thread data TX[%d]:\n", i); 7018c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 7028c2ecf20Sopenharmony_ci (u32)&ugeth->p_thread_data_tx[i]); 7038c2ecf20Sopenharmony_ci mem_disp((u8 *) & ugeth->p_thread_data_tx[i], 7048c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_thread_data_tx)); 7058c2ecf20Sopenharmony_ci } 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci if (ugeth->p_thread_data_rx) { 7088c2ecf20Sopenharmony_ci int numThreadsRxNumerical; 7098c2ecf20Sopenharmony_ci switch (ugeth->ug_info->numThreadsRx) { 7108c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_1: 7118c2ecf20Sopenharmony_ci numThreadsRxNumerical = 1; 7128c2ecf20Sopenharmony_ci break; 7138c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_2: 7148c2ecf20Sopenharmony_ci numThreadsRxNumerical = 2; 7158c2ecf20Sopenharmony_ci break; 7168c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_4: 7178c2ecf20Sopenharmony_ci numThreadsRxNumerical = 4; 7188c2ecf20Sopenharmony_ci break; 7198c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_6: 7208c2ecf20Sopenharmony_ci numThreadsRxNumerical = 6; 7218c2ecf20Sopenharmony_ci break; 7228c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_8: 7238c2ecf20Sopenharmony_ci numThreadsRxNumerical = 8; 7248c2ecf20Sopenharmony_ci break; 7258c2ecf20Sopenharmony_ci default: 7268c2ecf20Sopenharmony_ci numThreadsRxNumerical = 0; 7278c2ecf20Sopenharmony_ci break; 7288c2ecf20Sopenharmony_ci } 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci pr_info("Thread data RX:\n"); 7318c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 7328c2ecf20Sopenharmony_ci (u32)ugeth->p_thread_data_rx); 7338c2ecf20Sopenharmony_ci for (i = 0; i < numThreadsRxNumerical; i++) { 7348c2ecf20Sopenharmony_ci pr_info("Thread data RX[%d]:\n", i); 7358c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 7368c2ecf20Sopenharmony_ci (u32)&ugeth->p_thread_data_rx[i]); 7378c2ecf20Sopenharmony_ci mem_disp((u8 *) & ugeth->p_thread_data_rx[i], 7388c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_thread_data_rx)); 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci if (ugeth->p_exf_glbl_param) { 7428c2ecf20Sopenharmony_ci pr_info("EXF global param:\n"); 7438c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 7448c2ecf20Sopenharmony_ci (u32)ugeth->p_exf_glbl_param); 7458c2ecf20Sopenharmony_ci mem_disp((u8 *) ugeth->p_exf_glbl_param, 7468c2ecf20Sopenharmony_ci sizeof(*ugeth->p_exf_glbl_param)); 7478c2ecf20Sopenharmony_ci } 7488c2ecf20Sopenharmony_ci if (ugeth->p_tx_glbl_pram) { 7498c2ecf20Sopenharmony_ci pr_info("TX global param:\n"); 7508c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", (u32)ugeth->p_tx_glbl_pram); 7518c2ecf20Sopenharmony_ci pr_info("temoder : addr - 0x%08x, val - 0x%04x\n", 7528c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->temoder, 7538c2ecf20Sopenharmony_ci in_be16(&ugeth->p_tx_glbl_pram->temoder)); 7548c2ecf20Sopenharmony_ci pr_info("sqptr : addr - 0x%08x, val - 0x%08x\n", 7558c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->sqptr, 7568c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->sqptr)); 7578c2ecf20Sopenharmony_ci pr_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x\n", 7588c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->schedulerbasepointer, 7598c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer)); 7608c2ecf20Sopenharmony_ci pr_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x\n", 7618c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->txrmonbaseptr, 7628c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr)); 7638c2ecf20Sopenharmony_ci pr_info("tstate : addr - 0x%08x, val - 0x%08x\n", 7648c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->tstate, 7658c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->tstate)); 7668c2ecf20Sopenharmony_ci pr_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x\n", 7678c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->iphoffset[0], 7688c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram->iphoffset[0]); 7698c2ecf20Sopenharmony_ci pr_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x\n", 7708c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->iphoffset[1], 7718c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram->iphoffset[1]); 7728c2ecf20Sopenharmony_ci pr_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x\n", 7738c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->iphoffset[2], 7748c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram->iphoffset[2]); 7758c2ecf20Sopenharmony_ci pr_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x\n", 7768c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->iphoffset[3], 7778c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram->iphoffset[3]); 7788c2ecf20Sopenharmony_ci pr_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x\n", 7798c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->iphoffset[4], 7808c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram->iphoffset[4]); 7818c2ecf20Sopenharmony_ci pr_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x\n", 7828c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->iphoffset[5], 7838c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram->iphoffset[5]); 7848c2ecf20Sopenharmony_ci pr_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x\n", 7858c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->iphoffset[6], 7868c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram->iphoffset[6]); 7878c2ecf20Sopenharmony_ci pr_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x\n", 7888c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->iphoffset[7], 7898c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram->iphoffset[7]); 7908c2ecf20Sopenharmony_ci pr_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x\n", 7918c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->vtagtable[0], 7928c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0])); 7938c2ecf20Sopenharmony_ci pr_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x\n", 7948c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->vtagtable[1], 7958c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1])); 7968c2ecf20Sopenharmony_ci pr_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x\n", 7978c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->vtagtable[2], 7988c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2])); 7998c2ecf20Sopenharmony_ci pr_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x\n", 8008c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->vtagtable[3], 8018c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3])); 8028c2ecf20Sopenharmony_ci pr_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x\n", 8038c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->vtagtable[4], 8048c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4])); 8058c2ecf20Sopenharmony_ci pr_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x\n", 8068c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->vtagtable[5], 8078c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5])); 8088c2ecf20Sopenharmony_ci pr_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x\n", 8098c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->vtagtable[6], 8108c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6])); 8118c2ecf20Sopenharmony_ci pr_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x\n", 8128c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->vtagtable[7], 8138c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7])); 8148c2ecf20Sopenharmony_ci pr_info("tqptr : addr - 0x%08x, val - 0x%08x\n", 8158c2ecf20Sopenharmony_ci (u32)&ugeth->p_tx_glbl_pram->tqptr, 8168c2ecf20Sopenharmony_ci in_be32(&ugeth->p_tx_glbl_pram->tqptr)); 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci if (ugeth->p_rx_glbl_pram) { 8198c2ecf20Sopenharmony_ci pr_info("RX global param:\n"); 8208c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", (u32)ugeth->p_rx_glbl_pram); 8218c2ecf20Sopenharmony_ci pr_info("remoder : addr - 0x%08x, val - 0x%08x\n", 8228c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->remoder, 8238c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->remoder)); 8248c2ecf20Sopenharmony_ci pr_info("rqptr : addr - 0x%08x, val - 0x%08x\n", 8258c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->rqptr, 8268c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->rqptr)); 8278c2ecf20Sopenharmony_ci pr_info("typeorlen : addr - 0x%08x, val - 0x%04x\n", 8288c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->typeorlen, 8298c2ecf20Sopenharmony_ci in_be16(&ugeth->p_rx_glbl_pram->typeorlen)); 8308c2ecf20Sopenharmony_ci pr_info("rxgstpack : addr - 0x%08x, val - 0x%02x\n", 8318c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->rxgstpack, 8328c2ecf20Sopenharmony_ci ugeth->p_rx_glbl_pram->rxgstpack); 8338c2ecf20Sopenharmony_ci pr_info("rxrmonbaseptr : addr - 0x%08x, val - 0x%08x\n", 8348c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->rxrmonbaseptr, 8358c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr)); 8368c2ecf20Sopenharmony_ci pr_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x\n", 8378c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->intcoalescingptr, 8388c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr)); 8398c2ecf20Sopenharmony_ci pr_info("rstate : addr - 0x%08x, val - 0x%02x\n", 8408c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->rstate, 8418c2ecf20Sopenharmony_ci ugeth->p_rx_glbl_pram->rstate); 8428c2ecf20Sopenharmony_ci pr_info("mrblr : addr - 0x%08x, val - 0x%04x\n", 8438c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->mrblr, 8448c2ecf20Sopenharmony_ci in_be16(&ugeth->p_rx_glbl_pram->mrblr)); 8458c2ecf20Sopenharmony_ci pr_info("rbdqptr : addr - 0x%08x, val - 0x%08x\n", 8468c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->rbdqptr, 8478c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->rbdqptr)); 8488c2ecf20Sopenharmony_ci pr_info("mflr : addr - 0x%08x, val - 0x%04x\n", 8498c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->mflr, 8508c2ecf20Sopenharmony_ci in_be16(&ugeth->p_rx_glbl_pram->mflr)); 8518c2ecf20Sopenharmony_ci pr_info("minflr : addr - 0x%08x, val - 0x%04x\n", 8528c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->minflr, 8538c2ecf20Sopenharmony_ci in_be16(&ugeth->p_rx_glbl_pram->minflr)); 8548c2ecf20Sopenharmony_ci pr_info("maxd1 : addr - 0x%08x, val - 0x%04x\n", 8558c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->maxd1, 8568c2ecf20Sopenharmony_ci in_be16(&ugeth->p_rx_glbl_pram->maxd1)); 8578c2ecf20Sopenharmony_ci pr_info("maxd2 : addr - 0x%08x, val - 0x%04x\n", 8588c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->maxd2, 8598c2ecf20Sopenharmony_ci in_be16(&ugeth->p_rx_glbl_pram->maxd2)); 8608c2ecf20Sopenharmony_ci pr_info("ecamptr : addr - 0x%08x, val - 0x%08x\n", 8618c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->ecamptr, 8628c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->ecamptr)); 8638c2ecf20Sopenharmony_ci pr_info("l2qt : addr - 0x%08x, val - 0x%08x\n", 8648c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->l2qt, 8658c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->l2qt)); 8668c2ecf20Sopenharmony_ci pr_info("l3qt[0] : addr - 0x%08x, val - 0x%08x\n", 8678c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->l3qt[0], 8688c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->l3qt[0])); 8698c2ecf20Sopenharmony_ci pr_info("l3qt[1] : addr - 0x%08x, val - 0x%08x\n", 8708c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->l3qt[1], 8718c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->l3qt[1])); 8728c2ecf20Sopenharmony_ci pr_info("l3qt[2] : addr - 0x%08x, val - 0x%08x\n", 8738c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->l3qt[2], 8748c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->l3qt[2])); 8758c2ecf20Sopenharmony_ci pr_info("l3qt[3] : addr - 0x%08x, val - 0x%08x\n", 8768c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->l3qt[3], 8778c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->l3qt[3])); 8788c2ecf20Sopenharmony_ci pr_info("l3qt[4] : addr - 0x%08x, val - 0x%08x\n", 8798c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->l3qt[4], 8808c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->l3qt[4])); 8818c2ecf20Sopenharmony_ci pr_info("l3qt[5] : addr - 0x%08x, val - 0x%08x\n", 8828c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->l3qt[5], 8838c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->l3qt[5])); 8848c2ecf20Sopenharmony_ci pr_info("l3qt[6] : addr - 0x%08x, val - 0x%08x\n", 8858c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->l3qt[6], 8868c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->l3qt[6])); 8878c2ecf20Sopenharmony_ci pr_info("l3qt[7] : addr - 0x%08x, val - 0x%08x\n", 8888c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->l3qt[7], 8898c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->l3qt[7])); 8908c2ecf20Sopenharmony_ci pr_info("vlantype : addr - 0x%08x, val - 0x%04x\n", 8918c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->vlantype, 8928c2ecf20Sopenharmony_ci in_be16(&ugeth->p_rx_glbl_pram->vlantype)); 8938c2ecf20Sopenharmony_ci pr_info("vlantci : addr - 0x%08x, val - 0x%04x\n", 8948c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->vlantci, 8958c2ecf20Sopenharmony_ci in_be16(&ugeth->p_rx_glbl_pram->vlantci)); 8968c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) 8978c2ecf20Sopenharmony_ci pr_info("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x\n", 8988c2ecf20Sopenharmony_ci i, 8998c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->addressfiltering[i], 9008c2ecf20Sopenharmony_ci ugeth->p_rx_glbl_pram->addressfiltering[i]); 9018c2ecf20Sopenharmony_ci pr_info("exfGlobalParam : addr - 0x%08x, val - 0x%08x\n", 9028c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_glbl_pram->exfGlobalParam, 9038c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam)); 9048c2ecf20Sopenharmony_ci } 9058c2ecf20Sopenharmony_ci if (ugeth->p_send_q_mem_reg) { 9068c2ecf20Sopenharmony_ci pr_info("Send Q memory registers:\n"); 9078c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", (u32)ugeth->p_send_q_mem_reg); 9088c2ecf20Sopenharmony_ci for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { 9098c2ecf20Sopenharmony_ci pr_info("SQQD[%d]:\n", i); 9108c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 9118c2ecf20Sopenharmony_ci (u32)&ugeth->p_send_q_mem_reg->sqqd[i]); 9128c2ecf20Sopenharmony_ci mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i], 9138c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_send_queue_qd)); 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci if (ugeth->p_scheduler) { 9178c2ecf20Sopenharmony_ci pr_info("Scheduler:\n"); 9188c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", (u32)ugeth->p_scheduler); 9198c2ecf20Sopenharmony_ci mem_disp((u8 *) ugeth->p_scheduler, 9208c2ecf20Sopenharmony_ci sizeof(*ugeth->p_scheduler)); 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci if (ugeth->p_tx_fw_statistics_pram) { 9238c2ecf20Sopenharmony_ci pr_info("TX FW statistics pram:\n"); 9248c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 9258c2ecf20Sopenharmony_ci (u32)ugeth->p_tx_fw_statistics_pram); 9268c2ecf20Sopenharmony_ci mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram, 9278c2ecf20Sopenharmony_ci sizeof(*ugeth->p_tx_fw_statistics_pram)); 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci if (ugeth->p_rx_fw_statistics_pram) { 9308c2ecf20Sopenharmony_ci pr_info("RX FW statistics pram:\n"); 9318c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 9328c2ecf20Sopenharmony_ci (u32)ugeth->p_rx_fw_statistics_pram); 9338c2ecf20Sopenharmony_ci mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram, 9348c2ecf20Sopenharmony_ci sizeof(*ugeth->p_rx_fw_statistics_pram)); 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci if (ugeth->p_rx_irq_coalescing_tbl) { 9378c2ecf20Sopenharmony_ci pr_info("RX IRQ coalescing tables:\n"); 9388c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 9398c2ecf20Sopenharmony_ci (u32)ugeth->p_rx_irq_coalescing_tbl); 9408c2ecf20Sopenharmony_ci for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { 9418c2ecf20Sopenharmony_ci pr_info("RX IRQ coalescing table entry[%d]:\n", i); 9428c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 9438c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_irq_coalescing_tbl-> 9448c2ecf20Sopenharmony_ci coalescingentry[i]); 9458c2ecf20Sopenharmony_ci pr_info("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x\n", 9468c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_irq_coalescing_tbl-> 9478c2ecf20Sopenharmony_ci coalescingentry[i].interruptcoalescingmaxvalue, 9488c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_irq_coalescing_tbl-> 9498c2ecf20Sopenharmony_ci coalescingentry[i]. 9508c2ecf20Sopenharmony_ci interruptcoalescingmaxvalue)); 9518c2ecf20Sopenharmony_ci pr_info("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x\n", 9528c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_irq_coalescing_tbl-> 9538c2ecf20Sopenharmony_ci coalescingentry[i].interruptcoalescingcounter, 9548c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_irq_coalescing_tbl-> 9558c2ecf20Sopenharmony_ci coalescingentry[i]. 9568c2ecf20Sopenharmony_ci interruptcoalescingcounter)); 9578c2ecf20Sopenharmony_ci } 9588c2ecf20Sopenharmony_ci } 9598c2ecf20Sopenharmony_ci if (ugeth->p_rx_bd_qs_tbl) { 9608c2ecf20Sopenharmony_ci pr_info("RX BD QS tables:\n"); 9618c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", (u32)ugeth->p_rx_bd_qs_tbl); 9628c2ecf20Sopenharmony_ci for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { 9638c2ecf20Sopenharmony_ci pr_info("RX BD QS table[%d]:\n", i); 9648c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 9658c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_bd_qs_tbl[i]); 9668c2ecf20Sopenharmony_ci pr_info("bdbaseptr : addr - 0x%08x, val - 0x%08x\n", 9678c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr, 9688c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr)); 9698c2ecf20Sopenharmony_ci pr_info("bdptr : addr - 0x%08x, val - 0x%08x\n", 9708c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_bd_qs_tbl[i].bdptr, 9718c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr)); 9728c2ecf20Sopenharmony_ci pr_info("externalbdbaseptr: addr - 0x%08x, val - 0x%08x\n", 9738c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, 9748c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_bd_qs_tbl[i]. 9758c2ecf20Sopenharmony_ci externalbdbaseptr)); 9768c2ecf20Sopenharmony_ci pr_info("externalbdptr : addr - 0x%08x, val - 0x%08x\n", 9778c2ecf20Sopenharmony_ci (u32)&ugeth->p_rx_bd_qs_tbl[i].externalbdptr, 9788c2ecf20Sopenharmony_ci in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr)); 9798c2ecf20Sopenharmony_ci pr_info("ucode RX Prefetched BDs:\n"); 9808c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 9818c2ecf20Sopenharmony_ci (u32)qe_muram_addr(in_be32 9828c2ecf20Sopenharmony_ci (&ugeth->p_rx_bd_qs_tbl[i]. 9838c2ecf20Sopenharmony_ci bdbaseptr))); 9848c2ecf20Sopenharmony_ci mem_disp((u8 *) 9858c2ecf20Sopenharmony_ci qe_muram_addr(in_be32 9868c2ecf20Sopenharmony_ci (&ugeth->p_rx_bd_qs_tbl[i]. 9878c2ecf20Sopenharmony_ci bdbaseptr)), 9888c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_rx_prefetched_bds)); 9898c2ecf20Sopenharmony_ci } 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci if (ugeth->p_init_enet_param_shadow) { 9928c2ecf20Sopenharmony_ci int size; 9938c2ecf20Sopenharmony_ci pr_info("Init enet param shadow:\n"); 9948c2ecf20Sopenharmony_ci pr_info("Base address: 0x%08x\n", 9958c2ecf20Sopenharmony_ci (u32) ugeth->p_init_enet_param_shadow); 9968c2ecf20Sopenharmony_ci mem_disp((u8 *) ugeth->p_init_enet_param_shadow, 9978c2ecf20Sopenharmony_ci sizeof(*ugeth->p_init_enet_param_shadow)); 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci size = sizeof(struct ucc_geth_thread_rx_pram); 10008c2ecf20Sopenharmony_ci if (ugeth->ug_info->rxExtendedFiltering) { 10018c2ecf20Sopenharmony_ci size += 10028c2ecf20Sopenharmony_ci THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; 10038c2ecf20Sopenharmony_ci if (ugeth->ug_info->largestexternallookupkeysize == 10048c2ecf20Sopenharmony_ci QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES) 10058c2ecf20Sopenharmony_ci size += 10068c2ecf20Sopenharmony_ci THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8; 10078c2ecf20Sopenharmony_ci if (ugeth->ug_info->largestexternallookupkeysize == 10088c2ecf20Sopenharmony_ci QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES) 10098c2ecf20Sopenharmony_ci size += 10108c2ecf20Sopenharmony_ci THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16; 10118c2ecf20Sopenharmony_ci } 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci dump_init_enet_entries(ugeth, 10148c2ecf20Sopenharmony_ci &(ugeth->p_init_enet_param_shadow-> 10158c2ecf20Sopenharmony_ci txthread[0]), 10168c2ecf20Sopenharmony_ci ENET_INIT_PARAM_MAX_ENTRIES_TX, 10178c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_thread_tx_pram), 10188c2ecf20Sopenharmony_ci ugeth->ug_info->riscTx, 0); 10198c2ecf20Sopenharmony_ci dump_init_enet_entries(ugeth, 10208c2ecf20Sopenharmony_ci &(ugeth->p_init_enet_param_shadow-> 10218c2ecf20Sopenharmony_ci rxthread[0]), 10228c2ecf20Sopenharmony_ci ENET_INIT_PARAM_MAX_ENTRIES_RX, size, 10238c2ecf20Sopenharmony_ci ugeth->ug_info->riscRx, 1); 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci} 10268c2ecf20Sopenharmony_ci#endif /* DEBUG */ 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_cistatic void init_default_reg_vals(u32 __iomem *upsmr_register, 10298c2ecf20Sopenharmony_ci u32 __iomem *maccfg1_register, 10308c2ecf20Sopenharmony_ci u32 __iomem *maccfg2_register) 10318c2ecf20Sopenharmony_ci{ 10328c2ecf20Sopenharmony_ci out_be32(upsmr_register, UCC_GETH_UPSMR_INIT); 10338c2ecf20Sopenharmony_ci out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT); 10348c2ecf20Sopenharmony_ci out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT); 10358c2ecf20Sopenharmony_ci} 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_cistatic int init_half_duplex_params(int alt_beb, 10388c2ecf20Sopenharmony_ci int back_pressure_no_backoff, 10398c2ecf20Sopenharmony_ci int no_backoff, 10408c2ecf20Sopenharmony_ci int excess_defer, 10418c2ecf20Sopenharmony_ci u8 alt_beb_truncation, 10428c2ecf20Sopenharmony_ci u8 max_retransmissions, 10438c2ecf20Sopenharmony_ci u8 collision_window, 10448c2ecf20Sopenharmony_ci u32 __iomem *hafdup_register) 10458c2ecf20Sopenharmony_ci{ 10468c2ecf20Sopenharmony_ci u32 value = 0; 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) || 10498c2ecf20Sopenharmony_ci (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) || 10508c2ecf20Sopenharmony_ci (collision_window > HALFDUP_COLLISION_WINDOW_MAX)) 10518c2ecf20Sopenharmony_ci return -EINVAL; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci if (alt_beb) 10568c2ecf20Sopenharmony_ci value |= HALFDUP_ALT_BEB; 10578c2ecf20Sopenharmony_ci if (back_pressure_no_backoff) 10588c2ecf20Sopenharmony_ci value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF; 10598c2ecf20Sopenharmony_ci if (no_backoff) 10608c2ecf20Sopenharmony_ci value |= HALFDUP_NO_BACKOFF; 10618c2ecf20Sopenharmony_ci if (excess_defer) 10628c2ecf20Sopenharmony_ci value |= HALFDUP_EXCESSIVE_DEFER; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT); 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci value |= collision_window; 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci out_be32(hafdup_register, value); 10698c2ecf20Sopenharmony_ci return 0; 10708c2ecf20Sopenharmony_ci} 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_cistatic int init_inter_frame_gap_params(u8 non_btb_cs_ipg, 10738c2ecf20Sopenharmony_ci u8 non_btb_ipg, 10748c2ecf20Sopenharmony_ci u8 min_ifg, 10758c2ecf20Sopenharmony_ci u8 btb_ipg, 10768c2ecf20Sopenharmony_ci u32 __iomem *ipgifg_register) 10778c2ecf20Sopenharmony_ci{ 10788c2ecf20Sopenharmony_ci u32 value = 0; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci /* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back 10818c2ecf20Sopenharmony_ci IPG part 2 */ 10828c2ecf20Sopenharmony_ci if (non_btb_cs_ipg > non_btb_ipg) 10838c2ecf20Sopenharmony_ci return -EINVAL; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) || 10868c2ecf20Sopenharmony_ci (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) || 10878c2ecf20Sopenharmony_ci /*(min_ifg > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */ 10888c2ecf20Sopenharmony_ci (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX)) 10898c2ecf20Sopenharmony_ci return -EINVAL; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci value |= 10928c2ecf20Sopenharmony_ci ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) & 10938c2ecf20Sopenharmony_ci IPGIFG_NBTB_CS_IPG_MASK); 10948c2ecf20Sopenharmony_ci value |= 10958c2ecf20Sopenharmony_ci ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) & 10968c2ecf20Sopenharmony_ci IPGIFG_NBTB_IPG_MASK); 10978c2ecf20Sopenharmony_ci value |= 10988c2ecf20Sopenharmony_ci ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) & 10998c2ecf20Sopenharmony_ci IPGIFG_MIN_IFG_MASK); 11008c2ecf20Sopenharmony_ci value |= (btb_ipg & IPGIFG_BTB_IPG_MASK); 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci out_be32(ipgifg_register, value); 11038c2ecf20Sopenharmony_ci return 0; 11048c2ecf20Sopenharmony_ci} 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ciint init_flow_control_params(u32 automatic_flow_control_mode, 11078c2ecf20Sopenharmony_ci int rx_flow_control_enable, 11088c2ecf20Sopenharmony_ci int tx_flow_control_enable, 11098c2ecf20Sopenharmony_ci u16 pause_period, 11108c2ecf20Sopenharmony_ci u16 extension_field, 11118c2ecf20Sopenharmony_ci u32 __iomem *upsmr_register, 11128c2ecf20Sopenharmony_ci u32 __iomem *uempr_register, 11138c2ecf20Sopenharmony_ci u32 __iomem *maccfg1_register) 11148c2ecf20Sopenharmony_ci{ 11158c2ecf20Sopenharmony_ci u32 value = 0; 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci /* Set UEMPR register */ 11188c2ecf20Sopenharmony_ci value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT; 11198c2ecf20Sopenharmony_ci value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT; 11208c2ecf20Sopenharmony_ci out_be32(uempr_register, value); 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci /* Set UPSMR register */ 11238c2ecf20Sopenharmony_ci setbits32(upsmr_register, automatic_flow_control_mode); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci value = in_be32(maccfg1_register); 11268c2ecf20Sopenharmony_ci if (rx_flow_control_enable) 11278c2ecf20Sopenharmony_ci value |= MACCFG1_FLOW_RX; 11288c2ecf20Sopenharmony_ci if (tx_flow_control_enable) 11298c2ecf20Sopenharmony_ci value |= MACCFG1_FLOW_TX; 11308c2ecf20Sopenharmony_ci out_be32(maccfg1_register, value); 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci return 0; 11338c2ecf20Sopenharmony_ci} 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_cistatic int init_hw_statistics_gathering_mode(int enable_hardware_statistics, 11368c2ecf20Sopenharmony_ci int auto_zero_hardware_statistics, 11378c2ecf20Sopenharmony_ci u32 __iomem *upsmr_register, 11388c2ecf20Sopenharmony_ci u16 __iomem *uescr_register) 11398c2ecf20Sopenharmony_ci{ 11408c2ecf20Sopenharmony_ci u16 uescr_value = 0; 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci /* Enable hardware statistics gathering if requested */ 11438c2ecf20Sopenharmony_ci if (enable_hardware_statistics) 11448c2ecf20Sopenharmony_ci setbits32(upsmr_register, UCC_GETH_UPSMR_HSE); 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci /* Clear hardware statistics counters */ 11478c2ecf20Sopenharmony_ci uescr_value = in_be16(uescr_register); 11488c2ecf20Sopenharmony_ci uescr_value |= UESCR_CLRCNT; 11498c2ecf20Sopenharmony_ci /* Automatically zero hardware statistics counters on read, 11508c2ecf20Sopenharmony_ci if requested */ 11518c2ecf20Sopenharmony_ci if (auto_zero_hardware_statistics) 11528c2ecf20Sopenharmony_ci uescr_value |= UESCR_AUTOZ; 11538c2ecf20Sopenharmony_ci out_be16(uescr_register, uescr_value); 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci return 0; 11568c2ecf20Sopenharmony_ci} 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_cistatic int init_firmware_statistics_gathering_mode(int 11598c2ecf20Sopenharmony_ci enable_tx_firmware_statistics, 11608c2ecf20Sopenharmony_ci int enable_rx_firmware_statistics, 11618c2ecf20Sopenharmony_ci u32 __iomem *tx_rmon_base_ptr, 11628c2ecf20Sopenharmony_ci u32 tx_firmware_statistics_structure_address, 11638c2ecf20Sopenharmony_ci u32 __iomem *rx_rmon_base_ptr, 11648c2ecf20Sopenharmony_ci u32 rx_firmware_statistics_structure_address, 11658c2ecf20Sopenharmony_ci u16 __iomem *temoder_register, 11668c2ecf20Sopenharmony_ci u32 __iomem *remoder_register) 11678c2ecf20Sopenharmony_ci{ 11688c2ecf20Sopenharmony_ci /* Note: this function does not check if */ 11698c2ecf20Sopenharmony_ci /* the parameters it receives are NULL */ 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci if (enable_tx_firmware_statistics) { 11728c2ecf20Sopenharmony_ci out_be32(tx_rmon_base_ptr, 11738c2ecf20Sopenharmony_ci tx_firmware_statistics_structure_address); 11748c2ecf20Sopenharmony_ci setbits16(temoder_register, TEMODER_TX_RMON_STATISTICS_ENABLE); 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci if (enable_rx_firmware_statistics) { 11788c2ecf20Sopenharmony_ci out_be32(rx_rmon_base_ptr, 11798c2ecf20Sopenharmony_ci rx_firmware_statistics_structure_address); 11808c2ecf20Sopenharmony_ci setbits32(remoder_register, REMODER_RX_RMON_STATISTICS_ENABLE); 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci return 0; 11848c2ecf20Sopenharmony_ci} 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_cistatic int init_mac_station_addr_regs(u8 address_byte_0, 11878c2ecf20Sopenharmony_ci u8 address_byte_1, 11888c2ecf20Sopenharmony_ci u8 address_byte_2, 11898c2ecf20Sopenharmony_ci u8 address_byte_3, 11908c2ecf20Sopenharmony_ci u8 address_byte_4, 11918c2ecf20Sopenharmony_ci u8 address_byte_5, 11928c2ecf20Sopenharmony_ci u32 __iomem *macstnaddr1_register, 11938c2ecf20Sopenharmony_ci u32 __iomem *macstnaddr2_register) 11948c2ecf20Sopenharmony_ci{ 11958c2ecf20Sopenharmony_ci u32 value = 0; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci /* Example: for a station address of 0x12345678ABCD, */ 11988c2ecf20Sopenharmony_ci /* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */ 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci /* MACSTNADDR1 Register: */ 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci /* 0 7 8 15 */ 12038c2ecf20Sopenharmony_ci /* station address byte 5 station address byte 4 */ 12048c2ecf20Sopenharmony_ci /* 16 23 24 31 */ 12058c2ecf20Sopenharmony_ci /* station address byte 3 station address byte 2 */ 12068c2ecf20Sopenharmony_ci value |= (u32) ((address_byte_2 << 0) & 0x000000FF); 12078c2ecf20Sopenharmony_ci value |= (u32) ((address_byte_3 << 8) & 0x0000FF00); 12088c2ecf20Sopenharmony_ci value |= (u32) ((address_byte_4 << 16) & 0x00FF0000); 12098c2ecf20Sopenharmony_ci value |= (u32) ((address_byte_5 << 24) & 0xFF000000); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci out_be32(macstnaddr1_register, value); 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci /* MACSTNADDR2 Register: */ 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci /* 0 7 8 15 */ 12168c2ecf20Sopenharmony_ci /* station address byte 1 station address byte 0 */ 12178c2ecf20Sopenharmony_ci /* 16 23 24 31 */ 12188c2ecf20Sopenharmony_ci /* reserved reserved */ 12198c2ecf20Sopenharmony_ci value = 0; 12208c2ecf20Sopenharmony_ci value |= (u32) ((address_byte_0 << 16) & 0x00FF0000); 12218c2ecf20Sopenharmony_ci value |= (u32) ((address_byte_1 << 24) & 0xFF000000); 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci out_be32(macstnaddr2_register, value); 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci return 0; 12268c2ecf20Sopenharmony_ci} 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_cistatic int init_check_frame_length_mode(int length_check, 12298c2ecf20Sopenharmony_ci u32 __iomem *maccfg2_register) 12308c2ecf20Sopenharmony_ci{ 12318c2ecf20Sopenharmony_ci u32 value = 0; 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci value = in_be32(maccfg2_register); 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci if (length_check) 12368c2ecf20Sopenharmony_ci value |= MACCFG2_LC; 12378c2ecf20Sopenharmony_ci else 12388c2ecf20Sopenharmony_ci value &= ~MACCFG2_LC; 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci out_be32(maccfg2_register, value); 12418c2ecf20Sopenharmony_ci return 0; 12428c2ecf20Sopenharmony_ci} 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_cistatic int init_preamble_length(u8 preamble_length, 12458c2ecf20Sopenharmony_ci u32 __iomem *maccfg2_register) 12468c2ecf20Sopenharmony_ci{ 12478c2ecf20Sopenharmony_ci if ((preamble_length < 3) || (preamble_length > 7)) 12488c2ecf20Sopenharmony_ci return -EINVAL; 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci clrsetbits_be32(maccfg2_register, MACCFG2_PREL_MASK, 12518c2ecf20Sopenharmony_ci preamble_length << MACCFG2_PREL_SHIFT); 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci return 0; 12548c2ecf20Sopenharmony_ci} 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_cistatic int init_rx_parameters(int reject_broadcast, 12578c2ecf20Sopenharmony_ci int receive_short_frames, 12588c2ecf20Sopenharmony_ci int promiscuous, u32 __iomem *upsmr_register) 12598c2ecf20Sopenharmony_ci{ 12608c2ecf20Sopenharmony_ci u32 value = 0; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci value = in_be32(upsmr_register); 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci if (reject_broadcast) 12658c2ecf20Sopenharmony_ci value |= UCC_GETH_UPSMR_BRO; 12668c2ecf20Sopenharmony_ci else 12678c2ecf20Sopenharmony_ci value &= ~UCC_GETH_UPSMR_BRO; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci if (receive_short_frames) 12708c2ecf20Sopenharmony_ci value |= UCC_GETH_UPSMR_RSH; 12718c2ecf20Sopenharmony_ci else 12728c2ecf20Sopenharmony_ci value &= ~UCC_GETH_UPSMR_RSH; 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci if (promiscuous) 12758c2ecf20Sopenharmony_ci value |= UCC_GETH_UPSMR_PRO; 12768c2ecf20Sopenharmony_ci else 12778c2ecf20Sopenharmony_ci value &= ~UCC_GETH_UPSMR_PRO; 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci out_be32(upsmr_register, value); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci return 0; 12828c2ecf20Sopenharmony_ci} 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_cistatic int init_max_rx_buff_len(u16 max_rx_buf_len, 12858c2ecf20Sopenharmony_ci u16 __iomem *mrblr_register) 12868c2ecf20Sopenharmony_ci{ 12878c2ecf20Sopenharmony_ci /* max_rx_buf_len value must be a multiple of 128 */ 12888c2ecf20Sopenharmony_ci if ((max_rx_buf_len == 0) || 12898c2ecf20Sopenharmony_ci (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT)) 12908c2ecf20Sopenharmony_ci return -EINVAL; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci out_be16(mrblr_register, max_rx_buf_len); 12938c2ecf20Sopenharmony_ci return 0; 12948c2ecf20Sopenharmony_ci} 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_cistatic int init_min_frame_len(u16 min_frame_length, 12978c2ecf20Sopenharmony_ci u16 __iomem *minflr_register, 12988c2ecf20Sopenharmony_ci u16 __iomem *mrblr_register) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci u16 mrblr_value = 0; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci mrblr_value = in_be16(mrblr_register); 13038c2ecf20Sopenharmony_ci if (min_frame_length >= (mrblr_value - 4)) 13048c2ecf20Sopenharmony_ci return -EINVAL; 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci out_be16(minflr_register, min_frame_length); 13078c2ecf20Sopenharmony_ci return 0; 13088c2ecf20Sopenharmony_ci} 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_cistatic int adjust_enet_interface(struct ucc_geth_private *ugeth) 13118c2ecf20Sopenharmony_ci{ 13128c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 13138c2ecf20Sopenharmony_ci struct ucc_geth __iomem *ug_regs; 13148c2ecf20Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 13158c2ecf20Sopenharmony_ci int ret_val; 13168c2ecf20Sopenharmony_ci u32 upsmr, maccfg2; 13178c2ecf20Sopenharmony_ci u16 value; 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci ug_info = ugeth->ug_info; 13228c2ecf20Sopenharmony_ci ug_regs = ugeth->ug_regs; 13238c2ecf20Sopenharmony_ci uf_regs = ugeth->uccf->uf_regs; 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci /* Set MACCFG2 */ 13268c2ecf20Sopenharmony_ci maccfg2 = in_be32(&ug_regs->maccfg2); 13278c2ecf20Sopenharmony_ci maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; 13288c2ecf20Sopenharmony_ci if ((ugeth->max_speed == SPEED_10) || 13298c2ecf20Sopenharmony_ci (ugeth->max_speed == SPEED_100)) 13308c2ecf20Sopenharmony_ci maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; 13318c2ecf20Sopenharmony_ci else if (ugeth->max_speed == SPEED_1000) 13328c2ecf20Sopenharmony_ci maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; 13338c2ecf20Sopenharmony_ci maccfg2 |= ug_info->padAndCrc; 13348c2ecf20Sopenharmony_ci out_be32(&ug_regs->maccfg2, maccfg2); 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci /* Set UPSMR */ 13378c2ecf20Sopenharmony_ci upsmr = in_be32(&uf_regs->upsmr); 13388c2ecf20Sopenharmony_ci upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M | 13398c2ecf20Sopenharmony_ci UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM); 13408c2ecf20Sopenharmony_ci if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || 13418c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || 13428c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || 13438c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || 13448c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || 13458c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { 13468c2ecf20Sopenharmony_ci if (ugeth->phy_interface != PHY_INTERFACE_MODE_RMII) 13478c2ecf20Sopenharmony_ci upsmr |= UCC_GETH_UPSMR_RPM; 13488c2ecf20Sopenharmony_ci switch (ugeth->max_speed) { 13498c2ecf20Sopenharmony_ci case SPEED_10: 13508c2ecf20Sopenharmony_ci upsmr |= UCC_GETH_UPSMR_R10M; 13518c2ecf20Sopenharmony_ci fallthrough; 13528c2ecf20Sopenharmony_ci case SPEED_100: 13538c2ecf20Sopenharmony_ci if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI) 13548c2ecf20Sopenharmony_ci upsmr |= UCC_GETH_UPSMR_RMM; 13558c2ecf20Sopenharmony_ci } 13568c2ecf20Sopenharmony_ci } 13578c2ecf20Sopenharmony_ci if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || 13588c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { 13598c2ecf20Sopenharmony_ci upsmr |= UCC_GETH_UPSMR_TBIM; 13608c2ecf20Sopenharmony_ci } 13618c2ecf20Sopenharmony_ci if (ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII) 13628c2ecf20Sopenharmony_ci upsmr |= UCC_GETH_UPSMR_SGMM; 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci out_be32(&uf_regs->upsmr, upsmr); 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci /* Disable autonegotiation in tbi mode, because by default it 13678c2ecf20Sopenharmony_ci comes up in autonegotiation mode. */ 13688c2ecf20Sopenharmony_ci /* Note that this depends on proper setting in utbipar register. */ 13698c2ecf20Sopenharmony_ci if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) || 13708c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { 13718c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info = ugeth->ug_info; 13728c2ecf20Sopenharmony_ci struct phy_device *tbiphy; 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci if (!ug_info->tbi_node) 13758c2ecf20Sopenharmony_ci pr_warn("TBI mode requires that the device tree specify a tbi-handle\n"); 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci tbiphy = of_phy_find_device(ug_info->tbi_node); 13788c2ecf20Sopenharmony_ci if (!tbiphy) 13798c2ecf20Sopenharmony_ci pr_warn("Could not get TBI device\n"); 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci value = phy_read(tbiphy, ENET_TBI_MII_CR); 13828c2ecf20Sopenharmony_ci value &= ~0x1000; /* Turn off autonegotiation */ 13838c2ecf20Sopenharmony_ci phy_write(tbiphy, ENET_TBI_MII_CR, value); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci put_device(&tbiphy->mdio.dev); 13868c2ecf20Sopenharmony_ci } 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2); 13918c2ecf20Sopenharmony_ci if (ret_val != 0) { 13928c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 13938c2ecf20Sopenharmony_ci pr_err("Preamble length must be between 3 and 7 inclusive\n"); 13948c2ecf20Sopenharmony_ci return ret_val; 13958c2ecf20Sopenharmony_ci } 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci return 0; 13988c2ecf20Sopenharmony_ci} 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_cistatic int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) 14018c2ecf20Sopenharmony_ci{ 14028c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 14038c2ecf20Sopenharmony_ci u32 cecr_subblock; 14048c2ecf20Sopenharmony_ci u32 temp; 14058c2ecf20Sopenharmony_ci int i = 10; 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci /* Mask GRACEFUL STOP TX interrupt bit and clear it */ 14108c2ecf20Sopenharmony_ci clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA); 14118c2ecf20Sopenharmony_ci out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA); /* clear by writing 1 */ 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci /* Issue host command */ 14148c2ecf20Sopenharmony_ci cecr_subblock = 14158c2ecf20Sopenharmony_ci ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); 14168c2ecf20Sopenharmony_ci qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock, 14178c2ecf20Sopenharmony_ci QE_CR_PROTOCOL_ETHERNET, 0); 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci /* Wait for command to complete */ 14208c2ecf20Sopenharmony_ci do { 14218c2ecf20Sopenharmony_ci msleep(10); 14228c2ecf20Sopenharmony_ci temp = in_be32(uccf->p_ucce); 14238c2ecf20Sopenharmony_ci } while (!(temp & UCC_GETH_UCCE_GRA) && --i); 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci uccf->stopped_tx = 1; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci return 0; 14288c2ecf20Sopenharmony_ci} 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_cistatic int ugeth_graceful_stop_rx(struct ucc_geth_private *ugeth) 14318c2ecf20Sopenharmony_ci{ 14328c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 14338c2ecf20Sopenharmony_ci u32 cecr_subblock; 14348c2ecf20Sopenharmony_ci u8 temp; 14358c2ecf20Sopenharmony_ci int i = 10; 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci /* Clear acknowledge bit */ 14408c2ecf20Sopenharmony_ci temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); 14418c2ecf20Sopenharmony_ci temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX; 14428c2ecf20Sopenharmony_ci out_8(&ugeth->p_rx_glbl_pram->rxgstpack, temp); 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci /* Keep issuing command and checking acknowledge bit until 14458c2ecf20Sopenharmony_ci it is asserted, according to spec */ 14468c2ecf20Sopenharmony_ci do { 14478c2ecf20Sopenharmony_ci /* Issue host command */ 14488c2ecf20Sopenharmony_ci cecr_subblock = 14498c2ecf20Sopenharmony_ci ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info. 14508c2ecf20Sopenharmony_ci ucc_num); 14518c2ecf20Sopenharmony_ci qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, 14528c2ecf20Sopenharmony_ci QE_CR_PROTOCOL_ETHERNET, 0); 14538c2ecf20Sopenharmony_ci msleep(10); 14548c2ecf20Sopenharmony_ci temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack); 14558c2ecf20Sopenharmony_ci } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i); 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci uccf->stopped_rx = 1; 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci return 0; 14608c2ecf20Sopenharmony_ci} 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_cistatic int ugeth_restart_tx(struct ucc_geth_private *ugeth) 14638c2ecf20Sopenharmony_ci{ 14648c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 14658c2ecf20Sopenharmony_ci u32 cecr_subblock; 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci cecr_subblock = 14708c2ecf20Sopenharmony_ci ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); 14718c2ecf20Sopenharmony_ci qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0); 14728c2ecf20Sopenharmony_ci uccf->stopped_tx = 0; 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci return 0; 14758c2ecf20Sopenharmony_ci} 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_cistatic int ugeth_restart_rx(struct ucc_geth_private *ugeth) 14788c2ecf20Sopenharmony_ci{ 14798c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 14808c2ecf20Sopenharmony_ci u32 cecr_subblock; 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci cecr_subblock = 14858c2ecf20Sopenharmony_ci ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); 14868c2ecf20Sopenharmony_ci qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 14878c2ecf20Sopenharmony_ci 0); 14888c2ecf20Sopenharmony_ci uccf->stopped_rx = 0; 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci return 0; 14918c2ecf20Sopenharmony_ci} 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_cistatic int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode) 14948c2ecf20Sopenharmony_ci{ 14958c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 14968c2ecf20Sopenharmony_ci int enabled_tx, enabled_rx; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_ci /* check if the UCC number is in range. */ 15018c2ecf20Sopenharmony_ci if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { 15028c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 15038c2ecf20Sopenharmony_ci pr_err("ucc_num out of range\n"); 15048c2ecf20Sopenharmony_ci return -EINVAL; 15058c2ecf20Sopenharmony_ci } 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci enabled_tx = uccf->enabled_tx; 15088c2ecf20Sopenharmony_ci enabled_rx = uccf->enabled_rx; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci /* Get Tx and Rx going again, in case this channel was actively 15118c2ecf20Sopenharmony_ci disabled. */ 15128c2ecf20Sopenharmony_ci if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx) 15138c2ecf20Sopenharmony_ci ugeth_restart_tx(ugeth); 15148c2ecf20Sopenharmony_ci if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx) 15158c2ecf20Sopenharmony_ci ugeth_restart_rx(ugeth); 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci ucc_fast_enable(uccf, mode); /* OK to do even if not disabled */ 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci return 0; 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci} 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_cistatic int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode) 15248c2ecf20Sopenharmony_ci{ 15258c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci /* check if the UCC number is in range. */ 15308c2ecf20Sopenharmony_ci if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { 15318c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 15328c2ecf20Sopenharmony_ci pr_err("ucc_num out of range\n"); 15338c2ecf20Sopenharmony_ci return -EINVAL; 15348c2ecf20Sopenharmony_ci } 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci /* Stop any transmissions */ 15378c2ecf20Sopenharmony_ci if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx) 15388c2ecf20Sopenharmony_ci ugeth_graceful_stop_tx(ugeth); 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci /* Stop any receptions */ 15418c2ecf20Sopenharmony_ci if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx) 15428c2ecf20Sopenharmony_ci ugeth_graceful_stop_rx(ugeth); 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */ 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci return 0; 15478c2ecf20Sopenharmony_ci} 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_cistatic void ugeth_quiesce(struct ucc_geth_private *ugeth) 15508c2ecf20Sopenharmony_ci{ 15518c2ecf20Sopenharmony_ci /* Prevent any further xmits */ 15528c2ecf20Sopenharmony_ci netif_tx_stop_all_queues(ugeth->ndev); 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci /* Disable the interrupt to avoid NAPI rescheduling. */ 15558c2ecf20Sopenharmony_ci disable_irq(ugeth->ug_info->uf_info.irq); 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci /* Stop NAPI, and possibly wait for its completion. */ 15588c2ecf20Sopenharmony_ci napi_disable(&ugeth->napi); 15598c2ecf20Sopenharmony_ci} 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_cistatic void ugeth_activate(struct ucc_geth_private *ugeth) 15628c2ecf20Sopenharmony_ci{ 15638c2ecf20Sopenharmony_ci napi_enable(&ugeth->napi); 15648c2ecf20Sopenharmony_ci enable_irq(ugeth->ug_info->uf_info.irq); 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci /* allow to xmit again */ 15678c2ecf20Sopenharmony_ci netif_tx_wake_all_queues(ugeth->ndev); 15688c2ecf20Sopenharmony_ci __netdev_watchdog_up(ugeth->ndev); 15698c2ecf20Sopenharmony_ci} 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci/* Called every time the controller might need to be made 15728c2ecf20Sopenharmony_ci * aware of new link state. The PHY code conveys this 15738c2ecf20Sopenharmony_ci * information through variables in the ugeth structure, and this 15748c2ecf20Sopenharmony_ci * function converts those variables into the appropriate 15758c2ecf20Sopenharmony_ci * register values, and can bring down the device if needed. 15768c2ecf20Sopenharmony_ci */ 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_cistatic void adjust_link(struct net_device *dev) 15798c2ecf20Sopenharmony_ci{ 15808c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 15818c2ecf20Sopenharmony_ci struct ucc_geth __iomem *ug_regs; 15828c2ecf20Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 15838c2ecf20Sopenharmony_ci struct phy_device *phydev = ugeth->phydev; 15848c2ecf20Sopenharmony_ci int new_state = 0; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci ug_regs = ugeth->ug_regs; 15878c2ecf20Sopenharmony_ci uf_regs = ugeth->uccf->uf_regs; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci if (phydev->link) { 15908c2ecf20Sopenharmony_ci u32 tempval = in_be32(&ug_regs->maccfg2); 15918c2ecf20Sopenharmony_ci u32 upsmr = in_be32(&uf_regs->upsmr); 15928c2ecf20Sopenharmony_ci /* Now we make sure that we can be in full duplex mode. 15938c2ecf20Sopenharmony_ci * If not, we operate in half-duplex mode. */ 15948c2ecf20Sopenharmony_ci if (phydev->duplex != ugeth->oldduplex) { 15958c2ecf20Sopenharmony_ci new_state = 1; 15968c2ecf20Sopenharmony_ci if (!(phydev->duplex)) 15978c2ecf20Sopenharmony_ci tempval &= ~(MACCFG2_FDX); 15988c2ecf20Sopenharmony_ci else 15998c2ecf20Sopenharmony_ci tempval |= MACCFG2_FDX; 16008c2ecf20Sopenharmony_ci ugeth->oldduplex = phydev->duplex; 16018c2ecf20Sopenharmony_ci } 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci if (phydev->speed != ugeth->oldspeed) { 16048c2ecf20Sopenharmony_ci new_state = 1; 16058c2ecf20Sopenharmony_ci switch (phydev->speed) { 16068c2ecf20Sopenharmony_ci case SPEED_1000: 16078c2ecf20Sopenharmony_ci tempval = ((tempval & 16088c2ecf20Sopenharmony_ci ~(MACCFG2_INTERFACE_MODE_MASK)) | 16098c2ecf20Sopenharmony_ci MACCFG2_INTERFACE_MODE_BYTE); 16108c2ecf20Sopenharmony_ci break; 16118c2ecf20Sopenharmony_ci case SPEED_100: 16128c2ecf20Sopenharmony_ci case SPEED_10: 16138c2ecf20Sopenharmony_ci tempval = ((tempval & 16148c2ecf20Sopenharmony_ci ~(MACCFG2_INTERFACE_MODE_MASK)) | 16158c2ecf20Sopenharmony_ci MACCFG2_INTERFACE_MODE_NIBBLE); 16168c2ecf20Sopenharmony_ci /* if reduced mode, re-set UPSMR.R10M */ 16178c2ecf20Sopenharmony_ci if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) || 16188c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) || 16198c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) || 16208c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) || 16218c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) || 16228c2ecf20Sopenharmony_ci (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) { 16238c2ecf20Sopenharmony_ci if (phydev->speed == SPEED_10) 16248c2ecf20Sopenharmony_ci upsmr |= UCC_GETH_UPSMR_R10M; 16258c2ecf20Sopenharmony_ci else 16268c2ecf20Sopenharmony_ci upsmr &= ~UCC_GETH_UPSMR_R10M; 16278c2ecf20Sopenharmony_ci } 16288c2ecf20Sopenharmony_ci break; 16298c2ecf20Sopenharmony_ci default: 16308c2ecf20Sopenharmony_ci if (netif_msg_link(ugeth)) 16318c2ecf20Sopenharmony_ci pr_warn( 16328c2ecf20Sopenharmony_ci "%s: Ack! Speed (%d) is not 10/100/1000!", 16338c2ecf20Sopenharmony_ci dev->name, phydev->speed); 16348c2ecf20Sopenharmony_ci break; 16358c2ecf20Sopenharmony_ci } 16368c2ecf20Sopenharmony_ci ugeth->oldspeed = phydev->speed; 16378c2ecf20Sopenharmony_ci } 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci if (!ugeth->oldlink) { 16408c2ecf20Sopenharmony_ci new_state = 1; 16418c2ecf20Sopenharmony_ci ugeth->oldlink = 1; 16428c2ecf20Sopenharmony_ci } 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci if (new_state) { 16458c2ecf20Sopenharmony_ci /* 16468c2ecf20Sopenharmony_ci * To change the MAC configuration we need to disable 16478c2ecf20Sopenharmony_ci * the controller. To do so, we have to either grab 16488c2ecf20Sopenharmony_ci * ugeth->lock, which is a bad idea since 'graceful 16498c2ecf20Sopenharmony_ci * stop' commands might take quite a while, or we can 16508c2ecf20Sopenharmony_ci * quiesce driver's activity. 16518c2ecf20Sopenharmony_ci */ 16528c2ecf20Sopenharmony_ci ugeth_quiesce(ugeth); 16538c2ecf20Sopenharmony_ci ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci out_be32(&ug_regs->maccfg2, tempval); 16568c2ecf20Sopenharmony_ci out_be32(&uf_regs->upsmr, upsmr); 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); 16598c2ecf20Sopenharmony_ci ugeth_activate(ugeth); 16608c2ecf20Sopenharmony_ci } 16618c2ecf20Sopenharmony_ci } else if (ugeth->oldlink) { 16628c2ecf20Sopenharmony_ci new_state = 1; 16638c2ecf20Sopenharmony_ci ugeth->oldlink = 0; 16648c2ecf20Sopenharmony_ci ugeth->oldspeed = 0; 16658c2ecf20Sopenharmony_ci ugeth->oldduplex = -1; 16668c2ecf20Sopenharmony_ci } 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ci if (new_state && netif_msg_link(ugeth)) 16698c2ecf20Sopenharmony_ci phy_print_status(phydev); 16708c2ecf20Sopenharmony_ci} 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci/* Initialize TBI PHY interface for communicating with the 16738c2ecf20Sopenharmony_ci * SERDES lynx PHY on the chip. We communicate with this PHY 16748c2ecf20Sopenharmony_ci * through the MDIO bus on each controller, treating it as a 16758c2ecf20Sopenharmony_ci * "normal" PHY at the address found in the UTBIPA register. We assume 16768c2ecf20Sopenharmony_ci * that the UTBIPA register is valid. Either the MDIO bus code will set 16778c2ecf20Sopenharmony_ci * it to a value that doesn't conflict with other PHYs on the bus, or the 16788c2ecf20Sopenharmony_ci * value doesn't matter, as there are no other PHYs on the bus. 16798c2ecf20Sopenharmony_ci */ 16808c2ecf20Sopenharmony_cistatic void uec_configure_serdes(struct net_device *dev) 16818c2ecf20Sopenharmony_ci{ 16828c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 16838c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info = ugeth->ug_info; 16848c2ecf20Sopenharmony_ci struct phy_device *tbiphy; 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci if (!ug_info->tbi_node) { 16878c2ecf20Sopenharmony_ci dev_warn(&dev->dev, "SGMII mode requires that the device " 16888c2ecf20Sopenharmony_ci "tree specify a tbi-handle\n"); 16898c2ecf20Sopenharmony_ci return; 16908c2ecf20Sopenharmony_ci } 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_ci tbiphy = of_phy_find_device(ug_info->tbi_node); 16938c2ecf20Sopenharmony_ci if (!tbiphy) { 16948c2ecf20Sopenharmony_ci dev_err(&dev->dev, "error: Could not get TBI device\n"); 16958c2ecf20Sopenharmony_ci return; 16968c2ecf20Sopenharmony_ci } 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci /* 16998c2ecf20Sopenharmony_ci * If the link is already up, we must already be ok, and don't need to 17008c2ecf20Sopenharmony_ci * configure and reset the TBI<->SerDes link. Maybe U-Boot configured 17018c2ecf20Sopenharmony_ci * everything for us? Resetting it takes the link down and requires 17028c2ecf20Sopenharmony_ci * several seconds for it to come back. 17038c2ecf20Sopenharmony_ci */ 17048c2ecf20Sopenharmony_ci if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) { 17058c2ecf20Sopenharmony_ci put_device(&tbiphy->mdio.dev); 17068c2ecf20Sopenharmony_ci return; 17078c2ecf20Sopenharmony_ci } 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci /* Single clk mode, mii mode off(for serdes communication) */ 17108c2ecf20Sopenharmony_ci phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS); 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT); 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS); 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci put_device(&tbiphy->mdio.dev); 17178c2ecf20Sopenharmony_ci} 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci/* Configure the PHY for dev. 17208c2ecf20Sopenharmony_ci * returns 0 if success. -1 if failure 17218c2ecf20Sopenharmony_ci */ 17228c2ecf20Sopenharmony_cistatic int init_phy(struct net_device *dev) 17238c2ecf20Sopenharmony_ci{ 17248c2ecf20Sopenharmony_ci struct ucc_geth_private *priv = netdev_priv(dev); 17258c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info = priv->ug_info; 17268c2ecf20Sopenharmony_ci struct phy_device *phydev; 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci priv->oldlink = 0; 17298c2ecf20Sopenharmony_ci priv->oldspeed = 0; 17308c2ecf20Sopenharmony_ci priv->oldduplex = -1; 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0, 17338c2ecf20Sopenharmony_ci priv->phy_interface); 17348c2ecf20Sopenharmony_ci if (!phydev) { 17358c2ecf20Sopenharmony_ci dev_err(&dev->dev, "Could not attach to PHY\n"); 17368c2ecf20Sopenharmony_ci return -ENODEV; 17378c2ecf20Sopenharmony_ci } 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII) 17408c2ecf20Sopenharmony_ci uec_configure_serdes(dev); 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ci phy_set_max_speed(phydev, priv->max_speed); 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci priv->phydev = phydev; 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci return 0; 17478c2ecf20Sopenharmony_ci} 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_cistatic void ugeth_dump_regs(struct ucc_geth_private *ugeth) 17508c2ecf20Sopenharmony_ci{ 17518c2ecf20Sopenharmony_ci#ifdef DEBUG 17528c2ecf20Sopenharmony_ci ucc_fast_dump_regs(ugeth->uccf); 17538c2ecf20Sopenharmony_ci dump_regs(ugeth); 17548c2ecf20Sopenharmony_ci dump_bds(ugeth); 17558c2ecf20Sopenharmony_ci#endif 17568c2ecf20Sopenharmony_ci} 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_cistatic int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private * 17598c2ecf20Sopenharmony_ci ugeth, 17608c2ecf20Sopenharmony_ci enum enet_addr_type 17618c2ecf20Sopenharmony_ci enet_addr_type) 17628c2ecf20Sopenharmony_ci{ 17638c2ecf20Sopenharmony_ci struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; 17648c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 17658c2ecf20Sopenharmony_ci enum comm_dir comm_dir; 17668c2ecf20Sopenharmony_ci struct list_head *p_lh; 17678c2ecf20Sopenharmony_ci u16 i, num; 17688c2ecf20Sopenharmony_ci u32 __iomem *addr_h; 17698c2ecf20Sopenharmony_ci u32 __iomem *addr_l; 17708c2ecf20Sopenharmony_ci u8 *p_counter; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci p_82xx_addr_filt = 17758c2ecf20Sopenharmony_ci (struct ucc_geth_82xx_address_filtering_pram __iomem *) 17768c2ecf20Sopenharmony_ci ugeth->p_rx_glbl_pram->addressfiltering; 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci if (enet_addr_type == ENET_ADDR_TYPE_GROUP) { 17798c2ecf20Sopenharmony_ci addr_h = &(p_82xx_addr_filt->gaddr_h); 17808c2ecf20Sopenharmony_ci addr_l = &(p_82xx_addr_filt->gaddr_l); 17818c2ecf20Sopenharmony_ci p_lh = &ugeth->group_hash_q; 17828c2ecf20Sopenharmony_ci p_counter = &(ugeth->numGroupAddrInHash); 17838c2ecf20Sopenharmony_ci } else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) { 17848c2ecf20Sopenharmony_ci addr_h = &(p_82xx_addr_filt->iaddr_h); 17858c2ecf20Sopenharmony_ci addr_l = &(p_82xx_addr_filt->iaddr_l); 17868c2ecf20Sopenharmony_ci p_lh = &ugeth->ind_hash_q; 17878c2ecf20Sopenharmony_ci p_counter = &(ugeth->numIndAddrInHash); 17888c2ecf20Sopenharmony_ci } else 17898c2ecf20Sopenharmony_ci return -EINVAL; 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_ci comm_dir = 0; 17928c2ecf20Sopenharmony_ci if (uccf->enabled_tx) 17938c2ecf20Sopenharmony_ci comm_dir |= COMM_DIR_TX; 17948c2ecf20Sopenharmony_ci if (uccf->enabled_rx) 17958c2ecf20Sopenharmony_ci comm_dir |= COMM_DIR_RX; 17968c2ecf20Sopenharmony_ci if (comm_dir) 17978c2ecf20Sopenharmony_ci ugeth_disable(ugeth, comm_dir); 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci /* Clear the hash table. */ 18008c2ecf20Sopenharmony_ci out_be32(addr_h, 0x00000000); 18018c2ecf20Sopenharmony_ci out_be32(addr_l, 0x00000000); 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci if (!p_lh) 18048c2ecf20Sopenharmony_ci return 0; 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci num = *p_counter; 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci /* Delete all remaining CQ elements */ 18098c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) 18108c2ecf20Sopenharmony_ci put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh))); 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci *p_counter = 0; 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_ci if (comm_dir) 18158c2ecf20Sopenharmony_ci ugeth_enable(ugeth, comm_dir); 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci return 0; 18188c2ecf20Sopenharmony_ci} 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_cistatic int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth, 18218c2ecf20Sopenharmony_ci u8 paddr_num) 18228c2ecf20Sopenharmony_ci{ 18238c2ecf20Sopenharmony_ci ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */ 18248c2ecf20Sopenharmony_ci return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */ 18258c2ecf20Sopenharmony_ci} 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_cistatic void ucc_geth_free_rx(struct ucc_geth_private *ugeth) 18288c2ecf20Sopenharmony_ci{ 18298c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 18308c2ecf20Sopenharmony_ci struct ucc_fast_info *uf_info; 18318c2ecf20Sopenharmony_ci u16 i, j; 18328c2ecf20Sopenharmony_ci u8 __iomem *bd; 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci ug_info = ugeth->ug_info; 18368c2ecf20Sopenharmony_ci uf_info = &ug_info->uf_info; 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { 18398c2ecf20Sopenharmony_ci if (ugeth->p_rx_bd_ring[i]) { 18408c2ecf20Sopenharmony_ci /* Return existing data buffers in ring */ 18418c2ecf20Sopenharmony_ci bd = ugeth->p_rx_bd_ring[i]; 18428c2ecf20Sopenharmony_ci for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) { 18438c2ecf20Sopenharmony_ci if (ugeth->rx_skbuff[i][j]) { 18448c2ecf20Sopenharmony_ci dma_unmap_single(ugeth->dev, 18458c2ecf20Sopenharmony_ci in_be32(&((struct qe_bd __iomem *)bd)->buf), 18468c2ecf20Sopenharmony_ci ugeth->ug_info-> 18478c2ecf20Sopenharmony_ci uf_info.max_rx_buf_length + 18488c2ecf20Sopenharmony_ci UCC_GETH_RX_DATA_BUF_ALIGNMENT, 18498c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 18508c2ecf20Sopenharmony_ci dev_kfree_skb_any( 18518c2ecf20Sopenharmony_ci ugeth->rx_skbuff[i][j]); 18528c2ecf20Sopenharmony_ci ugeth->rx_skbuff[i][j] = NULL; 18538c2ecf20Sopenharmony_ci } 18548c2ecf20Sopenharmony_ci bd += sizeof(struct qe_bd); 18558c2ecf20Sopenharmony_ci } 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci kfree(ugeth->rx_skbuff[i]); 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci if (ugeth->ug_info->uf_info.bd_mem_part == 18608c2ecf20Sopenharmony_ci MEM_PART_SYSTEM) 18618c2ecf20Sopenharmony_ci kfree((void *)ugeth->rx_bd_ring_offset[i]); 18628c2ecf20Sopenharmony_ci else if (ugeth->ug_info->uf_info.bd_mem_part == 18638c2ecf20Sopenharmony_ci MEM_PART_MURAM) 18648c2ecf20Sopenharmony_ci qe_muram_free(ugeth->rx_bd_ring_offset[i]); 18658c2ecf20Sopenharmony_ci ugeth->p_rx_bd_ring[i] = NULL; 18668c2ecf20Sopenharmony_ci } 18678c2ecf20Sopenharmony_ci } 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci} 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_cistatic void ucc_geth_free_tx(struct ucc_geth_private *ugeth) 18728c2ecf20Sopenharmony_ci{ 18738c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 18748c2ecf20Sopenharmony_ci struct ucc_fast_info *uf_info; 18758c2ecf20Sopenharmony_ci u16 i, j; 18768c2ecf20Sopenharmony_ci u8 __iomem *bd; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci netdev_reset_queue(ugeth->ndev); 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci ug_info = ugeth->ug_info; 18818c2ecf20Sopenharmony_ci uf_info = &ug_info->uf_info; 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { 18848c2ecf20Sopenharmony_ci bd = ugeth->p_tx_bd_ring[i]; 18858c2ecf20Sopenharmony_ci if (!bd) 18868c2ecf20Sopenharmony_ci continue; 18878c2ecf20Sopenharmony_ci for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { 18888c2ecf20Sopenharmony_ci if (ugeth->tx_skbuff[i][j]) { 18898c2ecf20Sopenharmony_ci dma_unmap_single(ugeth->dev, 18908c2ecf20Sopenharmony_ci in_be32(&((struct qe_bd __iomem *)bd)->buf), 18918c2ecf20Sopenharmony_ci (in_be32((u32 __iomem *)bd) & 18928c2ecf20Sopenharmony_ci BD_LENGTH_MASK), 18938c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 18948c2ecf20Sopenharmony_ci dev_kfree_skb_any(ugeth->tx_skbuff[i][j]); 18958c2ecf20Sopenharmony_ci ugeth->tx_skbuff[i][j] = NULL; 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci } 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci kfree(ugeth->tx_skbuff[i]); 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ci if (ugeth->p_tx_bd_ring[i]) { 19028c2ecf20Sopenharmony_ci if (ugeth->ug_info->uf_info.bd_mem_part == 19038c2ecf20Sopenharmony_ci MEM_PART_SYSTEM) 19048c2ecf20Sopenharmony_ci kfree((void *)ugeth->tx_bd_ring_offset[i]); 19058c2ecf20Sopenharmony_ci else if (ugeth->ug_info->uf_info.bd_mem_part == 19068c2ecf20Sopenharmony_ci MEM_PART_MURAM) 19078c2ecf20Sopenharmony_ci qe_muram_free(ugeth->tx_bd_ring_offset[i]); 19088c2ecf20Sopenharmony_ci ugeth->p_tx_bd_ring[i] = NULL; 19098c2ecf20Sopenharmony_ci } 19108c2ecf20Sopenharmony_ci } 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci} 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_cistatic void ucc_geth_memclean(struct ucc_geth_private *ugeth) 19158c2ecf20Sopenharmony_ci{ 19168c2ecf20Sopenharmony_ci if (!ugeth) 19178c2ecf20Sopenharmony_ci return; 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_ci if (ugeth->uccf) { 19208c2ecf20Sopenharmony_ci ucc_fast_free(ugeth->uccf); 19218c2ecf20Sopenharmony_ci ugeth->uccf = NULL; 19228c2ecf20Sopenharmony_ci } 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci if (ugeth->p_thread_data_tx) { 19258c2ecf20Sopenharmony_ci qe_muram_free(ugeth->thread_dat_tx_offset); 19268c2ecf20Sopenharmony_ci ugeth->p_thread_data_tx = NULL; 19278c2ecf20Sopenharmony_ci } 19288c2ecf20Sopenharmony_ci if (ugeth->p_thread_data_rx) { 19298c2ecf20Sopenharmony_ci qe_muram_free(ugeth->thread_dat_rx_offset); 19308c2ecf20Sopenharmony_ci ugeth->p_thread_data_rx = NULL; 19318c2ecf20Sopenharmony_ci } 19328c2ecf20Sopenharmony_ci if (ugeth->p_exf_glbl_param) { 19338c2ecf20Sopenharmony_ci qe_muram_free(ugeth->exf_glbl_param_offset); 19348c2ecf20Sopenharmony_ci ugeth->p_exf_glbl_param = NULL; 19358c2ecf20Sopenharmony_ci } 19368c2ecf20Sopenharmony_ci if (ugeth->p_rx_glbl_pram) { 19378c2ecf20Sopenharmony_ci qe_muram_free(ugeth->rx_glbl_pram_offset); 19388c2ecf20Sopenharmony_ci ugeth->p_rx_glbl_pram = NULL; 19398c2ecf20Sopenharmony_ci } 19408c2ecf20Sopenharmony_ci if (ugeth->p_tx_glbl_pram) { 19418c2ecf20Sopenharmony_ci qe_muram_free(ugeth->tx_glbl_pram_offset); 19428c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram = NULL; 19438c2ecf20Sopenharmony_ci } 19448c2ecf20Sopenharmony_ci if (ugeth->p_send_q_mem_reg) { 19458c2ecf20Sopenharmony_ci qe_muram_free(ugeth->send_q_mem_reg_offset); 19468c2ecf20Sopenharmony_ci ugeth->p_send_q_mem_reg = NULL; 19478c2ecf20Sopenharmony_ci } 19488c2ecf20Sopenharmony_ci if (ugeth->p_scheduler) { 19498c2ecf20Sopenharmony_ci qe_muram_free(ugeth->scheduler_offset); 19508c2ecf20Sopenharmony_ci ugeth->p_scheduler = NULL; 19518c2ecf20Sopenharmony_ci } 19528c2ecf20Sopenharmony_ci if (ugeth->p_tx_fw_statistics_pram) { 19538c2ecf20Sopenharmony_ci qe_muram_free(ugeth->tx_fw_statistics_pram_offset); 19548c2ecf20Sopenharmony_ci ugeth->p_tx_fw_statistics_pram = NULL; 19558c2ecf20Sopenharmony_ci } 19568c2ecf20Sopenharmony_ci if (ugeth->p_rx_fw_statistics_pram) { 19578c2ecf20Sopenharmony_ci qe_muram_free(ugeth->rx_fw_statistics_pram_offset); 19588c2ecf20Sopenharmony_ci ugeth->p_rx_fw_statistics_pram = NULL; 19598c2ecf20Sopenharmony_ci } 19608c2ecf20Sopenharmony_ci if (ugeth->p_rx_irq_coalescing_tbl) { 19618c2ecf20Sopenharmony_ci qe_muram_free(ugeth->rx_irq_coalescing_tbl_offset); 19628c2ecf20Sopenharmony_ci ugeth->p_rx_irq_coalescing_tbl = NULL; 19638c2ecf20Sopenharmony_ci } 19648c2ecf20Sopenharmony_ci if (ugeth->p_rx_bd_qs_tbl) { 19658c2ecf20Sopenharmony_ci qe_muram_free(ugeth->rx_bd_qs_tbl_offset); 19668c2ecf20Sopenharmony_ci ugeth->p_rx_bd_qs_tbl = NULL; 19678c2ecf20Sopenharmony_ci } 19688c2ecf20Sopenharmony_ci if (ugeth->p_init_enet_param_shadow) { 19698c2ecf20Sopenharmony_ci return_init_enet_entries(ugeth, 19708c2ecf20Sopenharmony_ci &(ugeth->p_init_enet_param_shadow-> 19718c2ecf20Sopenharmony_ci rxthread[0]), 19728c2ecf20Sopenharmony_ci ENET_INIT_PARAM_MAX_ENTRIES_RX, 19738c2ecf20Sopenharmony_ci ugeth->ug_info->riscRx, 1); 19748c2ecf20Sopenharmony_ci return_init_enet_entries(ugeth, 19758c2ecf20Sopenharmony_ci &(ugeth->p_init_enet_param_shadow-> 19768c2ecf20Sopenharmony_ci txthread[0]), 19778c2ecf20Sopenharmony_ci ENET_INIT_PARAM_MAX_ENTRIES_TX, 19788c2ecf20Sopenharmony_ci ugeth->ug_info->riscTx, 0); 19798c2ecf20Sopenharmony_ci kfree(ugeth->p_init_enet_param_shadow); 19808c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow = NULL; 19818c2ecf20Sopenharmony_ci } 19828c2ecf20Sopenharmony_ci ucc_geth_free_tx(ugeth); 19838c2ecf20Sopenharmony_ci ucc_geth_free_rx(ugeth); 19848c2ecf20Sopenharmony_ci while (!list_empty(&ugeth->group_hash_q)) 19858c2ecf20Sopenharmony_ci put_enet_addr_container(ENET_ADDR_CONT_ENTRY 19868c2ecf20Sopenharmony_ci (dequeue(&ugeth->group_hash_q))); 19878c2ecf20Sopenharmony_ci while (!list_empty(&ugeth->ind_hash_q)) 19888c2ecf20Sopenharmony_ci put_enet_addr_container(ENET_ADDR_CONT_ENTRY 19898c2ecf20Sopenharmony_ci (dequeue(&ugeth->ind_hash_q))); 19908c2ecf20Sopenharmony_ci if (ugeth->ug_regs) { 19918c2ecf20Sopenharmony_ci iounmap(ugeth->ug_regs); 19928c2ecf20Sopenharmony_ci ugeth->ug_regs = NULL; 19938c2ecf20Sopenharmony_ci } 19948c2ecf20Sopenharmony_ci} 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_cistatic void ucc_geth_set_multi(struct net_device *dev) 19978c2ecf20Sopenharmony_ci{ 19988c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth; 19998c2ecf20Sopenharmony_ci struct netdev_hw_addr *ha; 20008c2ecf20Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 20018c2ecf20Sopenharmony_ci struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci ugeth = netdev_priv(dev); 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci uf_regs = ugeth->uccf->uf_regs; 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci if (dev->flags & IFF_PROMISC) { 20088c2ecf20Sopenharmony_ci setbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO); 20098c2ecf20Sopenharmony_ci } else { 20108c2ecf20Sopenharmony_ci clrbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO); 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci p_82xx_addr_filt = 20138c2ecf20Sopenharmony_ci (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth-> 20148c2ecf20Sopenharmony_ci p_rx_glbl_pram->addressfiltering; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci if (dev->flags & IFF_ALLMULTI) { 20178c2ecf20Sopenharmony_ci /* Catch all multicast addresses, so set the 20188c2ecf20Sopenharmony_ci * filter to all 1's. 20198c2ecf20Sopenharmony_ci */ 20208c2ecf20Sopenharmony_ci out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff); 20218c2ecf20Sopenharmony_ci out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff); 20228c2ecf20Sopenharmony_ci } else { 20238c2ecf20Sopenharmony_ci /* Clear filter and add the addresses in the list. 20248c2ecf20Sopenharmony_ci */ 20258c2ecf20Sopenharmony_ci out_be32(&p_82xx_addr_filt->gaddr_h, 0x0); 20268c2ecf20Sopenharmony_ci out_be32(&p_82xx_addr_filt->gaddr_l, 0x0); 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci netdev_for_each_mc_addr(ha, dev) { 20298c2ecf20Sopenharmony_ci /* Ask CPM to run CRC and set bit in 20308c2ecf20Sopenharmony_ci * filter mask. 20318c2ecf20Sopenharmony_ci */ 20328c2ecf20Sopenharmony_ci hw_add_addr_in_hash(ugeth, ha->addr); 20338c2ecf20Sopenharmony_ci } 20348c2ecf20Sopenharmony_ci } 20358c2ecf20Sopenharmony_ci } 20368c2ecf20Sopenharmony_ci} 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_cistatic void ucc_geth_stop(struct ucc_geth_private *ugeth) 20398c2ecf20Sopenharmony_ci{ 20408c2ecf20Sopenharmony_ci struct ucc_geth __iomem *ug_regs = ugeth->ug_regs; 20418c2ecf20Sopenharmony_ci struct phy_device *phydev = ugeth->phydev; 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci /* 20468c2ecf20Sopenharmony_ci * Tell the kernel the link is down. 20478c2ecf20Sopenharmony_ci * Must be done before disabling the controller 20488c2ecf20Sopenharmony_ci * or deadlock may happen. 20498c2ecf20Sopenharmony_ci */ 20508c2ecf20Sopenharmony_ci phy_stop(phydev); 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci /* Disable the controller */ 20538c2ecf20Sopenharmony_ci ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ci /* Mask all interrupts */ 20568c2ecf20Sopenharmony_ci out_be32(ugeth->uccf->p_uccm, 0x00000000); 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_ci /* Clear all interrupts */ 20598c2ecf20Sopenharmony_ci out_be32(ugeth->uccf->p_ucce, 0xffffffff); 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_ci /* Disable Rx and Tx */ 20628c2ecf20Sopenharmony_ci clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); 20638c2ecf20Sopenharmony_ci 20648c2ecf20Sopenharmony_ci ucc_geth_memclean(ugeth); 20658c2ecf20Sopenharmony_ci} 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_cistatic int ucc_struct_init(struct ucc_geth_private *ugeth) 20688c2ecf20Sopenharmony_ci{ 20698c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 20708c2ecf20Sopenharmony_ci struct ucc_fast_info *uf_info; 20718c2ecf20Sopenharmony_ci int i; 20728c2ecf20Sopenharmony_ci 20738c2ecf20Sopenharmony_ci ug_info = ugeth->ug_info; 20748c2ecf20Sopenharmony_ci uf_info = &ug_info->uf_info; 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_ci if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || 20778c2ecf20Sopenharmony_ci (uf_info->bd_mem_part == MEM_PART_MURAM))) { 20788c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 20798c2ecf20Sopenharmony_ci pr_err("Bad memory partition value\n"); 20808c2ecf20Sopenharmony_ci return -EINVAL; 20818c2ecf20Sopenharmony_ci } 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci /* Rx BD lengths */ 20848c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesRx; i++) { 20858c2ecf20Sopenharmony_ci if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) || 20868c2ecf20Sopenharmony_ci (ug_info->bdRingLenRx[i] % 20878c2ecf20Sopenharmony_ci UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) { 20888c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 20898c2ecf20Sopenharmony_ci pr_err("Rx BD ring length must be multiple of 4, no smaller than 8\n"); 20908c2ecf20Sopenharmony_ci return -EINVAL; 20918c2ecf20Sopenharmony_ci } 20928c2ecf20Sopenharmony_ci } 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci /* Tx BD lengths */ 20958c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesTx; i++) { 20968c2ecf20Sopenharmony_ci if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) { 20978c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 20988c2ecf20Sopenharmony_ci pr_err("Tx BD ring length must be no smaller than 2\n"); 20998c2ecf20Sopenharmony_ci return -EINVAL; 21008c2ecf20Sopenharmony_ci } 21018c2ecf20Sopenharmony_ci } 21028c2ecf20Sopenharmony_ci 21038c2ecf20Sopenharmony_ci /* mrblr */ 21048c2ecf20Sopenharmony_ci if ((uf_info->max_rx_buf_length == 0) || 21058c2ecf20Sopenharmony_ci (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) { 21068c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 21078c2ecf20Sopenharmony_ci pr_err("max_rx_buf_length must be non-zero multiple of 128\n"); 21088c2ecf20Sopenharmony_ci return -EINVAL; 21098c2ecf20Sopenharmony_ci } 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci /* num Tx queues */ 21128c2ecf20Sopenharmony_ci if (ug_info->numQueuesTx > NUM_TX_QUEUES) { 21138c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 21148c2ecf20Sopenharmony_ci pr_err("number of tx queues too large\n"); 21158c2ecf20Sopenharmony_ci return -EINVAL; 21168c2ecf20Sopenharmony_ci } 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci /* num Rx queues */ 21198c2ecf20Sopenharmony_ci if (ug_info->numQueuesRx > NUM_RX_QUEUES) { 21208c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 21218c2ecf20Sopenharmony_ci pr_err("number of rx queues too large\n"); 21228c2ecf20Sopenharmony_ci return -EINVAL; 21238c2ecf20Sopenharmony_ci } 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci /* l2qt */ 21268c2ecf20Sopenharmony_ci for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) { 21278c2ecf20Sopenharmony_ci if (ug_info->l2qt[i] >= ug_info->numQueuesRx) { 21288c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 21298c2ecf20Sopenharmony_ci pr_err("VLAN priority table entry must not be larger than number of Rx queues\n"); 21308c2ecf20Sopenharmony_ci return -EINVAL; 21318c2ecf20Sopenharmony_ci } 21328c2ecf20Sopenharmony_ci } 21338c2ecf20Sopenharmony_ci 21348c2ecf20Sopenharmony_ci /* l3qt */ 21358c2ecf20Sopenharmony_ci for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) { 21368c2ecf20Sopenharmony_ci if (ug_info->l3qt[i] >= ug_info->numQueuesRx) { 21378c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 21388c2ecf20Sopenharmony_ci pr_err("IP priority table entry must not be larger than number of Rx queues\n"); 21398c2ecf20Sopenharmony_ci return -EINVAL; 21408c2ecf20Sopenharmony_ci } 21418c2ecf20Sopenharmony_ci } 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci if (ug_info->cam && !ug_info->ecamptr) { 21448c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 21458c2ecf20Sopenharmony_ci pr_err("If cam mode is chosen, must supply cam ptr\n"); 21468c2ecf20Sopenharmony_ci return -EINVAL; 21478c2ecf20Sopenharmony_ci } 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci if ((ug_info->numStationAddresses != 21508c2ecf20Sopenharmony_ci UCC_GETH_NUM_OF_STATION_ADDRESSES_1) && 21518c2ecf20Sopenharmony_ci ug_info->rxExtendedFiltering) { 21528c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 21538c2ecf20Sopenharmony_ci pr_err("Number of station addresses greater than 1 not allowed in extended parsing mode\n"); 21548c2ecf20Sopenharmony_ci return -EINVAL; 21558c2ecf20Sopenharmony_ci } 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci /* Generate uccm_mask for receive */ 21588c2ecf20Sopenharmony_ci uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */ 21598c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesRx; i++) 21608c2ecf20Sopenharmony_ci uf_info->uccm_mask |= (UCC_GETH_UCCE_RXF0 << i); 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesTx; i++) 21638c2ecf20Sopenharmony_ci uf_info->uccm_mask |= (UCC_GETH_UCCE_TXB0 << i); 21648c2ecf20Sopenharmony_ci /* Initialize the general fast UCC block. */ 21658c2ecf20Sopenharmony_ci if (ucc_fast_init(uf_info, &ugeth->uccf)) { 21668c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 21678c2ecf20Sopenharmony_ci pr_err("Failed to init uccf\n"); 21688c2ecf20Sopenharmony_ci return -ENOMEM; 21698c2ecf20Sopenharmony_ci } 21708c2ecf20Sopenharmony_ci 21718c2ecf20Sopenharmony_ci /* read the number of risc engines, update the riscTx and riscRx 21728c2ecf20Sopenharmony_ci * if there are 4 riscs in QE 21738c2ecf20Sopenharmony_ci */ 21748c2ecf20Sopenharmony_ci if (qe_get_num_of_risc() == 4) { 21758c2ecf20Sopenharmony_ci ug_info->riscTx = QE_RISC_ALLOCATION_FOUR_RISCS; 21768c2ecf20Sopenharmony_ci ug_info->riscRx = QE_RISC_ALLOCATION_FOUR_RISCS; 21778c2ecf20Sopenharmony_ci } 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs)); 21808c2ecf20Sopenharmony_ci if (!ugeth->ug_regs) { 21818c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 21828c2ecf20Sopenharmony_ci pr_err("Failed to ioremap regs\n"); 21838c2ecf20Sopenharmony_ci return -ENOMEM; 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci return 0; 21878c2ecf20Sopenharmony_ci} 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_cistatic int ucc_geth_alloc_tx(struct ucc_geth_private *ugeth) 21908c2ecf20Sopenharmony_ci{ 21918c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 21928c2ecf20Sopenharmony_ci struct ucc_fast_info *uf_info; 21938c2ecf20Sopenharmony_ci int length; 21948c2ecf20Sopenharmony_ci u16 i, j; 21958c2ecf20Sopenharmony_ci u8 __iomem *bd; 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci ug_info = ugeth->ug_info; 21988c2ecf20Sopenharmony_ci uf_info = &ug_info->uf_info; 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_ci /* Allocate Tx bds */ 22018c2ecf20Sopenharmony_ci for (j = 0; j < ug_info->numQueuesTx; j++) { 22028c2ecf20Sopenharmony_ci /* Allocate in multiple of 22038c2ecf20Sopenharmony_ci UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT, 22048c2ecf20Sopenharmony_ci according to spec */ 22058c2ecf20Sopenharmony_ci length = ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)) 22068c2ecf20Sopenharmony_ci / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) 22078c2ecf20Sopenharmony_ci * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; 22088c2ecf20Sopenharmony_ci if ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)) % 22098c2ecf20Sopenharmony_ci UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) 22108c2ecf20Sopenharmony_ci length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; 22118c2ecf20Sopenharmony_ci if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { 22128c2ecf20Sopenharmony_ci u32 align = 4; 22138c2ecf20Sopenharmony_ci if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4) 22148c2ecf20Sopenharmony_ci align = UCC_GETH_TX_BD_RING_ALIGNMENT; 22158c2ecf20Sopenharmony_ci ugeth->tx_bd_ring_offset[j] = 22168c2ecf20Sopenharmony_ci (u32) kmalloc((u32) (length + align), GFP_KERNEL); 22178c2ecf20Sopenharmony_ci 22188c2ecf20Sopenharmony_ci if (ugeth->tx_bd_ring_offset[j] != 0) 22198c2ecf20Sopenharmony_ci ugeth->p_tx_bd_ring[j] = 22208c2ecf20Sopenharmony_ci (u8 __iomem *)((ugeth->tx_bd_ring_offset[j] + 22218c2ecf20Sopenharmony_ci align) & ~(align - 1)); 22228c2ecf20Sopenharmony_ci } else if (uf_info->bd_mem_part == MEM_PART_MURAM) { 22238c2ecf20Sopenharmony_ci ugeth->tx_bd_ring_offset[j] = 22248c2ecf20Sopenharmony_ci qe_muram_alloc(length, 22258c2ecf20Sopenharmony_ci UCC_GETH_TX_BD_RING_ALIGNMENT); 22268c2ecf20Sopenharmony_ci if (!IS_ERR_VALUE(ugeth->tx_bd_ring_offset[j])) 22278c2ecf20Sopenharmony_ci ugeth->p_tx_bd_ring[j] = 22288c2ecf20Sopenharmony_ci (u8 __iomem *) qe_muram_addr(ugeth-> 22298c2ecf20Sopenharmony_ci tx_bd_ring_offset[j]); 22308c2ecf20Sopenharmony_ci } 22318c2ecf20Sopenharmony_ci if (!ugeth->p_tx_bd_ring[j]) { 22328c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 22338c2ecf20Sopenharmony_ci pr_err("Can not allocate memory for Tx bd rings\n"); 22348c2ecf20Sopenharmony_ci return -ENOMEM; 22358c2ecf20Sopenharmony_ci } 22368c2ecf20Sopenharmony_ci /* Zero unused end of bd ring, according to spec */ 22378c2ecf20Sopenharmony_ci memset_io((void __iomem *)(ugeth->p_tx_bd_ring[j] + 22388c2ecf20Sopenharmony_ci ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)), 0, 22398c2ecf20Sopenharmony_ci length - ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)); 22408c2ecf20Sopenharmony_ci } 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ci /* Init Tx bds */ 22438c2ecf20Sopenharmony_ci for (j = 0; j < ug_info->numQueuesTx; j++) { 22448c2ecf20Sopenharmony_ci /* Setup the skbuff rings */ 22458c2ecf20Sopenharmony_ci ugeth->tx_skbuff[j] = 22468c2ecf20Sopenharmony_ci kmalloc_array(ugeth->ug_info->bdRingLenTx[j], 22478c2ecf20Sopenharmony_ci sizeof(struct sk_buff *), GFP_KERNEL); 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_ci if (ugeth->tx_skbuff[j] == NULL) { 22508c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 22518c2ecf20Sopenharmony_ci pr_err("Could not allocate tx_skbuff\n"); 22528c2ecf20Sopenharmony_ci return -ENOMEM; 22538c2ecf20Sopenharmony_ci } 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_ci for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++) 22568c2ecf20Sopenharmony_ci ugeth->tx_skbuff[j][i] = NULL; 22578c2ecf20Sopenharmony_ci 22588c2ecf20Sopenharmony_ci ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0; 22598c2ecf20Sopenharmony_ci bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j]; 22608c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->bdRingLenTx[j]; i++) { 22618c2ecf20Sopenharmony_ci /* clear bd buffer */ 22628c2ecf20Sopenharmony_ci out_be32(&((struct qe_bd __iomem *)bd)->buf, 0); 22638c2ecf20Sopenharmony_ci /* set bd status and length */ 22648c2ecf20Sopenharmony_ci out_be32((u32 __iomem *)bd, 0); 22658c2ecf20Sopenharmony_ci bd += sizeof(struct qe_bd); 22668c2ecf20Sopenharmony_ci } 22678c2ecf20Sopenharmony_ci bd -= sizeof(struct qe_bd); 22688c2ecf20Sopenharmony_ci /* set bd status and length */ 22698c2ecf20Sopenharmony_ci out_be32((u32 __iomem *)bd, T_W); /* for last BD set Wrap bit */ 22708c2ecf20Sopenharmony_ci } 22718c2ecf20Sopenharmony_ci 22728c2ecf20Sopenharmony_ci return 0; 22738c2ecf20Sopenharmony_ci} 22748c2ecf20Sopenharmony_ci 22758c2ecf20Sopenharmony_cistatic int ucc_geth_alloc_rx(struct ucc_geth_private *ugeth) 22768c2ecf20Sopenharmony_ci{ 22778c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 22788c2ecf20Sopenharmony_ci struct ucc_fast_info *uf_info; 22798c2ecf20Sopenharmony_ci int length; 22808c2ecf20Sopenharmony_ci u16 i, j; 22818c2ecf20Sopenharmony_ci u8 __iomem *bd; 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_ci ug_info = ugeth->ug_info; 22848c2ecf20Sopenharmony_ci uf_info = &ug_info->uf_info; 22858c2ecf20Sopenharmony_ci 22868c2ecf20Sopenharmony_ci /* Allocate Rx bds */ 22878c2ecf20Sopenharmony_ci for (j = 0; j < ug_info->numQueuesRx; j++) { 22888c2ecf20Sopenharmony_ci length = ug_info->bdRingLenRx[j] * sizeof(struct qe_bd); 22898c2ecf20Sopenharmony_ci if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { 22908c2ecf20Sopenharmony_ci u32 align = 4; 22918c2ecf20Sopenharmony_ci if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4) 22928c2ecf20Sopenharmony_ci align = UCC_GETH_RX_BD_RING_ALIGNMENT; 22938c2ecf20Sopenharmony_ci ugeth->rx_bd_ring_offset[j] = 22948c2ecf20Sopenharmony_ci (u32) kmalloc((u32) (length + align), GFP_KERNEL); 22958c2ecf20Sopenharmony_ci if (ugeth->rx_bd_ring_offset[j] != 0) 22968c2ecf20Sopenharmony_ci ugeth->p_rx_bd_ring[j] = 22978c2ecf20Sopenharmony_ci (u8 __iomem *)((ugeth->rx_bd_ring_offset[j] + 22988c2ecf20Sopenharmony_ci align) & ~(align - 1)); 22998c2ecf20Sopenharmony_ci } else if (uf_info->bd_mem_part == MEM_PART_MURAM) { 23008c2ecf20Sopenharmony_ci ugeth->rx_bd_ring_offset[j] = 23018c2ecf20Sopenharmony_ci qe_muram_alloc(length, 23028c2ecf20Sopenharmony_ci UCC_GETH_RX_BD_RING_ALIGNMENT); 23038c2ecf20Sopenharmony_ci if (!IS_ERR_VALUE(ugeth->rx_bd_ring_offset[j])) 23048c2ecf20Sopenharmony_ci ugeth->p_rx_bd_ring[j] = 23058c2ecf20Sopenharmony_ci (u8 __iomem *) qe_muram_addr(ugeth-> 23068c2ecf20Sopenharmony_ci rx_bd_ring_offset[j]); 23078c2ecf20Sopenharmony_ci } 23088c2ecf20Sopenharmony_ci if (!ugeth->p_rx_bd_ring[j]) { 23098c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 23108c2ecf20Sopenharmony_ci pr_err("Can not allocate memory for Rx bd rings\n"); 23118c2ecf20Sopenharmony_ci return -ENOMEM; 23128c2ecf20Sopenharmony_ci } 23138c2ecf20Sopenharmony_ci } 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci /* Init Rx bds */ 23168c2ecf20Sopenharmony_ci for (j = 0; j < ug_info->numQueuesRx; j++) { 23178c2ecf20Sopenharmony_ci /* Setup the skbuff rings */ 23188c2ecf20Sopenharmony_ci ugeth->rx_skbuff[j] = 23198c2ecf20Sopenharmony_ci kmalloc_array(ugeth->ug_info->bdRingLenRx[j], 23208c2ecf20Sopenharmony_ci sizeof(struct sk_buff *), GFP_KERNEL); 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci if (ugeth->rx_skbuff[j] == NULL) { 23238c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 23248c2ecf20Sopenharmony_ci pr_err("Could not allocate rx_skbuff\n"); 23258c2ecf20Sopenharmony_ci return -ENOMEM; 23268c2ecf20Sopenharmony_ci } 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_ci for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++) 23298c2ecf20Sopenharmony_ci ugeth->rx_skbuff[j][i] = NULL; 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci ugeth->skb_currx[j] = 0; 23328c2ecf20Sopenharmony_ci bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j]; 23338c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->bdRingLenRx[j]; i++) { 23348c2ecf20Sopenharmony_ci /* set bd status and length */ 23358c2ecf20Sopenharmony_ci out_be32((u32 __iomem *)bd, R_I); 23368c2ecf20Sopenharmony_ci /* clear bd buffer */ 23378c2ecf20Sopenharmony_ci out_be32(&((struct qe_bd __iomem *)bd)->buf, 0); 23388c2ecf20Sopenharmony_ci bd += sizeof(struct qe_bd); 23398c2ecf20Sopenharmony_ci } 23408c2ecf20Sopenharmony_ci bd -= sizeof(struct qe_bd); 23418c2ecf20Sopenharmony_ci /* set bd status and length */ 23428c2ecf20Sopenharmony_ci out_be32((u32 __iomem *)bd, R_W); /* for last BD set Wrap bit */ 23438c2ecf20Sopenharmony_ci } 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_ci return 0; 23468c2ecf20Sopenharmony_ci} 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_cistatic int ucc_geth_startup(struct ucc_geth_private *ugeth) 23498c2ecf20Sopenharmony_ci{ 23508c2ecf20Sopenharmony_ci struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt; 23518c2ecf20Sopenharmony_ci struct ucc_geth_init_pram __iomem *p_init_enet_pram; 23528c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 23538c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 23548c2ecf20Sopenharmony_ci struct ucc_fast_info *uf_info; 23558c2ecf20Sopenharmony_ci struct ucc_fast __iomem *uf_regs; 23568c2ecf20Sopenharmony_ci struct ucc_geth __iomem *ug_regs; 23578c2ecf20Sopenharmony_ci int ret_val = -EINVAL; 23588c2ecf20Sopenharmony_ci u32 remoder = UCC_GETH_REMODER_INIT; 23598c2ecf20Sopenharmony_ci u32 init_enet_pram_offset, cecr_subblock, command; 23608c2ecf20Sopenharmony_ci u32 ifstat, i, j, size, l2qt, l3qt; 23618c2ecf20Sopenharmony_ci u16 temoder = UCC_GETH_TEMODER_INIT; 23628c2ecf20Sopenharmony_ci u16 test; 23638c2ecf20Sopenharmony_ci u8 function_code = 0; 23648c2ecf20Sopenharmony_ci u8 __iomem *endOfRing; 23658c2ecf20Sopenharmony_ci u8 numThreadsRxNumerical, numThreadsTxNumerical; 23668c2ecf20Sopenharmony_ci 23678c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 23688c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 23698c2ecf20Sopenharmony_ci ug_info = ugeth->ug_info; 23708c2ecf20Sopenharmony_ci uf_info = &ug_info->uf_info; 23718c2ecf20Sopenharmony_ci uf_regs = uccf->uf_regs; 23728c2ecf20Sopenharmony_ci ug_regs = ugeth->ug_regs; 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci switch (ug_info->numThreadsRx) { 23758c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_1: 23768c2ecf20Sopenharmony_ci numThreadsRxNumerical = 1; 23778c2ecf20Sopenharmony_ci break; 23788c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_2: 23798c2ecf20Sopenharmony_ci numThreadsRxNumerical = 2; 23808c2ecf20Sopenharmony_ci break; 23818c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_4: 23828c2ecf20Sopenharmony_ci numThreadsRxNumerical = 4; 23838c2ecf20Sopenharmony_ci break; 23848c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_6: 23858c2ecf20Sopenharmony_ci numThreadsRxNumerical = 6; 23868c2ecf20Sopenharmony_ci break; 23878c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_8: 23888c2ecf20Sopenharmony_ci numThreadsRxNumerical = 8; 23898c2ecf20Sopenharmony_ci break; 23908c2ecf20Sopenharmony_ci default: 23918c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 23928c2ecf20Sopenharmony_ci pr_err("Bad number of Rx threads value\n"); 23938c2ecf20Sopenharmony_ci return -EINVAL; 23948c2ecf20Sopenharmony_ci } 23958c2ecf20Sopenharmony_ci 23968c2ecf20Sopenharmony_ci switch (ug_info->numThreadsTx) { 23978c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_1: 23988c2ecf20Sopenharmony_ci numThreadsTxNumerical = 1; 23998c2ecf20Sopenharmony_ci break; 24008c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_2: 24018c2ecf20Sopenharmony_ci numThreadsTxNumerical = 2; 24028c2ecf20Sopenharmony_ci break; 24038c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_4: 24048c2ecf20Sopenharmony_ci numThreadsTxNumerical = 4; 24058c2ecf20Sopenharmony_ci break; 24068c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_6: 24078c2ecf20Sopenharmony_ci numThreadsTxNumerical = 6; 24088c2ecf20Sopenharmony_ci break; 24098c2ecf20Sopenharmony_ci case UCC_GETH_NUM_OF_THREADS_8: 24108c2ecf20Sopenharmony_ci numThreadsTxNumerical = 8; 24118c2ecf20Sopenharmony_ci break; 24128c2ecf20Sopenharmony_ci default: 24138c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 24148c2ecf20Sopenharmony_ci pr_err("Bad number of Tx threads value\n"); 24158c2ecf20Sopenharmony_ci return -EINVAL; 24168c2ecf20Sopenharmony_ci } 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_ci /* Calculate rx_extended_features */ 24198c2ecf20Sopenharmony_ci ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck || 24208c2ecf20Sopenharmony_ci ug_info->ipAddressAlignment || 24218c2ecf20Sopenharmony_ci (ug_info->numStationAddresses != 24228c2ecf20Sopenharmony_ci UCC_GETH_NUM_OF_STATION_ADDRESSES_1); 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_ci ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features || 24258c2ecf20Sopenharmony_ci (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) || 24268c2ecf20Sopenharmony_ci (ug_info->vlanOperationNonTagged != 24278c2ecf20Sopenharmony_ci UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP); 24288c2ecf20Sopenharmony_ci 24298c2ecf20Sopenharmony_ci init_default_reg_vals(&uf_regs->upsmr, 24308c2ecf20Sopenharmony_ci &ug_regs->maccfg1, &ug_regs->maccfg2); 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci /* Set UPSMR */ 24338c2ecf20Sopenharmony_ci /* For more details see the hardware spec. */ 24348c2ecf20Sopenharmony_ci init_rx_parameters(ug_info->bro, 24358c2ecf20Sopenharmony_ci ug_info->rsh, ug_info->pro, &uf_regs->upsmr); 24368c2ecf20Sopenharmony_ci 24378c2ecf20Sopenharmony_ci /* We're going to ignore other registers for now, */ 24388c2ecf20Sopenharmony_ci /* except as needed to get up and running */ 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci /* Set MACCFG1 */ 24418c2ecf20Sopenharmony_ci /* For more details see the hardware spec. */ 24428c2ecf20Sopenharmony_ci init_flow_control_params(ug_info->aufc, 24438c2ecf20Sopenharmony_ci ug_info->receiveFlowControl, 24448c2ecf20Sopenharmony_ci ug_info->transmitFlowControl, 24458c2ecf20Sopenharmony_ci ug_info->pausePeriod, 24468c2ecf20Sopenharmony_ci ug_info->extensionField, 24478c2ecf20Sopenharmony_ci &uf_regs->upsmr, 24488c2ecf20Sopenharmony_ci &ug_regs->uempr, &ug_regs->maccfg1); 24498c2ecf20Sopenharmony_ci 24508c2ecf20Sopenharmony_ci setbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_ci /* Set IPGIFG */ 24538c2ecf20Sopenharmony_ci /* For more details see the hardware spec. */ 24548c2ecf20Sopenharmony_ci ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1, 24558c2ecf20Sopenharmony_ci ug_info->nonBackToBackIfgPart2, 24568c2ecf20Sopenharmony_ci ug_info-> 24578c2ecf20Sopenharmony_ci miminumInterFrameGapEnforcement, 24588c2ecf20Sopenharmony_ci ug_info->backToBackInterFrameGap, 24598c2ecf20Sopenharmony_ci &ug_regs->ipgifg); 24608c2ecf20Sopenharmony_ci if (ret_val != 0) { 24618c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 24628c2ecf20Sopenharmony_ci pr_err("IPGIFG initialization parameter too large\n"); 24638c2ecf20Sopenharmony_ci return ret_val; 24648c2ecf20Sopenharmony_ci } 24658c2ecf20Sopenharmony_ci 24668c2ecf20Sopenharmony_ci /* Set HAFDUP */ 24678c2ecf20Sopenharmony_ci /* For more details see the hardware spec. */ 24688c2ecf20Sopenharmony_ci ret_val = init_half_duplex_params(ug_info->altBeb, 24698c2ecf20Sopenharmony_ci ug_info->backPressureNoBackoff, 24708c2ecf20Sopenharmony_ci ug_info->noBackoff, 24718c2ecf20Sopenharmony_ci ug_info->excessDefer, 24728c2ecf20Sopenharmony_ci ug_info->altBebTruncation, 24738c2ecf20Sopenharmony_ci ug_info->maxRetransmission, 24748c2ecf20Sopenharmony_ci ug_info->collisionWindow, 24758c2ecf20Sopenharmony_ci &ug_regs->hafdup); 24768c2ecf20Sopenharmony_ci if (ret_val != 0) { 24778c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 24788c2ecf20Sopenharmony_ci pr_err("Half Duplex initialization parameter too large\n"); 24798c2ecf20Sopenharmony_ci return ret_val; 24808c2ecf20Sopenharmony_ci } 24818c2ecf20Sopenharmony_ci 24828c2ecf20Sopenharmony_ci /* Set IFSTAT */ 24838c2ecf20Sopenharmony_ci /* For more details see the hardware spec. */ 24848c2ecf20Sopenharmony_ci /* Read only - resets upon read */ 24858c2ecf20Sopenharmony_ci ifstat = in_be32(&ug_regs->ifstat); 24868c2ecf20Sopenharmony_ci 24878c2ecf20Sopenharmony_ci /* Clear UEMPR */ 24888c2ecf20Sopenharmony_ci /* For more details see the hardware spec. */ 24898c2ecf20Sopenharmony_ci out_be32(&ug_regs->uempr, 0); 24908c2ecf20Sopenharmony_ci 24918c2ecf20Sopenharmony_ci /* Set UESCR */ 24928c2ecf20Sopenharmony_ci /* For more details see the hardware spec. */ 24938c2ecf20Sopenharmony_ci init_hw_statistics_gathering_mode((ug_info->statisticsMode & 24948c2ecf20Sopenharmony_ci UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE), 24958c2ecf20Sopenharmony_ci 0, &uf_regs->upsmr, &ug_regs->uescr); 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci ret_val = ucc_geth_alloc_tx(ugeth); 24988c2ecf20Sopenharmony_ci if (ret_val != 0) 24998c2ecf20Sopenharmony_ci return ret_val; 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_ci ret_val = ucc_geth_alloc_rx(ugeth); 25028c2ecf20Sopenharmony_ci if (ret_val != 0) 25038c2ecf20Sopenharmony_ci return ret_val; 25048c2ecf20Sopenharmony_ci 25058c2ecf20Sopenharmony_ci /* 25068c2ecf20Sopenharmony_ci * Global PRAM 25078c2ecf20Sopenharmony_ci */ 25088c2ecf20Sopenharmony_ci /* Tx global PRAM */ 25098c2ecf20Sopenharmony_ci /* Allocate global tx parameter RAM page */ 25108c2ecf20Sopenharmony_ci ugeth->tx_glbl_pram_offset = 25118c2ecf20Sopenharmony_ci qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram), 25128c2ecf20Sopenharmony_ci UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT); 25138c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->tx_glbl_pram_offset)) { 25148c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 25158c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_tx_glbl_pram\n"); 25168c2ecf20Sopenharmony_ci return -ENOMEM; 25178c2ecf20Sopenharmony_ci } 25188c2ecf20Sopenharmony_ci ugeth->p_tx_glbl_pram = 25198c2ecf20Sopenharmony_ci (struct ucc_geth_tx_global_pram __iomem *) qe_muram_addr(ugeth-> 25208c2ecf20Sopenharmony_ci tx_glbl_pram_offset); 25218c2ecf20Sopenharmony_ci /* Zero out p_tx_glbl_pram */ 25228c2ecf20Sopenharmony_ci memset_io((void __iomem *)ugeth->p_tx_glbl_pram, 0, sizeof(struct ucc_geth_tx_global_pram)); 25238c2ecf20Sopenharmony_ci 25248c2ecf20Sopenharmony_ci /* Fill global PRAM */ 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci /* TQPTR */ 25278c2ecf20Sopenharmony_ci /* Size varies with number of Tx threads */ 25288c2ecf20Sopenharmony_ci ugeth->thread_dat_tx_offset = 25298c2ecf20Sopenharmony_ci qe_muram_alloc(numThreadsTxNumerical * 25308c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_thread_data_tx) + 25318c2ecf20Sopenharmony_ci 32 * (numThreadsTxNumerical == 1), 25328c2ecf20Sopenharmony_ci UCC_GETH_THREAD_DATA_ALIGNMENT); 25338c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->thread_dat_tx_offset)) { 25348c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 25358c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_thread_data_tx\n"); 25368c2ecf20Sopenharmony_ci return -ENOMEM; 25378c2ecf20Sopenharmony_ci } 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_ci ugeth->p_thread_data_tx = 25408c2ecf20Sopenharmony_ci (struct ucc_geth_thread_data_tx __iomem *) qe_muram_addr(ugeth-> 25418c2ecf20Sopenharmony_ci thread_dat_tx_offset); 25428c2ecf20Sopenharmony_ci out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset); 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_ci /* vtagtable */ 25458c2ecf20Sopenharmony_ci for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++) 25468c2ecf20Sopenharmony_ci out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i], 25478c2ecf20Sopenharmony_ci ug_info->vtagtable[i]); 25488c2ecf20Sopenharmony_ci 25498c2ecf20Sopenharmony_ci /* iphoffset */ 25508c2ecf20Sopenharmony_ci for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++) 25518c2ecf20Sopenharmony_ci out_8(&ugeth->p_tx_glbl_pram->iphoffset[i], 25528c2ecf20Sopenharmony_ci ug_info->iphoffset[i]); 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci /* SQPTR */ 25558c2ecf20Sopenharmony_ci /* Size varies with number of Tx queues */ 25568c2ecf20Sopenharmony_ci ugeth->send_q_mem_reg_offset = 25578c2ecf20Sopenharmony_ci qe_muram_alloc(ug_info->numQueuesTx * 25588c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_send_queue_qd), 25598c2ecf20Sopenharmony_ci UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT); 25608c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->send_q_mem_reg_offset)) { 25618c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 25628c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_send_q_mem_reg\n"); 25638c2ecf20Sopenharmony_ci return -ENOMEM; 25648c2ecf20Sopenharmony_ci } 25658c2ecf20Sopenharmony_ci 25668c2ecf20Sopenharmony_ci ugeth->p_send_q_mem_reg = 25678c2ecf20Sopenharmony_ci (struct ucc_geth_send_queue_mem_region __iomem *) qe_muram_addr(ugeth-> 25688c2ecf20Sopenharmony_ci send_q_mem_reg_offset); 25698c2ecf20Sopenharmony_ci out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset); 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ci /* Setup the table */ 25728c2ecf20Sopenharmony_ci /* Assume BD rings are already established */ 25738c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesTx; i++) { 25748c2ecf20Sopenharmony_ci endOfRing = 25758c2ecf20Sopenharmony_ci ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] - 25768c2ecf20Sopenharmony_ci 1) * sizeof(struct qe_bd); 25778c2ecf20Sopenharmony_ci if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) { 25788c2ecf20Sopenharmony_ci out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base, 25798c2ecf20Sopenharmony_ci (u32) virt_to_phys(ugeth->p_tx_bd_ring[i])); 25808c2ecf20Sopenharmony_ci out_be32(&ugeth->p_send_q_mem_reg->sqqd[i]. 25818c2ecf20Sopenharmony_ci last_bd_completed_address, 25828c2ecf20Sopenharmony_ci (u32) virt_to_phys(endOfRing)); 25838c2ecf20Sopenharmony_ci } else if (ugeth->ug_info->uf_info.bd_mem_part == 25848c2ecf20Sopenharmony_ci MEM_PART_MURAM) { 25858c2ecf20Sopenharmony_ci out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base, 25868c2ecf20Sopenharmony_ci (u32)qe_muram_dma(ugeth->p_tx_bd_ring[i])); 25878c2ecf20Sopenharmony_ci out_be32(&ugeth->p_send_q_mem_reg->sqqd[i]. 25888c2ecf20Sopenharmony_ci last_bd_completed_address, 25898c2ecf20Sopenharmony_ci (u32)qe_muram_dma(endOfRing)); 25908c2ecf20Sopenharmony_ci } 25918c2ecf20Sopenharmony_ci } 25928c2ecf20Sopenharmony_ci 25938c2ecf20Sopenharmony_ci /* schedulerbasepointer */ 25948c2ecf20Sopenharmony_ci 25958c2ecf20Sopenharmony_ci if (ug_info->numQueuesTx > 1) { 25968c2ecf20Sopenharmony_ci /* scheduler exists only if more than 1 tx queue */ 25978c2ecf20Sopenharmony_ci ugeth->scheduler_offset = 25988c2ecf20Sopenharmony_ci qe_muram_alloc(sizeof(struct ucc_geth_scheduler), 25998c2ecf20Sopenharmony_ci UCC_GETH_SCHEDULER_ALIGNMENT); 26008c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->scheduler_offset)) { 26018c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 26028c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_scheduler\n"); 26038c2ecf20Sopenharmony_ci return -ENOMEM; 26048c2ecf20Sopenharmony_ci } 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci ugeth->p_scheduler = 26078c2ecf20Sopenharmony_ci (struct ucc_geth_scheduler __iomem *) qe_muram_addr(ugeth-> 26088c2ecf20Sopenharmony_ci scheduler_offset); 26098c2ecf20Sopenharmony_ci out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer, 26108c2ecf20Sopenharmony_ci ugeth->scheduler_offset); 26118c2ecf20Sopenharmony_ci /* Zero out p_scheduler */ 26128c2ecf20Sopenharmony_ci memset_io((void __iomem *)ugeth->p_scheduler, 0, sizeof(struct ucc_geth_scheduler)); 26138c2ecf20Sopenharmony_ci 26148c2ecf20Sopenharmony_ci /* Set values in scheduler */ 26158c2ecf20Sopenharmony_ci out_be32(&ugeth->p_scheduler->mblinterval, 26168c2ecf20Sopenharmony_ci ug_info->mblinterval); 26178c2ecf20Sopenharmony_ci out_be16(&ugeth->p_scheduler->nortsrbytetime, 26188c2ecf20Sopenharmony_ci ug_info->nortsrbytetime); 26198c2ecf20Sopenharmony_ci out_8(&ugeth->p_scheduler->fracsiz, ug_info->fracsiz); 26208c2ecf20Sopenharmony_ci out_8(&ugeth->p_scheduler->strictpriorityq, 26218c2ecf20Sopenharmony_ci ug_info->strictpriorityq); 26228c2ecf20Sopenharmony_ci out_8(&ugeth->p_scheduler->txasap, ug_info->txasap); 26238c2ecf20Sopenharmony_ci out_8(&ugeth->p_scheduler->extrabw, ug_info->extrabw); 26248c2ecf20Sopenharmony_ci for (i = 0; i < NUM_TX_QUEUES; i++) 26258c2ecf20Sopenharmony_ci out_8(&ugeth->p_scheduler->weightfactor[i], 26268c2ecf20Sopenharmony_ci ug_info->weightfactor[i]); 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci /* Set pointers to cpucount registers in scheduler */ 26298c2ecf20Sopenharmony_ci ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0); 26308c2ecf20Sopenharmony_ci ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1); 26318c2ecf20Sopenharmony_ci ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2); 26328c2ecf20Sopenharmony_ci ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3); 26338c2ecf20Sopenharmony_ci ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4); 26348c2ecf20Sopenharmony_ci ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5); 26358c2ecf20Sopenharmony_ci ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6); 26368c2ecf20Sopenharmony_ci ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7); 26378c2ecf20Sopenharmony_ci } 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_ci /* schedulerbasepointer */ 26408c2ecf20Sopenharmony_ci /* TxRMON_PTR (statistics) */ 26418c2ecf20Sopenharmony_ci if (ug_info-> 26428c2ecf20Sopenharmony_ci statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { 26438c2ecf20Sopenharmony_ci ugeth->tx_fw_statistics_pram_offset = 26448c2ecf20Sopenharmony_ci qe_muram_alloc(sizeof 26458c2ecf20Sopenharmony_ci (struct ucc_geth_tx_firmware_statistics_pram), 26468c2ecf20Sopenharmony_ci UCC_GETH_TX_STATISTICS_ALIGNMENT); 26478c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->tx_fw_statistics_pram_offset)) { 26488c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 26498c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_tx_fw_statistics_pram\n"); 26508c2ecf20Sopenharmony_ci return -ENOMEM; 26518c2ecf20Sopenharmony_ci } 26528c2ecf20Sopenharmony_ci ugeth->p_tx_fw_statistics_pram = 26538c2ecf20Sopenharmony_ci (struct ucc_geth_tx_firmware_statistics_pram __iomem *) 26548c2ecf20Sopenharmony_ci qe_muram_addr(ugeth->tx_fw_statistics_pram_offset); 26558c2ecf20Sopenharmony_ci /* Zero out p_tx_fw_statistics_pram */ 26568c2ecf20Sopenharmony_ci memset_io((void __iomem *)ugeth->p_tx_fw_statistics_pram, 26578c2ecf20Sopenharmony_ci 0, sizeof(struct ucc_geth_tx_firmware_statistics_pram)); 26588c2ecf20Sopenharmony_ci } 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci /* temoder */ 26618c2ecf20Sopenharmony_ci /* Already has speed set */ 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci if (ug_info->numQueuesTx > 1) 26648c2ecf20Sopenharmony_ci temoder |= TEMODER_SCHEDULER_ENABLE; 26658c2ecf20Sopenharmony_ci if (ug_info->ipCheckSumGenerate) 26668c2ecf20Sopenharmony_ci temoder |= TEMODER_IP_CHECKSUM_GENERATE; 26678c2ecf20Sopenharmony_ci temoder |= ((ug_info->numQueuesTx - 1) << TEMODER_NUM_OF_QUEUES_SHIFT); 26688c2ecf20Sopenharmony_ci out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder); 26698c2ecf20Sopenharmony_ci 26708c2ecf20Sopenharmony_ci test = in_be16(&ugeth->p_tx_glbl_pram->temoder); 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ci /* Function code register value to be used later */ 26738c2ecf20Sopenharmony_ci function_code = UCC_BMR_BO_BE | UCC_BMR_GBL; 26748c2ecf20Sopenharmony_ci /* Required for QE */ 26758c2ecf20Sopenharmony_ci 26768c2ecf20Sopenharmony_ci /* function code register */ 26778c2ecf20Sopenharmony_ci out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24); 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_ci /* Rx global PRAM */ 26808c2ecf20Sopenharmony_ci /* Allocate global rx parameter RAM page */ 26818c2ecf20Sopenharmony_ci ugeth->rx_glbl_pram_offset = 26828c2ecf20Sopenharmony_ci qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram), 26838c2ecf20Sopenharmony_ci UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT); 26848c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->rx_glbl_pram_offset)) { 26858c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 26868c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_rx_glbl_pram\n"); 26878c2ecf20Sopenharmony_ci return -ENOMEM; 26888c2ecf20Sopenharmony_ci } 26898c2ecf20Sopenharmony_ci ugeth->p_rx_glbl_pram = 26908c2ecf20Sopenharmony_ci (struct ucc_geth_rx_global_pram __iomem *) qe_muram_addr(ugeth-> 26918c2ecf20Sopenharmony_ci rx_glbl_pram_offset); 26928c2ecf20Sopenharmony_ci /* Zero out p_rx_glbl_pram */ 26938c2ecf20Sopenharmony_ci memset_io((void __iomem *)ugeth->p_rx_glbl_pram, 0, sizeof(struct ucc_geth_rx_global_pram)); 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci /* Fill global PRAM */ 26968c2ecf20Sopenharmony_ci 26978c2ecf20Sopenharmony_ci /* RQPTR */ 26988c2ecf20Sopenharmony_ci /* Size varies with number of Rx threads */ 26998c2ecf20Sopenharmony_ci ugeth->thread_dat_rx_offset = 27008c2ecf20Sopenharmony_ci qe_muram_alloc(numThreadsRxNumerical * 27018c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_thread_data_rx), 27028c2ecf20Sopenharmony_ci UCC_GETH_THREAD_DATA_ALIGNMENT); 27038c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->thread_dat_rx_offset)) { 27048c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 27058c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_thread_data_rx\n"); 27068c2ecf20Sopenharmony_ci return -ENOMEM; 27078c2ecf20Sopenharmony_ci } 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_ci ugeth->p_thread_data_rx = 27108c2ecf20Sopenharmony_ci (struct ucc_geth_thread_data_rx __iomem *) qe_muram_addr(ugeth-> 27118c2ecf20Sopenharmony_ci thread_dat_rx_offset); 27128c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset); 27138c2ecf20Sopenharmony_ci 27148c2ecf20Sopenharmony_ci /* typeorlen */ 27158c2ecf20Sopenharmony_ci out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen); 27168c2ecf20Sopenharmony_ci 27178c2ecf20Sopenharmony_ci /* rxrmonbaseptr (statistics) */ 27188c2ecf20Sopenharmony_ci if (ug_info-> 27198c2ecf20Sopenharmony_ci statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { 27208c2ecf20Sopenharmony_ci ugeth->rx_fw_statistics_pram_offset = 27218c2ecf20Sopenharmony_ci qe_muram_alloc(sizeof 27228c2ecf20Sopenharmony_ci (struct ucc_geth_rx_firmware_statistics_pram), 27238c2ecf20Sopenharmony_ci UCC_GETH_RX_STATISTICS_ALIGNMENT); 27248c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->rx_fw_statistics_pram_offset)) { 27258c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 27268c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_rx_fw_statistics_pram\n"); 27278c2ecf20Sopenharmony_ci return -ENOMEM; 27288c2ecf20Sopenharmony_ci } 27298c2ecf20Sopenharmony_ci ugeth->p_rx_fw_statistics_pram = 27308c2ecf20Sopenharmony_ci (struct ucc_geth_rx_firmware_statistics_pram __iomem *) 27318c2ecf20Sopenharmony_ci qe_muram_addr(ugeth->rx_fw_statistics_pram_offset); 27328c2ecf20Sopenharmony_ci /* Zero out p_rx_fw_statistics_pram */ 27338c2ecf20Sopenharmony_ci memset_io((void __iomem *)ugeth->p_rx_fw_statistics_pram, 0, 27348c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_rx_firmware_statistics_pram)); 27358c2ecf20Sopenharmony_ci } 27368c2ecf20Sopenharmony_ci 27378c2ecf20Sopenharmony_ci /* intCoalescingPtr */ 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci /* Size varies with number of Rx queues */ 27408c2ecf20Sopenharmony_ci ugeth->rx_irq_coalescing_tbl_offset = 27418c2ecf20Sopenharmony_ci qe_muram_alloc(ug_info->numQueuesRx * 27428c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_rx_interrupt_coalescing_entry) 27438c2ecf20Sopenharmony_ci + 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); 27448c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->rx_irq_coalescing_tbl_offset)) { 27458c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 27468c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_rx_irq_coalescing_tbl\n"); 27478c2ecf20Sopenharmony_ci return -ENOMEM; 27488c2ecf20Sopenharmony_ci } 27498c2ecf20Sopenharmony_ci 27508c2ecf20Sopenharmony_ci ugeth->p_rx_irq_coalescing_tbl = 27518c2ecf20Sopenharmony_ci (struct ucc_geth_rx_interrupt_coalescing_table __iomem *) 27528c2ecf20Sopenharmony_ci qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset); 27538c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr, 27548c2ecf20Sopenharmony_ci ugeth->rx_irq_coalescing_tbl_offset); 27558c2ecf20Sopenharmony_ci 27568c2ecf20Sopenharmony_ci /* Fill interrupt coalescing table */ 27578c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesRx; i++) { 27588c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i]. 27598c2ecf20Sopenharmony_ci interruptcoalescingmaxvalue, 27608c2ecf20Sopenharmony_ci ug_info->interruptcoalescingmaxvalue[i]); 27618c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i]. 27628c2ecf20Sopenharmony_ci interruptcoalescingcounter, 27638c2ecf20Sopenharmony_ci ug_info->interruptcoalescingmaxvalue[i]); 27648c2ecf20Sopenharmony_ci } 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ci /* MRBLR */ 27678c2ecf20Sopenharmony_ci init_max_rx_buff_len(uf_info->max_rx_buf_length, 27688c2ecf20Sopenharmony_ci &ugeth->p_rx_glbl_pram->mrblr); 27698c2ecf20Sopenharmony_ci /* MFLR */ 27708c2ecf20Sopenharmony_ci out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength); 27718c2ecf20Sopenharmony_ci /* MINFLR */ 27728c2ecf20Sopenharmony_ci init_min_frame_len(ug_info->minFrameLength, 27738c2ecf20Sopenharmony_ci &ugeth->p_rx_glbl_pram->minflr, 27748c2ecf20Sopenharmony_ci &ugeth->p_rx_glbl_pram->mrblr); 27758c2ecf20Sopenharmony_ci /* MAXD1 */ 27768c2ecf20Sopenharmony_ci out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length); 27778c2ecf20Sopenharmony_ci /* MAXD2 */ 27788c2ecf20Sopenharmony_ci out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length); 27798c2ecf20Sopenharmony_ci 27808c2ecf20Sopenharmony_ci /* l2qt */ 27818c2ecf20Sopenharmony_ci l2qt = 0; 27828c2ecf20Sopenharmony_ci for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) 27838c2ecf20Sopenharmony_ci l2qt |= (ug_info->l2qt[i] << (28 - 4 * i)); 27848c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt); 27858c2ecf20Sopenharmony_ci 27868c2ecf20Sopenharmony_ci /* l3qt */ 27878c2ecf20Sopenharmony_ci for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) { 27888c2ecf20Sopenharmony_ci l3qt = 0; 27898c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 27908c2ecf20Sopenharmony_ci l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i)); 27918c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_glbl_pram->l3qt[j/8], l3qt); 27928c2ecf20Sopenharmony_ci } 27938c2ecf20Sopenharmony_ci 27948c2ecf20Sopenharmony_ci /* vlantype */ 27958c2ecf20Sopenharmony_ci out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype); 27968c2ecf20Sopenharmony_ci 27978c2ecf20Sopenharmony_ci /* vlantci */ 27988c2ecf20Sopenharmony_ci out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci); 27998c2ecf20Sopenharmony_ci 28008c2ecf20Sopenharmony_ci /* ecamptr */ 28018c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr); 28028c2ecf20Sopenharmony_ci 28038c2ecf20Sopenharmony_ci /* RBDQPTR */ 28048c2ecf20Sopenharmony_ci /* Size varies with number of Rx queues */ 28058c2ecf20Sopenharmony_ci ugeth->rx_bd_qs_tbl_offset = 28068c2ecf20Sopenharmony_ci qe_muram_alloc(ug_info->numQueuesRx * 28078c2ecf20Sopenharmony_ci (sizeof(struct ucc_geth_rx_bd_queues_entry) + 28088c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_rx_prefetched_bds)), 28098c2ecf20Sopenharmony_ci UCC_GETH_RX_BD_QUEUES_ALIGNMENT); 28108c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->rx_bd_qs_tbl_offset)) { 28118c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 28128c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_rx_bd_qs_tbl\n"); 28138c2ecf20Sopenharmony_ci return -ENOMEM; 28148c2ecf20Sopenharmony_ci } 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci ugeth->p_rx_bd_qs_tbl = 28178c2ecf20Sopenharmony_ci (struct ucc_geth_rx_bd_queues_entry __iomem *) qe_muram_addr(ugeth-> 28188c2ecf20Sopenharmony_ci rx_bd_qs_tbl_offset); 28198c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset); 28208c2ecf20Sopenharmony_ci /* Zero out p_rx_bd_qs_tbl */ 28218c2ecf20Sopenharmony_ci memset_io((void __iomem *)ugeth->p_rx_bd_qs_tbl, 28228c2ecf20Sopenharmony_ci 0, 28238c2ecf20Sopenharmony_ci ug_info->numQueuesRx * (sizeof(struct ucc_geth_rx_bd_queues_entry) + 28248c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_rx_prefetched_bds))); 28258c2ecf20Sopenharmony_ci 28268c2ecf20Sopenharmony_ci /* Setup the table */ 28278c2ecf20Sopenharmony_ci /* Assume BD rings are already established */ 28288c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesRx; i++) { 28298c2ecf20Sopenharmony_ci if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) { 28308c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, 28318c2ecf20Sopenharmony_ci (u32) virt_to_phys(ugeth->p_rx_bd_ring[i])); 28328c2ecf20Sopenharmony_ci } else if (ugeth->ug_info->uf_info.bd_mem_part == 28338c2ecf20Sopenharmony_ci MEM_PART_MURAM) { 28348c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, 28358c2ecf20Sopenharmony_ci (u32)qe_muram_dma(ugeth->p_rx_bd_ring[i])); 28368c2ecf20Sopenharmony_ci } 28378c2ecf20Sopenharmony_ci /* rest of fields handled by QE */ 28388c2ecf20Sopenharmony_ci } 28398c2ecf20Sopenharmony_ci 28408c2ecf20Sopenharmony_ci /* remoder */ 28418c2ecf20Sopenharmony_ci /* Already has speed set */ 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci if (ugeth->rx_extended_features) 28448c2ecf20Sopenharmony_ci remoder |= REMODER_RX_EXTENDED_FEATURES; 28458c2ecf20Sopenharmony_ci if (ug_info->rxExtendedFiltering) 28468c2ecf20Sopenharmony_ci remoder |= REMODER_RX_EXTENDED_FILTERING; 28478c2ecf20Sopenharmony_ci if (ug_info->dynamicMaxFrameLength) 28488c2ecf20Sopenharmony_ci remoder |= REMODER_DYNAMIC_MAX_FRAME_LENGTH; 28498c2ecf20Sopenharmony_ci if (ug_info->dynamicMinFrameLength) 28508c2ecf20Sopenharmony_ci remoder |= REMODER_DYNAMIC_MIN_FRAME_LENGTH; 28518c2ecf20Sopenharmony_ci remoder |= 28528c2ecf20Sopenharmony_ci ug_info->vlanOperationTagged << REMODER_VLAN_OPERATION_TAGGED_SHIFT; 28538c2ecf20Sopenharmony_ci remoder |= 28548c2ecf20Sopenharmony_ci ug_info-> 28558c2ecf20Sopenharmony_ci vlanOperationNonTagged << REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT; 28568c2ecf20Sopenharmony_ci remoder |= ug_info->rxQoSMode << REMODER_RX_QOS_MODE_SHIFT; 28578c2ecf20Sopenharmony_ci remoder |= ((ug_info->numQueuesRx - 1) << REMODER_NUM_OF_QUEUES_SHIFT); 28588c2ecf20Sopenharmony_ci if (ug_info->ipCheckSumCheck) 28598c2ecf20Sopenharmony_ci remoder |= REMODER_IP_CHECKSUM_CHECK; 28608c2ecf20Sopenharmony_ci if (ug_info->ipAddressAlignment) 28618c2ecf20Sopenharmony_ci remoder |= REMODER_IP_ADDRESS_ALIGNMENT; 28628c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_glbl_pram->remoder, remoder); 28638c2ecf20Sopenharmony_ci 28648c2ecf20Sopenharmony_ci /* Note that this function must be called */ 28658c2ecf20Sopenharmony_ci /* ONLY AFTER p_tx_fw_statistics_pram */ 28668c2ecf20Sopenharmony_ci /* andp_UccGethRxFirmwareStatisticsPram are allocated ! */ 28678c2ecf20Sopenharmony_ci init_firmware_statistics_gathering_mode((ug_info-> 28688c2ecf20Sopenharmony_ci statisticsMode & 28698c2ecf20Sopenharmony_ci UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX), 28708c2ecf20Sopenharmony_ci (ug_info->statisticsMode & 28718c2ecf20Sopenharmony_ci UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX), 28728c2ecf20Sopenharmony_ci &ugeth->p_tx_glbl_pram->txrmonbaseptr, 28738c2ecf20Sopenharmony_ci ugeth->tx_fw_statistics_pram_offset, 28748c2ecf20Sopenharmony_ci &ugeth->p_rx_glbl_pram->rxrmonbaseptr, 28758c2ecf20Sopenharmony_ci ugeth->rx_fw_statistics_pram_offset, 28768c2ecf20Sopenharmony_ci &ugeth->p_tx_glbl_pram->temoder, 28778c2ecf20Sopenharmony_ci &ugeth->p_rx_glbl_pram->remoder); 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_ci /* function code register */ 28808c2ecf20Sopenharmony_ci out_8(&ugeth->p_rx_glbl_pram->rstate, function_code); 28818c2ecf20Sopenharmony_ci 28828c2ecf20Sopenharmony_ci /* initialize extended filtering */ 28838c2ecf20Sopenharmony_ci if (ug_info->rxExtendedFiltering) { 28848c2ecf20Sopenharmony_ci if (!ug_info->extendedFilteringChainPointer) { 28858c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 28868c2ecf20Sopenharmony_ci pr_err("Null Extended Filtering Chain Pointer\n"); 28878c2ecf20Sopenharmony_ci return -EINVAL; 28888c2ecf20Sopenharmony_ci } 28898c2ecf20Sopenharmony_ci 28908c2ecf20Sopenharmony_ci /* Allocate memory for extended filtering Mode Global 28918c2ecf20Sopenharmony_ci Parameters */ 28928c2ecf20Sopenharmony_ci ugeth->exf_glbl_param_offset = 28938c2ecf20Sopenharmony_ci qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram), 28948c2ecf20Sopenharmony_ci UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT); 28958c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(ugeth->exf_glbl_param_offset)) { 28968c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 28978c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_exf_glbl_param\n"); 28988c2ecf20Sopenharmony_ci return -ENOMEM; 28998c2ecf20Sopenharmony_ci } 29008c2ecf20Sopenharmony_ci 29018c2ecf20Sopenharmony_ci ugeth->p_exf_glbl_param = 29028c2ecf20Sopenharmony_ci (struct ucc_geth_exf_global_pram __iomem *) qe_muram_addr(ugeth-> 29038c2ecf20Sopenharmony_ci exf_glbl_param_offset); 29048c2ecf20Sopenharmony_ci out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam, 29058c2ecf20Sopenharmony_ci ugeth->exf_glbl_param_offset); 29068c2ecf20Sopenharmony_ci out_be32(&ugeth->p_exf_glbl_param->l2pcdptr, 29078c2ecf20Sopenharmony_ci (u32) ug_info->extendedFilteringChainPointer); 29088c2ecf20Sopenharmony_ci 29098c2ecf20Sopenharmony_ci } else { /* initialize 82xx style address filtering */ 29108c2ecf20Sopenharmony_ci 29118c2ecf20Sopenharmony_ci /* Init individual address recognition registers to disabled */ 29128c2ecf20Sopenharmony_ci 29138c2ecf20Sopenharmony_ci for (j = 0; j < NUM_OF_PADDRS; j++) 29148c2ecf20Sopenharmony_ci ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j); 29158c2ecf20Sopenharmony_ci 29168c2ecf20Sopenharmony_ci p_82xx_addr_filt = 29178c2ecf20Sopenharmony_ci (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth-> 29188c2ecf20Sopenharmony_ci p_rx_glbl_pram->addressfiltering; 29198c2ecf20Sopenharmony_ci 29208c2ecf20Sopenharmony_ci ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth, 29218c2ecf20Sopenharmony_ci ENET_ADDR_TYPE_GROUP); 29228c2ecf20Sopenharmony_ci ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth, 29238c2ecf20Sopenharmony_ci ENET_ADDR_TYPE_INDIVIDUAL); 29248c2ecf20Sopenharmony_ci } 29258c2ecf20Sopenharmony_ci 29268c2ecf20Sopenharmony_ci /* 29278c2ecf20Sopenharmony_ci * Initialize UCC at QE level 29288c2ecf20Sopenharmony_ci */ 29298c2ecf20Sopenharmony_ci 29308c2ecf20Sopenharmony_ci command = QE_INIT_TX_RX; 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci /* Allocate shadow InitEnet command parameter structure. 29338c2ecf20Sopenharmony_ci * This is needed because after the InitEnet command is executed, 29348c2ecf20Sopenharmony_ci * the structure in DPRAM is released, because DPRAM is a premium 29358c2ecf20Sopenharmony_ci * resource. 29368c2ecf20Sopenharmony_ci * This shadow structure keeps a copy of what was done so that the 29378c2ecf20Sopenharmony_ci * allocated resources can be released when the channel is freed. 29388c2ecf20Sopenharmony_ci */ 29398c2ecf20Sopenharmony_ci if (!(ugeth->p_init_enet_param_shadow = 29408c2ecf20Sopenharmony_ci kmalloc(sizeof(struct ucc_geth_init_pram), GFP_KERNEL))) { 29418c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 29428c2ecf20Sopenharmony_ci pr_err("Can not allocate memory for p_UccInitEnetParamShadows\n"); 29438c2ecf20Sopenharmony_ci return -ENOMEM; 29448c2ecf20Sopenharmony_ci } 29458c2ecf20Sopenharmony_ci /* Zero out *p_init_enet_param_shadow */ 29468c2ecf20Sopenharmony_ci memset((char *)ugeth->p_init_enet_param_shadow, 29478c2ecf20Sopenharmony_ci 0, sizeof(struct ucc_geth_init_pram)); 29488c2ecf20Sopenharmony_ci 29498c2ecf20Sopenharmony_ci /* Fill shadow InitEnet command parameter structure */ 29508c2ecf20Sopenharmony_ci 29518c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit1 = 29528c2ecf20Sopenharmony_ci ENET_INIT_PARAM_MAGIC_RES_INIT1; 29538c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit2 = 29548c2ecf20Sopenharmony_ci ENET_INIT_PARAM_MAGIC_RES_INIT2; 29558c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit3 = 29568c2ecf20Sopenharmony_ci ENET_INIT_PARAM_MAGIC_RES_INIT3; 29578c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit4 = 29588c2ecf20Sopenharmony_ci ENET_INIT_PARAM_MAGIC_RES_INIT4; 29598c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit5 = 29608c2ecf20Sopenharmony_ci ENET_INIT_PARAM_MAGIC_RES_INIT5; 29618c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= 29628c2ecf20Sopenharmony_ci ((u32) ug_info->numThreadsRx) << ENET_INIT_PARAM_RGF_SHIFT; 29638c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= 29648c2ecf20Sopenharmony_ci ((u32) ug_info->numThreadsTx) << ENET_INIT_PARAM_TGF_SHIFT; 29658c2ecf20Sopenharmony_ci 29668c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= 29678c2ecf20Sopenharmony_ci ugeth->rx_glbl_pram_offset | ug_info->riscRx; 29688c2ecf20Sopenharmony_ci if ((ug_info->largestexternallookupkeysize != 29698c2ecf20Sopenharmony_ci QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE) && 29708c2ecf20Sopenharmony_ci (ug_info->largestexternallookupkeysize != 29718c2ecf20Sopenharmony_ci QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) && 29728c2ecf20Sopenharmony_ci (ug_info->largestexternallookupkeysize != 29738c2ecf20Sopenharmony_ci QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) { 29748c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 29758c2ecf20Sopenharmony_ci pr_err("Invalid largest External Lookup Key Size\n"); 29768c2ecf20Sopenharmony_ci return -EINVAL; 29778c2ecf20Sopenharmony_ci } 29788c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->largestexternallookupkeysize = 29798c2ecf20Sopenharmony_ci ug_info->largestexternallookupkeysize; 29808c2ecf20Sopenharmony_ci size = sizeof(struct ucc_geth_thread_rx_pram); 29818c2ecf20Sopenharmony_ci if (ug_info->rxExtendedFiltering) { 29828c2ecf20Sopenharmony_ci size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; 29838c2ecf20Sopenharmony_ci if (ug_info->largestexternallookupkeysize == 29848c2ecf20Sopenharmony_ci QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) 29858c2ecf20Sopenharmony_ci size += 29868c2ecf20Sopenharmony_ci THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8; 29878c2ecf20Sopenharmony_ci if (ug_info->largestexternallookupkeysize == 29888c2ecf20Sopenharmony_ci QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES) 29898c2ecf20Sopenharmony_ci size += 29908c2ecf20Sopenharmony_ci THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16; 29918c2ecf20Sopenharmony_ci } 29928c2ecf20Sopenharmony_ci 29938c2ecf20Sopenharmony_ci if ((ret_val = fill_init_enet_entries(ugeth, &(ugeth-> 29948c2ecf20Sopenharmony_ci p_init_enet_param_shadow->rxthread[0]), 29958c2ecf20Sopenharmony_ci (u8) (numThreadsRxNumerical + 1) 29968c2ecf20Sopenharmony_ci /* Rx needs one extra for terminator */ 29978c2ecf20Sopenharmony_ci , size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT, 29988c2ecf20Sopenharmony_ci ug_info->riscRx, 1)) != 0) { 29998c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 30008c2ecf20Sopenharmony_ci pr_err("Can not fill p_init_enet_param_shadow\n"); 30018c2ecf20Sopenharmony_ci return ret_val; 30028c2ecf20Sopenharmony_ci } 30038c2ecf20Sopenharmony_ci 30048c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->txglobal = 30058c2ecf20Sopenharmony_ci ugeth->tx_glbl_pram_offset | ug_info->riscTx; 30068c2ecf20Sopenharmony_ci if ((ret_val = 30078c2ecf20Sopenharmony_ci fill_init_enet_entries(ugeth, 30088c2ecf20Sopenharmony_ci &(ugeth->p_init_enet_param_shadow-> 30098c2ecf20Sopenharmony_ci txthread[0]), numThreadsTxNumerical, 30108c2ecf20Sopenharmony_ci sizeof(struct ucc_geth_thread_tx_pram), 30118c2ecf20Sopenharmony_ci UCC_GETH_THREAD_TX_PRAM_ALIGNMENT, 30128c2ecf20Sopenharmony_ci ug_info->riscTx, 0)) != 0) { 30138c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 30148c2ecf20Sopenharmony_ci pr_err("Can not fill p_init_enet_param_shadow\n"); 30158c2ecf20Sopenharmony_ci return ret_val; 30168c2ecf20Sopenharmony_ci } 30178c2ecf20Sopenharmony_ci 30188c2ecf20Sopenharmony_ci /* Load Rx bds with buffers */ 30198c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesRx; i++) { 30208c2ecf20Sopenharmony_ci if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) { 30218c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 30228c2ecf20Sopenharmony_ci pr_err("Can not fill Rx bds with buffers\n"); 30238c2ecf20Sopenharmony_ci return ret_val; 30248c2ecf20Sopenharmony_ci } 30258c2ecf20Sopenharmony_ci } 30268c2ecf20Sopenharmony_ci 30278c2ecf20Sopenharmony_ci /* Allocate InitEnet command parameter structure */ 30288c2ecf20Sopenharmony_ci init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4); 30298c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(init_enet_pram_offset)) { 30308c2ecf20Sopenharmony_ci if (netif_msg_ifup(ugeth)) 30318c2ecf20Sopenharmony_ci pr_err("Can not allocate DPRAM memory for p_init_enet_pram\n"); 30328c2ecf20Sopenharmony_ci return -ENOMEM; 30338c2ecf20Sopenharmony_ci } 30348c2ecf20Sopenharmony_ci p_init_enet_pram = 30358c2ecf20Sopenharmony_ci (struct ucc_geth_init_pram __iomem *) qe_muram_addr(init_enet_pram_offset); 30368c2ecf20Sopenharmony_ci 30378c2ecf20Sopenharmony_ci /* Copy shadow InitEnet command parameter structure into PRAM */ 30388c2ecf20Sopenharmony_ci out_8(&p_init_enet_pram->resinit1, 30398c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit1); 30408c2ecf20Sopenharmony_ci out_8(&p_init_enet_pram->resinit2, 30418c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit2); 30428c2ecf20Sopenharmony_ci out_8(&p_init_enet_pram->resinit3, 30438c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit3); 30448c2ecf20Sopenharmony_ci out_8(&p_init_enet_pram->resinit4, 30458c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit4); 30468c2ecf20Sopenharmony_ci out_be16(&p_init_enet_pram->resinit5, 30478c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->resinit5); 30488c2ecf20Sopenharmony_ci out_8(&p_init_enet_pram->largestexternallookupkeysize, 30498c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->largestexternallookupkeysize); 30508c2ecf20Sopenharmony_ci out_be32(&p_init_enet_pram->rgftgfrxglobal, 30518c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->rgftgfrxglobal); 30528c2ecf20Sopenharmony_ci for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_RX; i++) 30538c2ecf20Sopenharmony_ci out_be32(&p_init_enet_pram->rxthread[i], 30548c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->rxthread[i]); 30558c2ecf20Sopenharmony_ci out_be32(&p_init_enet_pram->txglobal, 30568c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->txglobal); 30578c2ecf20Sopenharmony_ci for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_TX; i++) 30588c2ecf20Sopenharmony_ci out_be32(&p_init_enet_pram->txthread[i], 30598c2ecf20Sopenharmony_ci ugeth->p_init_enet_param_shadow->txthread[i]); 30608c2ecf20Sopenharmony_ci 30618c2ecf20Sopenharmony_ci /* Issue QE command */ 30628c2ecf20Sopenharmony_ci cecr_subblock = 30638c2ecf20Sopenharmony_ci ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); 30648c2ecf20Sopenharmony_ci qe_issue_cmd(command, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 30658c2ecf20Sopenharmony_ci init_enet_pram_offset); 30668c2ecf20Sopenharmony_ci 30678c2ecf20Sopenharmony_ci /* Free InitEnet command parameter */ 30688c2ecf20Sopenharmony_ci qe_muram_free(init_enet_pram_offset); 30698c2ecf20Sopenharmony_ci 30708c2ecf20Sopenharmony_ci return 0; 30718c2ecf20Sopenharmony_ci} 30728c2ecf20Sopenharmony_ci 30738c2ecf20Sopenharmony_ci/* This is called by the kernel when a frame is ready for transmission. */ 30748c2ecf20Sopenharmony_ci/* It is pointed to by the dev->hard_start_xmit function pointer */ 30758c2ecf20Sopenharmony_cistatic netdev_tx_t 30768c2ecf20Sopenharmony_ciucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) 30778c2ecf20Sopenharmony_ci{ 30788c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 30798c2ecf20Sopenharmony_ci#ifdef CONFIG_UGETH_TX_ON_DEMAND 30808c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 30818c2ecf20Sopenharmony_ci#endif 30828c2ecf20Sopenharmony_ci u8 __iomem *bd; /* BD pointer */ 30838c2ecf20Sopenharmony_ci u32 bd_status; 30848c2ecf20Sopenharmony_ci u8 txQ = 0; 30858c2ecf20Sopenharmony_ci unsigned long flags; 30868c2ecf20Sopenharmony_ci 30878c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 30888c2ecf20Sopenharmony_ci 30898c2ecf20Sopenharmony_ci netdev_sent_queue(dev, skb->len); 30908c2ecf20Sopenharmony_ci spin_lock_irqsave(&ugeth->lock, flags); 30918c2ecf20Sopenharmony_ci 30928c2ecf20Sopenharmony_ci dev->stats.tx_bytes += skb->len; 30938c2ecf20Sopenharmony_ci 30948c2ecf20Sopenharmony_ci /* Start from the next BD that should be filled */ 30958c2ecf20Sopenharmony_ci bd = ugeth->txBd[txQ]; 30968c2ecf20Sopenharmony_ci bd_status = in_be32((u32 __iomem *)bd); 30978c2ecf20Sopenharmony_ci /* Save the skb pointer so we can free it later */ 30988c2ecf20Sopenharmony_ci ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb; 30998c2ecf20Sopenharmony_ci 31008c2ecf20Sopenharmony_ci /* Update the current skb pointer (wrapping if this was the last) */ 31018c2ecf20Sopenharmony_ci ugeth->skb_curtx[txQ] = 31028c2ecf20Sopenharmony_ci (ugeth->skb_curtx[txQ] + 31038c2ecf20Sopenharmony_ci 1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]); 31048c2ecf20Sopenharmony_ci 31058c2ecf20Sopenharmony_ci /* set up the buffer descriptor */ 31068c2ecf20Sopenharmony_ci out_be32(&((struct qe_bd __iomem *)bd)->buf, 31078c2ecf20Sopenharmony_ci dma_map_single(ugeth->dev, skb->data, 31088c2ecf20Sopenharmony_ci skb->len, DMA_TO_DEVICE)); 31098c2ecf20Sopenharmony_ci 31108c2ecf20Sopenharmony_ci /* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */ 31118c2ecf20Sopenharmony_ci 31128c2ecf20Sopenharmony_ci bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len; 31138c2ecf20Sopenharmony_ci 31148c2ecf20Sopenharmony_ci /* set bd status and length */ 31158c2ecf20Sopenharmony_ci out_be32((u32 __iomem *)bd, bd_status); 31168c2ecf20Sopenharmony_ci 31178c2ecf20Sopenharmony_ci /* Move to next BD in the ring */ 31188c2ecf20Sopenharmony_ci if (!(bd_status & T_W)) 31198c2ecf20Sopenharmony_ci bd += sizeof(struct qe_bd); 31208c2ecf20Sopenharmony_ci else 31218c2ecf20Sopenharmony_ci bd = ugeth->p_tx_bd_ring[txQ]; 31228c2ecf20Sopenharmony_ci 31238c2ecf20Sopenharmony_ci /* If the next BD still needs to be cleaned up, then the bds 31248c2ecf20Sopenharmony_ci are full. We need to tell the kernel to stop sending us stuff. */ 31258c2ecf20Sopenharmony_ci if (bd == ugeth->confBd[txQ]) { 31268c2ecf20Sopenharmony_ci if (!netif_queue_stopped(dev)) 31278c2ecf20Sopenharmony_ci netif_stop_queue(dev); 31288c2ecf20Sopenharmony_ci } 31298c2ecf20Sopenharmony_ci 31308c2ecf20Sopenharmony_ci ugeth->txBd[txQ] = bd; 31318c2ecf20Sopenharmony_ci 31328c2ecf20Sopenharmony_ci skb_tx_timestamp(skb); 31338c2ecf20Sopenharmony_ci 31348c2ecf20Sopenharmony_ci if (ugeth->p_scheduler) { 31358c2ecf20Sopenharmony_ci ugeth->cpucount[txQ]++; 31368c2ecf20Sopenharmony_ci /* Indicate to QE that there are more Tx bds ready for 31378c2ecf20Sopenharmony_ci transmission */ 31388c2ecf20Sopenharmony_ci /* This is done by writing a running counter of the bd 31398c2ecf20Sopenharmony_ci count to the scheduler PRAM. */ 31408c2ecf20Sopenharmony_ci out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]); 31418c2ecf20Sopenharmony_ci } 31428c2ecf20Sopenharmony_ci 31438c2ecf20Sopenharmony_ci#ifdef CONFIG_UGETH_TX_ON_DEMAND 31448c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 31458c2ecf20Sopenharmony_ci out_be16(uccf->p_utodr, UCC_FAST_TOD); 31468c2ecf20Sopenharmony_ci#endif 31478c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ugeth->lock, flags); 31488c2ecf20Sopenharmony_ci 31498c2ecf20Sopenharmony_ci return NETDEV_TX_OK; 31508c2ecf20Sopenharmony_ci} 31518c2ecf20Sopenharmony_ci 31528c2ecf20Sopenharmony_cistatic int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit) 31538c2ecf20Sopenharmony_ci{ 31548c2ecf20Sopenharmony_ci struct sk_buff *skb; 31558c2ecf20Sopenharmony_ci u8 __iomem *bd; 31568c2ecf20Sopenharmony_ci u16 length, howmany = 0; 31578c2ecf20Sopenharmony_ci u32 bd_status; 31588c2ecf20Sopenharmony_ci u8 *bdBuffer; 31598c2ecf20Sopenharmony_ci struct net_device *dev; 31608c2ecf20Sopenharmony_ci 31618c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 31628c2ecf20Sopenharmony_ci 31638c2ecf20Sopenharmony_ci dev = ugeth->ndev; 31648c2ecf20Sopenharmony_ci 31658c2ecf20Sopenharmony_ci /* collect received buffers */ 31668c2ecf20Sopenharmony_ci bd = ugeth->rxBd[rxQ]; 31678c2ecf20Sopenharmony_ci 31688c2ecf20Sopenharmony_ci bd_status = in_be32((u32 __iomem *)bd); 31698c2ecf20Sopenharmony_ci 31708c2ecf20Sopenharmony_ci /* while there are received buffers and BD is full (~R_E) */ 31718c2ecf20Sopenharmony_ci while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) { 31728c2ecf20Sopenharmony_ci bdBuffer = (u8 *) in_be32(&((struct qe_bd __iomem *)bd)->buf); 31738c2ecf20Sopenharmony_ci length = (u16) ((bd_status & BD_LENGTH_MASK) - 4); 31748c2ecf20Sopenharmony_ci skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]]; 31758c2ecf20Sopenharmony_ci 31768c2ecf20Sopenharmony_ci /* determine whether buffer is first, last, first and last 31778c2ecf20Sopenharmony_ci (single buffer frame) or middle (not first and not last) */ 31788c2ecf20Sopenharmony_ci if (!skb || 31798c2ecf20Sopenharmony_ci (!(bd_status & (R_F | R_L))) || 31808c2ecf20Sopenharmony_ci (bd_status & R_ERRORS_FATAL)) { 31818c2ecf20Sopenharmony_ci if (netif_msg_rx_err(ugeth)) 31828c2ecf20Sopenharmony_ci pr_err("%d: ERROR!!! skb - 0x%08x\n", 31838c2ecf20Sopenharmony_ci __LINE__, (u32)skb); 31848c2ecf20Sopenharmony_ci dev_kfree_skb(skb); 31858c2ecf20Sopenharmony_ci 31868c2ecf20Sopenharmony_ci ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL; 31878c2ecf20Sopenharmony_ci dev->stats.rx_dropped++; 31888c2ecf20Sopenharmony_ci } else { 31898c2ecf20Sopenharmony_ci dev->stats.rx_packets++; 31908c2ecf20Sopenharmony_ci howmany++; 31918c2ecf20Sopenharmony_ci 31928c2ecf20Sopenharmony_ci /* Prep the skb for the packet */ 31938c2ecf20Sopenharmony_ci skb_put(skb, length); 31948c2ecf20Sopenharmony_ci 31958c2ecf20Sopenharmony_ci /* Tell the skb what kind of packet this is */ 31968c2ecf20Sopenharmony_ci skb->protocol = eth_type_trans(skb, ugeth->ndev); 31978c2ecf20Sopenharmony_ci 31988c2ecf20Sopenharmony_ci dev->stats.rx_bytes += length; 31998c2ecf20Sopenharmony_ci /* Send the packet up the stack */ 32008c2ecf20Sopenharmony_ci netif_receive_skb(skb); 32018c2ecf20Sopenharmony_ci } 32028c2ecf20Sopenharmony_ci 32038c2ecf20Sopenharmony_ci skb = get_new_skb(ugeth, bd); 32048c2ecf20Sopenharmony_ci if (!skb) { 32058c2ecf20Sopenharmony_ci if (netif_msg_rx_err(ugeth)) 32068c2ecf20Sopenharmony_ci pr_warn("No Rx Data Buffer\n"); 32078c2ecf20Sopenharmony_ci dev->stats.rx_dropped++; 32088c2ecf20Sopenharmony_ci break; 32098c2ecf20Sopenharmony_ci } 32108c2ecf20Sopenharmony_ci 32118c2ecf20Sopenharmony_ci ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = skb; 32128c2ecf20Sopenharmony_ci 32138c2ecf20Sopenharmony_ci /* update to point at the next skb */ 32148c2ecf20Sopenharmony_ci ugeth->skb_currx[rxQ] = 32158c2ecf20Sopenharmony_ci (ugeth->skb_currx[rxQ] + 32168c2ecf20Sopenharmony_ci 1) & RX_RING_MOD_MASK(ugeth->ug_info->bdRingLenRx[rxQ]); 32178c2ecf20Sopenharmony_ci 32188c2ecf20Sopenharmony_ci if (bd_status & R_W) 32198c2ecf20Sopenharmony_ci bd = ugeth->p_rx_bd_ring[rxQ]; 32208c2ecf20Sopenharmony_ci else 32218c2ecf20Sopenharmony_ci bd += sizeof(struct qe_bd); 32228c2ecf20Sopenharmony_ci 32238c2ecf20Sopenharmony_ci bd_status = in_be32((u32 __iomem *)bd); 32248c2ecf20Sopenharmony_ci } 32258c2ecf20Sopenharmony_ci 32268c2ecf20Sopenharmony_ci ugeth->rxBd[rxQ] = bd; 32278c2ecf20Sopenharmony_ci return howmany; 32288c2ecf20Sopenharmony_ci} 32298c2ecf20Sopenharmony_ci 32308c2ecf20Sopenharmony_cistatic int ucc_geth_tx(struct net_device *dev, u8 txQ) 32318c2ecf20Sopenharmony_ci{ 32328c2ecf20Sopenharmony_ci /* Start from the next BD that should be filled */ 32338c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 32348c2ecf20Sopenharmony_ci unsigned int bytes_sent = 0; 32358c2ecf20Sopenharmony_ci int howmany = 0; 32368c2ecf20Sopenharmony_ci u8 __iomem *bd; /* BD pointer */ 32378c2ecf20Sopenharmony_ci u32 bd_status; 32388c2ecf20Sopenharmony_ci 32398c2ecf20Sopenharmony_ci bd = ugeth->confBd[txQ]; 32408c2ecf20Sopenharmony_ci bd_status = in_be32((u32 __iomem *)bd); 32418c2ecf20Sopenharmony_ci 32428c2ecf20Sopenharmony_ci /* Normal processing. */ 32438c2ecf20Sopenharmony_ci while ((bd_status & T_R) == 0) { 32448c2ecf20Sopenharmony_ci struct sk_buff *skb; 32458c2ecf20Sopenharmony_ci 32468c2ecf20Sopenharmony_ci /* BD contains already transmitted buffer. */ 32478c2ecf20Sopenharmony_ci /* Handle the transmitted buffer and release */ 32488c2ecf20Sopenharmony_ci /* the BD to be used with the current frame */ 32498c2ecf20Sopenharmony_ci 32508c2ecf20Sopenharmony_ci skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]; 32518c2ecf20Sopenharmony_ci if (!skb) 32528c2ecf20Sopenharmony_ci break; 32538c2ecf20Sopenharmony_ci howmany++; 32548c2ecf20Sopenharmony_ci bytes_sent += skb->len; 32558c2ecf20Sopenharmony_ci dev->stats.tx_packets++; 32568c2ecf20Sopenharmony_ci 32578c2ecf20Sopenharmony_ci dev_consume_skb_any(skb); 32588c2ecf20Sopenharmony_ci 32598c2ecf20Sopenharmony_ci ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL; 32608c2ecf20Sopenharmony_ci ugeth->skb_dirtytx[txQ] = 32618c2ecf20Sopenharmony_ci (ugeth->skb_dirtytx[txQ] + 32628c2ecf20Sopenharmony_ci 1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]); 32638c2ecf20Sopenharmony_ci 32648c2ecf20Sopenharmony_ci /* We freed a buffer, so now we can restart transmission */ 32658c2ecf20Sopenharmony_ci if (netif_queue_stopped(dev)) 32668c2ecf20Sopenharmony_ci netif_wake_queue(dev); 32678c2ecf20Sopenharmony_ci 32688c2ecf20Sopenharmony_ci /* Advance the confirmation BD pointer */ 32698c2ecf20Sopenharmony_ci if (!(bd_status & T_W)) 32708c2ecf20Sopenharmony_ci bd += sizeof(struct qe_bd); 32718c2ecf20Sopenharmony_ci else 32728c2ecf20Sopenharmony_ci bd = ugeth->p_tx_bd_ring[txQ]; 32738c2ecf20Sopenharmony_ci bd_status = in_be32((u32 __iomem *)bd); 32748c2ecf20Sopenharmony_ci } 32758c2ecf20Sopenharmony_ci ugeth->confBd[txQ] = bd; 32768c2ecf20Sopenharmony_ci netdev_completed_queue(dev, howmany, bytes_sent); 32778c2ecf20Sopenharmony_ci return 0; 32788c2ecf20Sopenharmony_ci} 32798c2ecf20Sopenharmony_ci 32808c2ecf20Sopenharmony_cistatic int ucc_geth_poll(struct napi_struct *napi, int budget) 32818c2ecf20Sopenharmony_ci{ 32828c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = container_of(napi, struct ucc_geth_private, napi); 32838c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 32848c2ecf20Sopenharmony_ci int howmany, i; 32858c2ecf20Sopenharmony_ci 32868c2ecf20Sopenharmony_ci ug_info = ugeth->ug_info; 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci /* Tx event processing */ 32898c2ecf20Sopenharmony_ci spin_lock(&ugeth->lock); 32908c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesTx; i++) 32918c2ecf20Sopenharmony_ci ucc_geth_tx(ugeth->ndev, i); 32928c2ecf20Sopenharmony_ci spin_unlock(&ugeth->lock); 32938c2ecf20Sopenharmony_ci 32948c2ecf20Sopenharmony_ci howmany = 0; 32958c2ecf20Sopenharmony_ci for (i = 0; i < ug_info->numQueuesRx; i++) 32968c2ecf20Sopenharmony_ci howmany += ucc_geth_rx(ugeth, i, budget - howmany); 32978c2ecf20Sopenharmony_ci 32988c2ecf20Sopenharmony_ci if (howmany < budget) { 32998c2ecf20Sopenharmony_ci napi_complete_done(napi, howmany); 33008c2ecf20Sopenharmony_ci setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS | UCCE_TX_EVENTS); 33018c2ecf20Sopenharmony_ci } 33028c2ecf20Sopenharmony_ci 33038c2ecf20Sopenharmony_ci return howmany; 33048c2ecf20Sopenharmony_ci} 33058c2ecf20Sopenharmony_ci 33068c2ecf20Sopenharmony_cistatic irqreturn_t ucc_geth_irq_handler(int irq, void *info) 33078c2ecf20Sopenharmony_ci{ 33088c2ecf20Sopenharmony_ci struct net_device *dev = info; 33098c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 33108c2ecf20Sopenharmony_ci struct ucc_fast_private *uccf; 33118c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 33128c2ecf20Sopenharmony_ci register u32 ucce; 33138c2ecf20Sopenharmony_ci register u32 uccm; 33148c2ecf20Sopenharmony_ci 33158c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 33168c2ecf20Sopenharmony_ci 33178c2ecf20Sopenharmony_ci uccf = ugeth->uccf; 33188c2ecf20Sopenharmony_ci ug_info = ugeth->ug_info; 33198c2ecf20Sopenharmony_ci 33208c2ecf20Sopenharmony_ci /* read and clear events */ 33218c2ecf20Sopenharmony_ci ucce = (u32) in_be32(uccf->p_ucce); 33228c2ecf20Sopenharmony_ci uccm = (u32) in_be32(uccf->p_uccm); 33238c2ecf20Sopenharmony_ci ucce &= uccm; 33248c2ecf20Sopenharmony_ci out_be32(uccf->p_ucce, ucce); 33258c2ecf20Sopenharmony_ci 33268c2ecf20Sopenharmony_ci /* check for receive events that require processing */ 33278c2ecf20Sopenharmony_ci if (ucce & (UCCE_RX_EVENTS | UCCE_TX_EVENTS)) { 33288c2ecf20Sopenharmony_ci if (napi_schedule_prep(&ugeth->napi)) { 33298c2ecf20Sopenharmony_ci uccm &= ~(UCCE_RX_EVENTS | UCCE_TX_EVENTS); 33308c2ecf20Sopenharmony_ci out_be32(uccf->p_uccm, uccm); 33318c2ecf20Sopenharmony_ci __napi_schedule(&ugeth->napi); 33328c2ecf20Sopenharmony_ci } 33338c2ecf20Sopenharmony_ci } 33348c2ecf20Sopenharmony_ci 33358c2ecf20Sopenharmony_ci /* Errors and other events */ 33368c2ecf20Sopenharmony_ci if (ucce & UCCE_OTHER) { 33378c2ecf20Sopenharmony_ci if (ucce & UCC_GETH_UCCE_BSY) 33388c2ecf20Sopenharmony_ci dev->stats.rx_errors++; 33398c2ecf20Sopenharmony_ci if (ucce & UCC_GETH_UCCE_TXE) 33408c2ecf20Sopenharmony_ci dev->stats.tx_errors++; 33418c2ecf20Sopenharmony_ci } 33428c2ecf20Sopenharmony_ci 33438c2ecf20Sopenharmony_ci return IRQ_HANDLED; 33448c2ecf20Sopenharmony_ci} 33458c2ecf20Sopenharmony_ci 33468c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER 33478c2ecf20Sopenharmony_ci/* 33488c2ecf20Sopenharmony_ci * Polling 'interrupt' - used by things like netconsole to send skbs 33498c2ecf20Sopenharmony_ci * without having to re-enable interrupts. It's not called while 33508c2ecf20Sopenharmony_ci * the interrupt routine is executing. 33518c2ecf20Sopenharmony_ci */ 33528c2ecf20Sopenharmony_cistatic void ucc_netpoll(struct net_device *dev) 33538c2ecf20Sopenharmony_ci{ 33548c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 33558c2ecf20Sopenharmony_ci int irq = ugeth->ug_info->uf_info.irq; 33568c2ecf20Sopenharmony_ci 33578c2ecf20Sopenharmony_ci disable_irq(irq); 33588c2ecf20Sopenharmony_ci ucc_geth_irq_handler(irq, dev); 33598c2ecf20Sopenharmony_ci enable_irq(irq); 33608c2ecf20Sopenharmony_ci} 33618c2ecf20Sopenharmony_ci#endif /* CONFIG_NET_POLL_CONTROLLER */ 33628c2ecf20Sopenharmony_ci 33638c2ecf20Sopenharmony_cistatic int ucc_geth_set_mac_addr(struct net_device *dev, void *p) 33648c2ecf20Sopenharmony_ci{ 33658c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 33668c2ecf20Sopenharmony_ci struct sockaddr *addr = p; 33678c2ecf20Sopenharmony_ci 33688c2ecf20Sopenharmony_ci if (!is_valid_ether_addr(addr->sa_data)) 33698c2ecf20Sopenharmony_ci return -EADDRNOTAVAIL; 33708c2ecf20Sopenharmony_ci 33718c2ecf20Sopenharmony_ci memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); 33728c2ecf20Sopenharmony_ci 33738c2ecf20Sopenharmony_ci /* 33748c2ecf20Sopenharmony_ci * If device is not running, we will set mac addr register 33758c2ecf20Sopenharmony_ci * when opening the device. 33768c2ecf20Sopenharmony_ci */ 33778c2ecf20Sopenharmony_ci if (!netif_running(dev)) 33788c2ecf20Sopenharmony_ci return 0; 33798c2ecf20Sopenharmony_ci 33808c2ecf20Sopenharmony_ci spin_lock_irq(&ugeth->lock); 33818c2ecf20Sopenharmony_ci init_mac_station_addr_regs(dev->dev_addr[0], 33828c2ecf20Sopenharmony_ci dev->dev_addr[1], 33838c2ecf20Sopenharmony_ci dev->dev_addr[2], 33848c2ecf20Sopenharmony_ci dev->dev_addr[3], 33858c2ecf20Sopenharmony_ci dev->dev_addr[4], 33868c2ecf20Sopenharmony_ci dev->dev_addr[5], 33878c2ecf20Sopenharmony_ci &ugeth->ug_regs->macstnaddr1, 33888c2ecf20Sopenharmony_ci &ugeth->ug_regs->macstnaddr2); 33898c2ecf20Sopenharmony_ci spin_unlock_irq(&ugeth->lock); 33908c2ecf20Sopenharmony_ci 33918c2ecf20Sopenharmony_ci return 0; 33928c2ecf20Sopenharmony_ci} 33938c2ecf20Sopenharmony_ci 33948c2ecf20Sopenharmony_cistatic int ucc_geth_init_mac(struct ucc_geth_private *ugeth) 33958c2ecf20Sopenharmony_ci{ 33968c2ecf20Sopenharmony_ci struct net_device *dev = ugeth->ndev; 33978c2ecf20Sopenharmony_ci int err; 33988c2ecf20Sopenharmony_ci 33998c2ecf20Sopenharmony_ci err = ucc_struct_init(ugeth); 34008c2ecf20Sopenharmony_ci if (err) { 34018c2ecf20Sopenharmony_ci netif_err(ugeth, ifup, dev, "Cannot configure internal struct, aborting\n"); 34028c2ecf20Sopenharmony_ci goto err; 34038c2ecf20Sopenharmony_ci } 34048c2ecf20Sopenharmony_ci 34058c2ecf20Sopenharmony_ci err = ucc_geth_startup(ugeth); 34068c2ecf20Sopenharmony_ci if (err) { 34078c2ecf20Sopenharmony_ci netif_err(ugeth, ifup, dev, "Cannot configure net device, aborting\n"); 34088c2ecf20Sopenharmony_ci goto err; 34098c2ecf20Sopenharmony_ci } 34108c2ecf20Sopenharmony_ci 34118c2ecf20Sopenharmony_ci err = adjust_enet_interface(ugeth); 34128c2ecf20Sopenharmony_ci if (err) { 34138c2ecf20Sopenharmony_ci netif_err(ugeth, ifup, dev, "Cannot configure net device, aborting\n"); 34148c2ecf20Sopenharmony_ci goto err; 34158c2ecf20Sopenharmony_ci } 34168c2ecf20Sopenharmony_ci 34178c2ecf20Sopenharmony_ci /* Set MACSTNADDR1, MACSTNADDR2 */ 34188c2ecf20Sopenharmony_ci /* For more details see the hardware spec. */ 34198c2ecf20Sopenharmony_ci init_mac_station_addr_regs(dev->dev_addr[0], 34208c2ecf20Sopenharmony_ci dev->dev_addr[1], 34218c2ecf20Sopenharmony_ci dev->dev_addr[2], 34228c2ecf20Sopenharmony_ci dev->dev_addr[3], 34238c2ecf20Sopenharmony_ci dev->dev_addr[4], 34248c2ecf20Sopenharmony_ci dev->dev_addr[5], 34258c2ecf20Sopenharmony_ci &ugeth->ug_regs->macstnaddr1, 34268c2ecf20Sopenharmony_ci &ugeth->ug_regs->macstnaddr2); 34278c2ecf20Sopenharmony_ci 34288c2ecf20Sopenharmony_ci err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); 34298c2ecf20Sopenharmony_ci if (err) { 34308c2ecf20Sopenharmony_ci netif_err(ugeth, ifup, dev, "Cannot enable net device, aborting\n"); 34318c2ecf20Sopenharmony_ci goto err; 34328c2ecf20Sopenharmony_ci } 34338c2ecf20Sopenharmony_ci 34348c2ecf20Sopenharmony_ci return 0; 34358c2ecf20Sopenharmony_cierr: 34368c2ecf20Sopenharmony_ci ucc_geth_stop(ugeth); 34378c2ecf20Sopenharmony_ci return err; 34388c2ecf20Sopenharmony_ci} 34398c2ecf20Sopenharmony_ci 34408c2ecf20Sopenharmony_ci/* Called when something needs to use the ethernet device */ 34418c2ecf20Sopenharmony_ci/* Returns 0 for success. */ 34428c2ecf20Sopenharmony_cistatic int ucc_geth_open(struct net_device *dev) 34438c2ecf20Sopenharmony_ci{ 34448c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 34458c2ecf20Sopenharmony_ci int err; 34468c2ecf20Sopenharmony_ci 34478c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 34488c2ecf20Sopenharmony_ci 34498c2ecf20Sopenharmony_ci /* Test station address */ 34508c2ecf20Sopenharmony_ci if (dev->dev_addr[0] & ENET_GROUP_ADDR) { 34518c2ecf20Sopenharmony_ci netif_err(ugeth, ifup, dev, 34528c2ecf20Sopenharmony_ci "Multicast address used for station address - is this what you wanted?\n"); 34538c2ecf20Sopenharmony_ci return -EINVAL; 34548c2ecf20Sopenharmony_ci } 34558c2ecf20Sopenharmony_ci 34568c2ecf20Sopenharmony_ci err = init_phy(dev); 34578c2ecf20Sopenharmony_ci if (err) { 34588c2ecf20Sopenharmony_ci netif_err(ugeth, ifup, dev, "Cannot initialize PHY, aborting\n"); 34598c2ecf20Sopenharmony_ci return err; 34608c2ecf20Sopenharmony_ci } 34618c2ecf20Sopenharmony_ci 34628c2ecf20Sopenharmony_ci err = ucc_geth_init_mac(ugeth); 34638c2ecf20Sopenharmony_ci if (err) { 34648c2ecf20Sopenharmony_ci netif_err(ugeth, ifup, dev, "Cannot initialize MAC, aborting\n"); 34658c2ecf20Sopenharmony_ci goto err; 34668c2ecf20Sopenharmony_ci } 34678c2ecf20Sopenharmony_ci 34688c2ecf20Sopenharmony_ci err = request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 34698c2ecf20Sopenharmony_ci 0, "UCC Geth", dev); 34708c2ecf20Sopenharmony_ci if (err) { 34718c2ecf20Sopenharmony_ci netif_err(ugeth, ifup, dev, "Cannot get IRQ for net device, aborting\n"); 34728c2ecf20Sopenharmony_ci goto err; 34738c2ecf20Sopenharmony_ci } 34748c2ecf20Sopenharmony_ci 34758c2ecf20Sopenharmony_ci phy_start(ugeth->phydev); 34768c2ecf20Sopenharmony_ci napi_enable(&ugeth->napi); 34778c2ecf20Sopenharmony_ci netdev_reset_queue(dev); 34788c2ecf20Sopenharmony_ci netif_start_queue(dev); 34798c2ecf20Sopenharmony_ci 34808c2ecf20Sopenharmony_ci device_set_wakeup_capable(&dev->dev, 34818c2ecf20Sopenharmony_ci qe_alive_during_sleep() || ugeth->phydev->irq); 34828c2ecf20Sopenharmony_ci device_set_wakeup_enable(&dev->dev, ugeth->wol_en); 34838c2ecf20Sopenharmony_ci 34848c2ecf20Sopenharmony_ci return err; 34858c2ecf20Sopenharmony_ci 34868c2ecf20Sopenharmony_cierr: 34878c2ecf20Sopenharmony_ci ucc_geth_stop(ugeth); 34888c2ecf20Sopenharmony_ci return err; 34898c2ecf20Sopenharmony_ci} 34908c2ecf20Sopenharmony_ci 34918c2ecf20Sopenharmony_ci/* Stops the kernel queue, and halts the controller */ 34928c2ecf20Sopenharmony_cistatic int ucc_geth_close(struct net_device *dev) 34938c2ecf20Sopenharmony_ci{ 34948c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 34958c2ecf20Sopenharmony_ci 34968c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 34978c2ecf20Sopenharmony_ci 34988c2ecf20Sopenharmony_ci napi_disable(&ugeth->napi); 34998c2ecf20Sopenharmony_ci 35008c2ecf20Sopenharmony_ci cancel_work_sync(&ugeth->timeout_work); 35018c2ecf20Sopenharmony_ci ucc_geth_stop(ugeth); 35028c2ecf20Sopenharmony_ci phy_disconnect(ugeth->phydev); 35038c2ecf20Sopenharmony_ci ugeth->phydev = NULL; 35048c2ecf20Sopenharmony_ci 35058c2ecf20Sopenharmony_ci free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev); 35068c2ecf20Sopenharmony_ci 35078c2ecf20Sopenharmony_ci netif_stop_queue(dev); 35088c2ecf20Sopenharmony_ci netdev_reset_queue(dev); 35098c2ecf20Sopenharmony_ci 35108c2ecf20Sopenharmony_ci return 0; 35118c2ecf20Sopenharmony_ci} 35128c2ecf20Sopenharmony_ci 35138c2ecf20Sopenharmony_ci/* Reopen device. This will reset the MAC and PHY. */ 35148c2ecf20Sopenharmony_cistatic void ucc_geth_timeout_work(struct work_struct *work) 35158c2ecf20Sopenharmony_ci{ 35168c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth; 35178c2ecf20Sopenharmony_ci struct net_device *dev; 35188c2ecf20Sopenharmony_ci 35198c2ecf20Sopenharmony_ci ugeth = container_of(work, struct ucc_geth_private, timeout_work); 35208c2ecf20Sopenharmony_ci dev = ugeth->ndev; 35218c2ecf20Sopenharmony_ci 35228c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 35238c2ecf20Sopenharmony_ci 35248c2ecf20Sopenharmony_ci dev->stats.tx_errors++; 35258c2ecf20Sopenharmony_ci 35268c2ecf20Sopenharmony_ci ugeth_dump_regs(ugeth); 35278c2ecf20Sopenharmony_ci 35288c2ecf20Sopenharmony_ci if (dev->flags & IFF_UP) { 35298c2ecf20Sopenharmony_ci /* 35308c2ecf20Sopenharmony_ci * Must reset MAC *and* PHY. This is done by reopening 35318c2ecf20Sopenharmony_ci * the device. 35328c2ecf20Sopenharmony_ci */ 35338c2ecf20Sopenharmony_ci netif_tx_stop_all_queues(dev); 35348c2ecf20Sopenharmony_ci ucc_geth_stop(ugeth); 35358c2ecf20Sopenharmony_ci ucc_geth_init_mac(ugeth); 35368c2ecf20Sopenharmony_ci /* Must start PHY here */ 35378c2ecf20Sopenharmony_ci phy_start(ugeth->phydev); 35388c2ecf20Sopenharmony_ci netif_tx_start_all_queues(dev); 35398c2ecf20Sopenharmony_ci } 35408c2ecf20Sopenharmony_ci 35418c2ecf20Sopenharmony_ci netif_tx_schedule_all(dev); 35428c2ecf20Sopenharmony_ci} 35438c2ecf20Sopenharmony_ci 35448c2ecf20Sopenharmony_ci/* 35458c2ecf20Sopenharmony_ci * ucc_geth_timeout gets called when a packet has not been 35468c2ecf20Sopenharmony_ci * transmitted after a set amount of time. 35478c2ecf20Sopenharmony_ci */ 35488c2ecf20Sopenharmony_cistatic void ucc_geth_timeout(struct net_device *dev, unsigned int txqueue) 35498c2ecf20Sopenharmony_ci{ 35508c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 35518c2ecf20Sopenharmony_ci 35528c2ecf20Sopenharmony_ci schedule_work(&ugeth->timeout_work); 35538c2ecf20Sopenharmony_ci} 35548c2ecf20Sopenharmony_ci 35558c2ecf20Sopenharmony_ci 35568c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 35578c2ecf20Sopenharmony_ci 35588c2ecf20Sopenharmony_cistatic int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state) 35598c2ecf20Sopenharmony_ci{ 35608c2ecf20Sopenharmony_ci struct net_device *ndev = platform_get_drvdata(ofdev); 35618c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(ndev); 35628c2ecf20Sopenharmony_ci 35638c2ecf20Sopenharmony_ci if (!netif_running(ndev)) 35648c2ecf20Sopenharmony_ci return 0; 35658c2ecf20Sopenharmony_ci 35668c2ecf20Sopenharmony_ci netif_device_detach(ndev); 35678c2ecf20Sopenharmony_ci napi_disable(&ugeth->napi); 35688c2ecf20Sopenharmony_ci 35698c2ecf20Sopenharmony_ci /* 35708c2ecf20Sopenharmony_ci * Disable the controller, otherwise we'll wakeup on any network 35718c2ecf20Sopenharmony_ci * activity. 35728c2ecf20Sopenharmony_ci */ 35738c2ecf20Sopenharmony_ci ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); 35748c2ecf20Sopenharmony_ci 35758c2ecf20Sopenharmony_ci if (ugeth->wol_en & WAKE_MAGIC) { 35768c2ecf20Sopenharmony_ci setbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD); 35778c2ecf20Sopenharmony_ci setbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE); 35788c2ecf20Sopenharmony_ci ucc_fast_enable(ugeth->uccf, COMM_DIR_RX_AND_TX); 35798c2ecf20Sopenharmony_ci } else if (!(ugeth->wol_en & WAKE_PHY)) { 35808c2ecf20Sopenharmony_ci phy_stop(ugeth->phydev); 35818c2ecf20Sopenharmony_ci } 35828c2ecf20Sopenharmony_ci 35838c2ecf20Sopenharmony_ci return 0; 35848c2ecf20Sopenharmony_ci} 35858c2ecf20Sopenharmony_ci 35868c2ecf20Sopenharmony_cistatic int ucc_geth_resume(struct platform_device *ofdev) 35878c2ecf20Sopenharmony_ci{ 35888c2ecf20Sopenharmony_ci struct net_device *ndev = platform_get_drvdata(ofdev); 35898c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(ndev); 35908c2ecf20Sopenharmony_ci int err; 35918c2ecf20Sopenharmony_ci 35928c2ecf20Sopenharmony_ci if (!netif_running(ndev)) 35938c2ecf20Sopenharmony_ci return 0; 35948c2ecf20Sopenharmony_ci 35958c2ecf20Sopenharmony_ci if (qe_alive_during_sleep()) { 35968c2ecf20Sopenharmony_ci if (ugeth->wol_en & WAKE_MAGIC) { 35978c2ecf20Sopenharmony_ci ucc_fast_disable(ugeth->uccf, COMM_DIR_RX_AND_TX); 35988c2ecf20Sopenharmony_ci clrbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE); 35998c2ecf20Sopenharmony_ci clrbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD); 36008c2ecf20Sopenharmony_ci } 36018c2ecf20Sopenharmony_ci ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); 36028c2ecf20Sopenharmony_ci } else { 36038c2ecf20Sopenharmony_ci /* 36048c2ecf20Sopenharmony_ci * Full reinitialization is required if QE shuts down 36058c2ecf20Sopenharmony_ci * during sleep. 36068c2ecf20Sopenharmony_ci */ 36078c2ecf20Sopenharmony_ci ucc_geth_memclean(ugeth); 36088c2ecf20Sopenharmony_ci 36098c2ecf20Sopenharmony_ci err = ucc_geth_init_mac(ugeth); 36108c2ecf20Sopenharmony_ci if (err) { 36118c2ecf20Sopenharmony_ci netdev_err(ndev, "Cannot initialize MAC, aborting\n"); 36128c2ecf20Sopenharmony_ci return err; 36138c2ecf20Sopenharmony_ci } 36148c2ecf20Sopenharmony_ci } 36158c2ecf20Sopenharmony_ci 36168c2ecf20Sopenharmony_ci ugeth->oldlink = 0; 36178c2ecf20Sopenharmony_ci ugeth->oldspeed = 0; 36188c2ecf20Sopenharmony_ci ugeth->oldduplex = -1; 36198c2ecf20Sopenharmony_ci 36208c2ecf20Sopenharmony_ci phy_stop(ugeth->phydev); 36218c2ecf20Sopenharmony_ci phy_start(ugeth->phydev); 36228c2ecf20Sopenharmony_ci 36238c2ecf20Sopenharmony_ci napi_enable(&ugeth->napi); 36248c2ecf20Sopenharmony_ci netif_device_attach(ndev); 36258c2ecf20Sopenharmony_ci 36268c2ecf20Sopenharmony_ci return 0; 36278c2ecf20Sopenharmony_ci} 36288c2ecf20Sopenharmony_ci 36298c2ecf20Sopenharmony_ci#else 36308c2ecf20Sopenharmony_ci#define ucc_geth_suspend NULL 36318c2ecf20Sopenharmony_ci#define ucc_geth_resume NULL 36328c2ecf20Sopenharmony_ci#endif 36338c2ecf20Sopenharmony_ci 36348c2ecf20Sopenharmony_cistatic phy_interface_t to_phy_interface(const char *phy_connection_type) 36358c2ecf20Sopenharmony_ci{ 36368c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "mii") == 0) 36378c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_MII; 36388c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "gmii") == 0) 36398c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_GMII; 36408c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "tbi") == 0) 36418c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_TBI; 36428c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "rmii") == 0) 36438c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_RMII; 36448c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "rgmii") == 0) 36458c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_RGMII; 36468c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "rgmii-id") == 0) 36478c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_RGMII_ID; 36488c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "rgmii-txid") == 0) 36498c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_RGMII_TXID; 36508c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "rgmii-rxid") == 0) 36518c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_RGMII_RXID; 36528c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "rtbi") == 0) 36538c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_RTBI; 36548c2ecf20Sopenharmony_ci if (strcasecmp(phy_connection_type, "sgmii") == 0) 36558c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_SGMII; 36568c2ecf20Sopenharmony_ci 36578c2ecf20Sopenharmony_ci return PHY_INTERFACE_MODE_MII; 36588c2ecf20Sopenharmony_ci} 36598c2ecf20Sopenharmony_ci 36608c2ecf20Sopenharmony_cistatic int ucc_geth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 36618c2ecf20Sopenharmony_ci{ 36628c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 36638c2ecf20Sopenharmony_ci 36648c2ecf20Sopenharmony_ci if (!netif_running(dev)) 36658c2ecf20Sopenharmony_ci return -EINVAL; 36668c2ecf20Sopenharmony_ci 36678c2ecf20Sopenharmony_ci if (!ugeth->phydev) 36688c2ecf20Sopenharmony_ci return -ENODEV; 36698c2ecf20Sopenharmony_ci 36708c2ecf20Sopenharmony_ci return phy_mii_ioctl(ugeth->phydev, rq, cmd); 36718c2ecf20Sopenharmony_ci} 36728c2ecf20Sopenharmony_ci 36738c2ecf20Sopenharmony_cistatic const struct net_device_ops ucc_geth_netdev_ops = { 36748c2ecf20Sopenharmony_ci .ndo_open = ucc_geth_open, 36758c2ecf20Sopenharmony_ci .ndo_stop = ucc_geth_close, 36768c2ecf20Sopenharmony_ci .ndo_start_xmit = ucc_geth_start_xmit, 36778c2ecf20Sopenharmony_ci .ndo_validate_addr = eth_validate_addr, 36788c2ecf20Sopenharmony_ci .ndo_change_carrier = fixed_phy_change_carrier, 36798c2ecf20Sopenharmony_ci .ndo_set_mac_address = ucc_geth_set_mac_addr, 36808c2ecf20Sopenharmony_ci .ndo_set_rx_mode = ucc_geth_set_multi, 36818c2ecf20Sopenharmony_ci .ndo_tx_timeout = ucc_geth_timeout, 36828c2ecf20Sopenharmony_ci .ndo_do_ioctl = ucc_geth_ioctl, 36838c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER 36848c2ecf20Sopenharmony_ci .ndo_poll_controller = ucc_netpoll, 36858c2ecf20Sopenharmony_ci#endif 36868c2ecf20Sopenharmony_ci}; 36878c2ecf20Sopenharmony_ci 36888c2ecf20Sopenharmony_cistatic int ucc_geth_probe(struct platform_device* ofdev) 36898c2ecf20Sopenharmony_ci{ 36908c2ecf20Sopenharmony_ci struct device *device = &ofdev->dev; 36918c2ecf20Sopenharmony_ci struct device_node *np = ofdev->dev.of_node; 36928c2ecf20Sopenharmony_ci struct net_device *dev = NULL; 36938c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = NULL; 36948c2ecf20Sopenharmony_ci struct ucc_geth_info *ug_info; 36958c2ecf20Sopenharmony_ci struct resource res; 36968c2ecf20Sopenharmony_ci int err, ucc_num, max_speed = 0; 36978c2ecf20Sopenharmony_ci const unsigned int *prop; 36988c2ecf20Sopenharmony_ci const char *sprop; 36998c2ecf20Sopenharmony_ci const void *mac_addr; 37008c2ecf20Sopenharmony_ci phy_interface_t phy_interface; 37018c2ecf20Sopenharmony_ci static const int enet_to_speed[] = { 37028c2ecf20Sopenharmony_ci SPEED_10, SPEED_10, SPEED_10, 37038c2ecf20Sopenharmony_ci SPEED_100, SPEED_100, SPEED_100, 37048c2ecf20Sopenharmony_ci SPEED_1000, SPEED_1000, SPEED_1000, SPEED_1000, 37058c2ecf20Sopenharmony_ci }; 37068c2ecf20Sopenharmony_ci static const phy_interface_t enet_to_phy_interface[] = { 37078c2ecf20Sopenharmony_ci PHY_INTERFACE_MODE_MII, PHY_INTERFACE_MODE_RMII, 37088c2ecf20Sopenharmony_ci PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_MII, 37098c2ecf20Sopenharmony_ci PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII, 37108c2ecf20Sopenharmony_ci PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII, 37118c2ecf20Sopenharmony_ci PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI, 37128c2ecf20Sopenharmony_ci PHY_INTERFACE_MODE_SGMII, 37138c2ecf20Sopenharmony_ci }; 37148c2ecf20Sopenharmony_ci 37158c2ecf20Sopenharmony_ci ugeth_vdbg("%s: IN", __func__); 37168c2ecf20Sopenharmony_ci 37178c2ecf20Sopenharmony_ci prop = of_get_property(np, "cell-index", NULL); 37188c2ecf20Sopenharmony_ci if (!prop) { 37198c2ecf20Sopenharmony_ci prop = of_get_property(np, "device-id", NULL); 37208c2ecf20Sopenharmony_ci if (!prop) 37218c2ecf20Sopenharmony_ci return -ENODEV; 37228c2ecf20Sopenharmony_ci } 37238c2ecf20Sopenharmony_ci 37248c2ecf20Sopenharmony_ci ucc_num = *prop - 1; 37258c2ecf20Sopenharmony_ci if ((ucc_num < 0) || (ucc_num > 7)) 37268c2ecf20Sopenharmony_ci return -ENODEV; 37278c2ecf20Sopenharmony_ci 37288c2ecf20Sopenharmony_ci ug_info = &ugeth_info[ucc_num]; 37298c2ecf20Sopenharmony_ci if (ug_info == NULL) { 37308c2ecf20Sopenharmony_ci if (netif_msg_probe(&debug)) 37318c2ecf20Sopenharmony_ci pr_err("[%d] Missing additional data!\n", ucc_num); 37328c2ecf20Sopenharmony_ci return -ENODEV; 37338c2ecf20Sopenharmony_ci } 37348c2ecf20Sopenharmony_ci 37358c2ecf20Sopenharmony_ci ug_info->uf_info.ucc_num = ucc_num; 37368c2ecf20Sopenharmony_ci 37378c2ecf20Sopenharmony_ci sprop = of_get_property(np, "rx-clock-name", NULL); 37388c2ecf20Sopenharmony_ci if (sprop) { 37398c2ecf20Sopenharmony_ci ug_info->uf_info.rx_clock = qe_clock_source(sprop); 37408c2ecf20Sopenharmony_ci if ((ug_info->uf_info.rx_clock < QE_CLK_NONE) || 37418c2ecf20Sopenharmony_ci (ug_info->uf_info.rx_clock > QE_CLK24)) { 37428c2ecf20Sopenharmony_ci pr_err("invalid rx-clock-name property\n"); 37438c2ecf20Sopenharmony_ci return -EINVAL; 37448c2ecf20Sopenharmony_ci } 37458c2ecf20Sopenharmony_ci } else { 37468c2ecf20Sopenharmony_ci prop = of_get_property(np, "rx-clock", NULL); 37478c2ecf20Sopenharmony_ci if (!prop) { 37488c2ecf20Sopenharmony_ci /* If both rx-clock-name and rx-clock are missing, 37498c2ecf20Sopenharmony_ci we want to tell people to use rx-clock-name. */ 37508c2ecf20Sopenharmony_ci pr_err("missing rx-clock-name property\n"); 37518c2ecf20Sopenharmony_ci return -EINVAL; 37528c2ecf20Sopenharmony_ci } 37538c2ecf20Sopenharmony_ci if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) { 37548c2ecf20Sopenharmony_ci pr_err("invalid rx-clock property\n"); 37558c2ecf20Sopenharmony_ci return -EINVAL; 37568c2ecf20Sopenharmony_ci } 37578c2ecf20Sopenharmony_ci ug_info->uf_info.rx_clock = *prop; 37588c2ecf20Sopenharmony_ci } 37598c2ecf20Sopenharmony_ci 37608c2ecf20Sopenharmony_ci sprop = of_get_property(np, "tx-clock-name", NULL); 37618c2ecf20Sopenharmony_ci if (sprop) { 37628c2ecf20Sopenharmony_ci ug_info->uf_info.tx_clock = qe_clock_source(sprop); 37638c2ecf20Sopenharmony_ci if ((ug_info->uf_info.tx_clock < QE_CLK_NONE) || 37648c2ecf20Sopenharmony_ci (ug_info->uf_info.tx_clock > QE_CLK24)) { 37658c2ecf20Sopenharmony_ci pr_err("invalid tx-clock-name property\n"); 37668c2ecf20Sopenharmony_ci return -EINVAL; 37678c2ecf20Sopenharmony_ci } 37688c2ecf20Sopenharmony_ci } else { 37698c2ecf20Sopenharmony_ci prop = of_get_property(np, "tx-clock", NULL); 37708c2ecf20Sopenharmony_ci if (!prop) { 37718c2ecf20Sopenharmony_ci pr_err("missing tx-clock-name property\n"); 37728c2ecf20Sopenharmony_ci return -EINVAL; 37738c2ecf20Sopenharmony_ci } 37748c2ecf20Sopenharmony_ci if ((*prop < QE_CLK_NONE) || (*prop > QE_CLK24)) { 37758c2ecf20Sopenharmony_ci pr_err("invalid tx-clock property\n"); 37768c2ecf20Sopenharmony_ci return -EINVAL; 37778c2ecf20Sopenharmony_ci } 37788c2ecf20Sopenharmony_ci ug_info->uf_info.tx_clock = *prop; 37798c2ecf20Sopenharmony_ci } 37808c2ecf20Sopenharmony_ci 37818c2ecf20Sopenharmony_ci err = of_address_to_resource(np, 0, &res); 37828c2ecf20Sopenharmony_ci if (err) 37838c2ecf20Sopenharmony_ci return -EINVAL; 37848c2ecf20Sopenharmony_ci 37858c2ecf20Sopenharmony_ci ug_info->uf_info.regs = res.start; 37868c2ecf20Sopenharmony_ci ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); 37878c2ecf20Sopenharmony_ci 37888c2ecf20Sopenharmony_ci ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0); 37898c2ecf20Sopenharmony_ci if (!ug_info->phy_node && of_phy_is_fixed_link(np)) { 37908c2ecf20Sopenharmony_ci /* 37918c2ecf20Sopenharmony_ci * In the case of a fixed PHY, the DT node associated 37928c2ecf20Sopenharmony_ci * to the PHY is the Ethernet MAC DT node. 37938c2ecf20Sopenharmony_ci */ 37948c2ecf20Sopenharmony_ci err = of_phy_register_fixed_link(np); 37958c2ecf20Sopenharmony_ci if (err) 37968c2ecf20Sopenharmony_ci return err; 37978c2ecf20Sopenharmony_ci ug_info->phy_node = of_node_get(np); 37988c2ecf20Sopenharmony_ci } 37998c2ecf20Sopenharmony_ci 38008c2ecf20Sopenharmony_ci /* Find the TBI PHY node. If it's not there, we don't support SGMII */ 38018c2ecf20Sopenharmony_ci ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0); 38028c2ecf20Sopenharmony_ci 38038c2ecf20Sopenharmony_ci /* get the phy interface type, or default to MII */ 38048c2ecf20Sopenharmony_ci prop = of_get_property(np, "phy-connection-type", NULL); 38058c2ecf20Sopenharmony_ci if (!prop) { 38068c2ecf20Sopenharmony_ci /* handle interface property present in old trees */ 38078c2ecf20Sopenharmony_ci prop = of_get_property(ug_info->phy_node, "interface", NULL); 38088c2ecf20Sopenharmony_ci if (prop != NULL) { 38098c2ecf20Sopenharmony_ci phy_interface = enet_to_phy_interface[*prop]; 38108c2ecf20Sopenharmony_ci max_speed = enet_to_speed[*prop]; 38118c2ecf20Sopenharmony_ci } else 38128c2ecf20Sopenharmony_ci phy_interface = PHY_INTERFACE_MODE_MII; 38138c2ecf20Sopenharmony_ci } else { 38148c2ecf20Sopenharmony_ci phy_interface = to_phy_interface((const char *)prop); 38158c2ecf20Sopenharmony_ci } 38168c2ecf20Sopenharmony_ci 38178c2ecf20Sopenharmony_ci /* get speed, or derive from PHY interface */ 38188c2ecf20Sopenharmony_ci if (max_speed == 0) 38198c2ecf20Sopenharmony_ci switch (phy_interface) { 38208c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_GMII: 38218c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII: 38228c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII_ID: 38238c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII_RXID: 38248c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RGMII_TXID: 38258c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_TBI: 38268c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_RTBI: 38278c2ecf20Sopenharmony_ci case PHY_INTERFACE_MODE_SGMII: 38288c2ecf20Sopenharmony_ci max_speed = SPEED_1000; 38298c2ecf20Sopenharmony_ci break; 38308c2ecf20Sopenharmony_ci default: 38318c2ecf20Sopenharmony_ci max_speed = SPEED_100; 38328c2ecf20Sopenharmony_ci break; 38338c2ecf20Sopenharmony_ci } 38348c2ecf20Sopenharmony_ci 38358c2ecf20Sopenharmony_ci if (max_speed == SPEED_1000) { 38368c2ecf20Sopenharmony_ci unsigned int snums = qe_get_num_of_snums(); 38378c2ecf20Sopenharmony_ci 38388c2ecf20Sopenharmony_ci /* configure muram FIFOs for gigabit operation */ 38398c2ecf20Sopenharmony_ci ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT; 38408c2ecf20Sopenharmony_ci ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT; 38418c2ecf20Sopenharmony_ci ug_info->uf_info.urfset = UCC_GETH_URFSET_GIGA_INIT; 38428c2ecf20Sopenharmony_ci ug_info->uf_info.utfs = UCC_GETH_UTFS_GIGA_INIT; 38438c2ecf20Sopenharmony_ci ug_info->uf_info.utfet = UCC_GETH_UTFET_GIGA_INIT; 38448c2ecf20Sopenharmony_ci ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT; 38458c2ecf20Sopenharmony_ci ug_info->numThreadsTx = UCC_GETH_NUM_OF_THREADS_4; 38468c2ecf20Sopenharmony_ci 38478c2ecf20Sopenharmony_ci /* If QE's snum number is 46/76 which means we need to support 38488c2ecf20Sopenharmony_ci * 4 UECs at 1000Base-T simultaneously, we need to allocate 38498c2ecf20Sopenharmony_ci * more Threads to Rx. 38508c2ecf20Sopenharmony_ci */ 38518c2ecf20Sopenharmony_ci if ((snums == 76) || (snums == 46)) 38528c2ecf20Sopenharmony_ci ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_6; 38538c2ecf20Sopenharmony_ci else 38548c2ecf20Sopenharmony_ci ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4; 38558c2ecf20Sopenharmony_ci } 38568c2ecf20Sopenharmony_ci 38578c2ecf20Sopenharmony_ci if (netif_msg_probe(&debug)) 38588c2ecf20Sopenharmony_ci pr_info("UCC%1d at 0x%8llx (irq = %d)\n", 38598c2ecf20Sopenharmony_ci ug_info->uf_info.ucc_num + 1, 38608c2ecf20Sopenharmony_ci (u64)ug_info->uf_info.regs, 38618c2ecf20Sopenharmony_ci ug_info->uf_info.irq); 38628c2ecf20Sopenharmony_ci 38638c2ecf20Sopenharmony_ci /* Create an ethernet device instance */ 38648c2ecf20Sopenharmony_ci dev = alloc_etherdev(sizeof(*ugeth)); 38658c2ecf20Sopenharmony_ci 38668c2ecf20Sopenharmony_ci if (dev == NULL) { 38678c2ecf20Sopenharmony_ci err = -ENOMEM; 38688c2ecf20Sopenharmony_ci goto err_deregister_fixed_link; 38698c2ecf20Sopenharmony_ci } 38708c2ecf20Sopenharmony_ci 38718c2ecf20Sopenharmony_ci ugeth = netdev_priv(dev); 38728c2ecf20Sopenharmony_ci spin_lock_init(&ugeth->lock); 38738c2ecf20Sopenharmony_ci 38748c2ecf20Sopenharmony_ci /* Create CQs for hash tables */ 38758c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ugeth->group_hash_q); 38768c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ugeth->ind_hash_q); 38778c2ecf20Sopenharmony_ci 38788c2ecf20Sopenharmony_ci dev_set_drvdata(device, dev); 38798c2ecf20Sopenharmony_ci 38808c2ecf20Sopenharmony_ci /* Set the dev->base_addr to the gfar reg region */ 38818c2ecf20Sopenharmony_ci dev->base_addr = (unsigned long)(ug_info->uf_info.regs); 38828c2ecf20Sopenharmony_ci 38838c2ecf20Sopenharmony_ci SET_NETDEV_DEV(dev, device); 38848c2ecf20Sopenharmony_ci 38858c2ecf20Sopenharmony_ci /* Fill in the dev structure */ 38868c2ecf20Sopenharmony_ci uec_set_ethtool_ops(dev); 38878c2ecf20Sopenharmony_ci dev->netdev_ops = &ucc_geth_netdev_ops; 38888c2ecf20Sopenharmony_ci dev->watchdog_timeo = TX_TIMEOUT; 38898c2ecf20Sopenharmony_ci INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work); 38908c2ecf20Sopenharmony_ci netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, 64); 38918c2ecf20Sopenharmony_ci dev->mtu = 1500; 38928c2ecf20Sopenharmony_ci dev->max_mtu = 1518; 38938c2ecf20Sopenharmony_ci 38948c2ecf20Sopenharmony_ci ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT); 38958c2ecf20Sopenharmony_ci ugeth->phy_interface = phy_interface; 38968c2ecf20Sopenharmony_ci ugeth->max_speed = max_speed; 38978c2ecf20Sopenharmony_ci 38988c2ecf20Sopenharmony_ci /* Carrier starts down, phylib will bring it up */ 38998c2ecf20Sopenharmony_ci netif_carrier_off(dev); 39008c2ecf20Sopenharmony_ci 39018c2ecf20Sopenharmony_ci err = register_netdev(dev); 39028c2ecf20Sopenharmony_ci if (err) { 39038c2ecf20Sopenharmony_ci if (netif_msg_probe(ugeth)) 39048c2ecf20Sopenharmony_ci pr_err("%s: Cannot register net device, aborting\n", 39058c2ecf20Sopenharmony_ci dev->name); 39068c2ecf20Sopenharmony_ci goto err_free_netdev; 39078c2ecf20Sopenharmony_ci } 39088c2ecf20Sopenharmony_ci 39098c2ecf20Sopenharmony_ci mac_addr = of_get_mac_address(np); 39108c2ecf20Sopenharmony_ci if (!IS_ERR(mac_addr)) 39118c2ecf20Sopenharmony_ci ether_addr_copy(dev->dev_addr, mac_addr); 39128c2ecf20Sopenharmony_ci 39138c2ecf20Sopenharmony_ci ugeth->ug_info = ug_info; 39148c2ecf20Sopenharmony_ci ugeth->dev = device; 39158c2ecf20Sopenharmony_ci ugeth->ndev = dev; 39168c2ecf20Sopenharmony_ci ugeth->node = np; 39178c2ecf20Sopenharmony_ci 39188c2ecf20Sopenharmony_ci return 0; 39198c2ecf20Sopenharmony_ci 39208c2ecf20Sopenharmony_cierr_free_netdev: 39218c2ecf20Sopenharmony_ci free_netdev(dev); 39228c2ecf20Sopenharmony_cierr_deregister_fixed_link: 39238c2ecf20Sopenharmony_ci if (of_phy_is_fixed_link(np)) 39248c2ecf20Sopenharmony_ci of_phy_deregister_fixed_link(np); 39258c2ecf20Sopenharmony_ci of_node_put(ug_info->tbi_node); 39268c2ecf20Sopenharmony_ci of_node_put(ug_info->phy_node); 39278c2ecf20Sopenharmony_ci 39288c2ecf20Sopenharmony_ci return err; 39298c2ecf20Sopenharmony_ci} 39308c2ecf20Sopenharmony_ci 39318c2ecf20Sopenharmony_cistatic int ucc_geth_remove(struct platform_device* ofdev) 39328c2ecf20Sopenharmony_ci{ 39338c2ecf20Sopenharmony_ci struct net_device *dev = platform_get_drvdata(ofdev); 39348c2ecf20Sopenharmony_ci struct ucc_geth_private *ugeth = netdev_priv(dev); 39358c2ecf20Sopenharmony_ci struct device_node *np = ofdev->dev.of_node; 39368c2ecf20Sopenharmony_ci 39378c2ecf20Sopenharmony_ci unregister_netdev(dev); 39388c2ecf20Sopenharmony_ci ucc_geth_memclean(ugeth); 39398c2ecf20Sopenharmony_ci if (of_phy_is_fixed_link(np)) 39408c2ecf20Sopenharmony_ci of_phy_deregister_fixed_link(np); 39418c2ecf20Sopenharmony_ci of_node_put(ugeth->ug_info->tbi_node); 39428c2ecf20Sopenharmony_ci of_node_put(ugeth->ug_info->phy_node); 39438c2ecf20Sopenharmony_ci free_netdev(dev); 39448c2ecf20Sopenharmony_ci 39458c2ecf20Sopenharmony_ci return 0; 39468c2ecf20Sopenharmony_ci} 39478c2ecf20Sopenharmony_ci 39488c2ecf20Sopenharmony_cistatic const struct of_device_id ucc_geth_match[] = { 39498c2ecf20Sopenharmony_ci { 39508c2ecf20Sopenharmony_ci .type = "network", 39518c2ecf20Sopenharmony_ci .compatible = "ucc_geth", 39528c2ecf20Sopenharmony_ci }, 39538c2ecf20Sopenharmony_ci {}, 39548c2ecf20Sopenharmony_ci}; 39558c2ecf20Sopenharmony_ci 39568c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, ucc_geth_match); 39578c2ecf20Sopenharmony_ci 39588c2ecf20Sopenharmony_cistatic struct platform_driver ucc_geth_driver = { 39598c2ecf20Sopenharmony_ci .driver = { 39608c2ecf20Sopenharmony_ci .name = DRV_NAME, 39618c2ecf20Sopenharmony_ci .of_match_table = ucc_geth_match, 39628c2ecf20Sopenharmony_ci }, 39638c2ecf20Sopenharmony_ci .probe = ucc_geth_probe, 39648c2ecf20Sopenharmony_ci .remove = ucc_geth_remove, 39658c2ecf20Sopenharmony_ci .suspend = ucc_geth_suspend, 39668c2ecf20Sopenharmony_ci .resume = ucc_geth_resume, 39678c2ecf20Sopenharmony_ci}; 39688c2ecf20Sopenharmony_ci 39698c2ecf20Sopenharmony_cistatic int __init ucc_geth_init(void) 39708c2ecf20Sopenharmony_ci{ 39718c2ecf20Sopenharmony_ci int i, ret; 39728c2ecf20Sopenharmony_ci 39738c2ecf20Sopenharmony_ci if (netif_msg_drv(&debug)) 39748c2ecf20Sopenharmony_ci pr_info(DRV_DESC "\n"); 39758c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 39768c2ecf20Sopenharmony_ci memcpy(&(ugeth_info[i]), &ugeth_primary_info, 39778c2ecf20Sopenharmony_ci sizeof(ugeth_primary_info)); 39788c2ecf20Sopenharmony_ci 39798c2ecf20Sopenharmony_ci ret = platform_driver_register(&ucc_geth_driver); 39808c2ecf20Sopenharmony_ci 39818c2ecf20Sopenharmony_ci return ret; 39828c2ecf20Sopenharmony_ci} 39838c2ecf20Sopenharmony_ci 39848c2ecf20Sopenharmony_cistatic void __exit ucc_geth_exit(void) 39858c2ecf20Sopenharmony_ci{ 39868c2ecf20Sopenharmony_ci platform_driver_unregister(&ucc_geth_driver); 39878c2ecf20Sopenharmony_ci} 39888c2ecf20Sopenharmony_ci 39898c2ecf20Sopenharmony_cimodule_init(ucc_geth_init); 39908c2ecf20Sopenharmony_cimodule_exit(ucc_geth_exit); 39918c2ecf20Sopenharmony_ci 39928c2ecf20Sopenharmony_ciMODULE_AUTHOR("Freescale Semiconductor, Inc"); 39938c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DRV_DESC); 39948c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 3995