162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Author: Shlomi Gridish <gridish@freescale.com>
662306a36Sopenharmony_ci *	   Li Yang <leoli@freescale.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Description:
962306a36Sopenharmony_ci * QE UCC Gigabit Ethernet Driver
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <linux/kernel.h>
1562306a36Sopenharmony_ci#include <linux/init.h>
1662306a36Sopenharmony_ci#include <linux/errno.h>
1762306a36Sopenharmony_ci#include <linux/slab.h>
1862306a36Sopenharmony_ci#include <linux/stddef.h>
1962306a36Sopenharmony_ci#include <linux/module.h>
2062306a36Sopenharmony_ci#include <linux/interrupt.h>
2162306a36Sopenharmony_ci#include <linux/netdevice.h>
2262306a36Sopenharmony_ci#include <linux/etherdevice.h>
2362306a36Sopenharmony_ci#include <linux/skbuff.h>
2462306a36Sopenharmony_ci#include <linux/spinlock.h>
2562306a36Sopenharmony_ci#include <linux/mm.h>
2662306a36Sopenharmony_ci#include <linux/dma-mapping.h>
2762306a36Sopenharmony_ci#include <linux/mii.h>
2862306a36Sopenharmony_ci#include <linux/phy.h>
2962306a36Sopenharmony_ci#include <linux/phy_fixed.h>
3062306a36Sopenharmony_ci#include <linux/workqueue.h>
3162306a36Sopenharmony_ci#include <linux/of.h>
3262306a36Sopenharmony_ci#include <linux/of_address.h>
3362306a36Sopenharmony_ci#include <linux/of_irq.h>
3462306a36Sopenharmony_ci#include <linux/of_mdio.h>
3562306a36Sopenharmony_ci#include <linux/of_net.h>
3662306a36Sopenharmony_ci#include <linux/platform_device.h>
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#include <linux/uaccess.h>
3962306a36Sopenharmony_ci#include <asm/irq.h>
4062306a36Sopenharmony_ci#include <asm/io.h>
4162306a36Sopenharmony_ci#include <soc/fsl/qe/immap_qe.h>
4262306a36Sopenharmony_ci#include <soc/fsl/qe/qe.h>
4362306a36Sopenharmony_ci#include <soc/fsl/qe/ucc.h>
4462306a36Sopenharmony_ci#include <soc/fsl/qe/ucc_fast.h>
4562306a36Sopenharmony_ci#include <asm/machdep.h>
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#include "ucc_geth.h"
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#undef DEBUG
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#define ugeth_printk(level, format, arg...)  \
5262306a36Sopenharmony_ci        printk(level format "\n", ## arg)
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define ugeth_dbg(format, arg...)            \
5562306a36Sopenharmony_ci        ugeth_printk(KERN_DEBUG , format , ## arg)
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#ifdef UGETH_VERBOSE_DEBUG
5862306a36Sopenharmony_ci#define ugeth_vdbg ugeth_dbg
5962306a36Sopenharmony_ci#else
6062306a36Sopenharmony_ci#define ugeth_vdbg(fmt, args...) do { } while (0)
6162306a36Sopenharmony_ci#endif				/* UGETH_VERBOSE_DEBUG */
6262306a36Sopenharmony_ci#define UGETH_MSG_DEFAULT	(NETIF_MSG_IFUP << 1 ) - 1
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic DEFINE_SPINLOCK(ugeth_lock);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic struct {
6862306a36Sopenharmony_ci	u32 msg_enable;
6962306a36Sopenharmony_ci} debug = { -1 };
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cimodule_param_named(debug, debug.msg_enable, int, 0);
7262306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 0xffff=all)");
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistatic int ucc_geth_thread_count(enum ucc_geth_num_of_threads idx)
7562306a36Sopenharmony_ci{
7662306a36Sopenharmony_ci	static const u8 count[] = {
7762306a36Sopenharmony_ci		[UCC_GETH_NUM_OF_THREADS_1] = 1,
7862306a36Sopenharmony_ci		[UCC_GETH_NUM_OF_THREADS_2] = 2,
7962306a36Sopenharmony_ci		[UCC_GETH_NUM_OF_THREADS_4] = 4,
8062306a36Sopenharmony_ci		[UCC_GETH_NUM_OF_THREADS_6] = 6,
8162306a36Sopenharmony_ci		[UCC_GETH_NUM_OF_THREADS_8] = 8,
8262306a36Sopenharmony_ci	};
8362306a36Sopenharmony_ci	if (idx >= ARRAY_SIZE(count))
8462306a36Sopenharmony_ci		return 0;
8562306a36Sopenharmony_ci	return count[idx];
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic inline int ucc_geth_tx_queues(const struct ucc_geth_info *info)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	return 1;
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic inline int ucc_geth_rx_queues(const struct ucc_geth_info *info)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	return 1;
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic const struct ucc_geth_info ugeth_primary_info = {
9962306a36Sopenharmony_ci	.uf_info = {
10062306a36Sopenharmony_ci		    .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES,
10162306a36Sopenharmony_ci		    .max_rx_buf_length = 1536,
10262306a36Sopenharmony_ci		    /* adjusted at startup if max-speed 1000 */
10362306a36Sopenharmony_ci		    .urfs = UCC_GETH_URFS_INIT,
10462306a36Sopenharmony_ci		    .urfet = UCC_GETH_URFET_INIT,
10562306a36Sopenharmony_ci		    .urfset = UCC_GETH_URFSET_INIT,
10662306a36Sopenharmony_ci		    .utfs = UCC_GETH_UTFS_INIT,
10762306a36Sopenharmony_ci		    .utfet = UCC_GETH_UTFET_INIT,
10862306a36Sopenharmony_ci		    .utftt = UCC_GETH_UTFTT_INIT,
10962306a36Sopenharmony_ci		    .ufpt = 256,
11062306a36Sopenharmony_ci		    .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET,
11162306a36Sopenharmony_ci		    .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL,
11262306a36Sopenharmony_ci		    .tenc = UCC_FAST_TX_ENCODING_NRZ,
11362306a36Sopenharmony_ci		    .renc = UCC_FAST_RX_ENCODING_NRZ,
11462306a36Sopenharmony_ci		    .tcrc = UCC_FAST_16_BIT_CRC,
11562306a36Sopenharmony_ci		    .synl = UCC_FAST_SYNC_LEN_NOT_USED,
11662306a36Sopenharmony_ci		    },
11762306a36Sopenharmony_ci	.extendedFilteringChainPointer = ((uint32_t) NULL),
11862306a36Sopenharmony_ci	.typeorlen = 3072 /*1536 */ ,
11962306a36Sopenharmony_ci	.nonBackToBackIfgPart1 = 0x40,
12062306a36Sopenharmony_ci	.nonBackToBackIfgPart2 = 0x60,
12162306a36Sopenharmony_ci	.miminumInterFrameGapEnforcement = 0x50,
12262306a36Sopenharmony_ci	.backToBackInterFrameGap = 0x60,
12362306a36Sopenharmony_ci	.mblinterval = 128,
12462306a36Sopenharmony_ci	.nortsrbytetime = 5,
12562306a36Sopenharmony_ci	.fracsiz = 1,
12662306a36Sopenharmony_ci	.strictpriorityq = 0xff,
12762306a36Sopenharmony_ci	.altBebTruncation = 0xa,
12862306a36Sopenharmony_ci	.excessDefer = 1,
12962306a36Sopenharmony_ci	.maxRetransmission = 0xf,
13062306a36Sopenharmony_ci	.collisionWindow = 0x37,
13162306a36Sopenharmony_ci	.receiveFlowControl = 1,
13262306a36Sopenharmony_ci	.transmitFlowControl = 1,
13362306a36Sopenharmony_ci	.maxGroupAddrInHash = 4,
13462306a36Sopenharmony_ci	.maxIndAddrInHash = 4,
13562306a36Sopenharmony_ci	.prel = 7,
13662306a36Sopenharmony_ci	.maxFrameLength = 1518+16, /* Add extra bytes for VLANs etc. */
13762306a36Sopenharmony_ci	.minFrameLength = 64,
13862306a36Sopenharmony_ci	.maxD1Length = 1520+16, /* Add extra bytes for VLANs etc. */
13962306a36Sopenharmony_ci	.maxD2Length = 1520+16, /* Add extra bytes for VLANs etc. */
14062306a36Sopenharmony_ci	.vlantype = 0x8100,
14162306a36Sopenharmony_ci	.ecamptr = ((uint32_t) NULL),
14262306a36Sopenharmony_ci	.eventRegMask = UCCE_OTHER,
14362306a36Sopenharmony_ci	.pausePeriod = 0xf000,
14462306a36Sopenharmony_ci	.interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1},
14562306a36Sopenharmony_ci	.bdRingLenTx = {
14662306a36Sopenharmony_ci			TX_BD_RING_LEN,
14762306a36Sopenharmony_ci			TX_BD_RING_LEN,
14862306a36Sopenharmony_ci			TX_BD_RING_LEN,
14962306a36Sopenharmony_ci			TX_BD_RING_LEN,
15062306a36Sopenharmony_ci			TX_BD_RING_LEN,
15162306a36Sopenharmony_ci			TX_BD_RING_LEN,
15262306a36Sopenharmony_ci			TX_BD_RING_LEN,
15362306a36Sopenharmony_ci			TX_BD_RING_LEN},
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	.bdRingLenRx = {
15662306a36Sopenharmony_ci			RX_BD_RING_LEN,
15762306a36Sopenharmony_ci			RX_BD_RING_LEN,
15862306a36Sopenharmony_ci			RX_BD_RING_LEN,
15962306a36Sopenharmony_ci			RX_BD_RING_LEN,
16062306a36Sopenharmony_ci			RX_BD_RING_LEN,
16162306a36Sopenharmony_ci			RX_BD_RING_LEN,
16262306a36Sopenharmony_ci			RX_BD_RING_LEN,
16362306a36Sopenharmony_ci			RX_BD_RING_LEN},
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	.numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1,
16662306a36Sopenharmony_ci	.largestexternallookupkeysize =
16762306a36Sopenharmony_ci	    QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE,
16862306a36Sopenharmony_ci	.statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE |
16962306a36Sopenharmony_ci		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX |
17062306a36Sopenharmony_ci		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX,
17162306a36Sopenharmony_ci	.vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP,
17262306a36Sopenharmony_ci	.vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP,
17362306a36Sopenharmony_ci	.rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT,
17462306a36Sopenharmony_ci	.aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE,
17562306a36Sopenharmony_ci	.padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC,
17662306a36Sopenharmony_ci	.numThreadsTx = UCC_GETH_NUM_OF_THREADS_1,
17762306a36Sopenharmony_ci	.numThreadsRx = UCC_GETH_NUM_OF_THREADS_1,
17862306a36Sopenharmony_ci	.riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
17962306a36Sopenharmony_ci	.riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
18062306a36Sopenharmony_ci};
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci#ifdef DEBUG
18362306a36Sopenharmony_cistatic void mem_disp(u8 *addr, int size)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	u8 *i;
18662306a36Sopenharmony_ci	int size16Aling = (size >> 4) << 4;
18762306a36Sopenharmony_ci	int size4Aling = (size >> 2) << 2;
18862306a36Sopenharmony_ci	int notAlign = 0;
18962306a36Sopenharmony_ci	if (size % 16)
19062306a36Sopenharmony_ci		notAlign = 1;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16)
19362306a36Sopenharmony_ci		printk("0x%08x: %08x %08x %08x %08x\r\n",
19462306a36Sopenharmony_ci		       (u32) i,
19562306a36Sopenharmony_ci		       *((u32 *) (i)),
19662306a36Sopenharmony_ci		       *((u32 *) (i + 4)),
19762306a36Sopenharmony_ci		       *((u32 *) (i + 8)), *((u32 *) (i + 12)));
19862306a36Sopenharmony_ci	if (notAlign == 1)
19962306a36Sopenharmony_ci		printk("0x%08x: ", (u32) i);
20062306a36Sopenharmony_ci	for (; (u32) i < (u32) addr + size4Aling; i += 4)
20162306a36Sopenharmony_ci		printk("%08x ", *((u32 *) (i)));
20262306a36Sopenharmony_ci	for (; (u32) i < (u32) addr + size; i++)
20362306a36Sopenharmony_ci		printk("%02x", *((i)));
20462306a36Sopenharmony_ci	if (notAlign == 1)
20562306a36Sopenharmony_ci		printk("\r\n");
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci#endif /* DEBUG */
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic struct list_head *dequeue(struct list_head *lh)
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	unsigned long flags;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	spin_lock_irqsave(&ugeth_lock, flags);
21462306a36Sopenharmony_ci	if (!list_empty(lh)) {
21562306a36Sopenharmony_ci		struct list_head *node = lh->next;
21662306a36Sopenharmony_ci		list_del(node);
21762306a36Sopenharmony_ci		spin_unlock_irqrestore(&ugeth_lock, flags);
21862306a36Sopenharmony_ci		return node;
21962306a36Sopenharmony_ci	} else {
22062306a36Sopenharmony_ci		spin_unlock_irqrestore(&ugeth_lock, flags);
22162306a36Sopenharmony_ci		return NULL;
22262306a36Sopenharmony_ci	}
22362306a36Sopenharmony_ci}
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_cistatic struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
22662306a36Sopenharmony_ci		u8 __iomem *bd)
22762306a36Sopenharmony_ci{
22862306a36Sopenharmony_ci	struct sk_buff *skb;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	skb = netdev_alloc_skb(ugeth->ndev,
23162306a36Sopenharmony_ci			       ugeth->ug_info->uf_info.max_rx_buf_length +
23262306a36Sopenharmony_ci			       UCC_GETH_RX_DATA_BUF_ALIGNMENT);
23362306a36Sopenharmony_ci	if (!skb)
23462306a36Sopenharmony_ci		return NULL;
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	/* We need the data buffer to be aligned properly.  We will reserve
23762306a36Sopenharmony_ci	 * as many bytes as needed to align the data properly
23862306a36Sopenharmony_ci	 */
23962306a36Sopenharmony_ci	skb_reserve(skb,
24062306a36Sopenharmony_ci		    UCC_GETH_RX_DATA_BUF_ALIGNMENT -
24162306a36Sopenharmony_ci		    (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
24262306a36Sopenharmony_ci					      1)));
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	out_be32(&((struct qe_bd __iomem *)bd)->buf,
24562306a36Sopenharmony_ci		      dma_map_single(ugeth->dev,
24662306a36Sopenharmony_ci				     skb->data,
24762306a36Sopenharmony_ci				     ugeth->ug_info->uf_info.max_rx_buf_length +
24862306a36Sopenharmony_ci				     UCC_GETH_RX_DATA_BUF_ALIGNMENT,
24962306a36Sopenharmony_ci				     DMA_FROM_DEVICE));
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	out_be32((u32 __iomem *)bd,
25262306a36Sopenharmony_ci			(R_E | R_I | (in_be32((u32 __iomem*)bd) & R_W)));
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	return skb;
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cistatic int rx_bd_buffer_set(struct ucc_geth_private *ugeth, u8 rxQ)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	u8 __iomem *bd;
26062306a36Sopenharmony_ci	u32 bd_status;
26162306a36Sopenharmony_ci	struct sk_buff *skb;
26262306a36Sopenharmony_ci	int i;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	bd = ugeth->p_rx_bd_ring[rxQ];
26562306a36Sopenharmony_ci	i = 0;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	do {
26862306a36Sopenharmony_ci		bd_status = in_be32((u32 __iomem *)bd);
26962306a36Sopenharmony_ci		skb = get_new_skb(ugeth, bd);
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci		if (!skb)	/* If can not allocate data buffer,
27262306a36Sopenharmony_ci				abort. Cleanup will be elsewhere */
27362306a36Sopenharmony_ci			return -ENOMEM;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci		ugeth->rx_skbuff[rxQ][i] = skb;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci		/* advance the BD pointer */
27862306a36Sopenharmony_ci		bd += sizeof(struct qe_bd);
27962306a36Sopenharmony_ci		i++;
28062306a36Sopenharmony_ci	} while (!(bd_status & R_W));
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	return 0;
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_cistatic int fill_init_enet_entries(struct ucc_geth_private *ugeth,
28662306a36Sopenharmony_ci				  u32 *p_start,
28762306a36Sopenharmony_ci				  u8 num_entries,
28862306a36Sopenharmony_ci				  u32 thread_size,
28962306a36Sopenharmony_ci				  u32 thread_alignment,
29062306a36Sopenharmony_ci				  unsigned int risc,
29162306a36Sopenharmony_ci				  int skip_page_for_first_entry)
29262306a36Sopenharmony_ci{
29362306a36Sopenharmony_ci	u32 init_enet_offset;
29462306a36Sopenharmony_ci	u8 i;
29562306a36Sopenharmony_ci	int snum;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	for (i = 0; i < num_entries; i++) {
29862306a36Sopenharmony_ci		if ((snum = qe_get_snum()) < 0) {
29962306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
30062306a36Sopenharmony_ci				pr_err("Can not get SNUM\n");
30162306a36Sopenharmony_ci			return snum;
30262306a36Sopenharmony_ci		}
30362306a36Sopenharmony_ci		if ((i == 0) && skip_page_for_first_entry)
30462306a36Sopenharmony_ci		/* First entry of Rx does not have page */
30562306a36Sopenharmony_ci			init_enet_offset = 0;
30662306a36Sopenharmony_ci		else {
30762306a36Sopenharmony_ci			init_enet_offset =
30862306a36Sopenharmony_ci			    qe_muram_alloc(thread_size, thread_alignment);
30962306a36Sopenharmony_ci			if (IS_ERR_VALUE(init_enet_offset)) {
31062306a36Sopenharmony_ci				if (netif_msg_ifup(ugeth))
31162306a36Sopenharmony_ci					pr_err("Can not allocate DPRAM memory\n");
31262306a36Sopenharmony_ci				qe_put_snum((u8) snum);
31362306a36Sopenharmony_ci				return -ENOMEM;
31462306a36Sopenharmony_ci			}
31562306a36Sopenharmony_ci		}
31662306a36Sopenharmony_ci		*(p_start++) =
31762306a36Sopenharmony_ci		    ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset
31862306a36Sopenharmony_ci		    | risc;
31962306a36Sopenharmony_ci	}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	return 0;
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistatic int return_init_enet_entries(struct ucc_geth_private *ugeth,
32562306a36Sopenharmony_ci				    u32 *p_start,
32662306a36Sopenharmony_ci				    u8 num_entries,
32762306a36Sopenharmony_ci				    unsigned int risc,
32862306a36Sopenharmony_ci				    int skip_page_for_first_entry)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	u32 init_enet_offset;
33162306a36Sopenharmony_ci	u8 i;
33262306a36Sopenharmony_ci	int snum;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	for (i = 0; i < num_entries; i++) {
33562306a36Sopenharmony_ci		u32 val = *p_start;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci		/* Check that this entry was actually valid --
33862306a36Sopenharmony_ci		needed in case failed in allocations */
33962306a36Sopenharmony_ci		if ((val & ENET_INIT_PARAM_RISC_MASK) == risc) {
34062306a36Sopenharmony_ci			snum =
34162306a36Sopenharmony_ci			    (u32) (val & ENET_INIT_PARAM_SNUM_MASK) >>
34262306a36Sopenharmony_ci			    ENET_INIT_PARAM_SNUM_SHIFT;
34362306a36Sopenharmony_ci			qe_put_snum((u8) snum);
34462306a36Sopenharmony_ci			if (!((i == 0) && skip_page_for_first_entry)) {
34562306a36Sopenharmony_ci			/* First entry of Rx does not have page */
34662306a36Sopenharmony_ci				init_enet_offset =
34762306a36Sopenharmony_ci				    (val & ENET_INIT_PARAM_PTR_MASK);
34862306a36Sopenharmony_ci				qe_muram_free(init_enet_offset);
34962306a36Sopenharmony_ci			}
35062306a36Sopenharmony_ci			*p_start++ = 0;
35162306a36Sopenharmony_ci		}
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	return 0;
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci#ifdef DEBUG
35862306a36Sopenharmony_cistatic int dump_init_enet_entries(struct ucc_geth_private *ugeth,
35962306a36Sopenharmony_ci				  u32 __iomem *p_start,
36062306a36Sopenharmony_ci				  u8 num_entries,
36162306a36Sopenharmony_ci				  u32 thread_size,
36262306a36Sopenharmony_ci				  unsigned int risc,
36362306a36Sopenharmony_ci				  int skip_page_for_first_entry)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	u32 init_enet_offset;
36662306a36Sopenharmony_ci	u8 i;
36762306a36Sopenharmony_ci	int snum;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	for (i = 0; i < num_entries; i++) {
37062306a36Sopenharmony_ci		u32 val = in_be32(p_start);
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci		/* Check that this entry was actually valid --
37362306a36Sopenharmony_ci		needed in case failed in allocations */
37462306a36Sopenharmony_ci		if ((val & ENET_INIT_PARAM_RISC_MASK) == risc) {
37562306a36Sopenharmony_ci			snum =
37662306a36Sopenharmony_ci			    (u32) (val & ENET_INIT_PARAM_SNUM_MASK) >>
37762306a36Sopenharmony_ci			    ENET_INIT_PARAM_SNUM_SHIFT;
37862306a36Sopenharmony_ci			qe_put_snum((u8) snum);
37962306a36Sopenharmony_ci			if (!((i == 0) && skip_page_for_first_entry)) {
38062306a36Sopenharmony_ci			/* First entry of Rx does not have page */
38162306a36Sopenharmony_ci				init_enet_offset =
38262306a36Sopenharmony_ci				    (in_be32(p_start) &
38362306a36Sopenharmony_ci				     ENET_INIT_PARAM_PTR_MASK);
38462306a36Sopenharmony_ci				pr_info("Init enet entry %d:\n", i);
38562306a36Sopenharmony_ci				pr_info("Base address: 0x%08x\n",
38662306a36Sopenharmony_ci					(u32)qe_muram_addr(init_enet_offset));
38762306a36Sopenharmony_ci				mem_disp(qe_muram_addr(init_enet_offset),
38862306a36Sopenharmony_ci					 thread_size);
38962306a36Sopenharmony_ci			}
39062306a36Sopenharmony_ci			p_start++;
39162306a36Sopenharmony_ci		}
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	return 0;
39562306a36Sopenharmony_ci}
39662306a36Sopenharmony_ci#endif
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cistatic void put_enet_addr_container(struct enet_addr_container *enet_addr_cont)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	kfree(enet_addr_cont);
40162306a36Sopenharmony_ci}
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_cistatic void set_mac_addr(__be16 __iomem *reg, u8 *mac)
40462306a36Sopenharmony_ci{
40562306a36Sopenharmony_ci	out_be16(&reg[0], ((u16)mac[5] << 8) | mac[4]);
40662306a36Sopenharmony_ci	out_be16(&reg[1], ((u16)mac[3] << 8) | mac[2]);
40762306a36Sopenharmony_ci	out_be16(&reg[2], ((u16)mac[1] << 8) | mac[0]);
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num)
41162306a36Sopenharmony_ci{
41262306a36Sopenharmony_ci	struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	if (paddr_num >= NUM_OF_PADDRS) {
41562306a36Sopenharmony_ci		pr_warn("%s: Invalid paddr_num: %u\n", __func__, paddr_num);
41662306a36Sopenharmony_ci		return -EINVAL;
41762306a36Sopenharmony_ci	}
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	p_82xx_addr_filt =
42062306a36Sopenharmony_ci	    (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->p_rx_glbl_pram->
42162306a36Sopenharmony_ci	    addressfiltering;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	/* Writing address ff.ff.ff.ff.ff.ff disables address
42462306a36Sopenharmony_ci	recognition for this register */
42562306a36Sopenharmony_ci	out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff);
42662306a36Sopenharmony_ci	out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff);
42762306a36Sopenharmony_ci	out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	return 0;
43062306a36Sopenharmony_ci}
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_cistatic void hw_add_addr_in_hash(struct ucc_geth_private *ugeth,
43362306a36Sopenharmony_ci                                u8 *p_enet_addr)
43462306a36Sopenharmony_ci{
43562306a36Sopenharmony_ci	struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
43662306a36Sopenharmony_ci	u32 cecr_subblock;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	p_82xx_addr_filt =
43962306a36Sopenharmony_ci	    (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->p_rx_glbl_pram->
44062306a36Sopenharmony_ci	    addressfiltering;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	cecr_subblock =
44362306a36Sopenharmony_ci	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	/* Ethernet frames are defined in Little Endian mode,
44662306a36Sopenharmony_ci	therefore to insert */
44762306a36Sopenharmony_ci	/* the address to the hash (Big Endian mode), we reverse the bytes.*/
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	set_mac_addr(&p_82xx_addr_filt->taddr.h, p_enet_addr);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock,
45262306a36Sopenharmony_ci		     QE_CR_PROTOCOL_ETHERNET, 0);
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci#ifdef DEBUG
45662306a36Sopenharmony_cistatic void get_statistics(struct ucc_geth_private *ugeth,
45762306a36Sopenharmony_ci			   struct ucc_geth_tx_firmware_statistics *
45862306a36Sopenharmony_ci			   tx_firmware_statistics,
45962306a36Sopenharmony_ci			   struct ucc_geth_rx_firmware_statistics *
46062306a36Sopenharmony_ci			   rx_firmware_statistics,
46162306a36Sopenharmony_ci			   struct ucc_geth_hardware_statistics *hardware_statistics)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	struct ucc_fast __iomem *uf_regs;
46462306a36Sopenharmony_ci	struct ucc_geth __iomem *ug_regs;
46562306a36Sopenharmony_ci	struct ucc_geth_tx_firmware_statistics_pram *p_tx_fw_statistics_pram;
46662306a36Sopenharmony_ci	struct ucc_geth_rx_firmware_statistics_pram *p_rx_fw_statistics_pram;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	ug_regs = ugeth->ug_regs;
46962306a36Sopenharmony_ci	uf_regs = (struct ucc_fast __iomem *) ug_regs;
47062306a36Sopenharmony_ci	p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram;
47162306a36Sopenharmony_ci	p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram;
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	/* Tx firmware only if user handed pointer and driver actually
47462306a36Sopenharmony_ci	gathers Tx firmware statistics */
47562306a36Sopenharmony_ci	if (tx_firmware_statistics && p_tx_fw_statistics_pram) {
47662306a36Sopenharmony_ci		tx_firmware_statistics->sicoltx =
47762306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->sicoltx);
47862306a36Sopenharmony_ci		tx_firmware_statistics->mulcoltx =
47962306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->mulcoltx);
48062306a36Sopenharmony_ci		tx_firmware_statistics->latecoltxfr =
48162306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->latecoltxfr);
48262306a36Sopenharmony_ci		tx_firmware_statistics->frabortduecol =
48362306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->frabortduecol);
48462306a36Sopenharmony_ci		tx_firmware_statistics->frlostinmactxer =
48562306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->frlostinmactxer);
48662306a36Sopenharmony_ci		tx_firmware_statistics->carriersenseertx =
48762306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->carriersenseertx);
48862306a36Sopenharmony_ci		tx_firmware_statistics->frtxok =
48962306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->frtxok);
49062306a36Sopenharmony_ci		tx_firmware_statistics->txfrexcessivedefer =
49162306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer);
49262306a36Sopenharmony_ci		tx_firmware_statistics->txpkts256 =
49362306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->txpkts256);
49462306a36Sopenharmony_ci		tx_firmware_statistics->txpkts512 =
49562306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->txpkts512);
49662306a36Sopenharmony_ci		tx_firmware_statistics->txpkts1024 =
49762306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->txpkts1024);
49862306a36Sopenharmony_ci		tx_firmware_statistics->txpktsjumbo =
49962306a36Sopenharmony_ci		    in_be32(&p_tx_fw_statistics_pram->txpktsjumbo);
50062306a36Sopenharmony_ci	}
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	/* Rx firmware only if user handed pointer and driver actually
50362306a36Sopenharmony_ci	 * gathers Rx firmware statistics */
50462306a36Sopenharmony_ci	if (rx_firmware_statistics && p_rx_fw_statistics_pram) {
50562306a36Sopenharmony_ci		int i;
50662306a36Sopenharmony_ci		rx_firmware_statistics->frrxfcser =
50762306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->frrxfcser);
50862306a36Sopenharmony_ci		rx_firmware_statistics->fraligner =
50962306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->fraligner);
51062306a36Sopenharmony_ci		rx_firmware_statistics->inrangelenrxer =
51162306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->inrangelenrxer);
51262306a36Sopenharmony_ci		rx_firmware_statistics->outrangelenrxer =
51362306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->outrangelenrxer);
51462306a36Sopenharmony_ci		rx_firmware_statistics->frtoolong =
51562306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->frtoolong);
51662306a36Sopenharmony_ci		rx_firmware_statistics->runt =
51762306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->runt);
51862306a36Sopenharmony_ci		rx_firmware_statistics->verylongevent =
51962306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->verylongevent);
52062306a36Sopenharmony_ci		rx_firmware_statistics->symbolerror =
52162306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->symbolerror);
52262306a36Sopenharmony_ci		rx_firmware_statistics->dropbsy =
52362306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->dropbsy);
52462306a36Sopenharmony_ci		for (i = 0; i < 0x8; i++)
52562306a36Sopenharmony_ci			rx_firmware_statistics->res0[i] =
52662306a36Sopenharmony_ci			    p_rx_fw_statistics_pram->res0[i];
52762306a36Sopenharmony_ci		rx_firmware_statistics->mismatchdrop =
52862306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->mismatchdrop);
52962306a36Sopenharmony_ci		rx_firmware_statistics->underpkts =
53062306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->underpkts);
53162306a36Sopenharmony_ci		rx_firmware_statistics->pkts256 =
53262306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->pkts256);
53362306a36Sopenharmony_ci		rx_firmware_statistics->pkts512 =
53462306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->pkts512);
53562306a36Sopenharmony_ci		rx_firmware_statistics->pkts1024 =
53662306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->pkts1024);
53762306a36Sopenharmony_ci		rx_firmware_statistics->pktsjumbo =
53862306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->pktsjumbo);
53962306a36Sopenharmony_ci		rx_firmware_statistics->frlossinmacer =
54062306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->frlossinmacer);
54162306a36Sopenharmony_ci		rx_firmware_statistics->pausefr =
54262306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->pausefr);
54362306a36Sopenharmony_ci		for (i = 0; i < 0x4; i++)
54462306a36Sopenharmony_ci			rx_firmware_statistics->res1[i] =
54562306a36Sopenharmony_ci			    p_rx_fw_statistics_pram->res1[i];
54662306a36Sopenharmony_ci		rx_firmware_statistics->removevlan =
54762306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->removevlan);
54862306a36Sopenharmony_ci		rx_firmware_statistics->replacevlan =
54962306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->replacevlan);
55062306a36Sopenharmony_ci		rx_firmware_statistics->insertvlan =
55162306a36Sopenharmony_ci		    in_be32(&p_rx_fw_statistics_pram->insertvlan);
55262306a36Sopenharmony_ci	}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	/* Hardware only if user handed pointer and driver actually
55562306a36Sopenharmony_ci	gathers hardware statistics */
55662306a36Sopenharmony_ci	if (hardware_statistics &&
55762306a36Sopenharmony_ci	    (in_be32(&uf_regs->upsmr) & UCC_GETH_UPSMR_HSE)) {
55862306a36Sopenharmony_ci		hardware_statistics->tx64 = in_be32(&ug_regs->tx64);
55962306a36Sopenharmony_ci		hardware_statistics->tx127 = in_be32(&ug_regs->tx127);
56062306a36Sopenharmony_ci		hardware_statistics->tx255 = in_be32(&ug_regs->tx255);
56162306a36Sopenharmony_ci		hardware_statistics->rx64 = in_be32(&ug_regs->rx64);
56262306a36Sopenharmony_ci		hardware_statistics->rx127 = in_be32(&ug_regs->rx127);
56362306a36Sopenharmony_ci		hardware_statistics->rx255 = in_be32(&ug_regs->rx255);
56462306a36Sopenharmony_ci		hardware_statistics->txok = in_be32(&ug_regs->txok);
56562306a36Sopenharmony_ci		hardware_statistics->txcf = in_be16(&ug_regs->txcf);
56662306a36Sopenharmony_ci		hardware_statistics->tmca = in_be32(&ug_regs->tmca);
56762306a36Sopenharmony_ci		hardware_statistics->tbca = in_be32(&ug_regs->tbca);
56862306a36Sopenharmony_ci		hardware_statistics->rxfok = in_be32(&ug_regs->rxfok);
56962306a36Sopenharmony_ci		hardware_statistics->rxbok = in_be32(&ug_regs->rxbok);
57062306a36Sopenharmony_ci		hardware_statistics->rbyt = in_be32(&ug_regs->rbyt);
57162306a36Sopenharmony_ci		hardware_statistics->rmca = in_be32(&ug_regs->rmca);
57262306a36Sopenharmony_ci		hardware_statistics->rbca = in_be32(&ug_regs->rbca);
57362306a36Sopenharmony_ci	}
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_cistatic void dump_bds(struct ucc_geth_private *ugeth)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci	int i;
57962306a36Sopenharmony_ci	int length;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_tx_queues(ugeth->ug_info); i++) {
58262306a36Sopenharmony_ci		if (ugeth->p_tx_bd_ring[i]) {
58362306a36Sopenharmony_ci			length =
58462306a36Sopenharmony_ci			    (ugeth->ug_info->bdRingLenTx[i] *
58562306a36Sopenharmony_ci			     sizeof(struct qe_bd));
58662306a36Sopenharmony_ci			pr_info("TX BDs[%d]\n", i);
58762306a36Sopenharmony_ci			mem_disp(ugeth->p_tx_bd_ring[i], length);
58862306a36Sopenharmony_ci		}
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_rx_queues(ugeth->ug_info); i++) {
59162306a36Sopenharmony_ci		if (ugeth->p_rx_bd_ring[i]) {
59262306a36Sopenharmony_ci			length =
59362306a36Sopenharmony_ci			    (ugeth->ug_info->bdRingLenRx[i] *
59462306a36Sopenharmony_ci			     sizeof(struct qe_bd));
59562306a36Sopenharmony_ci			pr_info("RX BDs[%d]\n", i);
59662306a36Sopenharmony_ci			mem_disp(ugeth->p_rx_bd_ring[i], length);
59762306a36Sopenharmony_ci		}
59862306a36Sopenharmony_ci	}
59962306a36Sopenharmony_ci}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_cistatic void dump_regs(struct ucc_geth_private *ugeth)
60262306a36Sopenharmony_ci{
60362306a36Sopenharmony_ci	int i;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	pr_info("UCC%d Geth registers:\n", ugeth->ug_info->uf_info.ucc_num + 1);
60662306a36Sopenharmony_ci	pr_info("Base address: 0x%08x\n", (u32)ugeth->ug_regs);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	pr_info("maccfg1    : addr - 0x%08x, val - 0x%08x\n",
60962306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->maccfg1,
61062306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->maccfg1));
61162306a36Sopenharmony_ci	pr_info("maccfg2    : addr - 0x%08x, val - 0x%08x\n",
61262306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->maccfg2,
61362306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->maccfg2));
61462306a36Sopenharmony_ci	pr_info("ipgifg     : addr - 0x%08x, val - 0x%08x\n",
61562306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->ipgifg,
61662306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->ipgifg));
61762306a36Sopenharmony_ci	pr_info("hafdup     : addr - 0x%08x, val - 0x%08x\n",
61862306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->hafdup,
61962306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->hafdup));
62062306a36Sopenharmony_ci	pr_info("ifctl      : addr - 0x%08x, val - 0x%08x\n",
62162306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->ifctl,
62262306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->ifctl));
62362306a36Sopenharmony_ci	pr_info("ifstat     : addr - 0x%08x, val - 0x%08x\n",
62462306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->ifstat,
62562306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->ifstat));
62662306a36Sopenharmony_ci	pr_info("macstnaddr1: addr - 0x%08x, val - 0x%08x\n",
62762306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->macstnaddr1,
62862306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->macstnaddr1));
62962306a36Sopenharmony_ci	pr_info("macstnaddr2: addr - 0x%08x, val - 0x%08x\n",
63062306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->macstnaddr2,
63162306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->macstnaddr2));
63262306a36Sopenharmony_ci	pr_info("uempr      : addr - 0x%08x, val - 0x%08x\n",
63362306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->uempr,
63462306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->uempr));
63562306a36Sopenharmony_ci	pr_info("utbipar    : addr - 0x%08x, val - 0x%08x\n",
63662306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->utbipar,
63762306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->utbipar));
63862306a36Sopenharmony_ci	pr_info("uescr      : addr - 0x%08x, val - 0x%04x\n",
63962306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->uescr,
64062306a36Sopenharmony_ci		in_be16(&ugeth->ug_regs->uescr));
64162306a36Sopenharmony_ci	pr_info("tx64       : addr - 0x%08x, val - 0x%08x\n",
64262306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->tx64,
64362306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->tx64));
64462306a36Sopenharmony_ci	pr_info("tx127      : addr - 0x%08x, val - 0x%08x\n",
64562306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->tx127,
64662306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->tx127));
64762306a36Sopenharmony_ci	pr_info("tx255      : addr - 0x%08x, val - 0x%08x\n",
64862306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->tx255,
64962306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->tx255));
65062306a36Sopenharmony_ci	pr_info("rx64       : addr - 0x%08x, val - 0x%08x\n",
65162306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->rx64,
65262306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->rx64));
65362306a36Sopenharmony_ci	pr_info("rx127      : addr - 0x%08x, val - 0x%08x\n",
65462306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->rx127,
65562306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->rx127));
65662306a36Sopenharmony_ci	pr_info("rx255      : addr - 0x%08x, val - 0x%08x\n",
65762306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->rx255,
65862306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->rx255));
65962306a36Sopenharmony_ci	pr_info("txok       : addr - 0x%08x, val - 0x%08x\n",
66062306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->txok,
66162306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->txok));
66262306a36Sopenharmony_ci	pr_info("txcf       : addr - 0x%08x, val - 0x%04x\n",
66362306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->txcf,
66462306a36Sopenharmony_ci		in_be16(&ugeth->ug_regs->txcf));
66562306a36Sopenharmony_ci	pr_info("tmca       : addr - 0x%08x, val - 0x%08x\n",
66662306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->tmca,
66762306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->tmca));
66862306a36Sopenharmony_ci	pr_info("tbca       : addr - 0x%08x, val - 0x%08x\n",
66962306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->tbca,
67062306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->tbca));
67162306a36Sopenharmony_ci	pr_info("rxfok      : addr - 0x%08x, val - 0x%08x\n",
67262306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->rxfok,
67362306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->rxfok));
67462306a36Sopenharmony_ci	pr_info("rxbok      : addr - 0x%08x, val - 0x%08x\n",
67562306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->rxbok,
67662306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->rxbok));
67762306a36Sopenharmony_ci	pr_info("rbyt       : addr - 0x%08x, val - 0x%08x\n",
67862306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->rbyt,
67962306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->rbyt));
68062306a36Sopenharmony_ci	pr_info("rmca       : addr - 0x%08x, val - 0x%08x\n",
68162306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->rmca,
68262306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->rmca));
68362306a36Sopenharmony_ci	pr_info("rbca       : addr - 0x%08x, val - 0x%08x\n",
68462306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->rbca,
68562306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->rbca));
68662306a36Sopenharmony_ci	pr_info("scar       : addr - 0x%08x, val - 0x%08x\n",
68762306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->scar,
68862306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->scar));
68962306a36Sopenharmony_ci	pr_info("scam       : addr - 0x%08x, val - 0x%08x\n",
69062306a36Sopenharmony_ci		(u32)&ugeth->ug_regs->scam,
69162306a36Sopenharmony_ci		in_be32(&ugeth->ug_regs->scam));
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if (ugeth->p_thread_data_tx) {
69462306a36Sopenharmony_ci		int count = ucc_geth_thread_count(ugeth->ug_info->numThreadsTx);
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci		pr_info("Thread data TXs:\n");
69762306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n",
69862306a36Sopenharmony_ci			(u32)ugeth->p_thread_data_tx);
69962306a36Sopenharmony_ci		for (i = 0; i < count; i++) {
70062306a36Sopenharmony_ci			pr_info("Thread data TX[%d]:\n", i);
70162306a36Sopenharmony_ci			pr_info("Base address: 0x%08x\n",
70262306a36Sopenharmony_ci				(u32)&ugeth->p_thread_data_tx[i]);
70362306a36Sopenharmony_ci			mem_disp((u8 *) & ugeth->p_thread_data_tx[i],
70462306a36Sopenharmony_ci				 sizeof(struct ucc_geth_thread_data_tx));
70562306a36Sopenharmony_ci		}
70662306a36Sopenharmony_ci	}
70762306a36Sopenharmony_ci	if (ugeth->p_thread_data_rx) {
70862306a36Sopenharmony_ci		int count = ucc_geth_thread_count(ugeth->ug_info->numThreadsRx);
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci		pr_info("Thread data RX:\n");
71162306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n",
71262306a36Sopenharmony_ci			(u32)ugeth->p_thread_data_rx);
71362306a36Sopenharmony_ci		for (i = 0; i < count; i++) {
71462306a36Sopenharmony_ci			pr_info("Thread data RX[%d]:\n", i);
71562306a36Sopenharmony_ci			pr_info("Base address: 0x%08x\n",
71662306a36Sopenharmony_ci				(u32)&ugeth->p_thread_data_rx[i]);
71762306a36Sopenharmony_ci			mem_disp((u8 *) & ugeth->p_thread_data_rx[i],
71862306a36Sopenharmony_ci				 sizeof(struct ucc_geth_thread_data_rx));
71962306a36Sopenharmony_ci		}
72062306a36Sopenharmony_ci	}
72162306a36Sopenharmony_ci	if (ugeth->p_exf_glbl_param) {
72262306a36Sopenharmony_ci		pr_info("EXF global param:\n");
72362306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n",
72462306a36Sopenharmony_ci			(u32)ugeth->p_exf_glbl_param);
72562306a36Sopenharmony_ci		mem_disp((u8 *) ugeth->p_exf_glbl_param,
72662306a36Sopenharmony_ci			 sizeof(*ugeth->p_exf_glbl_param));
72762306a36Sopenharmony_ci	}
72862306a36Sopenharmony_ci	if (ugeth->p_tx_glbl_pram) {
72962306a36Sopenharmony_ci		pr_info("TX global param:\n");
73062306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n", (u32)ugeth->p_tx_glbl_pram);
73162306a36Sopenharmony_ci		pr_info("temoder      : addr - 0x%08x, val - 0x%04x\n",
73262306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->temoder,
73362306a36Sopenharmony_ci			in_be16(&ugeth->p_tx_glbl_pram->temoder));
73462306a36Sopenharmony_ci	       pr_info("sqptr        : addr - 0x%08x, val - 0x%08x\n",
73562306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->sqptr,
73662306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->sqptr));
73762306a36Sopenharmony_ci		pr_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x\n",
73862306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->schedulerbasepointer,
73962306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer));
74062306a36Sopenharmony_ci		pr_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x\n",
74162306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->txrmonbaseptr,
74262306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr));
74362306a36Sopenharmony_ci		pr_info("tstate       : addr - 0x%08x, val - 0x%08x\n",
74462306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->tstate,
74562306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->tstate));
74662306a36Sopenharmony_ci		pr_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x\n",
74762306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->iphoffset[0],
74862306a36Sopenharmony_ci			ugeth->p_tx_glbl_pram->iphoffset[0]);
74962306a36Sopenharmony_ci		pr_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x\n",
75062306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->iphoffset[1],
75162306a36Sopenharmony_ci			ugeth->p_tx_glbl_pram->iphoffset[1]);
75262306a36Sopenharmony_ci		pr_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x\n",
75362306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->iphoffset[2],
75462306a36Sopenharmony_ci			ugeth->p_tx_glbl_pram->iphoffset[2]);
75562306a36Sopenharmony_ci		pr_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x\n",
75662306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->iphoffset[3],
75762306a36Sopenharmony_ci			ugeth->p_tx_glbl_pram->iphoffset[3]);
75862306a36Sopenharmony_ci		pr_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x\n",
75962306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->iphoffset[4],
76062306a36Sopenharmony_ci			ugeth->p_tx_glbl_pram->iphoffset[4]);
76162306a36Sopenharmony_ci		pr_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x\n",
76262306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->iphoffset[5],
76362306a36Sopenharmony_ci			ugeth->p_tx_glbl_pram->iphoffset[5]);
76462306a36Sopenharmony_ci		pr_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x\n",
76562306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->iphoffset[6],
76662306a36Sopenharmony_ci			ugeth->p_tx_glbl_pram->iphoffset[6]);
76762306a36Sopenharmony_ci		pr_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x\n",
76862306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->iphoffset[7],
76962306a36Sopenharmony_ci			ugeth->p_tx_glbl_pram->iphoffset[7]);
77062306a36Sopenharmony_ci		pr_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x\n",
77162306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->vtagtable[0],
77262306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0]));
77362306a36Sopenharmony_ci		pr_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x\n",
77462306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->vtagtable[1],
77562306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1]));
77662306a36Sopenharmony_ci		pr_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x\n",
77762306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->vtagtable[2],
77862306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2]));
77962306a36Sopenharmony_ci		pr_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x\n",
78062306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->vtagtable[3],
78162306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3]));
78262306a36Sopenharmony_ci		pr_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x\n",
78362306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->vtagtable[4],
78462306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4]));
78562306a36Sopenharmony_ci		pr_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x\n",
78662306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->vtagtable[5],
78762306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5]));
78862306a36Sopenharmony_ci		pr_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x\n",
78962306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->vtagtable[6],
79062306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6]));
79162306a36Sopenharmony_ci		pr_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x\n",
79262306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->vtagtable[7],
79362306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7]));
79462306a36Sopenharmony_ci		pr_info("tqptr        : addr - 0x%08x, val - 0x%08x\n",
79562306a36Sopenharmony_ci			(u32)&ugeth->p_tx_glbl_pram->tqptr,
79662306a36Sopenharmony_ci			in_be32(&ugeth->p_tx_glbl_pram->tqptr));
79762306a36Sopenharmony_ci	}
79862306a36Sopenharmony_ci	if (ugeth->p_rx_glbl_pram) {
79962306a36Sopenharmony_ci		pr_info("RX global param:\n");
80062306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n", (u32)ugeth->p_rx_glbl_pram);
80162306a36Sopenharmony_ci		pr_info("remoder         : addr - 0x%08x, val - 0x%08x\n",
80262306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->remoder,
80362306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->remoder));
80462306a36Sopenharmony_ci		pr_info("rqptr           : addr - 0x%08x, val - 0x%08x\n",
80562306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->rqptr,
80662306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->rqptr));
80762306a36Sopenharmony_ci		pr_info("typeorlen       : addr - 0x%08x, val - 0x%04x\n",
80862306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->typeorlen,
80962306a36Sopenharmony_ci			in_be16(&ugeth->p_rx_glbl_pram->typeorlen));
81062306a36Sopenharmony_ci		pr_info("rxgstpack       : addr - 0x%08x, val - 0x%02x\n",
81162306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->rxgstpack,
81262306a36Sopenharmony_ci			ugeth->p_rx_glbl_pram->rxgstpack);
81362306a36Sopenharmony_ci		pr_info("rxrmonbaseptr   : addr - 0x%08x, val - 0x%08x\n",
81462306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->rxrmonbaseptr,
81562306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr));
81662306a36Sopenharmony_ci		pr_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x\n",
81762306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->intcoalescingptr,
81862306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr));
81962306a36Sopenharmony_ci		pr_info("rstate          : addr - 0x%08x, val - 0x%02x\n",
82062306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->rstate,
82162306a36Sopenharmony_ci			ugeth->p_rx_glbl_pram->rstate);
82262306a36Sopenharmony_ci		pr_info("mrblr           : addr - 0x%08x, val - 0x%04x\n",
82362306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->mrblr,
82462306a36Sopenharmony_ci			in_be16(&ugeth->p_rx_glbl_pram->mrblr));
82562306a36Sopenharmony_ci		pr_info("rbdqptr         : addr - 0x%08x, val - 0x%08x\n",
82662306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->rbdqptr,
82762306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->rbdqptr));
82862306a36Sopenharmony_ci		pr_info("mflr            : addr - 0x%08x, val - 0x%04x\n",
82962306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->mflr,
83062306a36Sopenharmony_ci			in_be16(&ugeth->p_rx_glbl_pram->mflr));
83162306a36Sopenharmony_ci		pr_info("minflr          : addr - 0x%08x, val - 0x%04x\n",
83262306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->minflr,
83362306a36Sopenharmony_ci			in_be16(&ugeth->p_rx_glbl_pram->minflr));
83462306a36Sopenharmony_ci		pr_info("maxd1           : addr - 0x%08x, val - 0x%04x\n",
83562306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->maxd1,
83662306a36Sopenharmony_ci			in_be16(&ugeth->p_rx_glbl_pram->maxd1));
83762306a36Sopenharmony_ci		pr_info("maxd2           : addr - 0x%08x, val - 0x%04x\n",
83862306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->maxd2,
83962306a36Sopenharmony_ci			in_be16(&ugeth->p_rx_glbl_pram->maxd2));
84062306a36Sopenharmony_ci		pr_info("ecamptr         : addr - 0x%08x, val - 0x%08x\n",
84162306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->ecamptr,
84262306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->ecamptr));
84362306a36Sopenharmony_ci		pr_info("l2qt            : addr - 0x%08x, val - 0x%08x\n",
84462306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->l2qt,
84562306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->l2qt));
84662306a36Sopenharmony_ci		pr_info("l3qt[0]         : addr - 0x%08x, val - 0x%08x\n",
84762306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->l3qt[0],
84862306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->l3qt[0]));
84962306a36Sopenharmony_ci		pr_info("l3qt[1]         : addr - 0x%08x, val - 0x%08x\n",
85062306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->l3qt[1],
85162306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->l3qt[1]));
85262306a36Sopenharmony_ci		pr_info("l3qt[2]         : addr - 0x%08x, val - 0x%08x\n",
85362306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->l3qt[2],
85462306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->l3qt[2]));
85562306a36Sopenharmony_ci		pr_info("l3qt[3]         : addr - 0x%08x, val - 0x%08x\n",
85662306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->l3qt[3],
85762306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->l3qt[3]));
85862306a36Sopenharmony_ci		pr_info("l3qt[4]         : addr - 0x%08x, val - 0x%08x\n",
85962306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->l3qt[4],
86062306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->l3qt[4]));
86162306a36Sopenharmony_ci		pr_info("l3qt[5]         : addr - 0x%08x, val - 0x%08x\n",
86262306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->l3qt[5],
86362306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->l3qt[5]));
86462306a36Sopenharmony_ci		pr_info("l3qt[6]         : addr - 0x%08x, val - 0x%08x\n",
86562306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->l3qt[6],
86662306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->l3qt[6]));
86762306a36Sopenharmony_ci		pr_info("l3qt[7]         : addr - 0x%08x, val - 0x%08x\n",
86862306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->l3qt[7],
86962306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->l3qt[7]));
87062306a36Sopenharmony_ci		pr_info("vlantype        : addr - 0x%08x, val - 0x%04x\n",
87162306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->vlantype,
87262306a36Sopenharmony_ci			in_be16(&ugeth->p_rx_glbl_pram->vlantype));
87362306a36Sopenharmony_ci		pr_info("vlantci         : addr - 0x%08x, val - 0x%04x\n",
87462306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->vlantci,
87562306a36Sopenharmony_ci			in_be16(&ugeth->p_rx_glbl_pram->vlantci));
87662306a36Sopenharmony_ci		for (i = 0; i < 64; i++)
87762306a36Sopenharmony_ci			pr_info("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x\n",
87862306a36Sopenharmony_ci				i,
87962306a36Sopenharmony_ci				(u32)&ugeth->p_rx_glbl_pram->addressfiltering[i],
88062306a36Sopenharmony_ci				ugeth->p_rx_glbl_pram->addressfiltering[i]);
88162306a36Sopenharmony_ci		pr_info("exfGlobalParam  : addr - 0x%08x, val - 0x%08x\n",
88262306a36Sopenharmony_ci			(u32)&ugeth->p_rx_glbl_pram->exfGlobalParam,
88362306a36Sopenharmony_ci			in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam));
88462306a36Sopenharmony_ci	}
88562306a36Sopenharmony_ci	if (ugeth->p_send_q_mem_reg) {
88662306a36Sopenharmony_ci		pr_info("Send Q memory registers:\n");
88762306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n", (u32)ugeth->p_send_q_mem_reg);
88862306a36Sopenharmony_ci		for (i = 0; i < ucc_geth_tx_queues(ugeth->ug_info); i++) {
88962306a36Sopenharmony_ci			pr_info("SQQD[%d]:\n", i);
89062306a36Sopenharmony_ci			pr_info("Base address: 0x%08x\n",
89162306a36Sopenharmony_ci				(u32)&ugeth->p_send_q_mem_reg->sqqd[i]);
89262306a36Sopenharmony_ci			mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i],
89362306a36Sopenharmony_ci				 sizeof(struct ucc_geth_send_queue_qd));
89462306a36Sopenharmony_ci		}
89562306a36Sopenharmony_ci	}
89662306a36Sopenharmony_ci	if (ugeth->p_scheduler) {
89762306a36Sopenharmony_ci		pr_info("Scheduler:\n");
89862306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n", (u32)ugeth->p_scheduler);
89962306a36Sopenharmony_ci		mem_disp((u8 *) ugeth->p_scheduler,
90062306a36Sopenharmony_ci			 sizeof(*ugeth->p_scheduler));
90162306a36Sopenharmony_ci	}
90262306a36Sopenharmony_ci	if (ugeth->p_tx_fw_statistics_pram) {
90362306a36Sopenharmony_ci		pr_info("TX FW statistics pram:\n");
90462306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n",
90562306a36Sopenharmony_ci			(u32)ugeth->p_tx_fw_statistics_pram);
90662306a36Sopenharmony_ci		mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram,
90762306a36Sopenharmony_ci			 sizeof(*ugeth->p_tx_fw_statistics_pram));
90862306a36Sopenharmony_ci	}
90962306a36Sopenharmony_ci	if (ugeth->p_rx_fw_statistics_pram) {
91062306a36Sopenharmony_ci		pr_info("RX FW statistics pram:\n");
91162306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n",
91262306a36Sopenharmony_ci			(u32)ugeth->p_rx_fw_statistics_pram);
91362306a36Sopenharmony_ci		mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram,
91462306a36Sopenharmony_ci			 sizeof(*ugeth->p_rx_fw_statistics_pram));
91562306a36Sopenharmony_ci	}
91662306a36Sopenharmony_ci	if (ugeth->p_rx_irq_coalescing_tbl) {
91762306a36Sopenharmony_ci		pr_info("RX IRQ coalescing tables:\n");
91862306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n",
91962306a36Sopenharmony_ci			(u32)ugeth->p_rx_irq_coalescing_tbl);
92062306a36Sopenharmony_ci		for (i = 0; i < ucc_geth_rx_queues(ugeth->ug_info); i++) {
92162306a36Sopenharmony_ci			pr_info("RX IRQ coalescing table entry[%d]:\n", i);
92262306a36Sopenharmony_ci			pr_info("Base address: 0x%08x\n",
92362306a36Sopenharmony_ci				(u32)&ugeth->p_rx_irq_coalescing_tbl->
92462306a36Sopenharmony_ci				coalescingentry[i]);
92562306a36Sopenharmony_ci			pr_info("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x\n",
92662306a36Sopenharmony_ci				(u32)&ugeth->p_rx_irq_coalescing_tbl->
92762306a36Sopenharmony_ci				coalescingentry[i].interruptcoalescingmaxvalue,
92862306a36Sopenharmony_ci				in_be32(&ugeth->p_rx_irq_coalescing_tbl->
92962306a36Sopenharmony_ci					coalescingentry[i].
93062306a36Sopenharmony_ci					interruptcoalescingmaxvalue));
93162306a36Sopenharmony_ci			pr_info("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x\n",
93262306a36Sopenharmony_ci				(u32)&ugeth->p_rx_irq_coalescing_tbl->
93362306a36Sopenharmony_ci				coalescingentry[i].interruptcoalescingcounter,
93462306a36Sopenharmony_ci				in_be32(&ugeth->p_rx_irq_coalescing_tbl->
93562306a36Sopenharmony_ci					coalescingentry[i].
93662306a36Sopenharmony_ci					interruptcoalescingcounter));
93762306a36Sopenharmony_ci		}
93862306a36Sopenharmony_ci	}
93962306a36Sopenharmony_ci	if (ugeth->p_rx_bd_qs_tbl) {
94062306a36Sopenharmony_ci		pr_info("RX BD QS tables:\n");
94162306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n", (u32)ugeth->p_rx_bd_qs_tbl);
94262306a36Sopenharmony_ci		for (i = 0; i < ucc_geth_rx_queues(ugeth->ug_info); i++) {
94362306a36Sopenharmony_ci			pr_info("RX BD QS table[%d]:\n", i);
94462306a36Sopenharmony_ci			pr_info("Base address: 0x%08x\n",
94562306a36Sopenharmony_ci				(u32)&ugeth->p_rx_bd_qs_tbl[i]);
94662306a36Sopenharmony_ci			pr_info("bdbaseptr        : addr - 0x%08x, val - 0x%08x\n",
94762306a36Sopenharmony_ci				(u32)&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr,
94862306a36Sopenharmony_ci				in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr));
94962306a36Sopenharmony_ci			pr_info("bdptr            : addr - 0x%08x, val - 0x%08x\n",
95062306a36Sopenharmony_ci				(u32)&ugeth->p_rx_bd_qs_tbl[i].bdptr,
95162306a36Sopenharmony_ci				in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr));
95262306a36Sopenharmony_ci			pr_info("externalbdbaseptr: addr - 0x%08x, val - 0x%08x\n",
95362306a36Sopenharmony_ci				(u32)&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
95462306a36Sopenharmony_ci				in_be32(&ugeth->p_rx_bd_qs_tbl[i].
95562306a36Sopenharmony_ci					externalbdbaseptr));
95662306a36Sopenharmony_ci			pr_info("externalbdptr    : addr - 0x%08x, val - 0x%08x\n",
95762306a36Sopenharmony_ci				(u32)&ugeth->p_rx_bd_qs_tbl[i].externalbdptr,
95862306a36Sopenharmony_ci				in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr));
95962306a36Sopenharmony_ci			pr_info("ucode RX Prefetched BDs:\n");
96062306a36Sopenharmony_ci			pr_info("Base address: 0x%08x\n",
96162306a36Sopenharmony_ci				(u32)qe_muram_addr(in_be32
96262306a36Sopenharmony_ci						   (&ugeth->p_rx_bd_qs_tbl[i].
96362306a36Sopenharmony_ci						    bdbaseptr)));
96462306a36Sopenharmony_ci			mem_disp((u8 *)
96562306a36Sopenharmony_ci				 qe_muram_addr(in_be32
96662306a36Sopenharmony_ci					       (&ugeth->p_rx_bd_qs_tbl[i].
96762306a36Sopenharmony_ci						bdbaseptr)),
96862306a36Sopenharmony_ci				 sizeof(struct ucc_geth_rx_prefetched_bds));
96962306a36Sopenharmony_ci		}
97062306a36Sopenharmony_ci	}
97162306a36Sopenharmony_ci	if (ugeth->p_init_enet_param_shadow) {
97262306a36Sopenharmony_ci		int size;
97362306a36Sopenharmony_ci		pr_info("Init enet param shadow:\n");
97462306a36Sopenharmony_ci		pr_info("Base address: 0x%08x\n",
97562306a36Sopenharmony_ci			(u32) ugeth->p_init_enet_param_shadow);
97662306a36Sopenharmony_ci		mem_disp((u8 *) ugeth->p_init_enet_param_shadow,
97762306a36Sopenharmony_ci			 sizeof(*ugeth->p_init_enet_param_shadow));
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci		size = sizeof(struct ucc_geth_thread_rx_pram);
98062306a36Sopenharmony_ci		if (ugeth->ug_info->rxExtendedFiltering) {
98162306a36Sopenharmony_ci			size +=
98262306a36Sopenharmony_ci			    THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
98362306a36Sopenharmony_ci			if (ugeth->ug_info->largestexternallookupkeysize ==
98462306a36Sopenharmony_ci			    QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
98562306a36Sopenharmony_ci				size +=
98662306a36Sopenharmony_ci			THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
98762306a36Sopenharmony_ci			if (ugeth->ug_info->largestexternallookupkeysize ==
98862306a36Sopenharmony_ci			    QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
98962306a36Sopenharmony_ci				size +=
99062306a36Sopenharmony_ci			THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
99162306a36Sopenharmony_ci		}
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci		dump_init_enet_entries(ugeth,
99462306a36Sopenharmony_ci				       &(ugeth->p_init_enet_param_shadow->
99562306a36Sopenharmony_ci					 txthread[0]),
99662306a36Sopenharmony_ci				       ENET_INIT_PARAM_MAX_ENTRIES_TX,
99762306a36Sopenharmony_ci				       sizeof(struct ucc_geth_thread_tx_pram),
99862306a36Sopenharmony_ci				       ugeth->ug_info->riscTx, 0);
99962306a36Sopenharmony_ci		dump_init_enet_entries(ugeth,
100062306a36Sopenharmony_ci				       &(ugeth->p_init_enet_param_shadow->
100162306a36Sopenharmony_ci					 rxthread[0]),
100262306a36Sopenharmony_ci				       ENET_INIT_PARAM_MAX_ENTRIES_RX, size,
100362306a36Sopenharmony_ci				       ugeth->ug_info->riscRx, 1);
100462306a36Sopenharmony_ci	}
100562306a36Sopenharmony_ci}
100662306a36Sopenharmony_ci#endif /* DEBUG */
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_cistatic void init_default_reg_vals(u32 __iomem *upsmr_register,
100962306a36Sopenharmony_ci				  u32 __iomem *maccfg1_register,
101062306a36Sopenharmony_ci				  u32 __iomem *maccfg2_register)
101162306a36Sopenharmony_ci{
101262306a36Sopenharmony_ci	out_be32(upsmr_register, UCC_GETH_UPSMR_INIT);
101362306a36Sopenharmony_ci	out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT);
101462306a36Sopenharmony_ci	out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT);
101562306a36Sopenharmony_ci}
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_cistatic int init_half_duplex_params(int alt_beb,
101862306a36Sopenharmony_ci				   int back_pressure_no_backoff,
101962306a36Sopenharmony_ci				   int no_backoff,
102062306a36Sopenharmony_ci				   int excess_defer,
102162306a36Sopenharmony_ci				   u8 alt_beb_truncation,
102262306a36Sopenharmony_ci				   u8 max_retransmissions,
102362306a36Sopenharmony_ci				   u8 collision_window,
102462306a36Sopenharmony_ci				   u32 __iomem *hafdup_register)
102562306a36Sopenharmony_ci{
102662306a36Sopenharmony_ci	u32 value = 0;
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) ||
102962306a36Sopenharmony_ci	    (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) ||
103062306a36Sopenharmony_ci	    (collision_window > HALFDUP_COLLISION_WINDOW_MAX))
103162306a36Sopenharmony_ci		return -EINVAL;
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT);
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	if (alt_beb)
103662306a36Sopenharmony_ci		value |= HALFDUP_ALT_BEB;
103762306a36Sopenharmony_ci	if (back_pressure_no_backoff)
103862306a36Sopenharmony_ci		value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF;
103962306a36Sopenharmony_ci	if (no_backoff)
104062306a36Sopenharmony_ci		value |= HALFDUP_NO_BACKOFF;
104162306a36Sopenharmony_ci	if (excess_defer)
104262306a36Sopenharmony_ci		value |= HALFDUP_EXCESSIVE_DEFER;
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT);
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	value |= collision_window;
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	out_be32(hafdup_register, value);
104962306a36Sopenharmony_ci	return 0;
105062306a36Sopenharmony_ci}
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_cistatic int init_inter_frame_gap_params(u8 non_btb_cs_ipg,
105362306a36Sopenharmony_ci				       u8 non_btb_ipg,
105462306a36Sopenharmony_ci				       u8 min_ifg,
105562306a36Sopenharmony_ci				       u8 btb_ipg,
105662306a36Sopenharmony_ci				       u32 __iomem *ipgifg_register)
105762306a36Sopenharmony_ci{
105862306a36Sopenharmony_ci	u32 value = 0;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	/* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back
106162306a36Sopenharmony_ci	IPG part 2 */
106262306a36Sopenharmony_ci	if (non_btb_cs_ipg > non_btb_ipg)
106362306a36Sopenharmony_ci		return -EINVAL;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) ||
106662306a36Sopenharmony_ci	    (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) ||
106762306a36Sopenharmony_ci	    /*(min_ifg        > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */
106862306a36Sopenharmony_ci	    (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX))
106962306a36Sopenharmony_ci		return -EINVAL;
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	value |=
107262306a36Sopenharmony_ci	    ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) &
107362306a36Sopenharmony_ci	     IPGIFG_NBTB_CS_IPG_MASK);
107462306a36Sopenharmony_ci	value |=
107562306a36Sopenharmony_ci	    ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) &
107662306a36Sopenharmony_ci	     IPGIFG_NBTB_IPG_MASK);
107762306a36Sopenharmony_ci	value |=
107862306a36Sopenharmony_ci	    ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) &
107962306a36Sopenharmony_ci	     IPGIFG_MIN_IFG_MASK);
108062306a36Sopenharmony_ci	value |= (btb_ipg & IPGIFG_BTB_IPG_MASK);
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	out_be32(ipgifg_register, value);
108362306a36Sopenharmony_ci	return 0;
108462306a36Sopenharmony_ci}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_ciint init_flow_control_params(u32 automatic_flow_control_mode,
108762306a36Sopenharmony_ci				    int rx_flow_control_enable,
108862306a36Sopenharmony_ci				    int tx_flow_control_enable,
108962306a36Sopenharmony_ci				    u16 pause_period,
109062306a36Sopenharmony_ci				    u16 extension_field,
109162306a36Sopenharmony_ci				    u32 __iomem *upsmr_register,
109262306a36Sopenharmony_ci				    u32 __iomem *uempr_register,
109362306a36Sopenharmony_ci				    u32 __iomem *maccfg1_register)
109462306a36Sopenharmony_ci{
109562306a36Sopenharmony_ci	u32 value = 0;
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	/* Set UEMPR register */
109862306a36Sopenharmony_ci	value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT;
109962306a36Sopenharmony_ci	value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT;
110062306a36Sopenharmony_ci	out_be32(uempr_register, value);
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	/* Set UPSMR register */
110362306a36Sopenharmony_ci	setbits32(upsmr_register, automatic_flow_control_mode);
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	value = in_be32(maccfg1_register);
110662306a36Sopenharmony_ci	if (rx_flow_control_enable)
110762306a36Sopenharmony_ci		value |= MACCFG1_FLOW_RX;
110862306a36Sopenharmony_ci	if (tx_flow_control_enable)
110962306a36Sopenharmony_ci		value |= MACCFG1_FLOW_TX;
111062306a36Sopenharmony_ci	out_be32(maccfg1_register, value);
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	return 0;
111362306a36Sopenharmony_ci}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_cistatic int init_hw_statistics_gathering_mode(int enable_hardware_statistics,
111662306a36Sopenharmony_ci					     int auto_zero_hardware_statistics,
111762306a36Sopenharmony_ci					     u32 __iomem *upsmr_register,
111862306a36Sopenharmony_ci					     u16 __iomem *uescr_register)
111962306a36Sopenharmony_ci{
112062306a36Sopenharmony_ci	u16 uescr_value = 0;
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	/* Enable hardware statistics gathering if requested */
112362306a36Sopenharmony_ci	if (enable_hardware_statistics)
112462306a36Sopenharmony_ci		setbits32(upsmr_register, UCC_GETH_UPSMR_HSE);
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_ci	/* Clear hardware statistics counters */
112762306a36Sopenharmony_ci	uescr_value = in_be16(uescr_register);
112862306a36Sopenharmony_ci	uescr_value |= UESCR_CLRCNT;
112962306a36Sopenharmony_ci	/* Automatically zero hardware statistics counters on read,
113062306a36Sopenharmony_ci	if requested */
113162306a36Sopenharmony_ci	if (auto_zero_hardware_statistics)
113262306a36Sopenharmony_ci		uescr_value |= UESCR_AUTOZ;
113362306a36Sopenharmony_ci	out_be16(uescr_register, uescr_value);
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	return 0;
113662306a36Sopenharmony_ci}
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_cistatic int init_firmware_statistics_gathering_mode(int
113962306a36Sopenharmony_ci		enable_tx_firmware_statistics,
114062306a36Sopenharmony_ci		int enable_rx_firmware_statistics,
114162306a36Sopenharmony_ci		u32 __iomem *tx_rmon_base_ptr,
114262306a36Sopenharmony_ci		u32 tx_firmware_statistics_structure_address,
114362306a36Sopenharmony_ci		u32 __iomem *rx_rmon_base_ptr,
114462306a36Sopenharmony_ci		u32 rx_firmware_statistics_structure_address,
114562306a36Sopenharmony_ci		u16 __iomem *temoder_register,
114662306a36Sopenharmony_ci		u32 __iomem *remoder_register)
114762306a36Sopenharmony_ci{
114862306a36Sopenharmony_ci	/* Note: this function does not check if */
114962306a36Sopenharmony_ci	/* the parameters it receives are NULL   */
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	if (enable_tx_firmware_statistics) {
115262306a36Sopenharmony_ci		out_be32(tx_rmon_base_ptr,
115362306a36Sopenharmony_ci			 tx_firmware_statistics_structure_address);
115462306a36Sopenharmony_ci		setbits16(temoder_register, TEMODER_TX_RMON_STATISTICS_ENABLE);
115562306a36Sopenharmony_ci	}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	if (enable_rx_firmware_statistics) {
115862306a36Sopenharmony_ci		out_be32(rx_rmon_base_ptr,
115962306a36Sopenharmony_ci			 rx_firmware_statistics_structure_address);
116062306a36Sopenharmony_ci		setbits32(remoder_register, REMODER_RX_RMON_STATISTICS_ENABLE);
116162306a36Sopenharmony_ci	}
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	return 0;
116462306a36Sopenharmony_ci}
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_cistatic int init_mac_station_addr_regs(u8 address_byte_0,
116762306a36Sopenharmony_ci				      u8 address_byte_1,
116862306a36Sopenharmony_ci				      u8 address_byte_2,
116962306a36Sopenharmony_ci				      u8 address_byte_3,
117062306a36Sopenharmony_ci				      u8 address_byte_4,
117162306a36Sopenharmony_ci				      u8 address_byte_5,
117262306a36Sopenharmony_ci				      u32 __iomem *macstnaddr1_register,
117362306a36Sopenharmony_ci				      u32 __iomem *macstnaddr2_register)
117462306a36Sopenharmony_ci{
117562306a36Sopenharmony_ci	u32 value = 0;
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci	/* Example: for a station address of 0x12345678ABCD, */
117862306a36Sopenharmony_ci	/* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	/* MACSTNADDR1 Register: */
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	/* 0                      7   8                      15  */
118362306a36Sopenharmony_ci	/* station address byte 5     station address byte 4     */
118462306a36Sopenharmony_ci	/* 16                     23  24                     31  */
118562306a36Sopenharmony_ci	/* station address byte 3     station address byte 2     */
118662306a36Sopenharmony_ci	value |= (u32) ((address_byte_2 << 0) & 0x000000FF);
118762306a36Sopenharmony_ci	value |= (u32) ((address_byte_3 << 8) & 0x0000FF00);
118862306a36Sopenharmony_ci	value |= (u32) ((address_byte_4 << 16) & 0x00FF0000);
118962306a36Sopenharmony_ci	value |= (u32) ((address_byte_5 << 24) & 0xFF000000);
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	out_be32(macstnaddr1_register, value);
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	/* MACSTNADDR2 Register: */
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci	/* 0                      7   8                      15  */
119662306a36Sopenharmony_ci	/* station address byte 1     station address byte 0     */
119762306a36Sopenharmony_ci	/* 16                     23  24                     31  */
119862306a36Sopenharmony_ci	/*         reserved                   reserved           */
119962306a36Sopenharmony_ci	value = 0;
120062306a36Sopenharmony_ci	value |= (u32) ((address_byte_0 << 16) & 0x00FF0000);
120162306a36Sopenharmony_ci	value |= (u32) ((address_byte_1 << 24) & 0xFF000000);
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci	out_be32(macstnaddr2_register, value);
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	return 0;
120662306a36Sopenharmony_ci}
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_cistatic int init_check_frame_length_mode(int length_check,
120962306a36Sopenharmony_ci					u32 __iomem *maccfg2_register)
121062306a36Sopenharmony_ci{
121162306a36Sopenharmony_ci	u32 value = 0;
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_ci	value = in_be32(maccfg2_register);
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	if (length_check)
121662306a36Sopenharmony_ci		value |= MACCFG2_LC;
121762306a36Sopenharmony_ci	else
121862306a36Sopenharmony_ci		value &= ~MACCFG2_LC;
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	out_be32(maccfg2_register, value);
122162306a36Sopenharmony_ci	return 0;
122262306a36Sopenharmony_ci}
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_cistatic int init_preamble_length(u8 preamble_length,
122562306a36Sopenharmony_ci				u32 __iomem *maccfg2_register)
122662306a36Sopenharmony_ci{
122762306a36Sopenharmony_ci	if ((preamble_length < 3) || (preamble_length > 7))
122862306a36Sopenharmony_ci		return -EINVAL;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	clrsetbits_be32(maccfg2_register, MACCFG2_PREL_MASK,
123162306a36Sopenharmony_ci			preamble_length << MACCFG2_PREL_SHIFT);
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	return 0;
123462306a36Sopenharmony_ci}
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_cistatic int init_rx_parameters(int reject_broadcast,
123762306a36Sopenharmony_ci			      int receive_short_frames,
123862306a36Sopenharmony_ci			      int promiscuous, u32 __iomem *upsmr_register)
123962306a36Sopenharmony_ci{
124062306a36Sopenharmony_ci	u32 value = 0;
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	value = in_be32(upsmr_register);
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	if (reject_broadcast)
124562306a36Sopenharmony_ci		value |= UCC_GETH_UPSMR_BRO;
124662306a36Sopenharmony_ci	else
124762306a36Sopenharmony_ci		value &= ~UCC_GETH_UPSMR_BRO;
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	if (receive_short_frames)
125062306a36Sopenharmony_ci		value |= UCC_GETH_UPSMR_RSH;
125162306a36Sopenharmony_ci	else
125262306a36Sopenharmony_ci		value &= ~UCC_GETH_UPSMR_RSH;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	if (promiscuous)
125562306a36Sopenharmony_ci		value |= UCC_GETH_UPSMR_PRO;
125662306a36Sopenharmony_ci	else
125762306a36Sopenharmony_ci		value &= ~UCC_GETH_UPSMR_PRO;
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	out_be32(upsmr_register, value);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	return 0;
126262306a36Sopenharmony_ci}
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_cistatic int init_max_rx_buff_len(u16 max_rx_buf_len,
126562306a36Sopenharmony_ci				u16 __iomem *mrblr_register)
126662306a36Sopenharmony_ci{
126762306a36Sopenharmony_ci	/* max_rx_buf_len value must be a multiple of 128 */
126862306a36Sopenharmony_ci	if ((max_rx_buf_len == 0) ||
126962306a36Sopenharmony_ci	    (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT))
127062306a36Sopenharmony_ci		return -EINVAL;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	out_be16(mrblr_register, max_rx_buf_len);
127362306a36Sopenharmony_ci	return 0;
127462306a36Sopenharmony_ci}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_cistatic int init_min_frame_len(u16 min_frame_length,
127762306a36Sopenharmony_ci			      u16 __iomem *minflr_register,
127862306a36Sopenharmony_ci			      u16 __iomem *mrblr_register)
127962306a36Sopenharmony_ci{
128062306a36Sopenharmony_ci	u16 mrblr_value = 0;
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	mrblr_value = in_be16(mrblr_register);
128362306a36Sopenharmony_ci	if (min_frame_length >= (mrblr_value - 4))
128462306a36Sopenharmony_ci		return -EINVAL;
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	out_be16(minflr_register, min_frame_length);
128762306a36Sopenharmony_ci	return 0;
128862306a36Sopenharmony_ci}
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_cistatic int adjust_enet_interface(struct ucc_geth_private *ugeth)
129162306a36Sopenharmony_ci{
129262306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
129362306a36Sopenharmony_ci	struct ucc_geth __iomem *ug_regs;
129462306a36Sopenharmony_ci	struct ucc_fast __iomem *uf_regs;
129562306a36Sopenharmony_ci	int ret_val;
129662306a36Sopenharmony_ci	u32 upsmr, maccfg2;
129762306a36Sopenharmony_ci	u16 value;
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci	ug_info = ugeth->ug_info;
130262306a36Sopenharmony_ci	ug_regs = ugeth->ug_regs;
130362306a36Sopenharmony_ci	uf_regs = ugeth->uccf->uf_regs;
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_ci	/*                    Set MACCFG2                    */
130662306a36Sopenharmony_ci	maccfg2 = in_be32(&ug_regs->maccfg2);
130762306a36Sopenharmony_ci	maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
130862306a36Sopenharmony_ci	if ((ugeth->max_speed == SPEED_10) ||
130962306a36Sopenharmony_ci	    (ugeth->max_speed == SPEED_100))
131062306a36Sopenharmony_ci		maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
131162306a36Sopenharmony_ci	else if (ugeth->max_speed == SPEED_1000)
131262306a36Sopenharmony_ci		maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
131362306a36Sopenharmony_ci	maccfg2 |= ug_info->padAndCrc;
131462306a36Sopenharmony_ci	out_be32(&ug_regs->maccfg2, maccfg2);
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	/*                    Set UPSMR                      */
131762306a36Sopenharmony_ci	upsmr = in_be32(&uf_regs->upsmr);
131862306a36Sopenharmony_ci	upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M |
131962306a36Sopenharmony_ci		   UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM);
132062306a36Sopenharmony_ci	if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
132162306a36Sopenharmony_ci	    (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
132262306a36Sopenharmony_ci	    (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
132362306a36Sopenharmony_ci	    (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
132462306a36Sopenharmony_ci	    (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
132562306a36Sopenharmony_ci	    (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
132662306a36Sopenharmony_ci		if (ugeth->phy_interface != PHY_INTERFACE_MODE_RMII)
132762306a36Sopenharmony_ci			upsmr |= UCC_GETH_UPSMR_RPM;
132862306a36Sopenharmony_ci		switch (ugeth->max_speed) {
132962306a36Sopenharmony_ci		case SPEED_10:
133062306a36Sopenharmony_ci			upsmr |= UCC_GETH_UPSMR_R10M;
133162306a36Sopenharmony_ci			fallthrough;
133262306a36Sopenharmony_ci		case SPEED_100:
133362306a36Sopenharmony_ci			if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI)
133462306a36Sopenharmony_ci				upsmr |= UCC_GETH_UPSMR_RMM;
133562306a36Sopenharmony_ci		}
133662306a36Sopenharmony_ci	}
133762306a36Sopenharmony_ci	if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
133862306a36Sopenharmony_ci	    (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
133962306a36Sopenharmony_ci		upsmr |= UCC_GETH_UPSMR_TBIM;
134062306a36Sopenharmony_ci	}
134162306a36Sopenharmony_ci	if (ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII)
134262306a36Sopenharmony_ci		upsmr |= UCC_GETH_UPSMR_SGMM;
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	out_be32(&uf_regs->upsmr, upsmr);
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci	/* Disable autonegotiation in tbi mode, because by default it
134762306a36Sopenharmony_ci	comes up in autonegotiation mode. */
134862306a36Sopenharmony_ci	/* Note that this depends on proper setting in utbipar register. */
134962306a36Sopenharmony_ci	if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
135062306a36Sopenharmony_ci	    (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
135162306a36Sopenharmony_ci		struct ucc_geth_info *ug_info = ugeth->ug_info;
135262306a36Sopenharmony_ci		struct phy_device *tbiphy;
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci		if (!ug_info->tbi_node)
135562306a36Sopenharmony_ci			pr_warn("TBI mode requires that the device tree specify a tbi-handle\n");
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci		tbiphy = of_phy_find_device(ug_info->tbi_node);
135862306a36Sopenharmony_ci		if (!tbiphy)
135962306a36Sopenharmony_ci			pr_warn("Could not get TBI device\n");
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci		value = phy_read(tbiphy, ENET_TBI_MII_CR);
136262306a36Sopenharmony_ci		value &= ~0x1000;	/* Turn off autonegotiation */
136362306a36Sopenharmony_ci		phy_write(tbiphy, ENET_TBI_MII_CR, value);
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci		put_device(&tbiphy->mdio.dev);
136662306a36Sopenharmony_ci	}
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci	ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2);
137162306a36Sopenharmony_ci	if (ret_val != 0) {
137262306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
137362306a36Sopenharmony_ci			pr_err("Preamble length must be between 3 and 7 inclusive\n");
137462306a36Sopenharmony_ci		return ret_val;
137562306a36Sopenharmony_ci	}
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	return 0;
137862306a36Sopenharmony_ci}
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_cistatic int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
138162306a36Sopenharmony_ci{
138262306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
138362306a36Sopenharmony_ci	u32 cecr_subblock;
138462306a36Sopenharmony_ci	u32 temp;
138562306a36Sopenharmony_ci	int i = 10;
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_ci	uccf = ugeth->uccf;
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ci	/* Mask GRACEFUL STOP TX interrupt bit and clear it */
139062306a36Sopenharmony_ci	clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA);
139162306a36Sopenharmony_ci	out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA);  /* clear by writing 1 */
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ci	/* Issue host command */
139462306a36Sopenharmony_ci	cecr_subblock =
139562306a36Sopenharmony_ci	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
139662306a36Sopenharmony_ci	qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
139762306a36Sopenharmony_ci		     QE_CR_PROTOCOL_ETHERNET, 0);
139862306a36Sopenharmony_ci
139962306a36Sopenharmony_ci	/* Wait for command to complete */
140062306a36Sopenharmony_ci	do {
140162306a36Sopenharmony_ci		msleep(10);
140262306a36Sopenharmony_ci		temp = in_be32(uccf->p_ucce);
140362306a36Sopenharmony_ci	} while (!(temp & UCC_GETH_UCCE_GRA) && --i);
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	uccf->stopped_tx = 1;
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci	return 0;
140862306a36Sopenharmony_ci}
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_cistatic int ugeth_graceful_stop_rx(struct ucc_geth_private *ugeth)
141162306a36Sopenharmony_ci{
141262306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
141362306a36Sopenharmony_ci	u32 cecr_subblock;
141462306a36Sopenharmony_ci	u8 temp;
141562306a36Sopenharmony_ci	int i = 10;
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	uccf = ugeth->uccf;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	/* Clear acknowledge bit */
142062306a36Sopenharmony_ci	temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
142162306a36Sopenharmony_ci	temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX;
142262306a36Sopenharmony_ci	out_8(&ugeth->p_rx_glbl_pram->rxgstpack, temp);
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci	/* Keep issuing command and checking acknowledge bit until
142562306a36Sopenharmony_ci	it is asserted, according to spec */
142662306a36Sopenharmony_ci	do {
142762306a36Sopenharmony_ci		/* Issue host command */
142862306a36Sopenharmony_ci		cecr_subblock =
142962306a36Sopenharmony_ci		    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.
143062306a36Sopenharmony_ci						ucc_num);
143162306a36Sopenharmony_ci		qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
143262306a36Sopenharmony_ci			     QE_CR_PROTOCOL_ETHERNET, 0);
143362306a36Sopenharmony_ci		msleep(10);
143462306a36Sopenharmony_ci		temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
143562306a36Sopenharmony_ci	} while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i);
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci	uccf->stopped_rx = 1;
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci	return 0;
144062306a36Sopenharmony_ci}
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_cistatic int ugeth_restart_tx(struct ucc_geth_private *ugeth)
144362306a36Sopenharmony_ci{
144462306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
144562306a36Sopenharmony_ci	u32 cecr_subblock;
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	uccf = ugeth->uccf;
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	cecr_subblock =
145062306a36Sopenharmony_ci	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
145162306a36Sopenharmony_ci	qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0);
145262306a36Sopenharmony_ci	uccf->stopped_tx = 0;
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	return 0;
145562306a36Sopenharmony_ci}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_cistatic int ugeth_restart_rx(struct ucc_geth_private *ugeth)
145862306a36Sopenharmony_ci{
145962306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
146062306a36Sopenharmony_ci	u32 cecr_subblock;
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci	uccf = ugeth->uccf;
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_ci	cecr_subblock =
146562306a36Sopenharmony_ci	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
146662306a36Sopenharmony_ci	qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET,
146762306a36Sopenharmony_ci		     0);
146862306a36Sopenharmony_ci	uccf->stopped_rx = 0;
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	return 0;
147162306a36Sopenharmony_ci}
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_cistatic int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode)
147462306a36Sopenharmony_ci{
147562306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
147662306a36Sopenharmony_ci	int enabled_tx, enabled_rx;
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci	uccf = ugeth->uccf;
147962306a36Sopenharmony_ci
148062306a36Sopenharmony_ci	/* check if the UCC number is in range. */
148162306a36Sopenharmony_ci	if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
148262306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
148362306a36Sopenharmony_ci			pr_err("ucc_num out of range\n");
148462306a36Sopenharmony_ci		return -EINVAL;
148562306a36Sopenharmony_ci	}
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	enabled_tx = uccf->enabled_tx;
148862306a36Sopenharmony_ci	enabled_rx = uccf->enabled_rx;
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	/* Get Tx and Rx going again, in case this channel was actively
149162306a36Sopenharmony_ci	disabled. */
149262306a36Sopenharmony_ci	if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx)
149362306a36Sopenharmony_ci		ugeth_restart_tx(ugeth);
149462306a36Sopenharmony_ci	if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx)
149562306a36Sopenharmony_ci		ugeth_restart_rx(ugeth);
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	ucc_fast_enable(uccf, mode);	/* OK to do even if not disabled */
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci	return 0;
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci}
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_cistatic int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode)
150462306a36Sopenharmony_ci{
150562306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	uccf = ugeth->uccf;
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci	/* check if the UCC number is in range. */
151062306a36Sopenharmony_ci	if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
151162306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
151262306a36Sopenharmony_ci			pr_err("ucc_num out of range\n");
151362306a36Sopenharmony_ci		return -EINVAL;
151462306a36Sopenharmony_ci	}
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci	/* Stop any transmissions */
151762306a36Sopenharmony_ci	if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx)
151862306a36Sopenharmony_ci		ugeth_graceful_stop_tx(ugeth);
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	/* Stop any receptions */
152162306a36Sopenharmony_ci	if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx)
152262306a36Sopenharmony_ci		ugeth_graceful_stop_rx(ugeth);
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci	ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	return 0;
152762306a36Sopenharmony_ci}
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_cistatic void ugeth_quiesce(struct ucc_geth_private *ugeth)
153062306a36Sopenharmony_ci{
153162306a36Sopenharmony_ci	/* Prevent any further xmits */
153262306a36Sopenharmony_ci	netif_tx_stop_all_queues(ugeth->ndev);
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_ci	/* Disable the interrupt to avoid NAPI rescheduling. */
153562306a36Sopenharmony_ci	disable_irq(ugeth->ug_info->uf_info.irq);
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci	/* Stop NAPI, and possibly wait for its completion. */
153862306a36Sopenharmony_ci	napi_disable(&ugeth->napi);
153962306a36Sopenharmony_ci}
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_cistatic void ugeth_activate(struct ucc_geth_private *ugeth)
154262306a36Sopenharmony_ci{
154362306a36Sopenharmony_ci	napi_enable(&ugeth->napi);
154462306a36Sopenharmony_ci	enable_irq(ugeth->ug_info->uf_info.irq);
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	/* allow to xmit again  */
154762306a36Sopenharmony_ci	netif_tx_wake_all_queues(ugeth->ndev);
154862306a36Sopenharmony_ci	__netdev_watchdog_up(ugeth->ndev);
154962306a36Sopenharmony_ci}
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci/* Called every time the controller might need to be made
155262306a36Sopenharmony_ci * aware of new link state.  The PHY code conveys this
155362306a36Sopenharmony_ci * information through variables in the ugeth structure, and this
155462306a36Sopenharmony_ci * function converts those variables into the appropriate
155562306a36Sopenharmony_ci * register values, and can bring down the device if needed.
155662306a36Sopenharmony_ci */
155762306a36Sopenharmony_ci
155862306a36Sopenharmony_cistatic void adjust_link(struct net_device *dev)
155962306a36Sopenharmony_ci{
156062306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
156162306a36Sopenharmony_ci	struct ucc_geth __iomem *ug_regs;
156262306a36Sopenharmony_ci	struct ucc_fast __iomem *uf_regs;
156362306a36Sopenharmony_ci	struct phy_device *phydev = ugeth->phydev;
156462306a36Sopenharmony_ci	int new_state = 0;
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	ug_regs = ugeth->ug_regs;
156762306a36Sopenharmony_ci	uf_regs = ugeth->uccf->uf_regs;
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_ci	if (phydev->link) {
157062306a36Sopenharmony_ci		u32 tempval = in_be32(&ug_regs->maccfg2);
157162306a36Sopenharmony_ci		u32 upsmr = in_be32(&uf_regs->upsmr);
157262306a36Sopenharmony_ci		/* Now we make sure that we can be in full duplex mode.
157362306a36Sopenharmony_ci		 * If not, we operate in half-duplex mode. */
157462306a36Sopenharmony_ci		if (phydev->duplex != ugeth->oldduplex) {
157562306a36Sopenharmony_ci			new_state = 1;
157662306a36Sopenharmony_ci			if (!(phydev->duplex))
157762306a36Sopenharmony_ci				tempval &= ~(MACCFG2_FDX);
157862306a36Sopenharmony_ci			else
157962306a36Sopenharmony_ci				tempval |= MACCFG2_FDX;
158062306a36Sopenharmony_ci			ugeth->oldduplex = phydev->duplex;
158162306a36Sopenharmony_ci		}
158262306a36Sopenharmony_ci
158362306a36Sopenharmony_ci		if (phydev->speed != ugeth->oldspeed) {
158462306a36Sopenharmony_ci			new_state = 1;
158562306a36Sopenharmony_ci			switch (phydev->speed) {
158662306a36Sopenharmony_ci			case SPEED_1000:
158762306a36Sopenharmony_ci				tempval = ((tempval &
158862306a36Sopenharmony_ci					    ~(MACCFG2_INTERFACE_MODE_MASK)) |
158962306a36Sopenharmony_ci					    MACCFG2_INTERFACE_MODE_BYTE);
159062306a36Sopenharmony_ci				break;
159162306a36Sopenharmony_ci			case SPEED_100:
159262306a36Sopenharmony_ci			case SPEED_10:
159362306a36Sopenharmony_ci				tempval = ((tempval &
159462306a36Sopenharmony_ci					    ~(MACCFG2_INTERFACE_MODE_MASK)) |
159562306a36Sopenharmony_ci					    MACCFG2_INTERFACE_MODE_NIBBLE);
159662306a36Sopenharmony_ci				/* if reduced mode, re-set UPSMR.R10M */
159762306a36Sopenharmony_ci				if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
159862306a36Sopenharmony_ci				    (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
159962306a36Sopenharmony_ci				    (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
160062306a36Sopenharmony_ci				    (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
160162306a36Sopenharmony_ci				    (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
160262306a36Sopenharmony_ci				    (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
160362306a36Sopenharmony_ci					if (phydev->speed == SPEED_10)
160462306a36Sopenharmony_ci						upsmr |= UCC_GETH_UPSMR_R10M;
160562306a36Sopenharmony_ci					else
160662306a36Sopenharmony_ci						upsmr &= ~UCC_GETH_UPSMR_R10M;
160762306a36Sopenharmony_ci				}
160862306a36Sopenharmony_ci				break;
160962306a36Sopenharmony_ci			default:
161062306a36Sopenharmony_ci				if (netif_msg_link(ugeth))
161162306a36Sopenharmony_ci					pr_warn(
161262306a36Sopenharmony_ci						"%s: Ack!  Speed (%d) is not 10/100/1000!",
161362306a36Sopenharmony_ci						dev->name, phydev->speed);
161462306a36Sopenharmony_ci				break;
161562306a36Sopenharmony_ci			}
161662306a36Sopenharmony_ci			ugeth->oldspeed = phydev->speed;
161762306a36Sopenharmony_ci		}
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_ci		if (!ugeth->oldlink) {
162062306a36Sopenharmony_ci			new_state = 1;
162162306a36Sopenharmony_ci			ugeth->oldlink = 1;
162262306a36Sopenharmony_ci		}
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci		if (new_state) {
162562306a36Sopenharmony_ci			/*
162662306a36Sopenharmony_ci			 * To change the MAC configuration we need to disable
162762306a36Sopenharmony_ci			 * the controller. To do so, we have to either grab
162862306a36Sopenharmony_ci			 * ugeth->lock, which is a bad idea since 'graceful
162962306a36Sopenharmony_ci			 * stop' commands might take quite a while, or we can
163062306a36Sopenharmony_ci			 * quiesce driver's activity.
163162306a36Sopenharmony_ci			 */
163262306a36Sopenharmony_ci			ugeth_quiesce(ugeth);
163362306a36Sopenharmony_ci			ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_ci			out_be32(&ug_regs->maccfg2, tempval);
163662306a36Sopenharmony_ci			out_be32(&uf_regs->upsmr, upsmr);
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci			ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
163962306a36Sopenharmony_ci			ugeth_activate(ugeth);
164062306a36Sopenharmony_ci		}
164162306a36Sopenharmony_ci	} else if (ugeth->oldlink) {
164262306a36Sopenharmony_ci			new_state = 1;
164362306a36Sopenharmony_ci			ugeth->oldlink = 0;
164462306a36Sopenharmony_ci			ugeth->oldspeed = 0;
164562306a36Sopenharmony_ci			ugeth->oldduplex = -1;
164662306a36Sopenharmony_ci	}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci	if (new_state && netif_msg_link(ugeth))
164962306a36Sopenharmony_ci		phy_print_status(phydev);
165062306a36Sopenharmony_ci}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_ci/* Initialize TBI PHY interface for communicating with the
165362306a36Sopenharmony_ci * SERDES lynx PHY on the chip.  We communicate with this PHY
165462306a36Sopenharmony_ci * through the MDIO bus on each controller, treating it as a
165562306a36Sopenharmony_ci * "normal" PHY at the address found in the UTBIPA register.  We assume
165662306a36Sopenharmony_ci * that the UTBIPA register is valid.  Either the MDIO bus code will set
165762306a36Sopenharmony_ci * it to a value that doesn't conflict with other PHYs on the bus, or the
165862306a36Sopenharmony_ci * value doesn't matter, as there are no other PHYs on the bus.
165962306a36Sopenharmony_ci */
166062306a36Sopenharmony_cistatic void uec_configure_serdes(struct net_device *dev)
166162306a36Sopenharmony_ci{
166262306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
166362306a36Sopenharmony_ci	struct ucc_geth_info *ug_info = ugeth->ug_info;
166462306a36Sopenharmony_ci	struct phy_device *tbiphy;
166562306a36Sopenharmony_ci
166662306a36Sopenharmony_ci	if (!ug_info->tbi_node) {
166762306a36Sopenharmony_ci		dev_warn(&dev->dev, "SGMII mode requires that the device "
166862306a36Sopenharmony_ci			"tree specify a tbi-handle\n");
166962306a36Sopenharmony_ci		return;
167062306a36Sopenharmony_ci	}
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	tbiphy = of_phy_find_device(ug_info->tbi_node);
167362306a36Sopenharmony_ci	if (!tbiphy) {
167462306a36Sopenharmony_ci		dev_err(&dev->dev, "error: Could not get TBI device\n");
167562306a36Sopenharmony_ci		return;
167662306a36Sopenharmony_ci	}
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_ci	/*
167962306a36Sopenharmony_ci	 * If the link is already up, we must already be ok, and don't need to
168062306a36Sopenharmony_ci	 * configure and reset the TBI<->SerDes link.  Maybe U-Boot configured
168162306a36Sopenharmony_ci	 * everything for us?  Resetting it takes the link down and requires
168262306a36Sopenharmony_ci	 * several seconds for it to come back.
168362306a36Sopenharmony_ci	 */
168462306a36Sopenharmony_ci	if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) {
168562306a36Sopenharmony_ci		put_device(&tbiphy->mdio.dev);
168662306a36Sopenharmony_ci		return;
168762306a36Sopenharmony_ci	}
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	/* Single clk mode, mii mode off(for serdes communication) */
169062306a36Sopenharmony_ci	phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS);
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_ci	phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS);
169562306a36Sopenharmony_ci
169662306a36Sopenharmony_ci	put_device(&tbiphy->mdio.dev);
169762306a36Sopenharmony_ci}
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci/* Configure the PHY for dev.
170062306a36Sopenharmony_ci * returns 0 if success.  -1 if failure
170162306a36Sopenharmony_ci */
170262306a36Sopenharmony_cistatic int init_phy(struct net_device *dev)
170362306a36Sopenharmony_ci{
170462306a36Sopenharmony_ci	struct ucc_geth_private *priv = netdev_priv(dev);
170562306a36Sopenharmony_ci	struct ucc_geth_info *ug_info = priv->ug_info;
170662306a36Sopenharmony_ci	struct phy_device *phydev;
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	priv->oldlink = 0;
170962306a36Sopenharmony_ci	priv->oldspeed = 0;
171062306a36Sopenharmony_ci	priv->oldduplex = -1;
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0,
171362306a36Sopenharmony_ci				priv->phy_interface);
171462306a36Sopenharmony_ci	if (!phydev) {
171562306a36Sopenharmony_ci		dev_err(&dev->dev, "Could not attach to PHY\n");
171662306a36Sopenharmony_ci		return -ENODEV;
171762306a36Sopenharmony_ci	}
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
172062306a36Sopenharmony_ci		uec_configure_serdes(dev);
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_ci	phy_set_max_speed(phydev, priv->max_speed);
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	priv->phydev = phydev;
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	return 0;
172762306a36Sopenharmony_ci}
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_cistatic void ugeth_dump_regs(struct ucc_geth_private *ugeth)
173062306a36Sopenharmony_ci{
173162306a36Sopenharmony_ci#ifdef DEBUG
173262306a36Sopenharmony_ci	ucc_fast_dump_regs(ugeth->uccf);
173362306a36Sopenharmony_ci	dump_regs(ugeth);
173462306a36Sopenharmony_ci	dump_bds(ugeth);
173562306a36Sopenharmony_ci#endif
173662306a36Sopenharmony_ci}
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_cistatic int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private *
173962306a36Sopenharmony_ci						       ugeth,
174062306a36Sopenharmony_ci						       enum enet_addr_type
174162306a36Sopenharmony_ci						       enet_addr_type)
174262306a36Sopenharmony_ci{
174362306a36Sopenharmony_ci	struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
174462306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
174562306a36Sopenharmony_ci	enum comm_dir comm_dir;
174662306a36Sopenharmony_ci	struct list_head *p_lh;
174762306a36Sopenharmony_ci	u16 i, num;
174862306a36Sopenharmony_ci	u32 __iomem *addr_h;
174962306a36Sopenharmony_ci	u32 __iomem *addr_l;
175062306a36Sopenharmony_ci	u8 *p_counter;
175162306a36Sopenharmony_ci
175262306a36Sopenharmony_ci	uccf = ugeth->uccf;
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	p_82xx_addr_filt =
175562306a36Sopenharmony_ci	    (struct ucc_geth_82xx_address_filtering_pram __iomem *)
175662306a36Sopenharmony_ci	    ugeth->p_rx_glbl_pram->addressfiltering;
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_ci	if (enet_addr_type == ENET_ADDR_TYPE_GROUP) {
175962306a36Sopenharmony_ci		addr_h = &(p_82xx_addr_filt->gaddr_h);
176062306a36Sopenharmony_ci		addr_l = &(p_82xx_addr_filt->gaddr_l);
176162306a36Sopenharmony_ci		p_lh = &ugeth->group_hash_q;
176262306a36Sopenharmony_ci		p_counter = &(ugeth->numGroupAddrInHash);
176362306a36Sopenharmony_ci	} else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) {
176462306a36Sopenharmony_ci		addr_h = &(p_82xx_addr_filt->iaddr_h);
176562306a36Sopenharmony_ci		addr_l = &(p_82xx_addr_filt->iaddr_l);
176662306a36Sopenharmony_ci		p_lh = &ugeth->ind_hash_q;
176762306a36Sopenharmony_ci		p_counter = &(ugeth->numIndAddrInHash);
176862306a36Sopenharmony_ci	} else
176962306a36Sopenharmony_ci		return -EINVAL;
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_ci	comm_dir = 0;
177262306a36Sopenharmony_ci	if (uccf->enabled_tx)
177362306a36Sopenharmony_ci		comm_dir |= COMM_DIR_TX;
177462306a36Sopenharmony_ci	if (uccf->enabled_rx)
177562306a36Sopenharmony_ci		comm_dir |= COMM_DIR_RX;
177662306a36Sopenharmony_ci	if (comm_dir)
177762306a36Sopenharmony_ci		ugeth_disable(ugeth, comm_dir);
177862306a36Sopenharmony_ci
177962306a36Sopenharmony_ci	/* Clear the hash table. */
178062306a36Sopenharmony_ci	out_be32(addr_h, 0x00000000);
178162306a36Sopenharmony_ci	out_be32(addr_l, 0x00000000);
178262306a36Sopenharmony_ci
178362306a36Sopenharmony_ci	if (!p_lh)
178462306a36Sopenharmony_ci		return 0;
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci	num = *p_counter;
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_ci	/* Delete all remaining CQ elements */
178962306a36Sopenharmony_ci	for (i = 0; i < num; i++)
179062306a36Sopenharmony_ci		put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh)));
179162306a36Sopenharmony_ci
179262306a36Sopenharmony_ci	*p_counter = 0;
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci	if (comm_dir)
179562306a36Sopenharmony_ci		ugeth_enable(ugeth, comm_dir);
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci	return 0;
179862306a36Sopenharmony_ci}
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_cistatic int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth,
180162306a36Sopenharmony_ci						    u8 paddr_num)
180262306a36Sopenharmony_ci{
180362306a36Sopenharmony_ci	ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */
180462306a36Sopenharmony_ci	return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */
180562306a36Sopenharmony_ci}
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_cistatic void ucc_geth_free_rx(struct ucc_geth_private *ugeth)
180862306a36Sopenharmony_ci{
180962306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
181062306a36Sopenharmony_ci	struct ucc_fast_info *uf_info;
181162306a36Sopenharmony_ci	u16 i, j;
181262306a36Sopenharmony_ci	u8 __iomem *bd;
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	ug_info = ugeth->ug_info;
181662306a36Sopenharmony_ci	uf_info = &ug_info->uf_info;
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_rx_queues(ugeth->ug_info); i++) {
181962306a36Sopenharmony_ci		if (ugeth->p_rx_bd_ring[i]) {
182062306a36Sopenharmony_ci			/* Return existing data buffers in ring */
182162306a36Sopenharmony_ci			bd = ugeth->p_rx_bd_ring[i];
182262306a36Sopenharmony_ci			for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
182362306a36Sopenharmony_ci				if (ugeth->rx_skbuff[i][j]) {
182462306a36Sopenharmony_ci					dma_unmap_single(ugeth->dev,
182562306a36Sopenharmony_ci						in_be32(&((struct qe_bd __iomem *)bd)->buf),
182662306a36Sopenharmony_ci						ugeth->ug_info->
182762306a36Sopenharmony_ci						uf_info.max_rx_buf_length +
182862306a36Sopenharmony_ci						UCC_GETH_RX_DATA_BUF_ALIGNMENT,
182962306a36Sopenharmony_ci						DMA_FROM_DEVICE);
183062306a36Sopenharmony_ci					dev_kfree_skb_any(
183162306a36Sopenharmony_ci						ugeth->rx_skbuff[i][j]);
183262306a36Sopenharmony_ci					ugeth->rx_skbuff[i][j] = NULL;
183362306a36Sopenharmony_ci				}
183462306a36Sopenharmony_ci				bd += sizeof(struct qe_bd);
183562306a36Sopenharmony_ci			}
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_ci			kfree(ugeth->rx_skbuff[i]);
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci			kfree(ugeth->p_rx_bd_ring[i]);
184062306a36Sopenharmony_ci			ugeth->p_rx_bd_ring[i] = NULL;
184162306a36Sopenharmony_ci		}
184262306a36Sopenharmony_ci	}
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci}
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_cistatic void ucc_geth_free_tx(struct ucc_geth_private *ugeth)
184762306a36Sopenharmony_ci{
184862306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
184962306a36Sopenharmony_ci	struct ucc_fast_info *uf_info;
185062306a36Sopenharmony_ci	u16 i, j;
185162306a36Sopenharmony_ci	u8 __iomem *bd;
185262306a36Sopenharmony_ci
185362306a36Sopenharmony_ci	netdev_reset_queue(ugeth->ndev);
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	ug_info = ugeth->ug_info;
185662306a36Sopenharmony_ci	uf_info = &ug_info->uf_info;
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_tx_queues(ugeth->ug_info); i++) {
185962306a36Sopenharmony_ci		bd = ugeth->p_tx_bd_ring[i];
186062306a36Sopenharmony_ci		if (!bd)
186162306a36Sopenharmony_ci			continue;
186262306a36Sopenharmony_ci		for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
186362306a36Sopenharmony_ci			if (ugeth->tx_skbuff[i][j]) {
186462306a36Sopenharmony_ci				dma_unmap_single(ugeth->dev,
186562306a36Sopenharmony_ci						 in_be32(&((struct qe_bd __iomem *)bd)->buf),
186662306a36Sopenharmony_ci						 (in_be32((u32 __iomem *)bd) &
186762306a36Sopenharmony_ci						  BD_LENGTH_MASK),
186862306a36Sopenharmony_ci						 DMA_TO_DEVICE);
186962306a36Sopenharmony_ci				dev_kfree_skb_any(ugeth->tx_skbuff[i][j]);
187062306a36Sopenharmony_ci				ugeth->tx_skbuff[i][j] = NULL;
187162306a36Sopenharmony_ci			}
187262306a36Sopenharmony_ci		}
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci		kfree(ugeth->tx_skbuff[i]);
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_ci		kfree(ugeth->p_tx_bd_ring[i]);
187762306a36Sopenharmony_ci		ugeth->p_tx_bd_ring[i] = NULL;
187862306a36Sopenharmony_ci	}
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci}
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_cistatic void ucc_geth_memclean(struct ucc_geth_private *ugeth)
188362306a36Sopenharmony_ci{
188462306a36Sopenharmony_ci	if (!ugeth)
188562306a36Sopenharmony_ci		return;
188662306a36Sopenharmony_ci
188762306a36Sopenharmony_ci	if (ugeth->uccf) {
188862306a36Sopenharmony_ci		ucc_fast_free(ugeth->uccf);
188962306a36Sopenharmony_ci		ugeth->uccf = NULL;
189062306a36Sopenharmony_ci	}
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_thread_data_tx);
189362306a36Sopenharmony_ci	ugeth->p_thread_data_tx = NULL;
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_thread_data_rx);
189662306a36Sopenharmony_ci	ugeth->p_thread_data_rx = NULL;
189762306a36Sopenharmony_ci
189862306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_exf_glbl_param);
189962306a36Sopenharmony_ci	ugeth->p_exf_glbl_param = NULL;
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_rx_glbl_pram);
190262306a36Sopenharmony_ci	ugeth->p_rx_glbl_pram = NULL;
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_tx_glbl_pram);
190562306a36Sopenharmony_ci	ugeth->p_tx_glbl_pram = NULL;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_send_q_mem_reg);
190862306a36Sopenharmony_ci	ugeth->p_send_q_mem_reg = NULL;
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_scheduler);
191162306a36Sopenharmony_ci	ugeth->p_scheduler = NULL;
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_tx_fw_statistics_pram);
191462306a36Sopenharmony_ci	ugeth->p_tx_fw_statistics_pram = NULL;
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_rx_fw_statistics_pram);
191762306a36Sopenharmony_ci	ugeth->p_rx_fw_statistics_pram = NULL;
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_rx_irq_coalescing_tbl);
192062306a36Sopenharmony_ci	ugeth->p_rx_irq_coalescing_tbl = NULL;
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci	qe_muram_free_addr(ugeth->p_rx_bd_qs_tbl);
192362306a36Sopenharmony_ci	ugeth->p_rx_bd_qs_tbl = NULL;
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_ci	if (ugeth->p_init_enet_param_shadow) {
192662306a36Sopenharmony_ci		return_init_enet_entries(ugeth,
192762306a36Sopenharmony_ci					 &(ugeth->p_init_enet_param_shadow->
192862306a36Sopenharmony_ci					   rxthread[0]),
192962306a36Sopenharmony_ci					 ENET_INIT_PARAM_MAX_ENTRIES_RX,
193062306a36Sopenharmony_ci					 ugeth->ug_info->riscRx, 1);
193162306a36Sopenharmony_ci		return_init_enet_entries(ugeth,
193262306a36Sopenharmony_ci					 &(ugeth->p_init_enet_param_shadow->
193362306a36Sopenharmony_ci					   txthread[0]),
193462306a36Sopenharmony_ci					 ENET_INIT_PARAM_MAX_ENTRIES_TX,
193562306a36Sopenharmony_ci					 ugeth->ug_info->riscTx, 0);
193662306a36Sopenharmony_ci		kfree(ugeth->p_init_enet_param_shadow);
193762306a36Sopenharmony_ci		ugeth->p_init_enet_param_shadow = NULL;
193862306a36Sopenharmony_ci	}
193962306a36Sopenharmony_ci	ucc_geth_free_tx(ugeth);
194062306a36Sopenharmony_ci	ucc_geth_free_rx(ugeth);
194162306a36Sopenharmony_ci	while (!list_empty(&ugeth->group_hash_q))
194262306a36Sopenharmony_ci		put_enet_addr_container(ENET_ADDR_CONT_ENTRY
194362306a36Sopenharmony_ci					(dequeue(&ugeth->group_hash_q)));
194462306a36Sopenharmony_ci	while (!list_empty(&ugeth->ind_hash_q))
194562306a36Sopenharmony_ci		put_enet_addr_container(ENET_ADDR_CONT_ENTRY
194662306a36Sopenharmony_ci					(dequeue(&ugeth->ind_hash_q)));
194762306a36Sopenharmony_ci	if (ugeth->ug_regs) {
194862306a36Sopenharmony_ci		iounmap(ugeth->ug_regs);
194962306a36Sopenharmony_ci		ugeth->ug_regs = NULL;
195062306a36Sopenharmony_ci	}
195162306a36Sopenharmony_ci}
195262306a36Sopenharmony_ci
195362306a36Sopenharmony_cistatic void ucc_geth_set_multi(struct net_device *dev)
195462306a36Sopenharmony_ci{
195562306a36Sopenharmony_ci	struct ucc_geth_private *ugeth;
195662306a36Sopenharmony_ci	struct netdev_hw_addr *ha;
195762306a36Sopenharmony_ci	struct ucc_fast __iomem *uf_regs;
195862306a36Sopenharmony_ci	struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
195962306a36Sopenharmony_ci
196062306a36Sopenharmony_ci	ugeth = netdev_priv(dev);
196162306a36Sopenharmony_ci
196262306a36Sopenharmony_ci	uf_regs = ugeth->uccf->uf_regs;
196362306a36Sopenharmony_ci
196462306a36Sopenharmony_ci	if (dev->flags & IFF_PROMISC) {
196562306a36Sopenharmony_ci		setbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);
196662306a36Sopenharmony_ci	} else {
196762306a36Sopenharmony_ci		clrbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci		p_82xx_addr_filt =
197062306a36Sopenharmony_ci		    (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->
197162306a36Sopenharmony_ci		    p_rx_glbl_pram->addressfiltering;
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci		if (dev->flags & IFF_ALLMULTI) {
197462306a36Sopenharmony_ci			/* Catch all multicast addresses, so set the
197562306a36Sopenharmony_ci			 * filter to all 1's.
197662306a36Sopenharmony_ci			 */
197762306a36Sopenharmony_ci			out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff);
197862306a36Sopenharmony_ci			out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff);
197962306a36Sopenharmony_ci		} else {
198062306a36Sopenharmony_ci			/* Clear filter and add the addresses in the list.
198162306a36Sopenharmony_ci			 */
198262306a36Sopenharmony_ci			out_be32(&p_82xx_addr_filt->gaddr_h, 0x0);
198362306a36Sopenharmony_ci			out_be32(&p_82xx_addr_filt->gaddr_l, 0x0);
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci			netdev_for_each_mc_addr(ha, dev) {
198662306a36Sopenharmony_ci				/* Ask CPM to run CRC and set bit in
198762306a36Sopenharmony_ci				 * filter mask.
198862306a36Sopenharmony_ci				 */
198962306a36Sopenharmony_ci				hw_add_addr_in_hash(ugeth, ha->addr);
199062306a36Sopenharmony_ci			}
199162306a36Sopenharmony_ci		}
199262306a36Sopenharmony_ci	}
199362306a36Sopenharmony_ci}
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_cistatic void ucc_geth_stop(struct ucc_geth_private *ugeth)
199662306a36Sopenharmony_ci{
199762306a36Sopenharmony_ci	struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;
199862306a36Sopenharmony_ci	struct phy_device *phydev = ugeth->phydev;
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
200162306a36Sopenharmony_ci
200262306a36Sopenharmony_ci	/*
200362306a36Sopenharmony_ci	 * Tell the kernel the link is down.
200462306a36Sopenharmony_ci	 * Must be done before disabling the controller
200562306a36Sopenharmony_ci	 * or deadlock may happen.
200662306a36Sopenharmony_ci	 */
200762306a36Sopenharmony_ci	phy_stop(phydev);
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci	/* Disable the controller */
201062306a36Sopenharmony_ci	ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
201162306a36Sopenharmony_ci
201262306a36Sopenharmony_ci	/* Mask all interrupts */
201362306a36Sopenharmony_ci	out_be32(ugeth->uccf->p_uccm, 0x00000000);
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	/* Clear all interrupts */
201662306a36Sopenharmony_ci	out_be32(ugeth->uccf->p_ucce, 0xffffffff);
201762306a36Sopenharmony_ci
201862306a36Sopenharmony_ci	/* Disable Rx and Tx */
201962306a36Sopenharmony_ci	clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	ucc_geth_memclean(ugeth);
202262306a36Sopenharmony_ci}
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_cistatic int ucc_struct_init(struct ucc_geth_private *ugeth)
202562306a36Sopenharmony_ci{
202662306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
202762306a36Sopenharmony_ci	struct ucc_fast_info *uf_info;
202862306a36Sopenharmony_ci	int i;
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci	ug_info = ugeth->ug_info;
203162306a36Sopenharmony_ci	uf_info = &ug_info->uf_info;
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_ci	/* Rx BD lengths */
203462306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_rx_queues(ug_info); i++) {
203562306a36Sopenharmony_ci		if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) ||
203662306a36Sopenharmony_ci		    (ug_info->bdRingLenRx[i] %
203762306a36Sopenharmony_ci		     UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) {
203862306a36Sopenharmony_ci			if (netif_msg_probe(ugeth))
203962306a36Sopenharmony_ci				pr_err("Rx BD ring length must be multiple of 4, no smaller than 8\n");
204062306a36Sopenharmony_ci			return -EINVAL;
204162306a36Sopenharmony_ci		}
204262306a36Sopenharmony_ci	}
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_ci	/* Tx BD lengths */
204562306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_tx_queues(ug_info); i++) {
204662306a36Sopenharmony_ci		if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) {
204762306a36Sopenharmony_ci			if (netif_msg_probe(ugeth))
204862306a36Sopenharmony_ci				pr_err("Tx BD ring length must be no smaller than 2\n");
204962306a36Sopenharmony_ci			return -EINVAL;
205062306a36Sopenharmony_ci		}
205162306a36Sopenharmony_ci	}
205262306a36Sopenharmony_ci
205362306a36Sopenharmony_ci	/* mrblr */
205462306a36Sopenharmony_ci	if ((uf_info->max_rx_buf_length == 0) ||
205562306a36Sopenharmony_ci	    (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) {
205662306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
205762306a36Sopenharmony_ci			pr_err("max_rx_buf_length must be non-zero multiple of 128\n");
205862306a36Sopenharmony_ci		return -EINVAL;
205962306a36Sopenharmony_ci	}
206062306a36Sopenharmony_ci
206162306a36Sopenharmony_ci	/* num Tx queues */
206262306a36Sopenharmony_ci	if (ucc_geth_tx_queues(ug_info) > NUM_TX_QUEUES) {
206362306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
206462306a36Sopenharmony_ci			pr_err("number of tx queues too large\n");
206562306a36Sopenharmony_ci		return -EINVAL;
206662306a36Sopenharmony_ci	}
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci	/* num Rx queues */
206962306a36Sopenharmony_ci	if (ucc_geth_rx_queues(ug_info) > NUM_RX_QUEUES) {
207062306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
207162306a36Sopenharmony_ci			pr_err("number of rx queues too large\n");
207262306a36Sopenharmony_ci		return -EINVAL;
207362306a36Sopenharmony_ci	}
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	/* l2qt */
207662306a36Sopenharmony_ci	for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) {
207762306a36Sopenharmony_ci		if (ug_info->l2qt[i] >= ucc_geth_rx_queues(ug_info)) {
207862306a36Sopenharmony_ci			if (netif_msg_probe(ugeth))
207962306a36Sopenharmony_ci				pr_err("VLAN priority table entry must not be larger than number of Rx queues\n");
208062306a36Sopenharmony_ci			return -EINVAL;
208162306a36Sopenharmony_ci		}
208262306a36Sopenharmony_ci	}
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_ci	/* l3qt */
208562306a36Sopenharmony_ci	for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) {
208662306a36Sopenharmony_ci		if (ug_info->l3qt[i] >= ucc_geth_rx_queues(ug_info)) {
208762306a36Sopenharmony_ci			if (netif_msg_probe(ugeth))
208862306a36Sopenharmony_ci				pr_err("IP priority table entry must not be larger than number of Rx queues\n");
208962306a36Sopenharmony_ci			return -EINVAL;
209062306a36Sopenharmony_ci		}
209162306a36Sopenharmony_ci	}
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_ci	if (ug_info->cam && !ug_info->ecamptr) {
209462306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
209562306a36Sopenharmony_ci			pr_err("If cam mode is chosen, must supply cam ptr\n");
209662306a36Sopenharmony_ci		return -EINVAL;
209762306a36Sopenharmony_ci	}
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	if ((ug_info->numStationAddresses !=
210062306a36Sopenharmony_ci	     UCC_GETH_NUM_OF_STATION_ADDRESSES_1) &&
210162306a36Sopenharmony_ci	    ug_info->rxExtendedFiltering) {
210262306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
210362306a36Sopenharmony_ci			pr_err("Number of station addresses greater than 1 not allowed in extended parsing mode\n");
210462306a36Sopenharmony_ci		return -EINVAL;
210562306a36Sopenharmony_ci	}
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci	/* Generate uccm_mask for receive */
210862306a36Sopenharmony_ci	uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */
210962306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_rx_queues(ug_info); i++)
211062306a36Sopenharmony_ci		uf_info->uccm_mask |= (UCC_GETH_UCCE_RXF0 << i);
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_tx_queues(ug_info); i++)
211362306a36Sopenharmony_ci		uf_info->uccm_mask |= (UCC_GETH_UCCE_TXB0 << i);
211462306a36Sopenharmony_ci	/* Initialize the general fast UCC block. */
211562306a36Sopenharmony_ci	if (ucc_fast_init(uf_info, &ugeth->uccf)) {
211662306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
211762306a36Sopenharmony_ci			pr_err("Failed to init uccf\n");
211862306a36Sopenharmony_ci		return -ENOMEM;
211962306a36Sopenharmony_ci	}
212062306a36Sopenharmony_ci
212162306a36Sopenharmony_ci	/* read the number of risc engines, update the riscTx and riscRx
212262306a36Sopenharmony_ci	 * if there are 4 riscs in QE
212362306a36Sopenharmony_ci	 */
212462306a36Sopenharmony_ci	if (qe_get_num_of_risc() == 4) {
212562306a36Sopenharmony_ci		ug_info->riscTx = QE_RISC_ALLOCATION_FOUR_RISCS;
212662306a36Sopenharmony_ci		ug_info->riscRx = QE_RISC_ALLOCATION_FOUR_RISCS;
212762306a36Sopenharmony_ci	}
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci	ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs));
213062306a36Sopenharmony_ci	if (!ugeth->ug_regs) {
213162306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
213262306a36Sopenharmony_ci			pr_err("Failed to ioremap regs\n");
213362306a36Sopenharmony_ci		return -ENOMEM;
213462306a36Sopenharmony_ci	}
213562306a36Sopenharmony_ci
213662306a36Sopenharmony_ci	return 0;
213762306a36Sopenharmony_ci}
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_cistatic int ucc_geth_alloc_tx(struct ucc_geth_private *ugeth)
214062306a36Sopenharmony_ci{
214162306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
214262306a36Sopenharmony_ci	struct ucc_fast_info *uf_info;
214362306a36Sopenharmony_ci	int length;
214462306a36Sopenharmony_ci	u16 i, j;
214562306a36Sopenharmony_ci	u8 __iomem *bd;
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci	ug_info = ugeth->ug_info;
214862306a36Sopenharmony_ci	uf_info = &ug_info->uf_info;
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_ci	/* Allocate Tx bds */
215162306a36Sopenharmony_ci	for (j = 0; j < ucc_geth_tx_queues(ug_info); j++) {
215262306a36Sopenharmony_ci		u32 align = max(UCC_GETH_TX_BD_RING_ALIGNMENT,
215362306a36Sopenharmony_ci				UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT);
215462306a36Sopenharmony_ci		u32 alloc;
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_ci		length = ug_info->bdRingLenTx[j] * sizeof(struct qe_bd);
215762306a36Sopenharmony_ci		alloc = round_up(length, align);
215862306a36Sopenharmony_ci		alloc = roundup_pow_of_two(alloc);
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_ci		ugeth->p_tx_bd_ring[j] = kmalloc(alloc, GFP_KERNEL);
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci		if (!ugeth->p_tx_bd_ring[j]) {
216362306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
216462306a36Sopenharmony_ci				pr_err("Can not allocate memory for Tx bd rings\n");
216562306a36Sopenharmony_ci			return -ENOMEM;
216662306a36Sopenharmony_ci		}
216762306a36Sopenharmony_ci		/* Zero unused end of bd ring, according to spec */
216862306a36Sopenharmony_ci		memset(ugeth->p_tx_bd_ring[j] + length, 0, alloc - length);
216962306a36Sopenharmony_ci	}
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_ci	/* Init Tx bds */
217262306a36Sopenharmony_ci	for (j = 0; j < ucc_geth_tx_queues(ug_info); j++) {
217362306a36Sopenharmony_ci		/* Setup the skbuff rings */
217462306a36Sopenharmony_ci		ugeth->tx_skbuff[j] =
217562306a36Sopenharmony_ci			kcalloc(ugeth->ug_info->bdRingLenTx[j],
217662306a36Sopenharmony_ci				sizeof(struct sk_buff *), GFP_KERNEL);
217762306a36Sopenharmony_ci
217862306a36Sopenharmony_ci		if (ugeth->tx_skbuff[j] == NULL) {
217962306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
218062306a36Sopenharmony_ci				pr_err("Could not allocate tx_skbuff\n");
218162306a36Sopenharmony_ci			return -ENOMEM;
218262306a36Sopenharmony_ci		}
218362306a36Sopenharmony_ci
218462306a36Sopenharmony_ci		ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0;
218562306a36Sopenharmony_ci		bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j];
218662306a36Sopenharmony_ci		for (i = 0; i < ug_info->bdRingLenTx[j]; i++) {
218762306a36Sopenharmony_ci			/* clear bd buffer */
218862306a36Sopenharmony_ci			out_be32(&((struct qe_bd __iomem *)bd)->buf, 0);
218962306a36Sopenharmony_ci			/* set bd status and length */
219062306a36Sopenharmony_ci			out_be32((u32 __iomem *)bd, 0);
219162306a36Sopenharmony_ci			bd += sizeof(struct qe_bd);
219262306a36Sopenharmony_ci		}
219362306a36Sopenharmony_ci		bd -= sizeof(struct qe_bd);
219462306a36Sopenharmony_ci		/* set bd status and length */
219562306a36Sopenharmony_ci		out_be32((u32 __iomem *)bd, T_W); /* for last BD set Wrap bit */
219662306a36Sopenharmony_ci	}
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci	return 0;
219962306a36Sopenharmony_ci}
220062306a36Sopenharmony_ci
220162306a36Sopenharmony_cistatic int ucc_geth_alloc_rx(struct ucc_geth_private *ugeth)
220262306a36Sopenharmony_ci{
220362306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
220462306a36Sopenharmony_ci	struct ucc_fast_info *uf_info;
220562306a36Sopenharmony_ci	int length;
220662306a36Sopenharmony_ci	u16 i, j;
220762306a36Sopenharmony_ci	u8 __iomem *bd;
220862306a36Sopenharmony_ci
220962306a36Sopenharmony_ci	ug_info = ugeth->ug_info;
221062306a36Sopenharmony_ci	uf_info = &ug_info->uf_info;
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_ci	/* Allocate Rx bds */
221362306a36Sopenharmony_ci	for (j = 0; j < ucc_geth_rx_queues(ug_info); j++) {
221462306a36Sopenharmony_ci		u32 align = UCC_GETH_RX_BD_RING_ALIGNMENT;
221562306a36Sopenharmony_ci		u32 alloc;
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci		length = ug_info->bdRingLenRx[j] * sizeof(struct qe_bd);
221862306a36Sopenharmony_ci		alloc = round_up(length, align);
221962306a36Sopenharmony_ci		alloc = roundup_pow_of_two(alloc);
222062306a36Sopenharmony_ci
222162306a36Sopenharmony_ci		ugeth->p_rx_bd_ring[j] = kmalloc(alloc, GFP_KERNEL);
222262306a36Sopenharmony_ci		if (!ugeth->p_rx_bd_ring[j]) {
222362306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
222462306a36Sopenharmony_ci				pr_err("Can not allocate memory for Rx bd rings\n");
222562306a36Sopenharmony_ci			return -ENOMEM;
222662306a36Sopenharmony_ci		}
222762306a36Sopenharmony_ci	}
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci	/* Init Rx bds */
223062306a36Sopenharmony_ci	for (j = 0; j < ucc_geth_rx_queues(ug_info); j++) {
223162306a36Sopenharmony_ci		/* Setup the skbuff rings */
223262306a36Sopenharmony_ci		ugeth->rx_skbuff[j] =
223362306a36Sopenharmony_ci			kcalloc(ugeth->ug_info->bdRingLenRx[j],
223462306a36Sopenharmony_ci				sizeof(struct sk_buff *), GFP_KERNEL);
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci		if (ugeth->rx_skbuff[j] == NULL) {
223762306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
223862306a36Sopenharmony_ci				pr_err("Could not allocate rx_skbuff\n");
223962306a36Sopenharmony_ci			return -ENOMEM;
224062306a36Sopenharmony_ci		}
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_ci		ugeth->skb_currx[j] = 0;
224362306a36Sopenharmony_ci		bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j];
224462306a36Sopenharmony_ci		for (i = 0; i < ug_info->bdRingLenRx[j]; i++) {
224562306a36Sopenharmony_ci			/* set bd status and length */
224662306a36Sopenharmony_ci			out_be32((u32 __iomem *)bd, R_I);
224762306a36Sopenharmony_ci			/* clear bd buffer */
224862306a36Sopenharmony_ci			out_be32(&((struct qe_bd __iomem *)bd)->buf, 0);
224962306a36Sopenharmony_ci			bd += sizeof(struct qe_bd);
225062306a36Sopenharmony_ci		}
225162306a36Sopenharmony_ci		bd -= sizeof(struct qe_bd);
225262306a36Sopenharmony_ci		/* set bd status and length */
225362306a36Sopenharmony_ci		out_be32((u32 __iomem *)bd, R_W); /* for last BD set Wrap bit */
225462306a36Sopenharmony_ci	}
225562306a36Sopenharmony_ci
225662306a36Sopenharmony_ci	return 0;
225762306a36Sopenharmony_ci}
225862306a36Sopenharmony_ci
225962306a36Sopenharmony_cistatic int ucc_geth_startup(struct ucc_geth_private *ugeth)
226062306a36Sopenharmony_ci{
226162306a36Sopenharmony_ci	struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
226262306a36Sopenharmony_ci	struct ucc_geth_init_pram __iomem *p_init_enet_pram;
226362306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
226462306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
226562306a36Sopenharmony_ci	struct ucc_fast_info *uf_info;
226662306a36Sopenharmony_ci	struct ucc_fast __iomem *uf_regs;
226762306a36Sopenharmony_ci	struct ucc_geth __iomem *ug_regs;
226862306a36Sopenharmony_ci	int ret_val = -EINVAL;
226962306a36Sopenharmony_ci	u32 remoder = UCC_GETH_REMODER_INIT;
227062306a36Sopenharmony_ci	u32 init_enet_pram_offset, cecr_subblock, command;
227162306a36Sopenharmony_ci	u32 ifstat, i, j, size, l2qt, l3qt;
227262306a36Sopenharmony_ci	u16 temoder = UCC_GETH_TEMODER_INIT;
227362306a36Sopenharmony_ci	u8 function_code = 0;
227462306a36Sopenharmony_ci	u8 __iomem *endOfRing;
227562306a36Sopenharmony_ci	u8 numThreadsRxNumerical, numThreadsTxNumerical;
227662306a36Sopenharmony_ci	s32 rx_glbl_pram_offset, tx_glbl_pram_offset;
227762306a36Sopenharmony_ci
227862306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
227962306a36Sopenharmony_ci	uccf = ugeth->uccf;
228062306a36Sopenharmony_ci	ug_info = ugeth->ug_info;
228162306a36Sopenharmony_ci	uf_info = &ug_info->uf_info;
228262306a36Sopenharmony_ci	uf_regs = uccf->uf_regs;
228362306a36Sopenharmony_ci	ug_regs = ugeth->ug_regs;
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	numThreadsRxNumerical = ucc_geth_thread_count(ug_info->numThreadsRx);
228662306a36Sopenharmony_ci	if (!numThreadsRxNumerical) {
228762306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
228862306a36Sopenharmony_ci			pr_err("Bad number of Rx threads value\n");
228962306a36Sopenharmony_ci		return -EINVAL;
229062306a36Sopenharmony_ci	}
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_ci	numThreadsTxNumerical = ucc_geth_thread_count(ug_info->numThreadsTx);
229362306a36Sopenharmony_ci	if (!numThreadsTxNumerical) {
229462306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
229562306a36Sopenharmony_ci			pr_err("Bad number of Tx threads value\n");
229662306a36Sopenharmony_ci		return -EINVAL;
229762306a36Sopenharmony_ci	}
229862306a36Sopenharmony_ci
229962306a36Sopenharmony_ci	/* Calculate rx_extended_features */
230062306a36Sopenharmony_ci	ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck ||
230162306a36Sopenharmony_ci	    ug_info->ipAddressAlignment ||
230262306a36Sopenharmony_ci	    (ug_info->numStationAddresses !=
230362306a36Sopenharmony_ci	     UCC_GETH_NUM_OF_STATION_ADDRESSES_1);
230462306a36Sopenharmony_ci
230562306a36Sopenharmony_ci	ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features ||
230662306a36Sopenharmony_ci		(ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) ||
230762306a36Sopenharmony_ci		(ug_info->vlanOperationNonTagged !=
230862306a36Sopenharmony_ci		 UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP);
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci	init_default_reg_vals(&uf_regs->upsmr,
231162306a36Sopenharmony_ci			      &ug_regs->maccfg1, &ug_regs->maccfg2);
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_ci	/*                    Set UPSMR                      */
231462306a36Sopenharmony_ci	/* For more details see the hardware spec.           */
231562306a36Sopenharmony_ci	init_rx_parameters(ug_info->bro,
231662306a36Sopenharmony_ci			   ug_info->rsh, ug_info->pro, &uf_regs->upsmr);
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_ci	/* We're going to ignore other registers for now, */
231962306a36Sopenharmony_ci	/* except as needed to get up and running         */
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ci	/*                    Set MACCFG1                    */
232262306a36Sopenharmony_ci	/* For more details see the hardware spec.           */
232362306a36Sopenharmony_ci	init_flow_control_params(ug_info->aufc,
232462306a36Sopenharmony_ci				 ug_info->receiveFlowControl,
232562306a36Sopenharmony_ci				 ug_info->transmitFlowControl,
232662306a36Sopenharmony_ci				 ug_info->pausePeriod,
232762306a36Sopenharmony_ci				 ug_info->extensionField,
232862306a36Sopenharmony_ci				 &uf_regs->upsmr,
232962306a36Sopenharmony_ci				 &ug_regs->uempr, &ug_regs->maccfg1);
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci	setbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
233262306a36Sopenharmony_ci
233362306a36Sopenharmony_ci	/*                    Set IPGIFG                     */
233462306a36Sopenharmony_ci	/* For more details see the hardware spec.           */
233562306a36Sopenharmony_ci	ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1,
233662306a36Sopenharmony_ci					      ug_info->nonBackToBackIfgPart2,
233762306a36Sopenharmony_ci					      ug_info->
233862306a36Sopenharmony_ci					      miminumInterFrameGapEnforcement,
233962306a36Sopenharmony_ci					      ug_info->backToBackInterFrameGap,
234062306a36Sopenharmony_ci					      &ug_regs->ipgifg);
234162306a36Sopenharmony_ci	if (ret_val != 0) {
234262306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
234362306a36Sopenharmony_ci			pr_err("IPGIFG initialization parameter too large\n");
234462306a36Sopenharmony_ci		return ret_val;
234562306a36Sopenharmony_ci	}
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ci	/*                    Set HAFDUP                     */
234862306a36Sopenharmony_ci	/* For more details see the hardware spec.           */
234962306a36Sopenharmony_ci	ret_val = init_half_duplex_params(ug_info->altBeb,
235062306a36Sopenharmony_ci					  ug_info->backPressureNoBackoff,
235162306a36Sopenharmony_ci					  ug_info->noBackoff,
235262306a36Sopenharmony_ci					  ug_info->excessDefer,
235362306a36Sopenharmony_ci					  ug_info->altBebTruncation,
235462306a36Sopenharmony_ci					  ug_info->maxRetransmission,
235562306a36Sopenharmony_ci					  ug_info->collisionWindow,
235662306a36Sopenharmony_ci					  &ug_regs->hafdup);
235762306a36Sopenharmony_ci	if (ret_val != 0) {
235862306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
235962306a36Sopenharmony_ci			pr_err("Half Duplex initialization parameter too large\n");
236062306a36Sopenharmony_ci		return ret_val;
236162306a36Sopenharmony_ci	}
236262306a36Sopenharmony_ci
236362306a36Sopenharmony_ci	/*                    Set IFSTAT                     */
236462306a36Sopenharmony_ci	/* For more details see the hardware spec.           */
236562306a36Sopenharmony_ci	/* Read only - resets upon read                      */
236662306a36Sopenharmony_ci	ifstat = in_be32(&ug_regs->ifstat);
236762306a36Sopenharmony_ci
236862306a36Sopenharmony_ci	/*                    Clear UEMPR                    */
236962306a36Sopenharmony_ci	/* For more details see the hardware spec.           */
237062306a36Sopenharmony_ci	out_be32(&ug_regs->uempr, 0);
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	/*                    Set UESCR                      */
237362306a36Sopenharmony_ci	/* For more details see the hardware spec.           */
237462306a36Sopenharmony_ci	init_hw_statistics_gathering_mode((ug_info->statisticsMode &
237562306a36Sopenharmony_ci				UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE),
237662306a36Sopenharmony_ci				0, &uf_regs->upsmr, &ug_regs->uescr);
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci	ret_val = ucc_geth_alloc_tx(ugeth);
237962306a36Sopenharmony_ci	if (ret_val != 0)
238062306a36Sopenharmony_ci		return ret_val;
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci	ret_val = ucc_geth_alloc_rx(ugeth);
238362306a36Sopenharmony_ci	if (ret_val != 0)
238462306a36Sopenharmony_ci		return ret_val;
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	/*
238762306a36Sopenharmony_ci	 * Global PRAM
238862306a36Sopenharmony_ci	 */
238962306a36Sopenharmony_ci	/* Tx global PRAM */
239062306a36Sopenharmony_ci	/* Allocate global tx parameter RAM page */
239162306a36Sopenharmony_ci	tx_glbl_pram_offset =
239262306a36Sopenharmony_ci	    qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram),
239362306a36Sopenharmony_ci			   UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT);
239462306a36Sopenharmony_ci	if (tx_glbl_pram_offset < 0) {
239562306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
239662306a36Sopenharmony_ci			pr_err("Can not allocate DPRAM memory for p_tx_glbl_pram\n");
239762306a36Sopenharmony_ci		return -ENOMEM;
239862306a36Sopenharmony_ci	}
239962306a36Sopenharmony_ci	ugeth->p_tx_glbl_pram = qe_muram_addr(tx_glbl_pram_offset);
240062306a36Sopenharmony_ci	/* Fill global PRAM */
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci	/* TQPTR */
240362306a36Sopenharmony_ci	/* Size varies with number of Tx threads */
240462306a36Sopenharmony_ci	ugeth->thread_dat_tx_offset =
240562306a36Sopenharmony_ci	    qe_muram_alloc(numThreadsTxNumerical *
240662306a36Sopenharmony_ci			   sizeof(struct ucc_geth_thread_data_tx) +
240762306a36Sopenharmony_ci			   32 * (numThreadsTxNumerical == 1),
240862306a36Sopenharmony_ci			   UCC_GETH_THREAD_DATA_ALIGNMENT);
240962306a36Sopenharmony_ci	if (IS_ERR_VALUE(ugeth->thread_dat_tx_offset)) {
241062306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
241162306a36Sopenharmony_ci			pr_err("Can not allocate DPRAM memory for p_thread_data_tx\n");
241262306a36Sopenharmony_ci		return -ENOMEM;
241362306a36Sopenharmony_ci	}
241462306a36Sopenharmony_ci
241562306a36Sopenharmony_ci	ugeth->p_thread_data_tx =
241662306a36Sopenharmony_ci	    (struct ucc_geth_thread_data_tx __iomem *) qe_muram_addr(ugeth->
241762306a36Sopenharmony_ci							thread_dat_tx_offset);
241862306a36Sopenharmony_ci	out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset);
241962306a36Sopenharmony_ci
242062306a36Sopenharmony_ci	/* vtagtable */
242162306a36Sopenharmony_ci	for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++)
242262306a36Sopenharmony_ci		out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i],
242362306a36Sopenharmony_ci			 ug_info->vtagtable[i]);
242462306a36Sopenharmony_ci
242562306a36Sopenharmony_ci	/* iphoffset */
242662306a36Sopenharmony_ci	for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++)
242762306a36Sopenharmony_ci		out_8(&ugeth->p_tx_glbl_pram->iphoffset[i],
242862306a36Sopenharmony_ci				ug_info->iphoffset[i]);
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci	/* SQPTR */
243162306a36Sopenharmony_ci	/* Size varies with number of Tx queues */
243262306a36Sopenharmony_ci	ugeth->send_q_mem_reg_offset =
243362306a36Sopenharmony_ci	    qe_muram_alloc(ucc_geth_tx_queues(ug_info) *
243462306a36Sopenharmony_ci			   sizeof(struct ucc_geth_send_queue_qd),
243562306a36Sopenharmony_ci			   UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT);
243662306a36Sopenharmony_ci	if (IS_ERR_VALUE(ugeth->send_q_mem_reg_offset)) {
243762306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
243862306a36Sopenharmony_ci			pr_err("Can not allocate DPRAM memory for p_send_q_mem_reg\n");
243962306a36Sopenharmony_ci		return -ENOMEM;
244062306a36Sopenharmony_ci	}
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	ugeth->p_send_q_mem_reg =
244362306a36Sopenharmony_ci	    (struct ucc_geth_send_queue_mem_region __iomem *) qe_muram_addr(ugeth->
244462306a36Sopenharmony_ci			send_q_mem_reg_offset);
244562306a36Sopenharmony_ci	out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset);
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci	/* Setup the table */
244862306a36Sopenharmony_ci	/* Assume BD rings are already established */
244962306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_tx_queues(ug_info); i++) {
245062306a36Sopenharmony_ci		endOfRing =
245162306a36Sopenharmony_ci		    ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] -
245262306a36Sopenharmony_ci					      1) * sizeof(struct qe_bd);
245362306a36Sopenharmony_ci		out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
245462306a36Sopenharmony_ci			 (u32) virt_to_phys(ugeth->p_tx_bd_ring[i]));
245562306a36Sopenharmony_ci		out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
245662306a36Sopenharmony_ci			 last_bd_completed_address,
245762306a36Sopenharmony_ci			 (u32) virt_to_phys(endOfRing));
245862306a36Sopenharmony_ci	}
245962306a36Sopenharmony_ci
246062306a36Sopenharmony_ci	/* schedulerbasepointer */
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_ci	if (ucc_geth_tx_queues(ug_info) > 1) {
246362306a36Sopenharmony_ci	/* scheduler exists only if more than 1 tx queue */
246462306a36Sopenharmony_ci		ugeth->scheduler_offset =
246562306a36Sopenharmony_ci		    qe_muram_alloc(sizeof(struct ucc_geth_scheduler),
246662306a36Sopenharmony_ci				   UCC_GETH_SCHEDULER_ALIGNMENT);
246762306a36Sopenharmony_ci		if (IS_ERR_VALUE(ugeth->scheduler_offset)) {
246862306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
246962306a36Sopenharmony_ci				pr_err("Can not allocate DPRAM memory for p_scheduler\n");
247062306a36Sopenharmony_ci			return -ENOMEM;
247162306a36Sopenharmony_ci		}
247262306a36Sopenharmony_ci
247362306a36Sopenharmony_ci		ugeth->p_scheduler =
247462306a36Sopenharmony_ci		    (struct ucc_geth_scheduler __iomem *) qe_muram_addr(ugeth->
247562306a36Sopenharmony_ci							   scheduler_offset);
247662306a36Sopenharmony_ci		out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer,
247762306a36Sopenharmony_ci			 ugeth->scheduler_offset);
247862306a36Sopenharmony_ci
247962306a36Sopenharmony_ci		/* Set values in scheduler */
248062306a36Sopenharmony_ci		out_be32(&ugeth->p_scheduler->mblinterval,
248162306a36Sopenharmony_ci			 ug_info->mblinterval);
248262306a36Sopenharmony_ci		out_be16(&ugeth->p_scheduler->nortsrbytetime,
248362306a36Sopenharmony_ci			 ug_info->nortsrbytetime);
248462306a36Sopenharmony_ci		out_8(&ugeth->p_scheduler->fracsiz, ug_info->fracsiz);
248562306a36Sopenharmony_ci		out_8(&ugeth->p_scheduler->strictpriorityq,
248662306a36Sopenharmony_ci				ug_info->strictpriorityq);
248762306a36Sopenharmony_ci		out_8(&ugeth->p_scheduler->txasap, ug_info->txasap);
248862306a36Sopenharmony_ci		out_8(&ugeth->p_scheduler->extrabw, ug_info->extrabw);
248962306a36Sopenharmony_ci		for (i = 0; i < NUM_TX_QUEUES; i++)
249062306a36Sopenharmony_ci			out_8(&ugeth->p_scheduler->weightfactor[i],
249162306a36Sopenharmony_ci			    ug_info->weightfactor[i]);
249262306a36Sopenharmony_ci
249362306a36Sopenharmony_ci		/* Set pointers to cpucount registers in scheduler */
249462306a36Sopenharmony_ci		ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0);
249562306a36Sopenharmony_ci		ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1);
249662306a36Sopenharmony_ci		ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2);
249762306a36Sopenharmony_ci		ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3);
249862306a36Sopenharmony_ci		ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4);
249962306a36Sopenharmony_ci		ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5);
250062306a36Sopenharmony_ci		ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6);
250162306a36Sopenharmony_ci		ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7);
250262306a36Sopenharmony_ci	}
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci	/* schedulerbasepointer */
250562306a36Sopenharmony_ci	/* TxRMON_PTR (statistics) */
250662306a36Sopenharmony_ci	if (ug_info->
250762306a36Sopenharmony_ci	    statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
250862306a36Sopenharmony_ci		ugeth->tx_fw_statistics_pram_offset =
250962306a36Sopenharmony_ci		    qe_muram_alloc(sizeof
251062306a36Sopenharmony_ci				   (struct ucc_geth_tx_firmware_statistics_pram),
251162306a36Sopenharmony_ci				   UCC_GETH_TX_STATISTICS_ALIGNMENT);
251262306a36Sopenharmony_ci		if (IS_ERR_VALUE(ugeth->tx_fw_statistics_pram_offset)) {
251362306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
251462306a36Sopenharmony_ci				pr_err("Can not allocate DPRAM memory for p_tx_fw_statistics_pram\n");
251562306a36Sopenharmony_ci			return -ENOMEM;
251662306a36Sopenharmony_ci		}
251762306a36Sopenharmony_ci		ugeth->p_tx_fw_statistics_pram =
251862306a36Sopenharmony_ci		    (struct ucc_geth_tx_firmware_statistics_pram __iomem *)
251962306a36Sopenharmony_ci		    qe_muram_addr(ugeth->tx_fw_statistics_pram_offset);
252062306a36Sopenharmony_ci	}
252162306a36Sopenharmony_ci
252262306a36Sopenharmony_ci	/* temoder */
252362306a36Sopenharmony_ci	/* Already has speed set */
252462306a36Sopenharmony_ci
252562306a36Sopenharmony_ci	if (ucc_geth_tx_queues(ug_info) > 1)
252662306a36Sopenharmony_ci		temoder |= TEMODER_SCHEDULER_ENABLE;
252762306a36Sopenharmony_ci	if (ug_info->ipCheckSumGenerate)
252862306a36Sopenharmony_ci		temoder |= TEMODER_IP_CHECKSUM_GENERATE;
252962306a36Sopenharmony_ci	temoder |= ((ucc_geth_tx_queues(ug_info) - 1) << TEMODER_NUM_OF_QUEUES_SHIFT);
253062306a36Sopenharmony_ci	out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder);
253162306a36Sopenharmony_ci
253262306a36Sopenharmony_ci	/* Function code register value to be used later */
253362306a36Sopenharmony_ci	function_code = UCC_BMR_BO_BE | UCC_BMR_GBL;
253462306a36Sopenharmony_ci	/* Required for QE */
253562306a36Sopenharmony_ci
253662306a36Sopenharmony_ci	/* function code register */
253762306a36Sopenharmony_ci	out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24);
253862306a36Sopenharmony_ci
253962306a36Sopenharmony_ci	/* Rx global PRAM */
254062306a36Sopenharmony_ci	/* Allocate global rx parameter RAM page */
254162306a36Sopenharmony_ci	rx_glbl_pram_offset =
254262306a36Sopenharmony_ci	    qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram),
254362306a36Sopenharmony_ci			   UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT);
254462306a36Sopenharmony_ci	if (rx_glbl_pram_offset < 0) {
254562306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
254662306a36Sopenharmony_ci			pr_err("Can not allocate DPRAM memory for p_rx_glbl_pram\n");
254762306a36Sopenharmony_ci		return -ENOMEM;
254862306a36Sopenharmony_ci	}
254962306a36Sopenharmony_ci	ugeth->p_rx_glbl_pram = qe_muram_addr(rx_glbl_pram_offset);
255062306a36Sopenharmony_ci	/* Fill global PRAM */
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ci	/* RQPTR */
255362306a36Sopenharmony_ci	/* Size varies with number of Rx threads */
255462306a36Sopenharmony_ci	ugeth->thread_dat_rx_offset =
255562306a36Sopenharmony_ci	    qe_muram_alloc(numThreadsRxNumerical *
255662306a36Sopenharmony_ci			   sizeof(struct ucc_geth_thread_data_rx),
255762306a36Sopenharmony_ci			   UCC_GETH_THREAD_DATA_ALIGNMENT);
255862306a36Sopenharmony_ci	if (IS_ERR_VALUE(ugeth->thread_dat_rx_offset)) {
255962306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
256062306a36Sopenharmony_ci			pr_err("Can not allocate DPRAM memory for p_thread_data_rx\n");
256162306a36Sopenharmony_ci		return -ENOMEM;
256262306a36Sopenharmony_ci	}
256362306a36Sopenharmony_ci
256462306a36Sopenharmony_ci	ugeth->p_thread_data_rx =
256562306a36Sopenharmony_ci	    (struct ucc_geth_thread_data_rx __iomem *) qe_muram_addr(ugeth->
256662306a36Sopenharmony_ci							thread_dat_rx_offset);
256762306a36Sopenharmony_ci	out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset);
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_ci	/* typeorlen */
257062306a36Sopenharmony_ci	out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen);
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci	/* rxrmonbaseptr (statistics) */
257362306a36Sopenharmony_ci	if (ug_info->
257462306a36Sopenharmony_ci	    statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
257562306a36Sopenharmony_ci		ugeth->rx_fw_statistics_pram_offset =
257662306a36Sopenharmony_ci		    qe_muram_alloc(sizeof
257762306a36Sopenharmony_ci				   (struct ucc_geth_rx_firmware_statistics_pram),
257862306a36Sopenharmony_ci				   UCC_GETH_RX_STATISTICS_ALIGNMENT);
257962306a36Sopenharmony_ci		if (IS_ERR_VALUE(ugeth->rx_fw_statistics_pram_offset)) {
258062306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
258162306a36Sopenharmony_ci				pr_err("Can not allocate DPRAM memory for p_rx_fw_statistics_pram\n");
258262306a36Sopenharmony_ci			return -ENOMEM;
258362306a36Sopenharmony_ci		}
258462306a36Sopenharmony_ci		ugeth->p_rx_fw_statistics_pram =
258562306a36Sopenharmony_ci		    (struct ucc_geth_rx_firmware_statistics_pram __iomem *)
258662306a36Sopenharmony_ci		    qe_muram_addr(ugeth->rx_fw_statistics_pram_offset);
258762306a36Sopenharmony_ci	}
258862306a36Sopenharmony_ci
258962306a36Sopenharmony_ci	/* intCoalescingPtr */
259062306a36Sopenharmony_ci
259162306a36Sopenharmony_ci	/* Size varies with number of Rx queues */
259262306a36Sopenharmony_ci	ugeth->rx_irq_coalescing_tbl_offset =
259362306a36Sopenharmony_ci	    qe_muram_alloc(ucc_geth_rx_queues(ug_info) *
259462306a36Sopenharmony_ci			   sizeof(struct ucc_geth_rx_interrupt_coalescing_entry)
259562306a36Sopenharmony_ci			   + 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT);
259662306a36Sopenharmony_ci	if (IS_ERR_VALUE(ugeth->rx_irq_coalescing_tbl_offset)) {
259762306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
259862306a36Sopenharmony_ci			pr_err("Can not allocate DPRAM memory for p_rx_irq_coalescing_tbl\n");
259962306a36Sopenharmony_ci		return -ENOMEM;
260062306a36Sopenharmony_ci	}
260162306a36Sopenharmony_ci
260262306a36Sopenharmony_ci	ugeth->p_rx_irq_coalescing_tbl =
260362306a36Sopenharmony_ci	    (struct ucc_geth_rx_interrupt_coalescing_table __iomem *)
260462306a36Sopenharmony_ci	    qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset);
260562306a36Sopenharmony_ci	out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr,
260662306a36Sopenharmony_ci		 ugeth->rx_irq_coalescing_tbl_offset);
260762306a36Sopenharmony_ci
260862306a36Sopenharmony_ci	/* Fill interrupt coalescing table */
260962306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_rx_queues(ug_info); i++) {
261062306a36Sopenharmony_ci		out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
261162306a36Sopenharmony_ci			 interruptcoalescingmaxvalue,
261262306a36Sopenharmony_ci			 ug_info->interruptcoalescingmaxvalue[i]);
261362306a36Sopenharmony_ci		out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
261462306a36Sopenharmony_ci			 interruptcoalescingcounter,
261562306a36Sopenharmony_ci			 ug_info->interruptcoalescingmaxvalue[i]);
261662306a36Sopenharmony_ci	}
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_ci	/* MRBLR */
261962306a36Sopenharmony_ci	init_max_rx_buff_len(uf_info->max_rx_buf_length,
262062306a36Sopenharmony_ci			     &ugeth->p_rx_glbl_pram->mrblr);
262162306a36Sopenharmony_ci	/* MFLR */
262262306a36Sopenharmony_ci	out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength);
262362306a36Sopenharmony_ci	/* MINFLR */
262462306a36Sopenharmony_ci	init_min_frame_len(ug_info->minFrameLength,
262562306a36Sopenharmony_ci			   &ugeth->p_rx_glbl_pram->minflr,
262662306a36Sopenharmony_ci			   &ugeth->p_rx_glbl_pram->mrblr);
262762306a36Sopenharmony_ci	/* MAXD1 */
262862306a36Sopenharmony_ci	out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length);
262962306a36Sopenharmony_ci	/* MAXD2 */
263062306a36Sopenharmony_ci	out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length);
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	/* l2qt */
263362306a36Sopenharmony_ci	l2qt = 0;
263462306a36Sopenharmony_ci	for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++)
263562306a36Sopenharmony_ci		l2qt |= (ug_info->l2qt[i] << (28 - 4 * i));
263662306a36Sopenharmony_ci	out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt);
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci	/* l3qt */
263962306a36Sopenharmony_ci	for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) {
264062306a36Sopenharmony_ci		l3qt = 0;
264162306a36Sopenharmony_ci		for (i = 0; i < 8; i++)
264262306a36Sopenharmony_ci			l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i));
264362306a36Sopenharmony_ci		out_be32(&ugeth->p_rx_glbl_pram->l3qt[j/8], l3qt);
264462306a36Sopenharmony_ci	}
264562306a36Sopenharmony_ci
264662306a36Sopenharmony_ci	/* vlantype */
264762306a36Sopenharmony_ci	out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype);
264862306a36Sopenharmony_ci
264962306a36Sopenharmony_ci	/* vlantci */
265062306a36Sopenharmony_ci	out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci);
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci	/* ecamptr */
265362306a36Sopenharmony_ci	out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr);
265462306a36Sopenharmony_ci
265562306a36Sopenharmony_ci	/* RBDQPTR */
265662306a36Sopenharmony_ci	/* Size varies with number of Rx queues */
265762306a36Sopenharmony_ci	ugeth->rx_bd_qs_tbl_offset =
265862306a36Sopenharmony_ci	    qe_muram_alloc(ucc_geth_rx_queues(ug_info) *
265962306a36Sopenharmony_ci			   (sizeof(struct ucc_geth_rx_bd_queues_entry) +
266062306a36Sopenharmony_ci			    sizeof(struct ucc_geth_rx_prefetched_bds)),
266162306a36Sopenharmony_ci			   UCC_GETH_RX_BD_QUEUES_ALIGNMENT);
266262306a36Sopenharmony_ci	if (IS_ERR_VALUE(ugeth->rx_bd_qs_tbl_offset)) {
266362306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
266462306a36Sopenharmony_ci			pr_err("Can not allocate DPRAM memory for p_rx_bd_qs_tbl\n");
266562306a36Sopenharmony_ci		return -ENOMEM;
266662306a36Sopenharmony_ci	}
266762306a36Sopenharmony_ci
266862306a36Sopenharmony_ci	ugeth->p_rx_bd_qs_tbl =
266962306a36Sopenharmony_ci	    (struct ucc_geth_rx_bd_queues_entry __iomem *) qe_muram_addr(ugeth->
267062306a36Sopenharmony_ci				    rx_bd_qs_tbl_offset);
267162306a36Sopenharmony_ci	out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset);
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_ci	/* Setup the table */
267462306a36Sopenharmony_ci	/* Assume BD rings are already established */
267562306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_rx_queues(ug_info); i++) {
267662306a36Sopenharmony_ci		out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
267762306a36Sopenharmony_ci			 (u32) virt_to_phys(ugeth->p_rx_bd_ring[i]));
267862306a36Sopenharmony_ci		/* rest of fields handled by QE */
267962306a36Sopenharmony_ci	}
268062306a36Sopenharmony_ci
268162306a36Sopenharmony_ci	/* remoder */
268262306a36Sopenharmony_ci	/* Already has speed set */
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci	if (ugeth->rx_extended_features)
268562306a36Sopenharmony_ci		remoder |= REMODER_RX_EXTENDED_FEATURES;
268662306a36Sopenharmony_ci	if (ug_info->rxExtendedFiltering)
268762306a36Sopenharmony_ci		remoder |= REMODER_RX_EXTENDED_FILTERING;
268862306a36Sopenharmony_ci	if (ug_info->dynamicMaxFrameLength)
268962306a36Sopenharmony_ci		remoder |= REMODER_DYNAMIC_MAX_FRAME_LENGTH;
269062306a36Sopenharmony_ci	if (ug_info->dynamicMinFrameLength)
269162306a36Sopenharmony_ci		remoder |= REMODER_DYNAMIC_MIN_FRAME_LENGTH;
269262306a36Sopenharmony_ci	remoder |=
269362306a36Sopenharmony_ci	    ug_info->vlanOperationTagged << REMODER_VLAN_OPERATION_TAGGED_SHIFT;
269462306a36Sopenharmony_ci	remoder |=
269562306a36Sopenharmony_ci	    ug_info->
269662306a36Sopenharmony_ci	    vlanOperationNonTagged << REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT;
269762306a36Sopenharmony_ci	remoder |= ug_info->rxQoSMode << REMODER_RX_QOS_MODE_SHIFT;
269862306a36Sopenharmony_ci	remoder |= ((ucc_geth_rx_queues(ug_info) - 1) << REMODER_NUM_OF_QUEUES_SHIFT);
269962306a36Sopenharmony_ci	if (ug_info->ipCheckSumCheck)
270062306a36Sopenharmony_ci		remoder |= REMODER_IP_CHECKSUM_CHECK;
270162306a36Sopenharmony_ci	if (ug_info->ipAddressAlignment)
270262306a36Sopenharmony_ci		remoder |= REMODER_IP_ADDRESS_ALIGNMENT;
270362306a36Sopenharmony_ci	out_be32(&ugeth->p_rx_glbl_pram->remoder, remoder);
270462306a36Sopenharmony_ci
270562306a36Sopenharmony_ci	/* Note that this function must be called */
270662306a36Sopenharmony_ci	/* ONLY AFTER p_tx_fw_statistics_pram */
270762306a36Sopenharmony_ci	/* andp_UccGethRxFirmwareStatisticsPram are allocated ! */
270862306a36Sopenharmony_ci	init_firmware_statistics_gathering_mode((ug_info->
270962306a36Sopenharmony_ci		statisticsMode &
271062306a36Sopenharmony_ci		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX),
271162306a36Sopenharmony_ci		(ug_info->statisticsMode &
271262306a36Sopenharmony_ci		UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX),
271362306a36Sopenharmony_ci		&ugeth->p_tx_glbl_pram->txrmonbaseptr,
271462306a36Sopenharmony_ci		ugeth->tx_fw_statistics_pram_offset,
271562306a36Sopenharmony_ci		&ugeth->p_rx_glbl_pram->rxrmonbaseptr,
271662306a36Sopenharmony_ci		ugeth->rx_fw_statistics_pram_offset,
271762306a36Sopenharmony_ci		&ugeth->p_tx_glbl_pram->temoder,
271862306a36Sopenharmony_ci		&ugeth->p_rx_glbl_pram->remoder);
271962306a36Sopenharmony_ci
272062306a36Sopenharmony_ci	/* function code register */
272162306a36Sopenharmony_ci	out_8(&ugeth->p_rx_glbl_pram->rstate, function_code);
272262306a36Sopenharmony_ci
272362306a36Sopenharmony_ci	/* initialize extended filtering */
272462306a36Sopenharmony_ci	if (ug_info->rxExtendedFiltering) {
272562306a36Sopenharmony_ci		if (!ug_info->extendedFilteringChainPointer) {
272662306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
272762306a36Sopenharmony_ci				pr_err("Null Extended Filtering Chain Pointer\n");
272862306a36Sopenharmony_ci			return -EINVAL;
272962306a36Sopenharmony_ci		}
273062306a36Sopenharmony_ci
273162306a36Sopenharmony_ci		/* Allocate memory for extended filtering Mode Global
273262306a36Sopenharmony_ci		Parameters */
273362306a36Sopenharmony_ci		ugeth->exf_glbl_param_offset =
273462306a36Sopenharmony_ci		    qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram),
273562306a36Sopenharmony_ci		UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT);
273662306a36Sopenharmony_ci		if (IS_ERR_VALUE(ugeth->exf_glbl_param_offset)) {
273762306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
273862306a36Sopenharmony_ci				pr_err("Can not allocate DPRAM memory for p_exf_glbl_param\n");
273962306a36Sopenharmony_ci			return -ENOMEM;
274062306a36Sopenharmony_ci		}
274162306a36Sopenharmony_ci
274262306a36Sopenharmony_ci		ugeth->p_exf_glbl_param =
274362306a36Sopenharmony_ci		    (struct ucc_geth_exf_global_pram __iomem *) qe_muram_addr(ugeth->
274462306a36Sopenharmony_ci				 exf_glbl_param_offset);
274562306a36Sopenharmony_ci		out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam,
274662306a36Sopenharmony_ci			 ugeth->exf_glbl_param_offset);
274762306a36Sopenharmony_ci		out_be32(&ugeth->p_exf_glbl_param->l2pcdptr,
274862306a36Sopenharmony_ci			 (u32) ug_info->extendedFilteringChainPointer);
274962306a36Sopenharmony_ci
275062306a36Sopenharmony_ci	} else {		/* initialize 82xx style address filtering */
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_ci		/* Init individual address recognition registers to disabled */
275362306a36Sopenharmony_ci
275462306a36Sopenharmony_ci		for (j = 0; j < NUM_OF_PADDRS; j++)
275562306a36Sopenharmony_ci			ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j);
275662306a36Sopenharmony_ci
275762306a36Sopenharmony_ci		p_82xx_addr_filt =
275862306a36Sopenharmony_ci		    (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->
275962306a36Sopenharmony_ci		    p_rx_glbl_pram->addressfiltering;
276062306a36Sopenharmony_ci
276162306a36Sopenharmony_ci		ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
276262306a36Sopenharmony_ci			ENET_ADDR_TYPE_GROUP);
276362306a36Sopenharmony_ci		ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth,
276462306a36Sopenharmony_ci			ENET_ADDR_TYPE_INDIVIDUAL);
276562306a36Sopenharmony_ci	}
276662306a36Sopenharmony_ci
276762306a36Sopenharmony_ci	/*
276862306a36Sopenharmony_ci	 * Initialize UCC at QE level
276962306a36Sopenharmony_ci	 */
277062306a36Sopenharmony_ci
277162306a36Sopenharmony_ci	command = QE_INIT_TX_RX;
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_ci	/* Allocate shadow InitEnet command parameter structure.
277462306a36Sopenharmony_ci	 * This is needed because after the InitEnet command is executed,
277562306a36Sopenharmony_ci	 * the structure in DPRAM is released, because DPRAM is a premium
277662306a36Sopenharmony_ci	 * resource.
277762306a36Sopenharmony_ci	 * This shadow structure keeps a copy of what was done so that the
277862306a36Sopenharmony_ci	 * allocated resources can be released when the channel is freed.
277962306a36Sopenharmony_ci	 */
278062306a36Sopenharmony_ci	if (!(ugeth->p_init_enet_param_shadow =
278162306a36Sopenharmony_ci	      kzalloc(sizeof(struct ucc_geth_init_pram), GFP_KERNEL))) {
278262306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
278362306a36Sopenharmony_ci			pr_err("Can not allocate memory for p_UccInitEnetParamShadows\n");
278462306a36Sopenharmony_ci		return -ENOMEM;
278562306a36Sopenharmony_ci	}
278662306a36Sopenharmony_ci
278762306a36Sopenharmony_ci	/* Fill shadow InitEnet command parameter structure */
278862306a36Sopenharmony_ci
278962306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->resinit1 =
279062306a36Sopenharmony_ci	    ENET_INIT_PARAM_MAGIC_RES_INIT1;
279162306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->resinit2 =
279262306a36Sopenharmony_ci	    ENET_INIT_PARAM_MAGIC_RES_INIT2;
279362306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->resinit3 =
279462306a36Sopenharmony_ci	    ENET_INIT_PARAM_MAGIC_RES_INIT3;
279562306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->resinit4 =
279662306a36Sopenharmony_ci	    ENET_INIT_PARAM_MAGIC_RES_INIT4;
279762306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->resinit5 =
279862306a36Sopenharmony_ci	    ENET_INIT_PARAM_MAGIC_RES_INIT5;
279962306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
280062306a36Sopenharmony_ci	    ((u32) ug_info->numThreadsRx) << ENET_INIT_PARAM_RGF_SHIFT;
280162306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
280262306a36Sopenharmony_ci	    ((u32) ug_info->numThreadsTx) << ENET_INIT_PARAM_TGF_SHIFT;
280362306a36Sopenharmony_ci
280462306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->rgftgfrxglobal |=
280562306a36Sopenharmony_ci	    rx_glbl_pram_offset | ug_info->riscRx;
280662306a36Sopenharmony_ci	if ((ug_info->largestexternallookupkeysize !=
280762306a36Sopenharmony_ci	     QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE) &&
280862306a36Sopenharmony_ci	    (ug_info->largestexternallookupkeysize !=
280962306a36Sopenharmony_ci	     QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) &&
281062306a36Sopenharmony_ci	    (ug_info->largestexternallookupkeysize !=
281162306a36Sopenharmony_ci	     QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) {
281262306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
281362306a36Sopenharmony_ci			pr_err("Invalid largest External Lookup Key Size\n");
281462306a36Sopenharmony_ci		return -EINVAL;
281562306a36Sopenharmony_ci	}
281662306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->largestexternallookupkeysize =
281762306a36Sopenharmony_ci	    ug_info->largestexternallookupkeysize;
281862306a36Sopenharmony_ci	size = sizeof(struct ucc_geth_thread_rx_pram);
281962306a36Sopenharmony_ci	if (ug_info->rxExtendedFiltering) {
282062306a36Sopenharmony_ci		size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
282162306a36Sopenharmony_ci		if (ug_info->largestexternallookupkeysize ==
282262306a36Sopenharmony_ci		    QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
282362306a36Sopenharmony_ci			size +=
282462306a36Sopenharmony_ci			    THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
282562306a36Sopenharmony_ci		if (ug_info->largestexternallookupkeysize ==
282662306a36Sopenharmony_ci		    QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
282762306a36Sopenharmony_ci			size +=
282862306a36Sopenharmony_ci			    THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
282962306a36Sopenharmony_ci	}
283062306a36Sopenharmony_ci
283162306a36Sopenharmony_ci	if ((ret_val = fill_init_enet_entries(ugeth, &(ugeth->
283262306a36Sopenharmony_ci		p_init_enet_param_shadow->rxthread[0]),
283362306a36Sopenharmony_ci		(u8) (numThreadsRxNumerical + 1)
283462306a36Sopenharmony_ci		/* Rx needs one extra for terminator */
283562306a36Sopenharmony_ci		, size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT,
283662306a36Sopenharmony_ci		ug_info->riscRx, 1)) != 0) {
283762306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
283862306a36Sopenharmony_ci			pr_err("Can not fill p_init_enet_param_shadow\n");
283962306a36Sopenharmony_ci		return ret_val;
284062306a36Sopenharmony_ci	}
284162306a36Sopenharmony_ci
284262306a36Sopenharmony_ci	ugeth->p_init_enet_param_shadow->txglobal =
284362306a36Sopenharmony_ci	    tx_glbl_pram_offset | ug_info->riscTx;
284462306a36Sopenharmony_ci	if ((ret_val =
284562306a36Sopenharmony_ci	     fill_init_enet_entries(ugeth,
284662306a36Sopenharmony_ci				    &(ugeth->p_init_enet_param_shadow->
284762306a36Sopenharmony_ci				      txthread[0]), numThreadsTxNumerical,
284862306a36Sopenharmony_ci				    sizeof(struct ucc_geth_thread_tx_pram),
284962306a36Sopenharmony_ci				    UCC_GETH_THREAD_TX_PRAM_ALIGNMENT,
285062306a36Sopenharmony_ci				    ug_info->riscTx, 0)) != 0) {
285162306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
285262306a36Sopenharmony_ci			pr_err("Can not fill p_init_enet_param_shadow\n");
285362306a36Sopenharmony_ci		return ret_val;
285462306a36Sopenharmony_ci	}
285562306a36Sopenharmony_ci
285662306a36Sopenharmony_ci	/* Load Rx bds with buffers */
285762306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_rx_queues(ug_info); i++) {
285862306a36Sopenharmony_ci		if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) {
285962306a36Sopenharmony_ci			if (netif_msg_ifup(ugeth))
286062306a36Sopenharmony_ci				pr_err("Can not fill Rx bds with buffers\n");
286162306a36Sopenharmony_ci			return ret_val;
286262306a36Sopenharmony_ci		}
286362306a36Sopenharmony_ci	}
286462306a36Sopenharmony_ci
286562306a36Sopenharmony_ci	/* Allocate InitEnet command parameter structure */
286662306a36Sopenharmony_ci	init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4);
286762306a36Sopenharmony_ci	if (IS_ERR_VALUE(init_enet_pram_offset)) {
286862306a36Sopenharmony_ci		if (netif_msg_ifup(ugeth))
286962306a36Sopenharmony_ci			pr_err("Can not allocate DPRAM memory for p_init_enet_pram\n");
287062306a36Sopenharmony_ci		return -ENOMEM;
287162306a36Sopenharmony_ci	}
287262306a36Sopenharmony_ci	p_init_enet_pram =
287362306a36Sopenharmony_ci	    (struct ucc_geth_init_pram __iomem *) qe_muram_addr(init_enet_pram_offset);
287462306a36Sopenharmony_ci
287562306a36Sopenharmony_ci	/* Copy shadow InitEnet command parameter structure into PRAM */
287662306a36Sopenharmony_ci	out_8(&p_init_enet_pram->resinit1,
287762306a36Sopenharmony_ci			ugeth->p_init_enet_param_shadow->resinit1);
287862306a36Sopenharmony_ci	out_8(&p_init_enet_pram->resinit2,
287962306a36Sopenharmony_ci			ugeth->p_init_enet_param_shadow->resinit2);
288062306a36Sopenharmony_ci	out_8(&p_init_enet_pram->resinit3,
288162306a36Sopenharmony_ci			ugeth->p_init_enet_param_shadow->resinit3);
288262306a36Sopenharmony_ci	out_8(&p_init_enet_pram->resinit4,
288362306a36Sopenharmony_ci			ugeth->p_init_enet_param_shadow->resinit4);
288462306a36Sopenharmony_ci	out_be16(&p_init_enet_pram->resinit5,
288562306a36Sopenharmony_ci		 ugeth->p_init_enet_param_shadow->resinit5);
288662306a36Sopenharmony_ci	out_8(&p_init_enet_pram->largestexternallookupkeysize,
288762306a36Sopenharmony_ci	    ugeth->p_init_enet_param_shadow->largestexternallookupkeysize);
288862306a36Sopenharmony_ci	out_be32(&p_init_enet_pram->rgftgfrxglobal,
288962306a36Sopenharmony_ci		 ugeth->p_init_enet_param_shadow->rgftgfrxglobal);
289062306a36Sopenharmony_ci	for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_RX; i++)
289162306a36Sopenharmony_ci		out_be32(&p_init_enet_pram->rxthread[i],
289262306a36Sopenharmony_ci			 ugeth->p_init_enet_param_shadow->rxthread[i]);
289362306a36Sopenharmony_ci	out_be32(&p_init_enet_pram->txglobal,
289462306a36Sopenharmony_ci		 ugeth->p_init_enet_param_shadow->txglobal);
289562306a36Sopenharmony_ci	for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_TX; i++)
289662306a36Sopenharmony_ci		out_be32(&p_init_enet_pram->txthread[i],
289762306a36Sopenharmony_ci			 ugeth->p_init_enet_param_shadow->txthread[i]);
289862306a36Sopenharmony_ci
289962306a36Sopenharmony_ci	/* Issue QE command */
290062306a36Sopenharmony_ci	cecr_subblock =
290162306a36Sopenharmony_ci	    ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
290262306a36Sopenharmony_ci	qe_issue_cmd(command, cecr_subblock, QE_CR_PROTOCOL_ETHERNET,
290362306a36Sopenharmony_ci		     init_enet_pram_offset);
290462306a36Sopenharmony_ci
290562306a36Sopenharmony_ci	/* Free InitEnet command parameter */
290662306a36Sopenharmony_ci	qe_muram_free(init_enet_pram_offset);
290762306a36Sopenharmony_ci
290862306a36Sopenharmony_ci	return 0;
290962306a36Sopenharmony_ci}
291062306a36Sopenharmony_ci
291162306a36Sopenharmony_ci/* This is called by the kernel when a frame is ready for transmission. */
291262306a36Sopenharmony_ci/* It is pointed to by the dev->hard_start_xmit function pointer */
291362306a36Sopenharmony_cistatic netdev_tx_t
291462306a36Sopenharmony_ciucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
291562306a36Sopenharmony_ci{
291662306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
291762306a36Sopenharmony_ci#ifdef CONFIG_UGETH_TX_ON_DEMAND
291862306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
291962306a36Sopenharmony_ci#endif
292062306a36Sopenharmony_ci	u8 __iomem *bd;			/* BD pointer */
292162306a36Sopenharmony_ci	u32 bd_status;
292262306a36Sopenharmony_ci	u8 txQ = 0;
292362306a36Sopenharmony_ci	unsigned long flags;
292462306a36Sopenharmony_ci
292562306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
292662306a36Sopenharmony_ci
292762306a36Sopenharmony_ci	netdev_sent_queue(dev, skb->len);
292862306a36Sopenharmony_ci	spin_lock_irqsave(&ugeth->lock, flags);
292962306a36Sopenharmony_ci
293062306a36Sopenharmony_ci	dev->stats.tx_bytes += skb->len;
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_ci	/* Start from the next BD that should be filled */
293362306a36Sopenharmony_ci	bd = ugeth->txBd[txQ];
293462306a36Sopenharmony_ci	bd_status = in_be32((u32 __iomem *)bd);
293562306a36Sopenharmony_ci	/* Save the skb pointer so we can free it later */
293662306a36Sopenharmony_ci	ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb;
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	/* Update the current skb pointer (wrapping if this was the last) */
293962306a36Sopenharmony_ci	ugeth->skb_curtx[txQ] =
294062306a36Sopenharmony_ci	    (ugeth->skb_curtx[txQ] +
294162306a36Sopenharmony_ci	     1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]);
294262306a36Sopenharmony_ci
294362306a36Sopenharmony_ci	/* set up the buffer descriptor */
294462306a36Sopenharmony_ci	out_be32(&((struct qe_bd __iomem *)bd)->buf,
294562306a36Sopenharmony_ci		      dma_map_single(ugeth->dev, skb->data,
294662306a36Sopenharmony_ci			      skb->len, DMA_TO_DEVICE));
294762306a36Sopenharmony_ci
294862306a36Sopenharmony_ci	/* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */
294962306a36Sopenharmony_ci
295062306a36Sopenharmony_ci	bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len;
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	/* set bd status and length */
295362306a36Sopenharmony_ci	out_be32((u32 __iomem *)bd, bd_status);
295462306a36Sopenharmony_ci
295562306a36Sopenharmony_ci	/* Move to next BD in the ring */
295662306a36Sopenharmony_ci	if (!(bd_status & T_W))
295762306a36Sopenharmony_ci		bd += sizeof(struct qe_bd);
295862306a36Sopenharmony_ci	else
295962306a36Sopenharmony_ci		bd = ugeth->p_tx_bd_ring[txQ];
296062306a36Sopenharmony_ci
296162306a36Sopenharmony_ci	/* If the next BD still needs to be cleaned up, then the bds
296262306a36Sopenharmony_ci	   are full.  We need to tell the kernel to stop sending us stuff. */
296362306a36Sopenharmony_ci	if (bd == ugeth->confBd[txQ]) {
296462306a36Sopenharmony_ci		if (!netif_queue_stopped(dev))
296562306a36Sopenharmony_ci			netif_stop_queue(dev);
296662306a36Sopenharmony_ci	}
296762306a36Sopenharmony_ci
296862306a36Sopenharmony_ci	ugeth->txBd[txQ] = bd;
296962306a36Sopenharmony_ci
297062306a36Sopenharmony_ci	skb_tx_timestamp(skb);
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_ci	if (ugeth->p_scheduler) {
297362306a36Sopenharmony_ci		ugeth->cpucount[txQ]++;
297462306a36Sopenharmony_ci		/* Indicate to QE that there are more Tx bds ready for
297562306a36Sopenharmony_ci		transmission */
297662306a36Sopenharmony_ci		/* This is done by writing a running counter of the bd
297762306a36Sopenharmony_ci		count to the scheduler PRAM. */
297862306a36Sopenharmony_ci		out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]);
297962306a36Sopenharmony_ci	}
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_ci#ifdef CONFIG_UGETH_TX_ON_DEMAND
298262306a36Sopenharmony_ci	uccf = ugeth->uccf;
298362306a36Sopenharmony_ci	out_be16(uccf->p_utodr, UCC_FAST_TOD);
298462306a36Sopenharmony_ci#endif
298562306a36Sopenharmony_ci	spin_unlock_irqrestore(&ugeth->lock, flags);
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci	return NETDEV_TX_OK;
298862306a36Sopenharmony_ci}
298962306a36Sopenharmony_ci
299062306a36Sopenharmony_cistatic int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit)
299162306a36Sopenharmony_ci{
299262306a36Sopenharmony_ci	struct sk_buff *skb;
299362306a36Sopenharmony_ci	u8 __iomem *bd;
299462306a36Sopenharmony_ci	u16 length, howmany = 0;
299562306a36Sopenharmony_ci	u32 bd_status;
299662306a36Sopenharmony_ci	u8 *bdBuffer;
299762306a36Sopenharmony_ci	struct net_device *dev;
299862306a36Sopenharmony_ci
299962306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
300062306a36Sopenharmony_ci
300162306a36Sopenharmony_ci	dev = ugeth->ndev;
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_ci	/* collect received buffers */
300462306a36Sopenharmony_ci	bd = ugeth->rxBd[rxQ];
300562306a36Sopenharmony_ci
300662306a36Sopenharmony_ci	bd_status = in_be32((u32 __iomem *)bd);
300762306a36Sopenharmony_ci
300862306a36Sopenharmony_ci	/* while there are received buffers and BD is full (~R_E) */
300962306a36Sopenharmony_ci	while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) {
301062306a36Sopenharmony_ci		bdBuffer = (u8 *) in_be32(&((struct qe_bd __iomem *)bd)->buf);
301162306a36Sopenharmony_ci		length = (u16) ((bd_status & BD_LENGTH_MASK) - 4);
301262306a36Sopenharmony_ci		skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]];
301362306a36Sopenharmony_ci
301462306a36Sopenharmony_ci		/* determine whether buffer is first, last, first and last
301562306a36Sopenharmony_ci		(single buffer frame) or middle (not first and not last) */
301662306a36Sopenharmony_ci		if (!skb ||
301762306a36Sopenharmony_ci		    (!(bd_status & (R_F | R_L))) ||
301862306a36Sopenharmony_ci		    (bd_status & R_ERRORS_FATAL)) {
301962306a36Sopenharmony_ci			if (netif_msg_rx_err(ugeth))
302062306a36Sopenharmony_ci				pr_err("%d: ERROR!!! skb - 0x%08x\n",
302162306a36Sopenharmony_ci				       __LINE__, (u32)skb);
302262306a36Sopenharmony_ci			dev_kfree_skb(skb);
302362306a36Sopenharmony_ci
302462306a36Sopenharmony_ci			ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL;
302562306a36Sopenharmony_ci			dev->stats.rx_dropped++;
302662306a36Sopenharmony_ci		} else {
302762306a36Sopenharmony_ci			dev->stats.rx_packets++;
302862306a36Sopenharmony_ci			howmany++;
302962306a36Sopenharmony_ci
303062306a36Sopenharmony_ci			/* Prep the skb for the packet */
303162306a36Sopenharmony_ci			skb_put(skb, length);
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_ci			/* Tell the skb what kind of packet this is */
303462306a36Sopenharmony_ci			skb->protocol = eth_type_trans(skb, ugeth->ndev);
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_ci			dev->stats.rx_bytes += length;
303762306a36Sopenharmony_ci			/* Send the packet up the stack */
303862306a36Sopenharmony_ci			netif_receive_skb(skb);
303962306a36Sopenharmony_ci		}
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_ci		skb = get_new_skb(ugeth, bd);
304262306a36Sopenharmony_ci		if (!skb) {
304362306a36Sopenharmony_ci			if (netif_msg_rx_err(ugeth))
304462306a36Sopenharmony_ci				pr_warn("No Rx Data Buffer\n");
304562306a36Sopenharmony_ci			dev->stats.rx_dropped++;
304662306a36Sopenharmony_ci			break;
304762306a36Sopenharmony_ci		}
304862306a36Sopenharmony_ci
304962306a36Sopenharmony_ci		ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = skb;
305062306a36Sopenharmony_ci
305162306a36Sopenharmony_ci		/* update to point at the next skb */
305262306a36Sopenharmony_ci		ugeth->skb_currx[rxQ] =
305362306a36Sopenharmony_ci		    (ugeth->skb_currx[rxQ] +
305462306a36Sopenharmony_ci		     1) & RX_RING_MOD_MASK(ugeth->ug_info->bdRingLenRx[rxQ]);
305562306a36Sopenharmony_ci
305662306a36Sopenharmony_ci		if (bd_status & R_W)
305762306a36Sopenharmony_ci			bd = ugeth->p_rx_bd_ring[rxQ];
305862306a36Sopenharmony_ci		else
305962306a36Sopenharmony_ci			bd += sizeof(struct qe_bd);
306062306a36Sopenharmony_ci
306162306a36Sopenharmony_ci		bd_status = in_be32((u32 __iomem *)bd);
306262306a36Sopenharmony_ci	}
306362306a36Sopenharmony_ci
306462306a36Sopenharmony_ci	ugeth->rxBd[rxQ] = bd;
306562306a36Sopenharmony_ci	return howmany;
306662306a36Sopenharmony_ci}
306762306a36Sopenharmony_ci
306862306a36Sopenharmony_cistatic int ucc_geth_tx(struct net_device *dev, u8 txQ)
306962306a36Sopenharmony_ci{
307062306a36Sopenharmony_ci	/* Start from the next BD that should be filled */
307162306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
307262306a36Sopenharmony_ci	unsigned int bytes_sent = 0;
307362306a36Sopenharmony_ci	int howmany = 0;
307462306a36Sopenharmony_ci	u8 __iomem *bd;		/* BD pointer */
307562306a36Sopenharmony_ci	u32 bd_status;
307662306a36Sopenharmony_ci
307762306a36Sopenharmony_ci	bd = ugeth->confBd[txQ];
307862306a36Sopenharmony_ci	bd_status = in_be32((u32 __iomem *)bd);
307962306a36Sopenharmony_ci
308062306a36Sopenharmony_ci	/* Normal processing. */
308162306a36Sopenharmony_ci	while ((bd_status & T_R) == 0) {
308262306a36Sopenharmony_ci		struct sk_buff *skb;
308362306a36Sopenharmony_ci
308462306a36Sopenharmony_ci		/* BD contains already transmitted buffer.   */
308562306a36Sopenharmony_ci		/* Handle the transmitted buffer and release */
308662306a36Sopenharmony_ci		/* the BD to be used with the current frame  */
308762306a36Sopenharmony_ci
308862306a36Sopenharmony_ci		skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]];
308962306a36Sopenharmony_ci		if (!skb)
309062306a36Sopenharmony_ci			break;
309162306a36Sopenharmony_ci		howmany++;
309262306a36Sopenharmony_ci		bytes_sent += skb->len;
309362306a36Sopenharmony_ci		dev->stats.tx_packets++;
309462306a36Sopenharmony_ci
309562306a36Sopenharmony_ci		dev_consume_skb_any(skb);
309662306a36Sopenharmony_ci
309762306a36Sopenharmony_ci		ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL;
309862306a36Sopenharmony_ci		ugeth->skb_dirtytx[txQ] =
309962306a36Sopenharmony_ci		    (ugeth->skb_dirtytx[txQ] +
310062306a36Sopenharmony_ci		     1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]);
310162306a36Sopenharmony_ci
310262306a36Sopenharmony_ci		/* We freed a buffer, so now we can restart transmission */
310362306a36Sopenharmony_ci		if (netif_queue_stopped(dev))
310462306a36Sopenharmony_ci			netif_wake_queue(dev);
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci		/* Advance the confirmation BD pointer */
310762306a36Sopenharmony_ci		if (!(bd_status & T_W))
310862306a36Sopenharmony_ci			bd += sizeof(struct qe_bd);
310962306a36Sopenharmony_ci		else
311062306a36Sopenharmony_ci			bd = ugeth->p_tx_bd_ring[txQ];
311162306a36Sopenharmony_ci		bd_status = in_be32((u32 __iomem *)bd);
311262306a36Sopenharmony_ci	}
311362306a36Sopenharmony_ci	ugeth->confBd[txQ] = bd;
311462306a36Sopenharmony_ci	netdev_completed_queue(dev, howmany, bytes_sent);
311562306a36Sopenharmony_ci	return 0;
311662306a36Sopenharmony_ci}
311762306a36Sopenharmony_ci
311862306a36Sopenharmony_cistatic int ucc_geth_poll(struct napi_struct *napi, int budget)
311962306a36Sopenharmony_ci{
312062306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = container_of(napi, struct ucc_geth_private, napi);
312162306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
312262306a36Sopenharmony_ci	int howmany, i;
312362306a36Sopenharmony_ci
312462306a36Sopenharmony_ci	ug_info = ugeth->ug_info;
312562306a36Sopenharmony_ci
312662306a36Sopenharmony_ci	/* Tx event processing */
312762306a36Sopenharmony_ci	spin_lock(&ugeth->lock);
312862306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_tx_queues(ug_info); i++)
312962306a36Sopenharmony_ci		ucc_geth_tx(ugeth->ndev, i);
313062306a36Sopenharmony_ci	spin_unlock(&ugeth->lock);
313162306a36Sopenharmony_ci
313262306a36Sopenharmony_ci	howmany = 0;
313362306a36Sopenharmony_ci	for (i = 0; i < ucc_geth_rx_queues(ug_info); i++)
313462306a36Sopenharmony_ci		howmany += ucc_geth_rx(ugeth, i, budget - howmany);
313562306a36Sopenharmony_ci
313662306a36Sopenharmony_ci	if (howmany < budget) {
313762306a36Sopenharmony_ci		napi_complete_done(napi, howmany);
313862306a36Sopenharmony_ci		setbits32(ugeth->uccf->p_uccm, UCCE_RX_EVENTS | UCCE_TX_EVENTS);
313962306a36Sopenharmony_ci	}
314062306a36Sopenharmony_ci
314162306a36Sopenharmony_ci	return howmany;
314262306a36Sopenharmony_ci}
314362306a36Sopenharmony_ci
314462306a36Sopenharmony_cistatic irqreturn_t ucc_geth_irq_handler(int irq, void *info)
314562306a36Sopenharmony_ci{
314662306a36Sopenharmony_ci	struct net_device *dev = info;
314762306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
314862306a36Sopenharmony_ci	struct ucc_fast_private *uccf;
314962306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
315062306a36Sopenharmony_ci	register u32 ucce;
315162306a36Sopenharmony_ci	register u32 uccm;
315262306a36Sopenharmony_ci
315362306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
315462306a36Sopenharmony_ci
315562306a36Sopenharmony_ci	uccf = ugeth->uccf;
315662306a36Sopenharmony_ci	ug_info = ugeth->ug_info;
315762306a36Sopenharmony_ci
315862306a36Sopenharmony_ci	/* read and clear events */
315962306a36Sopenharmony_ci	ucce = (u32) in_be32(uccf->p_ucce);
316062306a36Sopenharmony_ci	uccm = (u32) in_be32(uccf->p_uccm);
316162306a36Sopenharmony_ci	ucce &= uccm;
316262306a36Sopenharmony_ci	out_be32(uccf->p_ucce, ucce);
316362306a36Sopenharmony_ci
316462306a36Sopenharmony_ci	/* check for receive events that require processing */
316562306a36Sopenharmony_ci	if (ucce & (UCCE_RX_EVENTS | UCCE_TX_EVENTS)) {
316662306a36Sopenharmony_ci		if (napi_schedule_prep(&ugeth->napi)) {
316762306a36Sopenharmony_ci			uccm &= ~(UCCE_RX_EVENTS | UCCE_TX_EVENTS);
316862306a36Sopenharmony_ci			out_be32(uccf->p_uccm, uccm);
316962306a36Sopenharmony_ci			__napi_schedule(&ugeth->napi);
317062306a36Sopenharmony_ci		}
317162306a36Sopenharmony_ci	}
317262306a36Sopenharmony_ci
317362306a36Sopenharmony_ci	/* Errors and other events */
317462306a36Sopenharmony_ci	if (ucce & UCCE_OTHER) {
317562306a36Sopenharmony_ci		if (ucce & UCC_GETH_UCCE_BSY)
317662306a36Sopenharmony_ci			dev->stats.rx_errors++;
317762306a36Sopenharmony_ci		if (ucce & UCC_GETH_UCCE_TXE)
317862306a36Sopenharmony_ci			dev->stats.tx_errors++;
317962306a36Sopenharmony_ci	}
318062306a36Sopenharmony_ci
318162306a36Sopenharmony_ci	return IRQ_HANDLED;
318262306a36Sopenharmony_ci}
318362306a36Sopenharmony_ci
318462306a36Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
318562306a36Sopenharmony_ci/*
318662306a36Sopenharmony_ci * Polling 'interrupt' - used by things like netconsole to send skbs
318762306a36Sopenharmony_ci * without having to re-enable interrupts. It's not called while
318862306a36Sopenharmony_ci * the interrupt routine is executing.
318962306a36Sopenharmony_ci */
319062306a36Sopenharmony_cistatic void ucc_netpoll(struct net_device *dev)
319162306a36Sopenharmony_ci{
319262306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
319362306a36Sopenharmony_ci	int irq = ugeth->ug_info->uf_info.irq;
319462306a36Sopenharmony_ci
319562306a36Sopenharmony_ci	disable_irq(irq);
319662306a36Sopenharmony_ci	ucc_geth_irq_handler(irq, dev);
319762306a36Sopenharmony_ci	enable_irq(irq);
319862306a36Sopenharmony_ci}
319962306a36Sopenharmony_ci#endif /* CONFIG_NET_POLL_CONTROLLER */
320062306a36Sopenharmony_ci
320162306a36Sopenharmony_cistatic int ucc_geth_set_mac_addr(struct net_device *dev, void *p)
320262306a36Sopenharmony_ci{
320362306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
320462306a36Sopenharmony_ci	struct sockaddr *addr = p;
320562306a36Sopenharmony_ci
320662306a36Sopenharmony_ci	if (!is_valid_ether_addr(addr->sa_data))
320762306a36Sopenharmony_ci		return -EADDRNOTAVAIL;
320862306a36Sopenharmony_ci
320962306a36Sopenharmony_ci	eth_hw_addr_set(dev, addr->sa_data);
321062306a36Sopenharmony_ci
321162306a36Sopenharmony_ci	/*
321262306a36Sopenharmony_ci	 * If device is not running, we will set mac addr register
321362306a36Sopenharmony_ci	 * when opening the device.
321462306a36Sopenharmony_ci	 */
321562306a36Sopenharmony_ci	if (!netif_running(dev))
321662306a36Sopenharmony_ci		return 0;
321762306a36Sopenharmony_ci
321862306a36Sopenharmony_ci	spin_lock_irq(&ugeth->lock);
321962306a36Sopenharmony_ci	init_mac_station_addr_regs(dev->dev_addr[0],
322062306a36Sopenharmony_ci				   dev->dev_addr[1],
322162306a36Sopenharmony_ci				   dev->dev_addr[2],
322262306a36Sopenharmony_ci				   dev->dev_addr[3],
322362306a36Sopenharmony_ci				   dev->dev_addr[4],
322462306a36Sopenharmony_ci				   dev->dev_addr[5],
322562306a36Sopenharmony_ci				   &ugeth->ug_regs->macstnaddr1,
322662306a36Sopenharmony_ci				   &ugeth->ug_regs->macstnaddr2);
322762306a36Sopenharmony_ci	spin_unlock_irq(&ugeth->lock);
322862306a36Sopenharmony_ci
322962306a36Sopenharmony_ci	return 0;
323062306a36Sopenharmony_ci}
323162306a36Sopenharmony_ci
323262306a36Sopenharmony_cistatic int ucc_geth_init_mac(struct ucc_geth_private *ugeth)
323362306a36Sopenharmony_ci{
323462306a36Sopenharmony_ci	struct net_device *dev = ugeth->ndev;
323562306a36Sopenharmony_ci	int err;
323662306a36Sopenharmony_ci
323762306a36Sopenharmony_ci	err = ucc_struct_init(ugeth);
323862306a36Sopenharmony_ci	if (err) {
323962306a36Sopenharmony_ci		netif_err(ugeth, ifup, dev, "Cannot configure internal struct, aborting\n");
324062306a36Sopenharmony_ci		goto err;
324162306a36Sopenharmony_ci	}
324262306a36Sopenharmony_ci
324362306a36Sopenharmony_ci	err = ucc_geth_startup(ugeth);
324462306a36Sopenharmony_ci	if (err) {
324562306a36Sopenharmony_ci		netif_err(ugeth, ifup, dev, "Cannot configure net device, aborting\n");
324662306a36Sopenharmony_ci		goto err;
324762306a36Sopenharmony_ci	}
324862306a36Sopenharmony_ci
324962306a36Sopenharmony_ci	err = adjust_enet_interface(ugeth);
325062306a36Sopenharmony_ci	if (err) {
325162306a36Sopenharmony_ci		netif_err(ugeth, ifup, dev, "Cannot configure net device, aborting\n");
325262306a36Sopenharmony_ci		goto err;
325362306a36Sopenharmony_ci	}
325462306a36Sopenharmony_ci
325562306a36Sopenharmony_ci	/*       Set MACSTNADDR1, MACSTNADDR2                */
325662306a36Sopenharmony_ci	/* For more details see the hardware spec.           */
325762306a36Sopenharmony_ci	init_mac_station_addr_regs(dev->dev_addr[0],
325862306a36Sopenharmony_ci				   dev->dev_addr[1],
325962306a36Sopenharmony_ci				   dev->dev_addr[2],
326062306a36Sopenharmony_ci				   dev->dev_addr[3],
326162306a36Sopenharmony_ci				   dev->dev_addr[4],
326262306a36Sopenharmony_ci				   dev->dev_addr[5],
326362306a36Sopenharmony_ci				   &ugeth->ug_regs->macstnaddr1,
326462306a36Sopenharmony_ci				   &ugeth->ug_regs->macstnaddr2);
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci	err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
326762306a36Sopenharmony_ci	if (err) {
326862306a36Sopenharmony_ci		netif_err(ugeth, ifup, dev, "Cannot enable net device, aborting\n");
326962306a36Sopenharmony_ci		goto err;
327062306a36Sopenharmony_ci	}
327162306a36Sopenharmony_ci
327262306a36Sopenharmony_ci	return 0;
327362306a36Sopenharmony_cierr:
327462306a36Sopenharmony_ci	ucc_geth_stop(ugeth);
327562306a36Sopenharmony_ci	return err;
327662306a36Sopenharmony_ci}
327762306a36Sopenharmony_ci
327862306a36Sopenharmony_ci/* Called when something needs to use the ethernet device */
327962306a36Sopenharmony_ci/* Returns 0 for success. */
328062306a36Sopenharmony_cistatic int ucc_geth_open(struct net_device *dev)
328162306a36Sopenharmony_ci{
328262306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
328362306a36Sopenharmony_ci	int err;
328462306a36Sopenharmony_ci
328562306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
328662306a36Sopenharmony_ci
328762306a36Sopenharmony_ci	/* Test station address */
328862306a36Sopenharmony_ci	if (dev->dev_addr[0] & ENET_GROUP_ADDR) {
328962306a36Sopenharmony_ci		netif_err(ugeth, ifup, dev,
329062306a36Sopenharmony_ci			  "Multicast address used for station address - is this what you wanted?\n");
329162306a36Sopenharmony_ci		return -EINVAL;
329262306a36Sopenharmony_ci	}
329362306a36Sopenharmony_ci
329462306a36Sopenharmony_ci	err = init_phy(dev);
329562306a36Sopenharmony_ci	if (err) {
329662306a36Sopenharmony_ci		netif_err(ugeth, ifup, dev, "Cannot initialize PHY, aborting\n");
329762306a36Sopenharmony_ci		return err;
329862306a36Sopenharmony_ci	}
329962306a36Sopenharmony_ci
330062306a36Sopenharmony_ci	err = ucc_geth_init_mac(ugeth);
330162306a36Sopenharmony_ci	if (err) {
330262306a36Sopenharmony_ci		netif_err(ugeth, ifup, dev, "Cannot initialize MAC, aborting\n");
330362306a36Sopenharmony_ci		goto err;
330462306a36Sopenharmony_ci	}
330562306a36Sopenharmony_ci
330662306a36Sopenharmony_ci	err = request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler,
330762306a36Sopenharmony_ci			  0, "UCC Geth", dev);
330862306a36Sopenharmony_ci	if (err) {
330962306a36Sopenharmony_ci		netif_err(ugeth, ifup, dev, "Cannot get IRQ for net device, aborting\n");
331062306a36Sopenharmony_ci		goto err;
331162306a36Sopenharmony_ci	}
331262306a36Sopenharmony_ci
331362306a36Sopenharmony_ci	phy_start(ugeth->phydev);
331462306a36Sopenharmony_ci	napi_enable(&ugeth->napi);
331562306a36Sopenharmony_ci	netdev_reset_queue(dev);
331662306a36Sopenharmony_ci	netif_start_queue(dev);
331762306a36Sopenharmony_ci
331862306a36Sopenharmony_ci	device_set_wakeup_capable(&dev->dev,
331962306a36Sopenharmony_ci			qe_alive_during_sleep() || ugeth->phydev->irq);
332062306a36Sopenharmony_ci	device_set_wakeup_enable(&dev->dev, ugeth->wol_en);
332162306a36Sopenharmony_ci
332262306a36Sopenharmony_ci	return err;
332362306a36Sopenharmony_ci
332462306a36Sopenharmony_cierr:
332562306a36Sopenharmony_ci	ucc_geth_stop(ugeth);
332662306a36Sopenharmony_ci	return err;
332762306a36Sopenharmony_ci}
332862306a36Sopenharmony_ci
332962306a36Sopenharmony_ci/* Stops the kernel queue, and halts the controller */
333062306a36Sopenharmony_cistatic int ucc_geth_close(struct net_device *dev)
333162306a36Sopenharmony_ci{
333262306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
333362306a36Sopenharmony_ci
333462306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
333562306a36Sopenharmony_ci
333662306a36Sopenharmony_ci	napi_disable(&ugeth->napi);
333762306a36Sopenharmony_ci
333862306a36Sopenharmony_ci	cancel_work_sync(&ugeth->timeout_work);
333962306a36Sopenharmony_ci	ucc_geth_stop(ugeth);
334062306a36Sopenharmony_ci	phy_disconnect(ugeth->phydev);
334162306a36Sopenharmony_ci	ugeth->phydev = NULL;
334262306a36Sopenharmony_ci
334362306a36Sopenharmony_ci	free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev);
334462306a36Sopenharmony_ci
334562306a36Sopenharmony_ci	netif_stop_queue(dev);
334662306a36Sopenharmony_ci	netdev_reset_queue(dev);
334762306a36Sopenharmony_ci
334862306a36Sopenharmony_ci	return 0;
334962306a36Sopenharmony_ci}
335062306a36Sopenharmony_ci
335162306a36Sopenharmony_ci/* Reopen device. This will reset the MAC and PHY. */
335262306a36Sopenharmony_cistatic void ucc_geth_timeout_work(struct work_struct *work)
335362306a36Sopenharmony_ci{
335462306a36Sopenharmony_ci	struct ucc_geth_private *ugeth;
335562306a36Sopenharmony_ci	struct net_device *dev;
335662306a36Sopenharmony_ci
335762306a36Sopenharmony_ci	ugeth = container_of(work, struct ucc_geth_private, timeout_work);
335862306a36Sopenharmony_ci	dev = ugeth->ndev;
335962306a36Sopenharmony_ci
336062306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
336162306a36Sopenharmony_ci
336262306a36Sopenharmony_ci	dev->stats.tx_errors++;
336362306a36Sopenharmony_ci
336462306a36Sopenharmony_ci	ugeth_dump_regs(ugeth);
336562306a36Sopenharmony_ci
336662306a36Sopenharmony_ci	if (dev->flags & IFF_UP) {
336762306a36Sopenharmony_ci		/*
336862306a36Sopenharmony_ci		 * Must reset MAC *and* PHY. This is done by reopening
336962306a36Sopenharmony_ci		 * the device.
337062306a36Sopenharmony_ci		 */
337162306a36Sopenharmony_ci		netif_tx_stop_all_queues(dev);
337262306a36Sopenharmony_ci		ucc_geth_stop(ugeth);
337362306a36Sopenharmony_ci		ucc_geth_init_mac(ugeth);
337462306a36Sopenharmony_ci		/* Must start PHY here */
337562306a36Sopenharmony_ci		phy_start(ugeth->phydev);
337662306a36Sopenharmony_ci		netif_tx_start_all_queues(dev);
337762306a36Sopenharmony_ci	}
337862306a36Sopenharmony_ci
337962306a36Sopenharmony_ci	netif_tx_schedule_all(dev);
338062306a36Sopenharmony_ci}
338162306a36Sopenharmony_ci
338262306a36Sopenharmony_ci/*
338362306a36Sopenharmony_ci * ucc_geth_timeout gets called when a packet has not been
338462306a36Sopenharmony_ci * transmitted after a set amount of time.
338562306a36Sopenharmony_ci */
338662306a36Sopenharmony_cistatic void ucc_geth_timeout(struct net_device *dev, unsigned int txqueue)
338762306a36Sopenharmony_ci{
338862306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
338962306a36Sopenharmony_ci
339062306a36Sopenharmony_ci	schedule_work(&ugeth->timeout_work);
339162306a36Sopenharmony_ci}
339262306a36Sopenharmony_ci
339362306a36Sopenharmony_ci
339462306a36Sopenharmony_ci#ifdef CONFIG_PM
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_cistatic int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state)
339762306a36Sopenharmony_ci{
339862306a36Sopenharmony_ci	struct net_device *ndev = platform_get_drvdata(ofdev);
339962306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(ndev);
340062306a36Sopenharmony_ci
340162306a36Sopenharmony_ci	if (!netif_running(ndev))
340262306a36Sopenharmony_ci		return 0;
340362306a36Sopenharmony_ci
340462306a36Sopenharmony_ci	netif_device_detach(ndev);
340562306a36Sopenharmony_ci	napi_disable(&ugeth->napi);
340662306a36Sopenharmony_ci
340762306a36Sopenharmony_ci	/*
340862306a36Sopenharmony_ci	 * Disable the controller, otherwise we'll wakeup on any network
340962306a36Sopenharmony_ci	 * activity.
341062306a36Sopenharmony_ci	 */
341162306a36Sopenharmony_ci	ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
341262306a36Sopenharmony_ci
341362306a36Sopenharmony_ci	if (ugeth->wol_en & WAKE_MAGIC) {
341462306a36Sopenharmony_ci		setbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
341562306a36Sopenharmony_ci		setbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
341662306a36Sopenharmony_ci		ucc_fast_enable(ugeth->uccf, COMM_DIR_RX_AND_TX);
341762306a36Sopenharmony_ci	} else if (!(ugeth->wol_en & WAKE_PHY)) {
341862306a36Sopenharmony_ci		phy_stop(ugeth->phydev);
341962306a36Sopenharmony_ci	}
342062306a36Sopenharmony_ci
342162306a36Sopenharmony_ci	return 0;
342262306a36Sopenharmony_ci}
342362306a36Sopenharmony_ci
342462306a36Sopenharmony_cistatic int ucc_geth_resume(struct platform_device *ofdev)
342562306a36Sopenharmony_ci{
342662306a36Sopenharmony_ci	struct net_device *ndev = platform_get_drvdata(ofdev);
342762306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(ndev);
342862306a36Sopenharmony_ci	int err;
342962306a36Sopenharmony_ci
343062306a36Sopenharmony_ci	if (!netif_running(ndev))
343162306a36Sopenharmony_ci		return 0;
343262306a36Sopenharmony_ci
343362306a36Sopenharmony_ci	if (qe_alive_during_sleep()) {
343462306a36Sopenharmony_ci		if (ugeth->wol_en & WAKE_MAGIC) {
343562306a36Sopenharmony_ci			ucc_fast_disable(ugeth->uccf, COMM_DIR_RX_AND_TX);
343662306a36Sopenharmony_ci			clrbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
343762306a36Sopenharmony_ci			clrbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
343862306a36Sopenharmony_ci		}
343962306a36Sopenharmony_ci		ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
344062306a36Sopenharmony_ci	} else {
344162306a36Sopenharmony_ci		/*
344262306a36Sopenharmony_ci		 * Full reinitialization is required if QE shuts down
344362306a36Sopenharmony_ci		 * during sleep.
344462306a36Sopenharmony_ci		 */
344562306a36Sopenharmony_ci		ucc_geth_memclean(ugeth);
344662306a36Sopenharmony_ci
344762306a36Sopenharmony_ci		err = ucc_geth_init_mac(ugeth);
344862306a36Sopenharmony_ci		if (err) {
344962306a36Sopenharmony_ci			netdev_err(ndev, "Cannot initialize MAC, aborting\n");
345062306a36Sopenharmony_ci			return err;
345162306a36Sopenharmony_ci		}
345262306a36Sopenharmony_ci	}
345362306a36Sopenharmony_ci
345462306a36Sopenharmony_ci	ugeth->oldlink = 0;
345562306a36Sopenharmony_ci	ugeth->oldspeed = 0;
345662306a36Sopenharmony_ci	ugeth->oldduplex = -1;
345762306a36Sopenharmony_ci
345862306a36Sopenharmony_ci	phy_stop(ugeth->phydev);
345962306a36Sopenharmony_ci	phy_start(ugeth->phydev);
346062306a36Sopenharmony_ci
346162306a36Sopenharmony_ci	napi_enable(&ugeth->napi);
346262306a36Sopenharmony_ci	netif_device_attach(ndev);
346362306a36Sopenharmony_ci
346462306a36Sopenharmony_ci	return 0;
346562306a36Sopenharmony_ci}
346662306a36Sopenharmony_ci
346762306a36Sopenharmony_ci#else
346862306a36Sopenharmony_ci#define ucc_geth_suspend NULL
346962306a36Sopenharmony_ci#define ucc_geth_resume NULL
347062306a36Sopenharmony_ci#endif
347162306a36Sopenharmony_ci
347262306a36Sopenharmony_cistatic phy_interface_t to_phy_interface(const char *phy_connection_type)
347362306a36Sopenharmony_ci{
347462306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "mii") == 0)
347562306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_MII;
347662306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "gmii") == 0)
347762306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_GMII;
347862306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "tbi") == 0)
347962306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_TBI;
348062306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "rmii") == 0)
348162306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_RMII;
348262306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "rgmii") == 0)
348362306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_RGMII;
348462306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "rgmii-id") == 0)
348562306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_RGMII_ID;
348662306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "rgmii-txid") == 0)
348762306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_RGMII_TXID;
348862306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "rgmii-rxid") == 0)
348962306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_RGMII_RXID;
349062306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "rtbi") == 0)
349162306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_RTBI;
349262306a36Sopenharmony_ci	if (strcasecmp(phy_connection_type, "sgmii") == 0)
349362306a36Sopenharmony_ci		return PHY_INTERFACE_MODE_SGMII;
349462306a36Sopenharmony_ci
349562306a36Sopenharmony_ci	return PHY_INTERFACE_MODE_MII;
349662306a36Sopenharmony_ci}
349762306a36Sopenharmony_ci
349862306a36Sopenharmony_cistatic int ucc_geth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
349962306a36Sopenharmony_ci{
350062306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
350162306a36Sopenharmony_ci
350262306a36Sopenharmony_ci	if (!netif_running(dev))
350362306a36Sopenharmony_ci		return -EINVAL;
350462306a36Sopenharmony_ci
350562306a36Sopenharmony_ci	if (!ugeth->phydev)
350662306a36Sopenharmony_ci		return -ENODEV;
350762306a36Sopenharmony_ci
350862306a36Sopenharmony_ci	return phy_mii_ioctl(ugeth->phydev, rq, cmd);
350962306a36Sopenharmony_ci}
351062306a36Sopenharmony_ci
351162306a36Sopenharmony_cistatic const struct net_device_ops ucc_geth_netdev_ops = {
351262306a36Sopenharmony_ci	.ndo_open		= ucc_geth_open,
351362306a36Sopenharmony_ci	.ndo_stop		= ucc_geth_close,
351462306a36Sopenharmony_ci	.ndo_start_xmit		= ucc_geth_start_xmit,
351562306a36Sopenharmony_ci	.ndo_validate_addr	= eth_validate_addr,
351662306a36Sopenharmony_ci	.ndo_change_carrier     = fixed_phy_change_carrier,
351762306a36Sopenharmony_ci	.ndo_set_mac_address	= ucc_geth_set_mac_addr,
351862306a36Sopenharmony_ci	.ndo_set_rx_mode	= ucc_geth_set_multi,
351962306a36Sopenharmony_ci	.ndo_tx_timeout		= ucc_geth_timeout,
352062306a36Sopenharmony_ci	.ndo_eth_ioctl		= ucc_geth_ioctl,
352162306a36Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
352262306a36Sopenharmony_ci	.ndo_poll_controller	= ucc_netpoll,
352362306a36Sopenharmony_ci#endif
352462306a36Sopenharmony_ci};
352562306a36Sopenharmony_ci
352662306a36Sopenharmony_cistatic int ucc_geth_parse_clock(struct device_node *np, const char *which,
352762306a36Sopenharmony_ci				enum qe_clock *out)
352862306a36Sopenharmony_ci{
352962306a36Sopenharmony_ci	const char *sprop;
353062306a36Sopenharmony_ci	char buf[24];
353162306a36Sopenharmony_ci
353262306a36Sopenharmony_ci	snprintf(buf, sizeof(buf), "%s-clock-name", which);
353362306a36Sopenharmony_ci	sprop = of_get_property(np, buf, NULL);
353462306a36Sopenharmony_ci	if (sprop) {
353562306a36Sopenharmony_ci		*out = qe_clock_source(sprop);
353662306a36Sopenharmony_ci	} else {
353762306a36Sopenharmony_ci		u32 val;
353862306a36Sopenharmony_ci
353962306a36Sopenharmony_ci		snprintf(buf, sizeof(buf), "%s-clock", which);
354062306a36Sopenharmony_ci		if (of_property_read_u32(np, buf, &val)) {
354162306a36Sopenharmony_ci			/* If both *-clock-name and *-clock are missing,
354262306a36Sopenharmony_ci			 * we want to tell people to use *-clock-name.
354362306a36Sopenharmony_ci			 */
354462306a36Sopenharmony_ci			pr_err("missing %s-clock-name property\n", buf);
354562306a36Sopenharmony_ci			return -EINVAL;
354662306a36Sopenharmony_ci		}
354762306a36Sopenharmony_ci		*out = val;
354862306a36Sopenharmony_ci	}
354962306a36Sopenharmony_ci	if (*out < QE_CLK_NONE || *out > QE_CLK24) {
355062306a36Sopenharmony_ci		pr_err("invalid %s property\n", buf);
355162306a36Sopenharmony_ci		return -EINVAL;
355262306a36Sopenharmony_ci	}
355362306a36Sopenharmony_ci	return 0;
355462306a36Sopenharmony_ci}
355562306a36Sopenharmony_ci
355662306a36Sopenharmony_cistatic int ucc_geth_probe(struct platform_device* ofdev)
355762306a36Sopenharmony_ci{
355862306a36Sopenharmony_ci	struct device *device = &ofdev->dev;
355962306a36Sopenharmony_ci	struct device_node *np = ofdev->dev.of_node;
356062306a36Sopenharmony_ci	struct net_device *dev = NULL;
356162306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = NULL;
356262306a36Sopenharmony_ci	struct ucc_geth_info *ug_info;
356362306a36Sopenharmony_ci	struct resource res;
356462306a36Sopenharmony_ci	int err, ucc_num, max_speed = 0;
356562306a36Sopenharmony_ci	const unsigned int *prop;
356662306a36Sopenharmony_ci	phy_interface_t phy_interface;
356762306a36Sopenharmony_ci	static const int enet_to_speed[] = {
356862306a36Sopenharmony_ci		SPEED_10, SPEED_10, SPEED_10,
356962306a36Sopenharmony_ci		SPEED_100, SPEED_100, SPEED_100,
357062306a36Sopenharmony_ci		SPEED_1000, SPEED_1000, SPEED_1000, SPEED_1000,
357162306a36Sopenharmony_ci	};
357262306a36Sopenharmony_ci	static const phy_interface_t enet_to_phy_interface[] = {
357362306a36Sopenharmony_ci		PHY_INTERFACE_MODE_MII, PHY_INTERFACE_MODE_RMII,
357462306a36Sopenharmony_ci		PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_MII,
357562306a36Sopenharmony_ci		PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII,
357662306a36Sopenharmony_ci		PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII,
357762306a36Sopenharmony_ci		PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
357862306a36Sopenharmony_ci		PHY_INTERFACE_MODE_SGMII,
357962306a36Sopenharmony_ci	};
358062306a36Sopenharmony_ci
358162306a36Sopenharmony_ci	ugeth_vdbg("%s: IN", __func__);
358262306a36Sopenharmony_ci
358362306a36Sopenharmony_ci	prop = of_get_property(np, "cell-index", NULL);
358462306a36Sopenharmony_ci	if (!prop) {
358562306a36Sopenharmony_ci		prop = of_get_property(np, "device-id", NULL);
358662306a36Sopenharmony_ci		if (!prop)
358762306a36Sopenharmony_ci			return -ENODEV;
358862306a36Sopenharmony_ci	}
358962306a36Sopenharmony_ci
359062306a36Sopenharmony_ci	ucc_num = *prop - 1;
359162306a36Sopenharmony_ci	if ((ucc_num < 0) || (ucc_num > 7))
359262306a36Sopenharmony_ci		return -ENODEV;
359362306a36Sopenharmony_ci
359462306a36Sopenharmony_ci	ug_info = kmemdup(&ugeth_primary_info, sizeof(*ug_info), GFP_KERNEL);
359562306a36Sopenharmony_ci	if (ug_info == NULL)
359662306a36Sopenharmony_ci		return -ENOMEM;
359762306a36Sopenharmony_ci
359862306a36Sopenharmony_ci	ug_info->uf_info.ucc_num = ucc_num;
359962306a36Sopenharmony_ci
360062306a36Sopenharmony_ci	err = ucc_geth_parse_clock(np, "rx", &ug_info->uf_info.rx_clock);
360162306a36Sopenharmony_ci	if (err)
360262306a36Sopenharmony_ci		goto err_free_info;
360362306a36Sopenharmony_ci	err = ucc_geth_parse_clock(np, "tx", &ug_info->uf_info.tx_clock);
360462306a36Sopenharmony_ci	if (err)
360562306a36Sopenharmony_ci		goto err_free_info;
360662306a36Sopenharmony_ci
360762306a36Sopenharmony_ci	err = of_address_to_resource(np, 0, &res);
360862306a36Sopenharmony_ci	if (err)
360962306a36Sopenharmony_ci		goto err_free_info;
361062306a36Sopenharmony_ci
361162306a36Sopenharmony_ci	ug_info->uf_info.regs = res.start;
361262306a36Sopenharmony_ci	ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
361362306a36Sopenharmony_ci
361462306a36Sopenharmony_ci	ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0);
361562306a36Sopenharmony_ci	if (!ug_info->phy_node && of_phy_is_fixed_link(np)) {
361662306a36Sopenharmony_ci		/*
361762306a36Sopenharmony_ci		 * In the case of a fixed PHY, the DT node associated
361862306a36Sopenharmony_ci		 * to the PHY is the Ethernet MAC DT node.
361962306a36Sopenharmony_ci		 */
362062306a36Sopenharmony_ci		err = of_phy_register_fixed_link(np);
362162306a36Sopenharmony_ci		if (err)
362262306a36Sopenharmony_ci			goto err_free_info;
362362306a36Sopenharmony_ci		ug_info->phy_node = of_node_get(np);
362462306a36Sopenharmony_ci	}
362562306a36Sopenharmony_ci
362662306a36Sopenharmony_ci	/* Find the TBI PHY node.  If it's not there, we don't support SGMII */
362762306a36Sopenharmony_ci	ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
362862306a36Sopenharmony_ci
362962306a36Sopenharmony_ci	/* get the phy interface type, or default to MII */
363062306a36Sopenharmony_ci	prop = of_get_property(np, "phy-connection-type", NULL);
363162306a36Sopenharmony_ci	if (!prop) {
363262306a36Sopenharmony_ci		/* handle interface property present in old trees */
363362306a36Sopenharmony_ci		prop = of_get_property(ug_info->phy_node, "interface", NULL);
363462306a36Sopenharmony_ci		if (prop != NULL) {
363562306a36Sopenharmony_ci			phy_interface = enet_to_phy_interface[*prop];
363662306a36Sopenharmony_ci			max_speed = enet_to_speed[*prop];
363762306a36Sopenharmony_ci		} else
363862306a36Sopenharmony_ci			phy_interface = PHY_INTERFACE_MODE_MII;
363962306a36Sopenharmony_ci	} else {
364062306a36Sopenharmony_ci		phy_interface = to_phy_interface((const char *)prop);
364162306a36Sopenharmony_ci	}
364262306a36Sopenharmony_ci
364362306a36Sopenharmony_ci	/* get speed, or derive from PHY interface */
364462306a36Sopenharmony_ci	if (max_speed == 0)
364562306a36Sopenharmony_ci		switch (phy_interface) {
364662306a36Sopenharmony_ci		case PHY_INTERFACE_MODE_GMII:
364762306a36Sopenharmony_ci		case PHY_INTERFACE_MODE_RGMII:
364862306a36Sopenharmony_ci		case PHY_INTERFACE_MODE_RGMII_ID:
364962306a36Sopenharmony_ci		case PHY_INTERFACE_MODE_RGMII_RXID:
365062306a36Sopenharmony_ci		case PHY_INTERFACE_MODE_RGMII_TXID:
365162306a36Sopenharmony_ci		case PHY_INTERFACE_MODE_TBI:
365262306a36Sopenharmony_ci		case PHY_INTERFACE_MODE_RTBI:
365362306a36Sopenharmony_ci		case PHY_INTERFACE_MODE_SGMII:
365462306a36Sopenharmony_ci			max_speed = SPEED_1000;
365562306a36Sopenharmony_ci			break;
365662306a36Sopenharmony_ci		default:
365762306a36Sopenharmony_ci			max_speed = SPEED_100;
365862306a36Sopenharmony_ci			break;
365962306a36Sopenharmony_ci		}
366062306a36Sopenharmony_ci
366162306a36Sopenharmony_ci	if (max_speed == SPEED_1000) {
366262306a36Sopenharmony_ci		unsigned int snums = qe_get_num_of_snums();
366362306a36Sopenharmony_ci
366462306a36Sopenharmony_ci		/* configure muram FIFOs for gigabit operation */
366562306a36Sopenharmony_ci		ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT;
366662306a36Sopenharmony_ci		ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT;
366762306a36Sopenharmony_ci		ug_info->uf_info.urfset = UCC_GETH_URFSET_GIGA_INIT;
366862306a36Sopenharmony_ci		ug_info->uf_info.utfs = UCC_GETH_UTFS_GIGA_INIT;
366962306a36Sopenharmony_ci		ug_info->uf_info.utfet = UCC_GETH_UTFET_GIGA_INIT;
367062306a36Sopenharmony_ci		ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT;
367162306a36Sopenharmony_ci		ug_info->numThreadsTx = UCC_GETH_NUM_OF_THREADS_4;
367262306a36Sopenharmony_ci
367362306a36Sopenharmony_ci		/* If QE's snum number is 46/76 which means we need to support
367462306a36Sopenharmony_ci		 * 4 UECs at 1000Base-T simultaneously, we need to allocate
367562306a36Sopenharmony_ci		 * more Threads to Rx.
367662306a36Sopenharmony_ci		 */
367762306a36Sopenharmony_ci		if ((snums == 76) || (snums == 46))
367862306a36Sopenharmony_ci			ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_6;
367962306a36Sopenharmony_ci		else
368062306a36Sopenharmony_ci			ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4;
368162306a36Sopenharmony_ci	}
368262306a36Sopenharmony_ci
368362306a36Sopenharmony_ci	if (netif_msg_probe(&debug))
368462306a36Sopenharmony_ci		pr_info("UCC%1d at 0x%8llx (irq = %d)\n",
368562306a36Sopenharmony_ci			ug_info->uf_info.ucc_num + 1,
368662306a36Sopenharmony_ci			(u64)ug_info->uf_info.regs,
368762306a36Sopenharmony_ci			ug_info->uf_info.irq);
368862306a36Sopenharmony_ci
368962306a36Sopenharmony_ci	/* Create an ethernet device instance */
369062306a36Sopenharmony_ci	dev = alloc_etherdev(sizeof(*ugeth));
369162306a36Sopenharmony_ci
369262306a36Sopenharmony_ci	if (dev == NULL) {
369362306a36Sopenharmony_ci		err = -ENOMEM;
369462306a36Sopenharmony_ci		goto err_deregister_fixed_link;
369562306a36Sopenharmony_ci	}
369662306a36Sopenharmony_ci
369762306a36Sopenharmony_ci	ugeth = netdev_priv(dev);
369862306a36Sopenharmony_ci	spin_lock_init(&ugeth->lock);
369962306a36Sopenharmony_ci
370062306a36Sopenharmony_ci	/* Create CQs for hash tables */
370162306a36Sopenharmony_ci	INIT_LIST_HEAD(&ugeth->group_hash_q);
370262306a36Sopenharmony_ci	INIT_LIST_HEAD(&ugeth->ind_hash_q);
370362306a36Sopenharmony_ci
370462306a36Sopenharmony_ci	dev_set_drvdata(device, dev);
370562306a36Sopenharmony_ci
370662306a36Sopenharmony_ci	/* Set the dev->base_addr to the gfar reg region */
370762306a36Sopenharmony_ci	dev->base_addr = (unsigned long)(ug_info->uf_info.regs);
370862306a36Sopenharmony_ci
370962306a36Sopenharmony_ci	SET_NETDEV_DEV(dev, device);
371062306a36Sopenharmony_ci
371162306a36Sopenharmony_ci	/* Fill in the dev structure */
371262306a36Sopenharmony_ci	uec_set_ethtool_ops(dev);
371362306a36Sopenharmony_ci	dev->netdev_ops = &ucc_geth_netdev_ops;
371462306a36Sopenharmony_ci	dev->watchdog_timeo = TX_TIMEOUT;
371562306a36Sopenharmony_ci	INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work);
371662306a36Sopenharmony_ci	netif_napi_add(dev, &ugeth->napi, ucc_geth_poll);
371762306a36Sopenharmony_ci	dev->mtu = 1500;
371862306a36Sopenharmony_ci	dev->max_mtu = 1518;
371962306a36Sopenharmony_ci
372062306a36Sopenharmony_ci	ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT);
372162306a36Sopenharmony_ci	ugeth->phy_interface = phy_interface;
372262306a36Sopenharmony_ci	ugeth->max_speed = max_speed;
372362306a36Sopenharmony_ci
372462306a36Sopenharmony_ci	/* Carrier starts down, phylib will bring it up */
372562306a36Sopenharmony_ci	netif_carrier_off(dev);
372662306a36Sopenharmony_ci
372762306a36Sopenharmony_ci	err = register_netdev(dev);
372862306a36Sopenharmony_ci	if (err) {
372962306a36Sopenharmony_ci		if (netif_msg_probe(ugeth))
373062306a36Sopenharmony_ci			pr_err("%s: Cannot register net device, aborting\n",
373162306a36Sopenharmony_ci			       dev->name);
373262306a36Sopenharmony_ci		goto err_free_netdev;
373362306a36Sopenharmony_ci	}
373462306a36Sopenharmony_ci
373562306a36Sopenharmony_ci	of_get_ethdev_address(np, dev);
373662306a36Sopenharmony_ci
373762306a36Sopenharmony_ci	ugeth->ug_info = ug_info;
373862306a36Sopenharmony_ci	ugeth->dev = device;
373962306a36Sopenharmony_ci	ugeth->ndev = dev;
374062306a36Sopenharmony_ci	ugeth->node = np;
374162306a36Sopenharmony_ci
374262306a36Sopenharmony_ci	return 0;
374362306a36Sopenharmony_ci
374462306a36Sopenharmony_cierr_free_netdev:
374562306a36Sopenharmony_ci	free_netdev(dev);
374662306a36Sopenharmony_cierr_deregister_fixed_link:
374762306a36Sopenharmony_ci	if (of_phy_is_fixed_link(np))
374862306a36Sopenharmony_ci		of_phy_deregister_fixed_link(np);
374962306a36Sopenharmony_ci	of_node_put(ug_info->tbi_node);
375062306a36Sopenharmony_ci	of_node_put(ug_info->phy_node);
375162306a36Sopenharmony_cierr_free_info:
375262306a36Sopenharmony_ci	kfree(ug_info);
375362306a36Sopenharmony_ci
375462306a36Sopenharmony_ci	return err;
375562306a36Sopenharmony_ci}
375662306a36Sopenharmony_ci
375762306a36Sopenharmony_cistatic void ucc_geth_remove(struct platform_device* ofdev)
375862306a36Sopenharmony_ci{
375962306a36Sopenharmony_ci	struct net_device *dev = platform_get_drvdata(ofdev);
376062306a36Sopenharmony_ci	struct ucc_geth_private *ugeth = netdev_priv(dev);
376162306a36Sopenharmony_ci	struct device_node *np = ofdev->dev.of_node;
376262306a36Sopenharmony_ci
376362306a36Sopenharmony_ci	unregister_netdev(dev);
376462306a36Sopenharmony_ci	ucc_geth_memclean(ugeth);
376562306a36Sopenharmony_ci	if (of_phy_is_fixed_link(np))
376662306a36Sopenharmony_ci		of_phy_deregister_fixed_link(np);
376762306a36Sopenharmony_ci	of_node_put(ugeth->ug_info->tbi_node);
376862306a36Sopenharmony_ci	of_node_put(ugeth->ug_info->phy_node);
376962306a36Sopenharmony_ci	kfree(ugeth->ug_info);
377062306a36Sopenharmony_ci	free_netdev(dev);
377162306a36Sopenharmony_ci}
377262306a36Sopenharmony_ci
377362306a36Sopenharmony_cistatic const struct of_device_id ucc_geth_match[] = {
377462306a36Sopenharmony_ci	{
377562306a36Sopenharmony_ci		.type = "network",
377662306a36Sopenharmony_ci		.compatible = "ucc_geth",
377762306a36Sopenharmony_ci	},
377862306a36Sopenharmony_ci	{},
377962306a36Sopenharmony_ci};
378062306a36Sopenharmony_ci
378162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ucc_geth_match);
378262306a36Sopenharmony_ci
378362306a36Sopenharmony_cistatic struct platform_driver ucc_geth_driver = {
378462306a36Sopenharmony_ci	.driver = {
378562306a36Sopenharmony_ci		.name = DRV_NAME,
378662306a36Sopenharmony_ci		.of_match_table = ucc_geth_match,
378762306a36Sopenharmony_ci	},
378862306a36Sopenharmony_ci	.probe		= ucc_geth_probe,
378962306a36Sopenharmony_ci	.remove_new	= ucc_geth_remove,
379062306a36Sopenharmony_ci	.suspend	= ucc_geth_suspend,
379162306a36Sopenharmony_ci	.resume		= ucc_geth_resume,
379262306a36Sopenharmony_ci};
379362306a36Sopenharmony_ci
379462306a36Sopenharmony_cistatic int __init ucc_geth_init(void)
379562306a36Sopenharmony_ci{
379662306a36Sopenharmony_ci	if (netif_msg_drv(&debug))
379762306a36Sopenharmony_ci		pr_info(DRV_DESC "\n");
379862306a36Sopenharmony_ci
379962306a36Sopenharmony_ci	return platform_driver_register(&ucc_geth_driver);
380062306a36Sopenharmony_ci}
380162306a36Sopenharmony_ci
380262306a36Sopenharmony_cistatic void __exit ucc_geth_exit(void)
380362306a36Sopenharmony_ci{
380462306a36Sopenharmony_ci	platform_driver_unregister(&ucc_geth_driver);
380562306a36Sopenharmony_ci}
380662306a36Sopenharmony_ci
380762306a36Sopenharmony_cimodule_init(ucc_geth_init);
380862306a36Sopenharmony_cimodule_exit(ucc_geth_exit);
380962306a36Sopenharmony_ci
381062306a36Sopenharmony_ciMODULE_AUTHOR("Freescale Semiconductor, Inc");
381162306a36Sopenharmony_ciMODULE_DESCRIPTION(DRV_DESC);
381262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
3813