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(&reg[0], ((u16)mac[5] << 8) | mac[4]);
3868c2ecf20Sopenharmony_ci	out_be16(&reg[1], ((u16)mac[3] << 8) | mac[2]);
3878c2ecf20Sopenharmony_ci	out_be16(&reg[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