18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2008-2015 Freescale Semiconductor Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
58c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions are met:
68c2ecf20Sopenharmony_ci *     * Redistributions of source code must retain the above copyright
78c2ecf20Sopenharmony_ci *       notice, this list of conditions and the following disclaimer.
88c2ecf20Sopenharmony_ci *     * Redistributions in binary form must reproduce the above copyright
98c2ecf20Sopenharmony_ci *       notice, this list of conditions and the following disclaimer in the
108c2ecf20Sopenharmony_ci *       documentation and/or other materials provided with the distribution.
118c2ecf20Sopenharmony_ci *     * Neither the name of Freescale Semiconductor nor the
128c2ecf20Sopenharmony_ci *       names of its contributors may be used to endorse or promote products
138c2ecf20Sopenharmony_ci *       derived from this software without specific prior written permission.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * ALTERNATIVELY, this software may be distributed under the terms of the
178c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") as published by the Free Software
188c2ecf20Sopenharmony_ci * Foundation, either version 2 of that License or (at your option) any
198c2ecf20Sopenharmony_ci * later version.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
228c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
238c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
248c2ecf20Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
258c2ecf20Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
268c2ecf20Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
278c2ecf20Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
288c2ecf20Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
298c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
308c2ecf20Sopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* FM MAC ... */
348c2ecf20Sopenharmony_ci#ifndef __FM_MAC_H
358c2ecf20Sopenharmony_ci#define __FM_MAC_H
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include "fman.h"
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#include <linux/slab.h>
408c2ecf20Sopenharmony_ci#include <linux/phy.h>
418c2ecf20Sopenharmony_ci#include <linux/if_ether.h>
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistruct fman_mac;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/* Ethernet Address */
468c2ecf20Sopenharmony_citypedef u8 enet_addr_t[ETH_ALEN];
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#define ENET_ADDR_TO_UINT64(_enet_addr)		\
498c2ecf20Sopenharmony_ci	(u64)(((u64)(_enet_addr)[0] << 40) |		\
508c2ecf20Sopenharmony_ci	      ((u64)(_enet_addr)[1] << 32) |		\
518c2ecf20Sopenharmony_ci	      ((u64)(_enet_addr)[2] << 24) |		\
528c2ecf20Sopenharmony_ci	      ((u64)(_enet_addr)[3] << 16) |		\
538c2ecf20Sopenharmony_ci	      ((u64)(_enet_addr)[4] << 8) |		\
548c2ecf20Sopenharmony_ci	      ((u64)(_enet_addr)[5]))
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \
578c2ecf20Sopenharmony_ci	do { \
588c2ecf20Sopenharmony_ci		int i; \
598c2ecf20Sopenharmony_ci		for (i = 0; i < ETH_ALEN; i++) \
608c2ecf20Sopenharmony_ci			(_enet_addr)[i] = \
618c2ecf20Sopenharmony_ci			(u8)((_addr64) >> ((5 - i) * 8)); \
628c2ecf20Sopenharmony_ci	} while (0)
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/* defaults */
658c2ecf20Sopenharmony_ci#define DEFAULT_RESET_ON_INIT                 false
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/* PFC defines */
688c2ecf20Sopenharmony_ci#define FSL_FM_PAUSE_TIME_ENABLE	0xf000
698c2ecf20Sopenharmony_ci#define FSL_FM_PAUSE_TIME_DISABLE	0
708c2ecf20Sopenharmony_ci#define FSL_FM_PAUSE_THRESH_DEFAULT	0
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#define FM_MAC_NO_PFC   0xff
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/* HASH defines */
758c2ecf20Sopenharmony_ci#define ETH_HASH_ENTRY_OBJ(ptr)	\
768c2ecf20Sopenharmony_ci	hlist_entry_safe(ptr, struct eth_hash_entry, node)
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/* Enumeration (bit flags) of communication modes (Transmit,
798c2ecf20Sopenharmony_ci * receive or both).
808c2ecf20Sopenharmony_ci */
818c2ecf20Sopenharmony_cienum comm_mode {
828c2ecf20Sopenharmony_ci	COMM_MODE_NONE = 0,	/* No transmit/receive communication */
838c2ecf20Sopenharmony_ci	COMM_MODE_RX = 1,	/* Only receive communication */
848c2ecf20Sopenharmony_ci	COMM_MODE_TX = 2,	/* Only transmit communication */
858c2ecf20Sopenharmony_ci	COMM_MODE_RX_AND_TX = 3	/* Both transmit and receive communication */
868c2ecf20Sopenharmony_ci};
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/* FM MAC Exceptions */
898c2ecf20Sopenharmony_cienum fman_mac_exceptions {
908c2ecf20Sopenharmony_ci	FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0
918c2ecf20Sopenharmony_ci	/* 10GEC MDIO scan event interrupt */
928c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_MDIO_CMD_CMPL
938c2ecf20Sopenharmony_ci	/* 10GEC MDIO command completion interrupt */
948c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_REM_FAULT
958c2ecf20Sopenharmony_ci	/* 10GEC, mEMAC Remote fault interrupt */
968c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_LOC_FAULT
978c2ecf20Sopenharmony_ci	/* 10GEC, mEMAC Local fault interrupt */
988c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_TX_ECC_ER
998c2ecf20Sopenharmony_ci	/* 10GEC, mEMAC Transmit frame ECC error interrupt */
1008c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_TX_FIFO_UNFL
1018c2ecf20Sopenharmony_ci	/* 10GEC, mEMAC Transmit FIFO underflow interrupt */
1028c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_TX_FIFO_OVFL
1038c2ecf20Sopenharmony_ci	/* 10GEC, mEMAC Transmit FIFO overflow interrupt */
1048c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_TX_ER
1058c2ecf20Sopenharmony_ci	/* 10GEC Transmit frame error interrupt */
1068c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_RX_FIFO_OVFL
1078c2ecf20Sopenharmony_ci	/* 10GEC, mEMAC Receive FIFO overflow interrupt */
1088c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_RX_ECC_ER
1098c2ecf20Sopenharmony_ci	/* 10GEC, mEMAC Receive frame ECC error interrupt */
1108c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_RX_JAB_FRM
1118c2ecf20Sopenharmony_ci	/* 10GEC Receive jabber frame interrupt */
1128c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_RX_OVRSZ_FRM
1138c2ecf20Sopenharmony_ci	/* 10GEC Receive oversized frame interrupt */
1148c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_RX_RUNT_FRM
1158c2ecf20Sopenharmony_ci	/* 10GEC Receive runt frame interrupt */
1168c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_RX_FRAG_FRM
1178c2ecf20Sopenharmony_ci	/* 10GEC Receive fragment frame interrupt */
1188c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_RX_LEN_ER
1198c2ecf20Sopenharmony_ci	/* 10GEC Receive payload length error interrupt */
1208c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_RX_CRC_ER
1218c2ecf20Sopenharmony_ci	/* 10GEC Receive CRC error interrupt */
1228c2ecf20Sopenharmony_ci	, FM_MAC_EX_10G_RX_ALIGN_ER
1238c2ecf20Sopenharmony_ci	/* 10GEC Receive alignment error interrupt */
1248c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_BAB_RX
1258c2ecf20Sopenharmony_ci	/* dTSEC Babbling receive error */
1268c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_RX_CTL
1278c2ecf20Sopenharmony_ci	/* dTSEC Receive control (pause frame) interrupt */
1288c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET
1298c2ecf20Sopenharmony_ci	/* dTSEC Graceful transmit stop complete */
1308c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_BAB_TX
1318c2ecf20Sopenharmony_ci	/* dTSEC Babbling transmit error */
1328c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_TX_CTL
1338c2ecf20Sopenharmony_ci	/* dTSEC Transmit control (pause frame) interrupt */
1348c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_TX_ERR
1358c2ecf20Sopenharmony_ci	/* dTSEC Transmit error */
1368c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_LATE_COL
1378c2ecf20Sopenharmony_ci	/* dTSEC Late collision */
1388c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_COL_RET_LMT
1398c2ecf20Sopenharmony_ci	/* dTSEC Collision retry limit */
1408c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_TX_FIFO_UNDRN
1418c2ecf20Sopenharmony_ci	/* dTSEC Transmit FIFO underrun */
1428c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_MAG_PCKT
1438c2ecf20Sopenharmony_ci	/* dTSEC Magic Packet detection */
1448c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_MII_MNG_RD_COMPLET
1458c2ecf20Sopenharmony_ci	/* dTSEC MII management read completion */
1468c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_MII_MNG_WR_COMPLET
1478c2ecf20Sopenharmony_ci	/* dTSEC MII management write completion */
1488c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET
1498c2ecf20Sopenharmony_ci	/* dTSEC Graceful receive stop complete */
1508c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_DATA_ERR
1518c2ecf20Sopenharmony_ci	/* dTSEC Internal data error on transmit */
1528c2ecf20Sopenharmony_ci	, FM_MAC_1G_RX_DATA_ERR
1538c2ecf20Sopenharmony_ci	/* dTSEC Internal data error on receive */
1548c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_1588_TS_RX_ERR
1558c2ecf20Sopenharmony_ci	/* dTSEC Time-Stamp Receive Error */
1568c2ecf20Sopenharmony_ci	, FM_MAC_EX_1G_RX_MIB_CNT_OVFL
1578c2ecf20Sopenharmony_ci	/* dTSEC MIB counter overflow */
1588c2ecf20Sopenharmony_ci	, FM_MAC_EX_TS_FIFO_ECC_ERR
1598c2ecf20Sopenharmony_ci	/* mEMAC Time-stamp FIFO ECC error interrupt;
1608c2ecf20Sopenharmony_ci	 * not supported on T4240/B4860 rev1 chips
1618c2ecf20Sopenharmony_ci	 */
1628c2ecf20Sopenharmony_ci	, FM_MAC_EX_MAGIC_PACKET_INDICATION = FM_MAC_EX_1G_MAG_PCKT
1638c2ecf20Sopenharmony_ci	/* mEMAC Magic Packet Indication Interrupt */
1648c2ecf20Sopenharmony_ci};
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistruct eth_hash_entry {
1678c2ecf20Sopenharmony_ci	u64 addr;		/* Ethernet Address  */
1688c2ecf20Sopenharmony_ci	struct list_head node;
1698c2ecf20Sopenharmony_ci};
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_citypedef void (fman_mac_exception_cb)(void *dev_id,
1728c2ecf20Sopenharmony_ci				    enum fman_mac_exceptions exceptions);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci/* FMan MAC config input */
1758c2ecf20Sopenharmony_cistruct fman_mac_params {
1768c2ecf20Sopenharmony_ci	/* Base of memory mapped FM MAC registers */
1778c2ecf20Sopenharmony_ci	void __iomem *base_addr;
1788c2ecf20Sopenharmony_ci	/* MAC address of device; First octet is sent first */
1798c2ecf20Sopenharmony_ci	enet_addr_t addr;
1808c2ecf20Sopenharmony_ci	/* MAC ID; numbering of dTSEC and 1G-mEMAC:
1818c2ecf20Sopenharmony_ci	 * 0 - FM_MAX_NUM_OF_1G_MACS;
1828c2ecf20Sopenharmony_ci	 * numbering of 10G-MAC (TGEC) and 10G-mEMAC:
1838c2ecf20Sopenharmony_ci	 * 0 - FM_MAX_NUM_OF_10G_MACS
1848c2ecf20Sopenharmony_ci	 */
1858c2ecf20Sopenharmony_ci	u8 mac_id;
1868c2ecf20Sopenharmony_ci	/* PHY interface */
1878c2ecf20Sopenharmony_ci	phy_interface_t	 phy_if;
1888c2ecf20Sopenharmony_ci	/* Note that the speed should indicate the maximum rate that
1898c2ecf20Sopenharmony_ci	 * this MAC should support rather than the actual speed;
1908c2ecf20Sopenharmony_ci	 */
1918c2ecf20Sopenharmony_ci	u16 max_speed;
1928c2ecf20Sopenharmony_ci	/* A handle to the FM object this port related to */
1938c2ecf20Sopenharmony_ci	void *fm;
1948c2ecf20Sopenharmony_ci	void *dev_id; /* device cookie used by the exception cbs */
1958c2ecf20Sopenharmony_ci	fman_mac_exception_cb *event_cb;    /* MDIO Events Callback Routine */
1968c2ecf20Sopenharmony_ci	fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */
1978c2ecf20Sopenharmony_ci	/* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC
1988c2ecf20Sopenharmony_ci	 * and phy or backplane; Note: 1000BaseX auto-negotiation relates only
1998c2ecf20Sopenharmony_ci	 * to interface between MAC and phy/backplane, SGMII phy can still
2008c2ecf20Sopenharmony_ci	 * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps
2018c2ecf20Sopenharmony_ci	*/
2028c2ecf20Sopenharmony_ci	bool basex_if;
2038c2ecf20Sopenharmony_ci	/* Pointer to TBI/PCS PHY node, used for TBI/PCS PHY access */
2048c2ecf20Sopenharmony_ci	struct device_node *internal_phy_node;
2058c2ecf20Sopenharmony_ci};
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cistruct eth_hash_t {
2088c2ecf20Sopenharmony_ci	u16 size;
2098c2ecf20Sopenharmony_ci	struct list_head *lsts;
2108c2ecf20Sopenharmony_ci};
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic inline struct eth_hash_entry
2138c2ecf20Sopenharmony_ci*dequeue_addr_from_hash_entry(struct list_head *addr_lst)
2148c2ecf20Sopenharmony_ci{
2158c2ecf20Sopenharmony_ci	struct eth_hash_entry *hash_entry = NULL;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	if (!list_empty(addr_lst)) {
2188c2ecf20Sopenharmony_ci		hash_entry = ETH_HASH_ENTRY_OBJ(addr_lst->next);
2198c2ecf20Sopenharmony_ci		list_del_init(&hash_entry->node);
2208c2ecf20Sopenharmony_ci	}
2218c2ecf20Sopenharmony_ci	return hash_entry;
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic inline void free_hash_table(struct eth_hash_t *hash)
2258c2ecf20Sopenharmony_ci{
2268c2ecf20Sopenharmony_ci	struct eth_hash_entry *hash_entry;
2278c2ecf20Sopenharmony_ci	int i = 0;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	if (hash) {
2308c2ecf20Sopenharmony_ci		if (hash->lsts) {
2318c2ecf20Sopenharmony_ci			for (i = 0; i < hash->size; i++) {
2328c2ecf20Sopenharmony_ci				hash_entry =
2338c2ecf20Sopenharmony_ci				dequeue_addr_from_hash_entry(&hash->lsts[i]);
2348c2ecf20Sopenharmony_ci				while (hash_entry) {
2358c2ecf20Sopenharmony_ci					kfree(hash_entry);
2368c2ecf20Sopenharmony_ci					hash_entry =
2378c2ecf20Sopenharmony_ci					dequeue_addr_from_hash_entry(&hash->
2388c2ecf20Sopenharmony_ci								     lsts[i]);
2398c2ecf20Sopenharmony_ci				}
2408c2ecf20Sopenharmony_ci			}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci			kfree(hash->lsts);
2438c2ecf20Sopenharmony_ci		}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci		kfree(hash);
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic inline struct eth_hash_t *alloc_hash_table(u16 size)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	u32 i;
2528c2ecf20Sopenharmony_ci	struct eth_hash_t *hash;
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	/* Allocate address hash table */
2558c2ecf20Sopenharmony_ci	hash = kmalloc(sizeof(*hash), GFP_KERNEL);
2568c2ecf20Sopenharmony_ci	if (!hash)
2578c2ecf20Sopenharmony_ci		return NULL;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	hash->size = size;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	hash->lsts = kmalloc_array(hash->size, sizeof(struct list_head),
2628c2ecf20Sopenharmony_ci				   GFP_KERNEL);
2638c2ecf20Sopenharmony_ci	if (!hash->lsts) {
2648c2ecf20Sopenharmony_ci		kfree(hash);
2658c2ecf20Sopenharmony_ci		return NULL;
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	for (i = 0; i < hash->size; i++)
2698c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&hash->lsts[i]);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	return hash;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci#endif /* __FM_MAC_H */
275