1 /* ===================================================================================
2  * Copyright (c) <2009> Synopsys, Inc.
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software annotated with this license and associated documentation files
7  * (the "Software"), to deal in the Software without restriction, including without
8  * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
17  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
20  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * =================================================================================== */
23 
24 
25 /** \file
26  * This is the network dependent layer to handle network related functionality.
27  * This file is tightly coupled to neworking frame work of linux 2.6.xx kernel.
28  * The functionality carried out in this file should be treated as an example only
29  * if the underlying operating system is not Linux.
30  *
31  * \note Many of the functions other than the device specific functions
32  *  changes for operating system other than Linux 2.6.xx
33  * \internal
34  *-----------------------------REVISION HISTORY-----------------------------------
35  * Synopsys			01/Aug/2007				Created
36  */
37 
38 #include "string.h"
39 #include "synopGMAC_network_interface.h"
40 
41 
42 synopGMACdevice GMACdev[GMAC_CNT];
43 static DmaDesc tx_desc[GMAC_CNT][TRANSMIT_DESC_SIZE] __attribute__ ((aligned (64)));
44 static DmaDesc rx_desc[GMAC_CNT][RECEIVE_DESC_SIZE] __attribute__ ((aligned (64)));
45 
46 //static struct sk_buff tx_buf[GMAC_CNT][TRANSMIT_DESC_SIZE] __attribute__ ((aligned (64)));
47 //static struct sk_buff rx_buf[GMAC_CNT][RECEIVE_DESC_SIZE] __attribute__ ((aligned (64)));
48 struct sk_buff tx_buf[GMAC_CNT][TRANSMIT_DESC_SIZE] __attribute__ ((aligned (64)));
49 struct sk_buff rx_buf[GMAC_CNT][RECEIVE_DESC_SIZE] __attribute__ ((aligned (64)));
50 
51 // These 2 are accessable from application
52 struct sk_buff txbuf[GMAC_CNT] __attribute__ ((aligned (64))); // set align to separate cacheable and non-cacheable data to different cache line.
53 struct sk_buff rxbuf[GMAC_CNT] __attribute__ ((aligned (64)));
54 
55 u8 mac_addr0[6] = DEFAULT_MAC0_ADDRESS;
56 u8 mac_addr1[6] = DEFAULT_MAC1_ADDRESS;
57 
58 //static struct timer_list synopGMAC_cable_unplug_timer;
59 //static u32 GMAC_Power_down; // This global variable is used to indicate the ISR whether the interrupts occured in the process of powering down the mac or not
60 
61 
62 /**
63  * Function used to detect the cable plugging and unplugging.
64  * This function gets scheduled once in every second and polls
65  * the PHY register for network cable plug/unplug. Once the
66  * connection is back the GMAC device is configured as per
67  * new Duplex mode and Speed of the connection.
68  * @param[in] u32 type but is not used currently.
69  * \return returns void.
70  * \note This function is tightly coupled with Linux 2.6.xx.
71  * \callgraph
72  */
73 
74 
75 
synopGMAC_powerdown_mac(synopGMACdevice * gmacdev)76 void synopGMAC_powerdown_mac(synopGMACdevice *gmacdev)
77 {
78     TR0("Put the GMAC to power down mode..\n");
79     // Disable the Dma engines in tx path
80     gmacdev->GMAC_Power_down = 1;	// Let ISR know that Mac is going to be in the power down mode
81     synopGMAC_disable_dma_tx(gmacdev);
82     plat_delay(10000);		//allow any pending transmission to complete
83     // Disable the Mac for both tx and rx
84     synopGMAC_tx_disable(gmacdev);
85     synopGMAC_rx_disable(gmacdev);
86     plat_delay(10000); 		//Allow any pending buffer to be read by host
87     //Disable the Dma in rx path
88     synopGMAC_disable_dma_rx(gmacdev);
89 
90     //enable the power down mode
91     //synopGMAC_pmt_unicast_enable(gmacdev);
92 
93     //prepare the gmac for magic packet reception and wake up frame reception
94     synopGMAC_magic_packet_enable(gmacdev);
95 
96     //gate the application and transmit clock inputs to the code. This is not done in this driver :).
97 
98     //enable the Mac for reception
99     synopGMAC_rx_enable(gmacdev);
100 
101     //Enable the assertion of PMT interrupt
102     synopGMAC_pmt_int_enable(gmacdev);
103     //enter the power down mode
104     synopGMAC_power_down_enable(gmacdev);
105     return;
106 }
107 
synopGMAC_powerup_mac(synopGMACdevice * gmacdev)108 void synopGMAC_powerup_mac(synopGMACdevice *gmacdev)
109 {
110     gmacdev->GMAC_Power_down = 0;	// Let ISR know that MAC is out of power down now
111     if( synopGMAC_is_magic_packet_received(gmacdev))
112         TR("GMAC wokeup due to Magic Pkt Received\n");
113     if(synopGMAC_is_wakeup_frame_received(gmacdev))
114         TR("GMAC wokeup due to Wakeup Frame Received\n");
115     //Disable the assertion of PMT interrupt
116     synopGMAC_pmt_int_disable(gmacdev);
117     //Enable the mac and Dma rx and tx paths
118     synopGMAC_rx_enable(gmacdev);
119     synopGMAC_enable_dma_rx(gmacdev);
120 
121     synopGMAC_tx_enable(gmacdev);
122     synopGMAC_enable_dma_tx(gmacdev);
123     return;
124 }
125 
126 /**
127   * This sets up the transmit Descriptor queue in ring or chain mode.
128   * This function is tightly coupled to the platform and operating system
129   * Device is interested only after the descriptors are setup. Therefore this function
130   * is not included in the device driver API. This function should be treated as an
131   * example code to design the descriptor structures for ring mode or chain mode.
132   * This function depends on the pcidev structure for allocation consistent dma-able memory in case of linux.
133   * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory
134   *	- Allocates the memory for the descriptors.
135   *	- Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor).
136   *	- Initialize the Busy and Next descriptors to first descriptor address.
137   * 	- Initialize the last descriptor with the endof ring in case of ring mode.
138   *	- Initialize the descriptors in chain mode.
139   * @param[in] pointer to synopGMACdevice.
140   * @param[in] pointer to pci_device structure.
141   * @param[in] number of descriptor expected in tx descriptor queue.
142   * @param[in] whether descriptors to be created in RING mode or CHAIN mode.
143   * \return 0 upon success. Error code upon failure.
144   * \note This function fails if allocation fails for required number of descriptors in Ring mode, but in chain mode
145   *  function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from this function
146   *  user should for gmacdev->TxDescCount to see how many descriptors are there in the chain. Should continue further
147   *  only if the number of descriptors in the chain meets the requirements
148   */
149 
synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc,u32 desc_mode)150 s32 synopGMAC_setup_tx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode)
151 {
152     s32 i;
153 
154     DmaDesc *first_desc = &tx_desc[gmacdev->Intf][0];
155     gmacdev->TxDescCount = 0;
156 
157 	TR("Total size of memory required for Tx Descriptors in Ring Mode = 0x%08x\n",((sizeof(DmaDesc) * no_of_desc)));
158 
159 	gmacdev->TxDescCount = no_of_desc;
160 	gmacdev->TxDesc      = first_desc;
161 #ifdef CACHE_ON
162 	gmacdev->TxDescDma   = (DmaDesc *)((u64)first_desc | 0x100000000);
163 #else
164 	gmacdev->TxDescDma   = (DmaDesc *)((u64)first_desc);
165 #endif
166 	for(i =0; i < gmacdev -> TxDescCount; i++) {
167 		synopGMAC_tx_desc_init_ring(gmacdev->TxDescDma + i, i == gmacdev->TxDescCount-1);
168 		TR("%02d %08x \n",i, (unsigned int)(gmacdev->TxDesc + i) );
169 	}
170 
171 
172     gmacdev->TxNext = 0;
173     gmacdev->TxBusy = 0;
174     gmacdev->TxNextDesc = gmacdev->TxDesc;
175     gmacdev->TxBusyDesc = gmacdev->TxDesc;
176     gmacdev->BusyTxDesc  = 0;
177 
178     return 0;
179 }
180 
181 
182 /**
183   * This sets up the receive Descriptor queue in ring or chain mode.
184   * This function is tightly coupled to the platform and operating system
185   * Device is interested only after the descriptors are setup. Therefore this function
186   * is not included in the device driver API. This function should be treated as an
187   * example code to design the descriptor structures in ring mode or chain mode.
188   * This function depends on the pcidev structure for allocation of consistent dma-able memory in case of linux.
189   * This limitation is due to the fact that linux uses pci structure to allocate a dmable memory
190   *	- Allocates the memory for the descriptors.
191   *	- Initialize the Busy and Next descriptors indices to 0(Indicating first descriptor).
192   *	- Initialize the Busy and Next descriptors to first descriptor address.
193   * 	- Initialize the last descriptor with the endof ring in case of ring mode.
194   *	- Initialize the descriptors in chain mode.
195   * @param[in] pointer to synopGMACdevice.
196   * @param[in] pointer to pci_device structure.
197   * @param[in] number of descriptor expected in rx descriptor queue.
198   * @param[in] whether descriptors to be created in RING mode or CHAIN mode.
199   * \return 0 upon success. Error code upon failure.
200   * \note This function fails if allocation fails for required number of descriptors in Ring mode, but in chain mode
201   *  function returns -ESYNOPGMACNOMEM in the process of descriptor chain creation. once returned from this function
202   *  user should for gmacdev->RxDescCount to see how many descriptors are there in the chain. Should continue further
203   *  only if the number of descriptors in the chain meets the requirements
204   */
synopGMAC_setup_rx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc,u32 desc_mode)205 s32 synopGMAC_setup_rx_desc_queue(synopGMACdevice * gmacdev,u32 no_of_desc, u32 desc_mode)
206 {
207     s32 i;
208     DmaDesc *first_desc = &rx_desc[gmacdev->Intf][0];
209     gmacdev->RxDescCount = 0;
210 
211 
212 	TR("total size of memory required for Rx Descriptors in Ring Mode = 0x%08x\n",((sizeof(DmaDesc) * no_of_desc)));
213 
214 	gmacdev->RxDescCount = no_of_desc;
215 	gmacdev->RxDesc      = first_desc;
216 #ifdef CACHE_ON
217 	gmacdev->RxDescDma   = (DmaDesc *)((u64)first_desc | 0x100000000);
218 #else
219 	gmacdev->RxDescDma   = (DmaDesc *)((u64)first_desc);
220 #endif
221 	for(i =0; i < gmacdev -> RxDescCount; i++) {
222 		synopGMAC_rx_desc_init_ring(gmacdev->RxDescDma + i, i == gmacdev->RxDescCount-1);
223 		TR("%02d %08x \n",i, (unsigned int)(gmacdev->RxDesc + i));
224 	}
225 
226 
227     gmacdev->RxNext = 0;
228     gmacdev->RxBusy = 0;
229     gmacdev->RxNextDesc = gmacdev->RxDesc;
230     gmacdev->RxBusyDesc = gmacdev->RxDesc;
231 
232     gmacdev->BusyRxDesc   = 0;
233 
234     return 0;
235 }
236 
237 /**
238   * This gives up the receive Descriptor queue in ring or chain mode.
239   * This function is tightly coupled to the platform and operating system
240   * Once device's Dma is stopped the memory descriptor memory and the buffer memory deallocation,
241   * is completely handled by the operating system, this call is kept outside the device driver Api.
242   * This function should be treated as an example code to de-allocate the descriptor structures in ring mode or chain mode
243   * and network buffer deallocation.
244   * This function depends on the pcidev structure for dma-able memory deallocation for both descriptor memory and the
245   * network buffer memory under linux.
246   * The responsibility of this function is to
247   *     - Free the network buffer memory if any.
248   *	- Fee the memory allocated for the descriptors.
249   * @param[in] pointer to synopGMACdevice.
250   * @param[in] pointer to pci_device structure.
251   * @param[in] number of descriptor expected in rx descriptor queue.
252   * @param[in] whether descriptors to be created in RING mode or CHAIN mode.
253   * \return 0 upon success. Error code upon failure.
254   * \note No referece should be made to descriptors once this function is called. This function is invoked when the device is closed.
255   */
synopGMAC_giveup_rx_desc_queue(synopGMACdevice * gmacdev,u32 desc_mode)256 void synopGMAC_giveup_rx_desc_queue(synopGMACdevice * gmacdev, u32 desc_mode)
257 {
258 	gmacdev->RxDesc    = NULL;
259 	gmacdev->RxDescDma = 0;
260 	return;
261 }
262 
263 /**
264   * This gives up the transmit Descriptor queue in ring or chain mode.
265   * This function is tightly coupled to the platform and operating system
266   * Once device's Dma is stopped the memory descriptor memory and the buffer memory deallocation,
267   * is completely handled by the operating system, this call is kept outside the device driver Api.
268   * This function should be treated as an example code to de-allocate the descriptor structures in ring mode or chain mode
269   * and network buffer deallocation.
270   * This function depends on the pcidev structure for dma-able memory deallocation for both descriptor memory and the
271   * network buffer memory under linux.
272   * The responsibility of this function is to
273   *     - Free the network buffer memory if any.
274   *	- Fee the memory allocated for the descriptors.
275   * @param[in] pointer to synopGMACdevice.
276   * @param[in] pointer to pci_device structure.
277   * @param[in] number of descriptor expected in tx descriptor queue.
278   * @param[in] whether descriptors to be created in RING mode or CHAIN mode.
279   * \return 0 upon success. Error code upon failure.
280   * \note No reference should be made to descriptors once this function is called. This function is invoked when the device is closed.
281   */
synopGMAC_giveup_tx_desc_queue(synopGMACdevice * gmacdev,u32 desc_mode)282 void synopGMAC_giveup_tx_desc_queue(synopGMACdevice * gmacdev, u32 desc_mode)
283 {
284 
285 
286 	gmacdev->TxDesc    = NULL;
287 	gmacdev->TxDescDma = 0;
288 	return;
289 }
290 
291 /**
292  * Function to handle housekeeping after a packet is transmitted over the wire.
293  * After the transmission of a packet DMA generates corresponding interrupt
294  * (if it is enabled). It takes care of returning the sk_buff to the linux
295  * kernel, updating the networking statistics and tracking the descriptors.
296  * @param[in] pointer to net_device structure.
297  * \return void.
298  * \note This function runs in interrupt context
299  */
synop_handle_transmit_over(int intf)300 void synop_handle_transmit_over(int intf)
301 {
302     synopGMACdevice * gmacdev;
303     s32 desc_index;
304     u32 data1;
305     u32 status;
306     u32 length1;
307     u32 dma_addr1;
308 
309     u32 ext_status;
310     //u16 time_stamp_higher;
311     u32 time_stamp_high;
312     u32 time_stamp_low;
313 
314 
315     gmacdev = &GMACdev[intf];
316 
317     /*Handle the transmit Descriptors*/
318     do {
319 
320         desc_index = synopGMAC_get_tx_qptr(gmacdev, &status, &dma_addr1, &length1, &data1,&ext_status,&time_stamp_high,&time_stamp_low);
321         //synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher);
322 
323         if(desc_index >= 0 /*&& data1 != 0*/) {
324             TR("Finished Transmit at Tx Descriptor %d for skb 0x%08x and buffer = %08x whose status is %08x \n", desc_index,data1,dma_addr1,status);
325 
326             if(synopGMAC_is_tx_ipv4header_checksum_error(gmacdev, status)) {
327                 TR("Harware Failed to Insert IPV4 Header Checksum\n");
328                 gmacdev->synopGMACNetStats.tx_ip_header_errors++;
329             }
330             if(synopGMAC_is_tx_payload_checksum_error(gmacdev, status)) {
331                 TR("Harware Failed to Insert Payload Checksum\n");
332                 gmacdev->synopGMACNetStats.tx_ip_payload_errors++;
333             }
334 
335 
336 
337             if(synopGMAC_is_desc_valid(status)) {
338             	gmacdev->synopGMACNetStats.tx_bytes += length1;
339             	gmacdev->synopGMACNetStats.tx_packets++;
340             	if(status & DescTxTSStatus) {
341             		gmacdev->tx_sec = time_stamp_high;
342             		gmacdev->tx_subsec = time_stamp_low;
343             	} else {
344             		gmacdev->tx_sec = 0;
345             		gmacdev->tx_subsec = 0;
346             	}
347             } else {
348                 TR("Error in Status %08x\n",status);
349                 gmacdev->synopGMACNetStats.tx_errors++;
350                 gmacdev->synopGMACNetStats.tx_aborted_errors += synopGMAC_is_tx_aborted(status);
351                 gmacdev->synopGMACNetStats.tx_carrier_errors += synopGMAC_is_tx_carrier_error(status);
352             }
353         }
354         gmacdev->synopGMACNetStats.collisions += synopGMAC_get_tx_collision_count(status);
355     } while(desc_index >= 0);
356 
357 }
358 
359 
360 
361 
362 /**
363  * Function to Receive a packet from the interface.
364  * After Receiving a packet, DMA transfers the received packet to the system memory
365  * and generates corresponding interrupt (if it is enabled). This function prepares
366  * the sk_buff for received packet after removing the ethernet CRC, and hands it over
367  * to linux networking stack.
368  * 	- Updataes the networking interface statistics
369  *	- Keeps track of the rx descriptors
370  * @param[in] pointer to net_device structure.
371  * \return void.
372  * \note This function runs in interrupt context.
373  */
374 extern DmaDesc * prevtx;  // for CRC test
synop_handle_received_data(int intf,u8 ** buf)375 s32 synop_handle_received_data(int intf, u8 **buf)      // Chris, to get RX buffer pointer
376 {
377 
378     synopGMACdevice * gmacdev;
379     s32 desc_index;
380 
381     u32 data1;
382     u32 len = 0;
383     u32 status;
384     u32 dma_addr1;
385 
386     u32 ext_status;
387     //u16 time_stamp_higher;
388     u32 time_stamp_high;
389     u32 time_stamp_low;
390     struct sk_buff *rb = &rxbuf[intf];
391 
392     //struct sk_buff *skb; //This is the pointer to hold the received data
393 
394     TR("%s\n",__FUNCTION__);
395 
396 
397 
398     gmacdev = &GMACdev[intf];
399 
400     /*Handle the Receive Descriptors*/
401     do {
402 
403         desc_index = synopGMAC_get_rx_qptr(gmacdev, &status,
404         		                           &dma_addr1, NULL, &data1,
405 										   &ext_status, &time_stamp_high, &time_stamp_low);
406         if(desc_index >0) {
407             //synopGMAC_TS_read_timestamp_higher_val(gmacdev, &time_stamp_higher);
408             //TR("S:%08x ES:%08x DA1:%08x d1:%08x TSH:%08x TSL:%08x TSHW:%08x \n",status,ext_status,dma_addr1, data1,time_stamp_high,time_stamp_low,time_stamp_higher);
409         	TR("S:%08x ES:%08x DA1:%08x d1:%08x TSH:%08x TSL:%08x\n",status,ext_status,dma_addr1, data1,time_stamp_high,time_stamp_low);
410         }
411 
412         if(desc_index >= 0 /*&& data1 != 0*/) {
413             TR("Received Data at Rx Descriptor %d for skb 0x%08x whose status is %08x\n",desc_index,data1,status);
414 
415 
416             //skb = (struct sk_buff *)((u64)data1);
417             if(1/*synopGMAC_is_rx_desc_valid(status)*/) {
418             	// Always enter this loop. synopGMAC_is_rx_desc_valid() also report invalid descriptor
419             	// if there's packet error generated by test code and drop it. But we need to execute ext_status
420             	// check code to tell what's going on.                                          --ya
421 
422                 len =  synopGMAC_get_rx_desc_frame_length(status) - 4; //Not interested in Ethernet CRC bytes
423 
424 
425                 // Now lets check for the IPC offloading
426                 /*  Since we have enabled the checksum offloading in hardware, lets inform the kernel
427                     not to perform the checksum computation on the incoming packet. Note that ip header
428                     checksum will be computed by the kernel immaterial of what we inform. Similary TCP/UDP/ICMP
429                     pseudo header checksum will be computed by the stack. What we can inform is not to perform
430                     payload checksum.
431                     When CHECKSUM_UNNECESSARY is set kernel bypasses the checksum computation.
432                 */
433 
434                 TR("Checksum Offloading will be done now\n");
435 
436                 if(synopGMAC_is_ext_status(gmacdev, status)) { // extended status present indicates that the RDES4 need to be probed
437                     TR("Extended Status present\n");
438                     if(synopGMAC_ES_is_IP_header_error(gmacdev,ext_status)) {      // IP header (IPV4) checksum error
439                         //Linux Kernel doesnot care for ipv4 header checksum. So we will simply proceed by printing a warning ....
440                         TR("(EXTSTS)Error in IP header error\n");
441                         gmacdev->synopGMACNetStats.rx_ip_header_errors++;
442                     }
443                     if(synopGMAC_ES_is_rx_checksum_bypassed(gmacdev,ext_status)) {  // Hardware engine bypassed the checksum computation/checking
444                         TR("(EXTSTS)Hardware bypassed checksum computation\n");
445                     }
446                     if(synopGMAC_ES_is_IP_payload_error(gmacdev,ext_status)) {      // IP payload checksum is in error (UDP/TCP/ICMP checksum error)
447                         TR("(EXTSTS) Error in EP payload\n");
448                         gmacdev->synopGMACNetStats.rx_ip_payload_errors++;
449                     }
450                 } else { // No extended status. So relevant information is available in the status itself
451                     if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxNoChkError ) {
452                         TR("Ip header and TCP/UDP payload checksum Bypassed <Chk Status = 4>  \n");
453                     }
454                     if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxIpHdrChkError ) {
455                         //Linux Kernel doesnot care for ipv4 header checksum. So we will simply proceed by printing a warning ....
456                         TR(" Error in 16bit IPV4 Header Checksum <Chk Status = 6>  \n");
457                         gmacdev->synopGMACNetStats.rx_ip_header_errors++;
458                     }
459                     if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxLenLT600 ) {
460                         TR("IEEE 802.3 type frame with Length field Lesss than 0x0600 <Chk Status = 0> \n");
461                     }
462                     if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxIpHdrPayLoadChkBypass ) {
463                         TR("Ip header and TCP/UDP payload checksum Bypassed <Chk Status = 1>\n");
464                     }
465                     if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxChkBypass ) {
466                         TR("Ip header and TCP/UDP payload checksum Bypassed <Chk Status = 3>  \n");
467                     }
468                     if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxPayLoadChkError ) {
469                         TR(" TCP/UDP payload checksum Error <Chk Status = 5>  \n");
470                         gmacdev->synopGMACNetStats.rx_ip_payload_errors++;
471                     }
472                     if(synopGMAC_is_rx_checksum_error(gmacdev, status) == RxIpHdrPayLoadChkError ) {
473                         //Linux Kernel doesnot care for ipv4 header checksum. So we will simply proceed by printing a warning ....
474                         TR(" Both IP header and Payload Checksum Error <Chk Status = 7>  \n");
475                         gmacdev->synopGMACNetStats.rx_ip_header_errors++;
476                         gmacdev->synopGMACNetStats.rx_ip_payload_errors++;
477                     }
478                 }
479 #if 0
480 #ifdef CACHE_ON
481                 memcpy((void *)rb->data, (void *)((u64)dma_addr1 | 0x100000000), len);
482 #else
483                 memcpy((void *)rb->data, (void *)((u64)dma_addr1), len);
484 #endif
485                 if(prevtx != NULL) {
486 #ifdef CACHE_ON
487                 memcpy((void *)(rb->data + len), (void *)((u64)(dma_addr1 | 0x100000000) + len), 4);
488 #else
489                 memcpy((void *)(rb->data + len), (void *)((u64)dma_addr1 + len), 4);
490 #endif
491                 }
492 #else
493                 *buf = (u8 *)(u32)((u64)dma_addr1);
494 #endif
495                 rb->rdy = 1;
496                 rb->len = len;
497                 gmacdev->synopGMACNetStats.rx_packets++;
498                 gmacdev->synopGMACNetStats.rx_bytes += len;
499                 if(status & DescRxTSAvailable) {
500                 	gmacdev->rx_sec = time_stamp_high;
501                 	gmacdev->rx_subsec = time_stamp_low;
502                 } else {
503             		gmacdev->rx_sec = 0;
504             		gmacdev->rx_subsec = 0;
505                 }
506             } else {
507                 /*Now the present skb should be set free*/
508             	TR("s: %08x\n",status);
509             	gmacdev->synopGMACNetStats.rx_errors++;
510             	gmacdev->synopGMACNetStats.collisions       += synopGMAC_is_rx_frame_collision(status);
511             	gmacdev->synopGMACNetStats.rx_crc_errors    += synopGMAC_is_rx_crc(status);
512             	gmacdev->synopGMACNetStats.rx_frame_errors  += synopGMAC_is_frame_dribbling_errors(status);
513             	gmacdev->synopGMACNetStats.rx_length_errors += synopGMAC_is_rx_frame_length_errors(status);
514             }
515         }
516     } while(0); //while(desc_index >= 0);
517     return len;
518 }
519 
520 u32 volatile LPIStsChange = 0;
521 u32 volatile LPIReg = 0;
522 /**
523  * Interrupt service routing.
524  * This is the function registered as ISR for device interrupts.
525  * @param[in] interrupt number.
526  * @param[in] void pointer to device unique structure (Required for shared interrupts in Linux).
527  * @param[in] pointer to pt_regs (not used).
528  * \return Returns IRQ_NONE if not device interrupts IRQ_HANDLED for device interrupts.
529  * \note This function runs in interrupt context
530  *
531  */
synopGMAC0_intr_handler(void)532 void synopGMAC0_intr_handler(void)
533 {
534     synopGMACdevice * gmacdev = &GMACdev[0];
535     u32 interrupt,dma_status_reg, mac_status_reg;
536     s32 status;
537 
538     // Check GMAC interrupt
539     mac_status_reg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacInterruptStatus);
540     if(mac_status_reg & GmacTSIntSts) {
541     	gmacdev->synopGMACNetStats.ts_int = 1;
542     	status = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacTSStatus);
543     	if(!(status & (1 << 1)))
544     		printf("TS alarm flag not set??\n");
545     	else
546     		printf("TS alarm!!!!!!!!!!!!!!!!\n");
547 
548     }
549     if(mac_status_reg & GmacLPIIntSts) {
550     	//printf("LPI\n");
551     	LPIStsChange = 1;
552     	LPIReg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacLPICtrlSts);
553 
554     }
555     if(mac_status_reg & GmacRgmiiIntSts) {
556     	u32 volatile reg;
557     	reg = synopGMACReadReg((u32 *)gmacdev->MacBase, GmacRgmiiCtrlSts);
558 
559     }
560     synopGMACWriteReg((u32 *)gmacdev->MacBase, GmacInterruptStatus ,mac_status_reg);
561 
562     /*Read the Dma interrupt status to know whether the interrupt got generated by our device or not*/
563     dma_status_reg = synopGMACReadReg((u32 *)gmacdev->DmaBase, DmaStatus);
564     //printf("i");
565     //printf("i %08x %08x\n", mac_status_reg, dma_status_reg);
566 
567     if(dma_status_reg == 0)
568         return;
569 
570     synopGMAC_disable_interrupt_all(gmacdev);
571 
572     TR("%s:Dma Status Reg: 0x%08x\n",__FUNCTION__,dma_status_reg);
573 
574     if(dma_status_reg & GmacPmtIntr) {
575         TR("%s:: Interrupt due to PMT module\n",__FUNCTION__);
576         synopGMAC_powerup_mac(gmacdev);
577     }
578 
579     if(dma_status_reg & GmacLineIntfIntr) {
580         TR("%s:: Interrupt due to GMAC LINE module\n",__FUNCTION__);
581     }
582 
583     /*Now lets handle the DMA interrupts*/
584     interrupt = synopGMAC_get_interrupt_type(gmacdev);
585     TR("%s:Interrupts to be handled: 0x%08x\n",__FUNCTION__,interrupt);
586 
587 
588     if(interrupt & synopGMACDmaError) {
589 
590         TR("%s::Fatal Bus Error Inetrrupt Seen\n",__FUNCTION__);
591         synopGMAC_disable_dma_tx(gmacdev);
592         synopGMAC_disable_dma_rx(gmacdev);
593 
594         synopGMAC_take_desc_ownership_tx(gmacdev);
595         synopGMAC_take_desc_ownership_rx(gmacdev);
596 
597         synopGMAC_init_tx_rx_desc_queue(gmacdev);
598 
599         synopGMAC_reset(gmacdev);//reset the DMA engine and the GMAC ip
600 
601         synopGMAC_set_mac_addr(gmacdev,GmacAddr0High,GmacAddr0Low, gmacdev->Intf == 0 ? mac_addr0 : mac_addr1);
602         synopGMAC_dma_bus_mode_init(gmacdev,DmaFixedBurstEnable| DmaBurstLength8 | DmaDescriptorSkip0/*DmaDescriptorSkip2*/ );
603         synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward);
604         synopGMAC_init_rx_desc_base(gmacdev);
605         synopGMAC_init_tx_desc_base(gmacdev);
606         synopGMAC_mac_init(gmacdev);
607         synopGMAC_enable_dma_rx(gmacdev);
608         synopGMAC_enable_dma_tx(gmacdev);
609 
610     }
611 
612 
613     if(interrupt & synopGMACDmaRxNormal) {
614         u8 **buf = NULL;
615     	//printf("rx\n");
616         TR("%s:: Rx Normal \n", __FUNCTION__);
617         synop_handle_received_data(0, buf);     // Chris, to get RX buffer pointer
618     }
619 
620     if(interrupt & synopGMACDmaRxAbnormal) {
621         TR("%s::Abnormal Rx Interrupt Seen\n",__FUNCTION__);
622     	gmacdev->synopGMACNetStats.rx_over_errors++;
623 #if 1
624 
625         if(gmacdev->GMAC_Power_down == 0) {	// If Mac is not in powerdown
626             synopGMAC_resume_dma_rx(gmacdev);//To handle GBPS with 12 descriptors
627         }
628 #endif
629     }
630 
631     if(interrupt & synopGMACDmaRxStopped) {
632         TR("%s::Receiver stopped seeing Rx interrupts\n",__FUNCTION__); //Receiver gone in to stopped state
633 #if 1
634         if(gmacdev->GMAC_Power_down == 0) {	// If Mac is not in powerdown
635         	gmacdev->synopGMACNetStats.rx_over_errors++;
636             synopGMAC_enable_dma_rx(gmacdev);
637         }
638 #endif
639     }
640 
641     if(interrupt & synopGMACDmaTxNormal) {
642     	//printf("tx\n");
643         //xmit function has done its job
644         TR("%s::Finished Normal Transmission \n",__FUNCTION__);
645         synop_handle_transmit_over(0);//Do whatever you want after the transmission is over
646 
647 
648     }
649 
650     if(interrupt & synopGMACDmaTxAbnormal) {
651         TR("%s::Abnormal Tx Interrupt Seen\n",__FUNCTION__);
652 #if 1
653         if(gmacdev->GMAC_Power_down == 0) {	// If Mac is not in powerdown
654             synop_handle_transmit_over(0);
655         }
656 #endif
657     }
658 
659 
660 
661     if(interrupt & synopGMACDmaTxStopped) {
662         TR("%s::Transmitter stopped sending the packets\n",__FUNCTION__);
663 #if 1
664         if(gmacdev->GMAC_Power_down == 0) {	// If Mac is not in powerdown
665             synopGMAC_disable_dma_tx(gmacdev);
666             synopGMAC_take_desc_ownership_tx(gmacdev);
667 
668             synopGMAC_enable_dma_tx(gmacdev);
669             TR("%s::Transmission Resumed\n",__FUNCTION__);
670         }
671 #endif
672     }
673 
674     /* Enable the interrupt before returning from ISR*/
675     synopGMAC_enable_interrupt(gmacdev,DmaIntEnable);
676     return;
677 }
678 
synopGMAC_set_speed(int intf)679 void synopGMAC_set_speed(int intf)
680 {
681 
682     synopGMACdevice *gmacdev = &GMACdev[intf];
683 
684 	switch (gmacdev->Speed) {
685 	case SPEED1000:
686 		synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii);
687 		break;
688 	case SPEED100:
689 		synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii);
690 		synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacFESpeed100);
691 		break;
692 	case SPEED10:
693 		synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii);
694 		synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacFESpeed100);
695 	default:
696 		break;
697 	}
698 
699 }
700 
701 /**
702  * Function used when the interface is opened for use.
703  * We register synopGMAC_linux_open function to linux open(). Basically this
704  * function prepares the the device for operation . This function is called whenever ifconfig (in Linux)
705  * activates the device (for example "ifconfig eth0 up"). This function registers
706  * system resources needed
707  * 	- Attaches device to device specific structure
708  * 	- Programs the MDC clock for PHY configuration
709  * 	- Check and initialize the PHY interface
710  *	- ISR registration
711  * 	- Setup and initialize Tx and Rx descriptors
712  *	- Initialize MAC and DMA
713  *	- Allocate Memory for RX descriptors (The should be DMAable)
714  * 	- Initialize one second timer to detect cable plug/unplug
715  *	- Configure and Enable Interrupts
716  *	- Enable Tx and Rx
717  *	- start the Linux network queue interface
718  * @param[in] pointer to net_device structure.
719  * \return Returns 0 on success and error status upon failure.
720  * \callgraph
721  */
722 
synopGMAC_open(int intf)723 s32 synopGMAC_open(int intf)
724 {
725     //s32 status = 0;
726     s32 i;
727     //s32 reserve_len=2;
728     struct sk_buff *skb;
729     synopGMACdevice * gmacdev = &GMACdev[intf];
730 
731     /*Attach the device to MAC struct This will configure all the required base addresses
732       such as Mac base, configuration base, phy base address(out of 32 possible phys )*/
733     if(intf == 0)
734     	synopGMAC_attach(gmacdev, GMAC0MappedAddr + MACBASE, GMAC0MappedAddr + DMABASE, DEFAULT_PHY_BASE);
735     else
736     	synopGMAC_attach(gmacdev, GMAC1MappedAddr + MACBASE, GMAC1MappedAddr + DMABASE, DEFAULT_PHY_BASE);
737 
738     synopGMAC_reset(gmacdev); // Reset to make RGMII/RMII setting take affect --ya
739     gmacdev->Intf = intf;
740     /*Lets read the version of ip in to device structure*/
741     synopGMAC_read_version(gmacdev);
742 
743     /*Check for Phy initialization*/
744     synopGMAC_set_mdc_clk_div(gmacdev,GmiiCsrClk5);
745     //synopGMAC_set_mdc_clk_div(gmacdev, (GmiiCsrClk2|BIT5));
746     gmacdev->ClockDivMdc = synopGMAC_get_mdc_clk_div(gmacdev);
747     //status = synopGMAC_check_phy_init(gmacdev);
748     synopGMAC_check_phy_init(gmacdev);
749 
750     /*Set up the tx and rx descriptor queue/ring*/
751 
752     synopGMAC_setup_tx_desc_queue(gmacdev,TRANSMIT_DESC_SIZE, RINGMODE);
753     synopGMAC_init_tx_desc_base(gmacdev);	//Program the transmit descriptor base address in to DmaTxBase addr
754 
755     synopGMAC_setup_rx_desc_queue(gmacdev,RECEIVE_DESC_SIZE, RINGMODE);
756     synopGMAC_init_rx_desc_base(gmacdev);	//Program the transmit descriptor base address in to DmaTxBase addr
757 
758 
759     synopGMAC_dma_bus_mode_init(gmacdev, DmaBurstLength32 | DmaDescriptorSkip0/*DmaDescriptorSkip2*/ | DmaDescriptor8Words ); //pbl32 incr with rxthreshold 128 and Desc is 8 Words
760 
761     synopGMAC_dma_control_init(gmacdev,DmaStoreAndForward |DmaTxSecondFrame|DmaRxThreshCtrl128);
762 
763     /*Initialize the mac interface*/
764 
765     synopGMAC_mac_init(gmacdev);
766     synopGMAC_promisc_enable(gmacdev);
767 
768     synopGMAC_pause_control(gmacdev); // This enables the pause control in Full duplex mode of operation
769 
770 #if 0
771     /*IPC Checksum offloading is enabled for this driver. Should only be used if Full Ip checksumm offload engine is configured in the hardware*/
772     synopGMAC_enable_rx_chksum_offload(gmacdev);  	//Enable the offload engine in the receive path
773     synopGMAC_rx_tcpip_chksum_drop_enable(gmacdev); // This is default configuration, DMA drops the packets if error in encapsulated ethernet payload
774 #endif
775 
776     for(i = 0; i < RECEIVE_DESC_SIZE; i ++) {
777         skb = &rx_buf[intf][i];
778         synopGMAC_set_rx_qptr(gmacdev, (u32)((u64)(skb->data) & 0xFFFFFFFF), sizeof(skb->data), (u32)((u64)skb & 0xFFFFFFFF));
779     }
780 
781     synopGMAC_clear_interrupt(gmacdev);
782 
783     synopGMAC_enable_interrupt(gmacdev,DmaIntEnable);
784     synopGMAC_enable_dma_rx(gmacdev);
785     synopGMAC_enable_dma_tx(gmacdev);
786 
787 
788     synopGMAC_set_mac_address(intf, intf == 0 ? mac_addr0 : mac_addr1);
789 
790 
791     return 0;
792 
793 }
794 
795 /**
796  * Function used when the interface is closed.
797  *
798  * This function is registered to linux stop() function. This function is
799  * called whenever ifconfig (in Linux) closes the device (for example "ifconfig eth0 down").
800  * This releases all the system resources allocated during open call.
801  * system resources int needs
802  * 	- Disable the device interrupts
803  * 	- Stop the receiver and get back all the rx descriptors from the DMA
804  * 	- Stop the transmitter and get back all the tx descriptors from the DMA
805  * 	- Stop the Linux network queue interface
806  *	- Free the irq (ISR registered is removed from the kernel)
807  * 	- Release the TX and RX descripor memory
808  *	- De-initialize one second timer rgistered for cable plug/unplug tracking
809  * @param[in] pointer to net_device structure.
810  * \return Returns 0 on success and error status upon failure.
811  * \callgraph
812  */
813 
synopGMAC_close(int intf)814 s32 synopGMAC_close(int intf)
815 {
816 
817     synopGMACdevice * gmacdev = &GMACdev[intf];;
818 
819 	//TR0("%s\n",__FUNCTION__);
820 
821 	/*Disable all the interrupts*/
822 	synopGMAC_disable_interrupt_all(gmacdev);
823 
824 
825 	TR("the synopGMAC interrupt has been disabled\n");
826 
827 	/*Disable the reception*/
828 	synopGMAC_disable_dma_rx(gmacdev);
829     synopGMAC_take_desc_ownership_rx(gmacdev);
830 	TR("the synopGMAC Reception has been disabled\n");
831 
832 	/*Disable the transmission*/
833 	synopGMAC_disable_dma_tx(gmacdev);
834     synopGMAC_take_desc_ownership_tx(gmacdev);
835 
836 	TR("the synopGMAC interrupt handler has been removed\n");
837 
838 	/*Free the Rx Descriptor contents*/
839 	TR("Now calling synopGMAC_giveup_rx_desc_queue \n");
840 	synopGMAC_giveup_rx_desc_queue(gmacdev, RINGMODE);
841 
842 	TR("Now calling synopGMAC_giveup_tx_desc_queue \n");
843 	synopGMAC_giveup_tx_desc_queue(gmacdev, RINGMODE);
844 
845 	return 0;
846 
847 }
848 
849 
850 /**
851  * Function to transmit a given packet on the wire.
852  * Whenever Linux Kernel has a packet ready to be transmitted, this function is called.
853  * The function prepares a packet and prepares the descriptor and
854  * enables/resumes the transmission.
855  * @param[in] pointer to sk_buff structure.
856  * @param[in] pointer to net_device structure.
857  * \return Returns 0 on success and Error code on failure.
858  * \note structure sk_buff is used to hold packet in Linux networking stacks.
859  */
synopGMAC_xmit_frames(struct sk_buff * skb,int intf,u32 offload_needed,u32 ts)860 s32 synopGMAC_xmit_frames(struct sk_buff *skb, int intf, u32 offload_needed, u32 ts)
861 {
862     s32 status = 0;
863 
864     u32 dma_addr = (u32)((u64)skb->data & 0xFFFFFFFF);
865 
866     synopGMACdevice * gmacdev;
867 
868 
869     gmacdev = &GMACdev[intf];
870 
871     /*Now we have skb ready and OS invoked this function. Lets make our DMA know about this*/
872     status = synopGMAC_set_tx_qptr(gmacdev, dma_addr, skb->len, (u32)((u64)skb & 0xFFFFFFFF), offload_needed, ts);
873     if(status < 0) {
874         TR0("%s No More Free Tx Descriptors\n",__FUNCTION__);
875         return -1;
876     }
877 
878     /*Now force the DMA to start transmission*/
879     synopGMAC_resume_dma_tx(gmacdev);
880 
881 
882     return 0;
883 }
884 
885 
886 /**
887  * Function to set ethernet address of the NIC.
888  * @param[in] pointer to net_device structure.
889  * @param[in] pointer to an address structure.
890  * \return Returns 0 on success Errorcode on failure.
891  */
synopGMAC_set_mac_address(int intf,u8 * macaddr)892 s32 synopGMAC_set_mac_address(int intf,  u8* macaddr)
893 {
894 
895 
896     synopGMACdevice * gmacdev = NULL;
897 
898     gmacdev = &GMACdev[intf];
899 
900 
901     synopGMAC_set_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, macaddr);
902 
903     return 0;
904 }
905 
906 // mode 0: 1000Mbps, 1: 100Mbps, 2: 10Mbps
907 
synopGMAC_set_mode(int intf,int mode)908 void synopGMAC_set_mode(int intf, int mode)
909 {
910 
911     synopGMACdevice *gmacdev = &GMACdev[intf];
912 
913     // Must stop Tx/Rx before change speed/mode
914     synopGMAC_tx_disable(gmacdev);
915     synopGMAC_rx_disable(gmacdev);
916 	switch (mode) {
917 	case 0:
918 		synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii);
919 		gmacdev->Speed = SPEED1000;
920 		break;
921 	case 1:
922 		synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii);
923 		synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacFESpeed100);
924 		gmacdev->Speed = SPEED100;
925 		break;
926 	case 2:
927 		synopGMACSetBits((u32 *)gmacdev->MacBase,GmacConfig,GmacMiiGmii);
928 		synopGMACClearBits((u32 *)gmacdev->MacBase,GmacConfig,GmacFESpeed100);
929 		gmacdev->Speed = SPEED10;
930 	default:
931 		break;
932 	}
933     synopGMAC_tx_enable(gmacdev);
934     synopGMAC_rx_enable(gmacdev);
935 }
936 
937