Commit | Line | Data |
---|---|---|
57ba4c9b IL |
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 | ||
43 | struct fman_mac; | |
44 | ||
45 | /* Ethernet Address */ | |
46 | typedef 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 | */ | |
81 | enum 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 */ | |
89 | enum 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 | ||
166 | struct eth_hash_entry { | |
167 | u64 addr; /* Ethernet Address */ | |
168 | struct list_head node; | |
169 | }; | |
170 | ||
171 | typedef void (fman_mac_exception_cb)(void *dev_id, | |
172 | enum fman_mac_exceptions exceptions); | |
173 | ||
174 | /* FMan MAC config input */ | |
175 | struct 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 | /* MDIO exceptions interrupt source - not valid for all | |
195 | * MACs; MUST be set to 'NO_IRQ' for MACs that don't have | |
196 | * mdio-irq, or for polling | |
197 | */ | |
198 | void *dev_id; /* device cookie used by the exception cbs */ | |
199 | fman_mac_exception_cb *event_cb; /* MDIO Events Callback Routine */ | |
200 | fman_mac_exception_cb *exception_cb;/* Exception Callback Routine */ | |
201 | /* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC | |
202 | * and phy or backplane; Note: 1000BaseX auto-negotiation relates only | |
203 | * to interface between MAC and phy/backplane, SGMII phy can still | |
204 | * synchronize with far-end phy at 10Mbps, 100Mbps or 1000Mbps | |
205 | */ | |
206 | bool basex_if; | |
207 | /* Pointer to TBI/PCS PHY node, used for TBI/PCS PHY access */ | |
208 | struct device_node *internal_phy_node; | |
209 | }; | |
210 | ||
211 | struct eth_hash_t { | |
212 | u16 size; | |
213 | struct list_head *lsts; | |
214 | }; | |
215 | ||
216 | static inline struct eth_hash_entry | |
217 | *dequeue_addr_from_hash_entry(struct list_head *addr_lst) | |
218 | { | |
219 | struct eth_hash_entry *hash_entry = NULL; | |
220 | ||
221 | if (!list_empty(addr_lst)) { | |
222 | hash_entry = ETH_HASH_ENTRY_OBJ(addr_lst->next); | |
223 | list_del_init(&hash_entry->node); | |
224 | } | |
225 | return hash_entry; | |
226 | } | |
227 | ||
228 | static inline void free_hash_table(struct eth_hash_t *hash) | |
229 | { | |
230 | struct eth_hash_entry *hash_entry; | |
231 | int i = 0; | |
232 | ||
233 | if (hash) { | |
234 | if (hash->lsts) { | |
235 | for (i = 0; i < hash->size; i++) { | |
236 | hash_entry = | |
237 | dequeue_addr_from_hash_entry(&hash->lsts[i]); | |
238 | while (hash_entry) { | |
239 | kfree(hash_entry); | |
240 | hash_entry = | |
241 | dequeue_addr_from_hash_entry(&hash-> | |
242 | lsts[i]); | |
243 | } | |
244 | } | |
245 | ||
246 | kfree(hash->lsts); | |
247 | } | |
248 | ||
249 | kfree(hash); | |
250 | } | |
251 | } | |
252 | ||
253 | static inline struct eth_hash_t *alloc_hash_table(u16 size) | |
254 | { | |
255 | u32 i; | |
256 | struct eth_hash_t *hash; | |
257 | ||
258 | /* Allocate address hash table */ | |
259 | hash = kmalloc_array(size, sizeof(struct eth_hash_t *), GFP_KERNEL); | |
260 | if (!hash) | |
261 | return NULL; | |
262 | ||
263 | hash->size = size; | |
264 | ||
265 | hash->lsts = kmalloc_array(hash->size, sizeof(struct list_head), | |
266 | GFP_KERNEL); | |
267 | if (!hash->lsts) { | |
268 | kfree(hash); | |
269 | return NULL; | |
270 | } | |
271 | ||
272 | for (i = 0; i < hash->size; i++) | |
273 | INIT_LIST_HEAD(&hash->lsts[i]); | |
274 | ||
275 | return hash; | |
276 | } | |
277 | ||
278 | #endif /* __FM_MAC_H */ |