1/*
2 * Copyright 2008-2015 Freescale Semiconductor Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above copyright
9 *       notice, this list of conditions and the following disclaimer in the
10 *       documentation and/or other materials provided with the distribution.
11 *     * Neither the name of Freescale Semiconductor nor the
12 *       names of its contributors may be used to endorse or promote products
13 *       derived from this software without specific prior written permission.
14 *
15 *
16 * ALTERNATIVELY, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") as published by the Free Software
18 * Foundation, either version 2 of that License or (at your option) any
19 * later version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/* FM MAC ... */
34#ifndef __FM_MAC_H
35#define __FM_MAC_H
36
37#include "fman.h"
38
39#include <linux/slab.h>
40#include <linux/phy.h>
41#include <linux/if_ether.h>
42
43struct fman_mac;
44
45/* Ethernet Address */
46typedef u8 enet_addr_t[ETH_ALEN];
47
48#define ENET_ADDR_TO_UINT64(_enet_addr)		\
49	(u64)(((u64)(_enet_addr)[0] << 40) |		\
50	      ((u64)(_enet_addr)[1] << 32) |		\
51	      ((u64)(_enet_addr)[2] << 24) |		\
52	      ((u64)(_enet_addr)[3] << 16) |		\
53	      ((u64)(_enet_addr)[4] << 8) |		\
54	      ((u64)(_enet_addr)[5]))
55
56#define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \
57	do { \
58		int i; \
59		for (i = 0; i < ETH_ALEN; i++) \
60			(_enet_addr)[i] = \
61			(u8)((_addr64) >> ((5 - i) * 8)); \
62	} while (0)
63
64/* defaults */
65#define DEFAULT_RESET_ON_INIT                 false
66
67/* PFC defines */
68#define FSL_FM_PAUSE_TIME_ENABLE	0xf000
69#define FSL_FM_PAUSE_TIME_DISABLE	0
70#define FSL_FM_PAUSE_THRESH_DEFAULT	0
71
72#define FM_MAC_NO_PFC   0xff
73
74/* HASH defines */
75#define ETH_HASH_ENTRY_OBJ(ptr)	\
76	hlist_entry_safe(ptr, struct eth_hash_entry, node)
77
78/* Enumeration (bit flags) of communication modes (Transmit,
79 * receive or both).
80 */
81enum comm_mode {
82	COMM_MODE_NONE = 0,	/* No transmit/receive communication */
83	COMM_MODE_RX = 1,	/* Only receive communication */
84	COMM_MODE_TX = 2,	/* Only transmit communication */
85	COMM_MODE_RX_AND_TX = 3	/* Both transmit and receive communication */
86};
87
88/* FM MAC Exceptions */
89enum fman_mac_exceptions {
90	FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0
91	/* 10GEC MDIO scan event interrupt */
92	, FM_MAC_EX_10G_MDIO_CMD_CMPL
93	/* 10GEC MDIO command completion interrupt */
94	, FM_MAC_EX_10G_REM_FAULT
95	/* 10GEC, mEMAC Remote fault interrupt */
96	, FM_MAC_EX_10G_LOC_FAULT
97	/* 10GEC, mEMAC Local fault interrupt */
98	, FM_MAC_EX_10G_TX_ECC_ER
99	/* 10GEC, mEMAC Transmit frame ECC error interrupt */
100	, FM_MAC_EX_10G_TX_FIFO_UNFL
101	/* 10GEC, mEMAC Transmit FIFO underflow interrupt */
102	, FM_MAC_EX_10G_TX_FIFO_OVFL
103	/* 10GEC, mEMAC Transmit FIFO overflow interrupt */
104	, FM_MAC_EX_10G_TX_ER
105	/* 10GEC Transmit frame error interrupt */
106	, FM_MAC_EX_10G_RX_FIFO_OVFL
107	/* 10GEC, mEMAC Receive FIFO overflow interrupt */
108	, FM_MAC_EX_10G_RX_ECC_ER
109	/* 10GEC, mEMAC Receive frame ECC error interrupt */
110	, FM_MAC_EX_10G_RX_JAB_FRM
111	/* 10GEC Receive jabber frame interrupt */
112	, FM_MAC_EX_10G_RX_OVRSZ_FRM
113	/* 10GEC Receive oversized frame interrupt */
114	, FM_MAC_EX_10G_RX_RUNT_FRM
115	/* 10GEC Receive runt frame interrupt */
116	, FM_MAC_EX_10G_RX_FRAG_FRM
117	/* 10GEC Receive fragment frame interrupt */
118	, FM_MAC_EX_10G_RX_LEN_ER
119	/* 10GEC Receive payload length error interrupt */
120	, FM_MAC_EX_10G_RX_CRC_ER
121	/* 10GEC Receive CRC error interrupt */
122	, FM_MAC_EX_10G_RX_ALIGN_ER
123	/* 10GEC Receive alignment error interrupt */
124	, FM_MAC_EX_1G_BAB_RX
125	/* dTSEC Babbling receive error */
126	, FM_MAC_EX_1G_RX_CTL
127	/* dTSEC Receive control (pause frame) interrupt */
128	, FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET
129	/* dTSEC Graceful transmit stop complete */
130	, FM_MAC_EX_1G_BAB_TX
131	/* dTSEC Babbling transmit error */
132	, FM_MAC_EX_1G_TX_CTL
133	/* dTSEC Transmit control (pause frame) interrupt */
134	, FM_MAC_EX_1G_TX_ERR
135	/* dTSEC Transmit error */
136	, FM_MAC_EX_1G_LATE_COL
137	/* dTSEC Late collision */
138	, FM_MAC_EX_1G_COL_RET_LMT
139	/* dTSEC Collision retry limit */
140	, FM_MAC_EX_1G_TX_FIFO_UNDRN
141	/* dTSEC Transmit FIFO underrun */
142	, FM_MAC_EX_1G_MAG_PCKT
143	/* dTSEC Magic Packet detection */
144	, FM_MAC_EX_1G_MII_MNG_RD_COMPLET
145	/* dTSEC MII management read completion */
146	, FM_MAC_EX_1G_MII_MNG_WR_COMPLET
147	/* dTSEC MII management write completion */
148	, FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET
149	/* dTSEC Graceful receive stop complete */
150	, FM_MAC_EX_1G_DATA_ERR
151	/* dTSEC Internal data error on transmit */
152	, FM_MAC_1G_RX_DATA_ERR
153	/* dTSEC Internal data error on receive */
154	, FM_MAC_EX_1G_1588_TS_RX_ERR
155	/* dTSEC Time-Stamp Receive Error */
156	, FM_MAC_EX_1G_RX_MIB_CNT_OVFL
157	/* dTSEC MIB counter overflow */
158	, FM_MAC_EX_TS_FIFO_ECC_ERR
159	/* mEMAC Time-stamp FIFO ECC error interrupt;
160	 * not supported on T4240/B4860 rev1 chips
161	 */
162	, FM_MAC_EX_MAGIC_PACKET_INDICATION = FM_MAC_EX_1G_MAG_PCKT
163	/* mEMAC Magic Packet Indication Interrupt */
164};
165
166struct eth_hash_entry {
167	u64 addr;		/* Ethernet Address  */
168	struct list_head node;
169};
170
171typedef void (fman_mac_exception_cb)(void *dev_id,
172				    enum fman_mac_exceptions exceptions);
173
174/* FMan MAC config input */
175struct fman_mac_params {
176	/* Base of memory mapped FM MAC registers */
177	void __iomem *base_addr;
178	/* MAC address of device; First octet is sent first */
179	enet_addr_t addr;
180	/* MAC ID; numbering of dTSEC and 1G-mEMAC:
181	 * 0 - FM_MAX_NUM_OF_1G_MACS;
182	 * numbering of 10G-MAC (TGEC) and 10G-mEMAC:
183	 * 0 - FM_MAX_NUM_OF_10G_MACS
184	 */
185	u8 mac_id;
186	/* PHY interface */
187	phy_interface_t	 phy_if;
188	/* Note that the speed should indicate the maximum rate that
189	 * this MAC should support rather than the actual speed;
190	 */
191	u16 max_speed;
192	/* A handle to the FM object this port related to */
193	void *fm;
194	void *dev_id; /* device cookie used by the exception cbs */
195	fman_mac_exception_cb *event_cb;    /* MDIO Events Callback Routine */
196	fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */
197	/* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC
198	 * and phy or backplane; Note: 1000BaseX auto-negotiation relates only
199	 * to interface between MAC and phy/backplane, SGMII phy can still
200	 * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps
201	*/
202	bool basex_if;
203	/* Pointer to TBI/PCS PHY node, used for TBI/PCS PHY access */
204	struct device_node *internal_phy_node;
205};
206
207struct eth_hash_t {
208	u16 size;
209	struct list_head *lsts;
210};
211
212static inline struct eth_hash_entry
213*dequeue_addr_from_hash_entry(struct list_head *addr_lst)
214{
215	struct eth_hash_entry *hash_entry = NULL;
216
217	if (!list_empty(addr_lst)) {
218		hash_entry = ETH_HASH_ENTRY_OBJ(addr_lst->next);
219		list_del_init(&hash_entry->node);
220	}
221	return hash_entry;
222}
223
224static inline void free_hash_table(struct eth_hash_t *hash)
225{
226	struct eth_hash_entry *hash_entry;
227	int i = 0;
228
229	if (hash) {
230		if (hash->lsts) {
231			for (i = 0; i < hash->size; i++) {
232				hash_entry =
233				dequeue_addr_from_hash_entry(&hash->lsts[i]);
234				while (hash_entry) {
235					kfree(hash_entry);
236					hash_entry =
237					dequeue_addr_from_hash_entry(&hash->
238								     lsts[i]);
239				}
240			}
241
242			kfree(hash->lsts);
243		}
244
245		kfree(hash);
246	}
247}
248
249static inline struct eth_hash_t *alloc_hash_table(u16 size)
250{
251	u32 i;
252	struct eth_hash_t *hash;
253
254	/* Allocate address hash table */
255	hash = kmalloc(sizeof(*hash), GFP_KERNEL);
256	if (!hash)
257		return NULL;
258
259	hash->size = size;
260
261	hash->lsts = kmalloc_array(hash->size, sizeof(struct list_head),
262				   GFP_KERNEL);
263	if (!hash->lsts) {
264		kfree(hash);
265		return NULL;
266	}
267
268	for (i = 0; i < hash->size; i++)
269		INIT_LIST_HEAD(&hash->lsts[i]);
270
271	return hash;
272}
273
274#endif /* __FM_MAC_H */
275