net: sxgbe: add basic framework for Samsung 10Gb ethernet driver
This patch adds support for Samsung 10Gb ethernet driver(sxgbe). - sxgbe core initialization - Tx and Rx support - MDIO support - ISRs for Tx and Rx - ifconfig support to driver Signed-off-by: Siva Reddy Kallam <siva.kallam@samsung.com> Signed-off-by: Vipul Pandya <vipul.pandya@samsung.com> Signed-off-by: Girish K S <ks.giri@samsung.com> Neatening-by: Joe Perches <joe@perches.com> Signed-off-by: Byungho An <bh74.an@samsung.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
					parent
					
						
							
								5221d3e66d
							
						
					
				
			
			
				commit
				
					
						1edb9ca69e
					
				
			
		
					 22 changed files with 5507 additions and 0 deletions
				
			
		|  | @ -150,6 +150,7 @@ config S6GMAC | ||||||
| 	  To compile this driver as a module, choose M here. The module | 	  To compile this driver as a module, choose M here. The module | ||||||
| 	  will be called s6gmac. | 	  will be called s6gmac. | ||||||
| 
 | 
 | ||||||
|  | source "drivers/net/ethernet/samsung/Kconfig" | ||||||
| source "drivers/net/ethernet/seeq/Kconfig" | source "drivers/net/ethernet/seeq/Kconfig" | ||||||
| source "drivers/net/ethernet/silan/Kconfig" | source "drivers/net/ethernet/silan/Kconfig" | ||||||
| source "drivers/net/ethernet/sis/Kconfig" | source "drivers/net/ethernet/sis/Kconfig" | ||||||
|  |  | ||||||
|  | @ -61,6 +61,7 @@ obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/ | ||||||
| obj-$(CONFIG_SH_ETH) += renesas/ | obj-$(CONFIG_SH_ETH) += renesas/ | ||||||
| obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ | obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ | ||||||
| obj-$(CONFIG_S6GMAC) += s6gmac.o | obj-$(CONFIG_S6GMAC) += s6gmac.o | ||||||
|  | obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/ | ||||||
| obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/ | obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/ | ||||||
| obj-$(CONFIG_NET_VENDOR_SILAN) += silan/ | obj-$(CONFIG_NET_VENDOR_SILAN) += silan/ | ||||||
| obj-$(CONFIG_NET_VENDOR_SIS) += sis/ | obj-$(CONFIG_NET_VENDOR_SIS) += sis/ | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								drivers/net/ethernet/samsung/Kconfig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								drivers/net/ethernet/samsung/Kconfig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | # | ||||||
|  | # Samsung Ethernet device configuration | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | config NET_VENDOR_SAMSUNG | ||||||
|  | 	bool "Samsung Ethernet device" | ||||||
|  | 	default y | ||||||
|  | 	---help--- | ||||||
|  | 	  This is the driver for the SXGBE 10G Ethernet IP block found on Samsung | ||||||
|  | 	  platforms. | ||||||
|  | 
 | ||||||
|  | if NET_VENDOR_SAMSUNG | ||||||
|  | 
 | ||||||
|  | source "drivers/net/ethernet/samsung/sxgbe/Kconfig" | ||||||
|  | 
 | ||||||
|  | endif # NET_VENDOR_SAMSUNG | ||||||
							
								
								
									
										5
									
								
								drivers/net/ethernet/samsung/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								drivers/net/ethernet/samsung/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | ||||||
|  | #
 | ||||||
|  | # Makefile for the Samsung Ethernet device drivers.
 | ||||||
|  | #
 | ||||||
|  | 
 | ||||||
|  | obj-$(CONFIG_SXGBE_ETH) += sxgbe/ | ||||||
							
								
								
									
										9
									
								
								drivers/net/ethernet/samsung/sxgbe/Kconfig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								drivers/net/ethernet/samsung/sxgbe/Kconfig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | config SXGBE_ETH | ||||||
|  | 	tristate "Samsung 10G/2.5G/1G SXGBE Ethernet driver" | ||||||
|  | 	depends on HAS_IOMEM && HAS_DMA | ||||||
|  | 	select PHYLIB | ||||||
|  | 	select CRC32 | ||||||
|  | 	select PTP_1588_CLOCK | ||||||
|  | 	---help--- | ||||||
|  | 	  This is the driver for the SXGBE 10G Ethernet IP block found on Samsung | ||||||
|  | 	  platforms. | ||||||
							
								
								
									
										4
									
								
								drivers/net/ethernet/samsung/sxgbe/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								drivers/net/ethernet/samsung/sxgbe/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | ||||||
|  | obj-$(CONFIG_SXGBE_ETH) += samsung-sxgbe.o | ||||||
|  | samsung-sxgbe-objs:= sxgbe_platform.o sxgbe_main.o sxgbe_desc.o \
 | ||||||
|  | 		sxgbe_dma.o sxgbe_core.o sxgbe_mtl.o  sxgbe_mdio.o \
 | ||||||
|  | 		sxgbe_ethtool.o sxgbe_xpcs.o $(samsung-sxgbe-y) | ||||||
							
								
								
									
										462
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										462
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,462 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef __SXGBE_COMMON_H__ | ||||||
|  | #define __SXGBE_COMMON_H__ | ||||||
|  | 
 | ||||||
|  | /* forward references */ | ||||||
|  | struct sxgbe_desc_ops; | ||||||
|  | struct sxgbe_dma_ops; | ||||||
|  | struct sxgbe_mtl_ops; | ||||||
|  | 
 | ||||||
|  | #define SXGBE_RESOURCE_NAME	"sam_sxgbeeth" | ||||||
|  | #define DRV_MODULE_VERSION	"November_2013" | ||||||
|  | 
 | ||||||
|  | /* MAX HW feature words */ | ||||||
|  | #define SXGBE_HW_WORDS 3 | ||||||
|  | 
 | ||||||
|  | #define SXGBE_RX_COE_NONE	0 | ||||||
|  | 
 | ||||||
|  | /* CSR Frequency Access Defines*/ | ||||||
|  | #define SXGBE_CSR_F_150M	150000000 | ||||||
|  | #define SXGBE_CSR_F_250M	250000000 | ||||||
|  | #define SXGBE_CSR_F_300M	300000000 | ||||||
|  | #define SXGBE_CSR_F_350M	350000000 | ||||||
|  | #define SXGBE_CSR_F_400M	400000000 | ||||||
|  | #define SXGBE_CSR_F_500M	500000000 | ||||||
|  | 
 | ||||||
|  | /* pause time */ | ||||||
|  | #define SXGBE_PAUSE_TIME 0x200 | ||||||
|  | 
 | ||||||
|  | /* tx queues */ | ||||||
|  | #define SXGBE_TX_QUEUES   8 | ||||||
|  | #define SXGBE_RX_QUEUES   16 | ||||||
|  | 
 | ||||||
|  | /* Calculated based how much time does it take to fill 256KB Rx memory
 | ||||||
|  |  * at 10Gb speed at 156MHz clock rate and considered little less then | ||||||
|  |  * the actual value. | ||||||
|  |  */ | ||||||
|  | #define SXGBE_MAX_DMA_RIWT	0x70 | ||||||
|  | #define SXGBE_MIN_DMA_RIWT	0x01 | ||||||
|  | 
 | ||||||
|  | /* Tx coalesce parameters */ | ||||||
|  | #define SXGBE_COAL_TX_TIMER	40000 | ||||||
|  | #define SXGBE_MAX_COAL_TX_TICK	100000 | ||||||
|  | #define SXGBE_TX_MAX_FRAMES	512 | ||||||
|  | #define SXGBE_TX_FRAMES	128 | ||||||
|  | 
 | ||||||
|  | /* SXGBE TX FIFO is 8K, Rx FIFO is 16K */ | ||||||
|  | #define BUF_SIZE_16KiB 16384 | ||||||
|  | #define BUF_SIZE_8KiB 8192 | ||||||
|  | #define BUF_SIZE_4KiB 4096 | ||||||
|  | #define BUF_SIZE_2KiB 2048 | ||||||
|  | 
 | ||||||
|  | #define SXGBE_DEFAULT_LIT_LS	0x3E8 | ||||||
|  | #define SXGBE_DEFAULT_TWT_LS	0x0 | ||||||
|  | 
 | ||||||
|  | /* Flow Control defines */ | ||||||
|  | #define SXGBE_FLOW_OFF		0 | ||||||
|  | #define SXGBE_FLOW_RX		1 | ||||||
|  | #define SXGBE_FLOW_TX		2 | ||||||
|  | #define SXGBE_FLOW_AUTO		(SXGBE_FLOW_TX | SXGBE_FLOW_RX) | ||||||
|  | 
 | ||||||
|  | #define SF_DMA_MODE 1		/* DMA STORE-AND-FORWARD Operation Mode */ | ||||||
|  | 
 | ||||||
|  | /* errors */ | ||||||
|  | #define RX_GMII_ERR		0x01 | ||||||
|  | #define RX_WATCHDOG_ERR		0x02 | ||||||
|  | #define RX_CRC_ERR		0x03 | ||||||
|  | #define RX_GAINT_ERR		0x04 | ||||||
|  | #define RX_IP_HDR_ERR		0x05 | ||||||
|  | #define RX_PAYLOAD_ERR		0x06 | ||||||
|  | #define RX_OVERFLOW_ERR		0x07 | ||||||
|  | 
 | ||||||
|  | /* pkt type */ | ||||||
|  | #define RX_LEN_PKT		0x00 | ||||||
|  | #define RX_MACCTL_PKT		0x01 | ||||||
|  | #define RX_DCBCTL_PKT		0x02 | ||||||
|  | #define RX_ARP_PKT		0x03 | ||||||
|  | #define RX_OAM_PKT		0x04 | ||||||
|  | #define RX_UNTAG_PKT		0x05 | ||||||
|  | #define RX_OTHER_PKT		0x07 | ||||||
|  | #define RX_SVLAN_PKT		0x08 | ||||||
|  | #define RX_CVLAN_PKT		0x09 | ||||||
|  | #define RX_DVLAN_OCVLAN_ICVLAN_PKT		0x0A | ||||||
|  | #define RX_DVLAN_OSVLAN_ISVLAN_PKT		0x0B | ||||||
|  | #define RX_DVLAN_OSVLAN_ICVLAN_PKT		0x0C | ||||||
|  | #define RX_DVLAN_OCVLAN_ISVLAN_PKT		0x0D | ||||||
|  | 
 | ||||||
|  | #define RX_NOT_IP_PKT		0x00 | ||||||
|  | #define RX_IPV4_TCP_PKT		0x01 | ||||||
|  | #define RX_IPV4_UDP_PKT		0x02 | ||||||
|  | #define RX_IPV4_ICMP_PKT	0x03 | ||||||
|  | #define RX_IPV4_UNKNOWN_PKT	0x07 | ||||||
|  | #define RX_IPV6_TCP_PKT		0x09 | ||||||
|  | #define RX_IPV6_UDP_PKT		0x0A | ||||||
|  | #define RX_IPV6_ICMP_PKT	0x0B | ||||||
|  | #define RX_IPV6_UNKNOWN_PKT	0x0F | ||||||
|  | 
 | ||||||
|  | #define RX_NO_PTP		0x00 | ||||||
|  | #define RX_PTP_SYNC		0x01 | ||||||
|  | #define RX_PTP_FOLLOW_UP	0x02 | ||||||
|  | #define RX_PTP_DELAY_REQ	0x03 | ||||||
|  | #define RX_PTP_DELAY_RESP	0x04 | ||||||
|  | #define RX_PTP_PDELAY_REQ	0x05 | ||||||
|  | #define RX_PTP_PDELAY_RESP	0x06 | ||||||
|  | #define RX_PTP_PDELAY_FOLLOW_UP	0x07 | ||||||
|  | #define RX_PTP_ANNOUNCE		0x08 | ||||||
|  | #define RX_PTP_MGMT		0x09 | ||||||
|  | #define RX_PTP_SIGNAL		0x0A | ||||||
|  | #define RX_PTP_RESV_MSG		0x0F | ||||||
|  | 
 | ||||||
|  | enum dma_irq_status { | ||||||
|  | 	tx_hard_error	= BIT(0), | ||||||
|  | 	tx_bump_tc	= BIT(1), | ||||||
|  | 	handle_tx	= BIT(2), | ||||||
|  | 	rx_hard_error	= BIT(3), | ||||||
|  | 	rx_bump_tc	= BIT(4), | ||||||
|  | 	handle_rx	= BIT(5), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define NETIF_F_HW_VLAN_ALL     (NETIF_F_HW_VLAN_CTAG_RX |	\ | ||||||
|  | 				 NETIF_F_HW_VLAN_STAG_RX |	\ | ||||||
|  | 				 NETIF_F_HW_VLAN_CTAG_TX |	\ | ||||||
|  | 				 NETIF_F_HW_VLAN_STAG_TX |	\ | ||||||
|  | 				 NETIF_F_HW_VLAN_CTAG_FILTER |	\ | ||||||
|  | 				 NETIF_F_HW_VLAN_STAG_FILTER) | ||||||
|  | 
 | ||||||
|  | /* MMC control defines */ | ||||||
|  | #define SXGBE_MMC_CTRL_CNT_FRZ  0x00000008 | ||||||
|  | 
 | ||||||
|  | /* SXGBE HW ADDR regs */ | ||||||
|  | #define SXGBE_ADDR_HIGH(reg)    (((reg > 15) ? 0x00000800 : 0x00000040) + \ | ||||||
|  | 				 (reg * 8)) | ||||||
|  | #define SXGBE_ADDR_LOW(reg)     (((reg > 15) ? 0x00000804 : 0x00000044) + \ | ||||||
|  | 				 (reg * 8)) | ||||||
|  | #define SXGBE_MAX_PERFECT_ADDRESSES 32 /* Maximum unicast perfect filtering */ | ||||||
|  | #define SXGBE_FRAME_FILTER       0x00000004      /* Frame Filter */ | ||||||
|  | 
 | ||||||
|  | /* SXGBE Frame Filter defines */ | ||||||
|  | #define SXGBE_FRAME_FILTER_PR    0x00000001      /* Promiscuous Mode */ | ||||||
|  | #define SXGBE_FRAME_FILTER_HUC   0x00000002      /* Hash Unicast */ | ||||||
|  | #define SXGBE_FRAME_FILTER_HMC   0x00000004      /* Hash Multicast */ | ||||||
|  | #define SXGBE_FRAME_FILTER_DAIF  0x00000008      /* DA Inverse Filtering */ | ||||||
|  | #define SXGBE_FRAME_FILTER_PM    0x00000010      /* Pass all multicast */ | ||||||
|  | #define SXGBE_FRAME_FILTER_DBF   0x00000020      /* Disable Broadcast frames */ | ||||||
|  | #define SXGBE_FRAME_FILTER_SAIF  0x00000100      /* Inverse Filtering */ | ||||||
|  | #define SXGBE_FRAME_FILTER_SAF   0x00000200      /* Source Address Filter */ | ||||||
|  | #define SXGBE_FRAME_FILTER_HPF   0x00000400      /* Hash or perfect Filter */ | ||||||
|  | #define SXGBE_FRAME_FILTER_RA    0x80000000      /* Receive all mode */ | ||||||
|  | 
 | ||||||
|  | #define SXGBE_HASH_TABLE_SIZE    64 | ||||||
|  | #define SXGBE_HASH_HIGH          0x00000008      /* Multicast Hash Table High */ | ||||||
|  | #define SXGBE_HASH_LOW           0x0000000c      /* Multicast Hash Table Low */ | ||||||
|  | 
 | ||||||
|  | #define SXGBE_HI_REG_AE          0x80000000 | ||||||
|  | 
 | ||||||
|  | /* Minimum and maximum MTU */ | ||||||
|  | #define MIN_MTU         68 | ||||||
|  | #define MAX_MTU         9000 | ||||||
|  | 
 | ||||||
|  | #define SXGBE_FOR_EACH_QUEUE(max_queues, queue_num)			\ | ||||||
|  | 	for (queue_num = 0; queue_num < max_queues; queue_num++) | ||||||
|  | 
 | ||||||
|  | /* sxgbe statistics counters */ | ||||||
|  | struct sxgbe_extra_stats { | ||||||
|  | 	/* TX/RX IRQ events */ | ||||||
|  | 	unsigned long tx_underflow_irq; | ||||||
|  | 	unsigned long tx_process_stopped_irq; | ||||||
|  | 	unsigned long tx_ctxt_desc_err; | ||||||
|  | 	unsigned long tx_threshold; | ||||||
|  | 	unsigned long rx_threshold; | ||||||
|  | 	unsigned long tx_pkt_n; | ||||||
|  | 	unsigned long rx_pkt_n; | ||||||
|  | 	unsigned long normal_irq_n; | ||||||
|  | 	unsigned long tx_normal_irq_n; | ||||||
|  | 	unsigned long rx_normal_irq_n; | ||||||
|  | 	unsigned long napi_poll; | ||||||
|  | 	unsigned long tx_clean; | ||||||
|  | 	unsigned long tx_reset_ic_bit; | ||||||
|  | 	unsigned long rx_process_stopped_irq; | ||||||
|  | 	unsigned long rx_underflow_irq; | ||||||
|  | 
 | ||||||
|  | 	/* Bus access errors */ | ||||||
|  | 	unsigned long fatal_bus_error_irq; | ||||||
|  | 	unsigned long tx_read_transfer_err; | ||||||
|  | 	unsigned long tx_write_transfer_err; | ||||||
|  | 	unsigned long tx_desc_access_err; | ||||||
|  | 	unsigned long tx_buffer_access_err; | ||||||
|  | 	unsigned long tx_data_transfer_err; | ||||||
|  | 	unsigned long rx_read_transfer_err; | ||||||
|  | 	unsigned long rx_write_transfer_err; | ||||||
|  | 	unsigned long rx_desc_access_err; | ||||||
|  | 	unsigned long rx_buffer_access_err; | ||||||
|  | 	unsigned long rx_data_transfer_err; | ||||||
|  | 
 | ||||||
|  | 	/* RX specific */ | ||||||
|  | 	/* L2 error */ | ||||||
|  | 	unsigned long rx_code_gmii_err; | ||||||
|  | 	unsigned long rx_watchdog_err; | ||||||
|  | 	unsigned long rx_crc_err; | ||||||
|  | 	unsigned long rx_gaint_pkt_err; | ||||||
|  | 	unsigned long ip_hdr_err; | ||||||
|  | 	unsigned long ip_payload_err; | ||||||
|  | 	unsigned long overflow_error; | ||||||
|  | 
 | ||||||
|  | 	/* L2 Pkt type */ | ||||||
|  | 	unsigned long len_pkt; | ||||||
|  | 	unsigned long mac_ctl_pkt; | ||||||
|  | 	unsigned long dcb_ctl_pkt; | ||||||
|  | 	unsigned long arp_pkt; | ||||||
|  | 	unsigned long oam_pkt; | ||||||
|  | 	unsigned long untag_okt; | ||||||
|  | 	unsigned long other_pkt; | ||||||
|  | 	unsigned long svlan_tag_pkt; | ||||||
|  | 	unsigned long cvlan_tag_pkt; | ||||||
|  | 	unsigned long dvlan_ocvlan_icvlan_pkt; | ||||||
|  | 	unsigned long dvlan_osvlan_isvlan_pkt; | ||||||
|  | 	unsigned long dvlan_osvlan_icvlan_pkt; | ||||||
|  | 	unsigned long dvan_ocvlan_icvlan_pkt; | ||||||
|  | 
 | ||||||
|  | 	/* L3/L4 Pkt type */ | ||||||
|  | 	unsigned long not_ip_pkt; | ||||||
|  | 	unsigned long ip4_tcp_pkt; | ||||||
|  | 	unsigned long ip4_udp_pkt; | ||||||
|  | 	unsigned long ip4_icmp_pkt; | ||||||
|  | 	unsigned long ip4_unknown_pkt; | ||||||
|  | 	unsigned long ip6_tcp_pkt; | ||||||
|  | 	unsigned long ip6_udp_pkt; | ||||||
|  | 	unsigned long ip6_icmp_pkt; | ||||||
|  | 	unsigned long ip6_unknown_pkt; | ||||||
|  | 
 | ||||||
|  | 	/* Filter specific */ | ||||||
|  | 	unsigned long vlan_filter_match; | ||||||
|  | 	unsigned long sa_filter_fail; | ||||||
|  | 	unsigned long da_filter_fail; | ||||||
|  | 	unsigned long hash_filter_pass; | ||||||
|  | 	unsigned long l3_filter_match; | ||||||
|  | 	unsigned long l4_filter_match; | ||||||
|  | 
 | ||||||
|  | 	/* RX context specific */ | ||||||
|  | 	unsigned long timestamp_dropped; | ||||||
|  | 	unsigned long rx_msg_type_no_ptp; | ||||||
|  | 	unsigned long rx_ptp_type_sync; | ||||||
|  | 	unsigned long rx_ptp_type_follow_up; | ||||||
|  | 	unsigned long rx_ptp_type_delay_req; | ||||||
|  | 	unsigned long rx_ptp_type_delay_resp; | ||||||
|  | 	unsigned long rx_ptp_type_pdelay_req; | ||||||
|  | 	unsigned long rx_ptp_type_pdelay_resp; | ||||||
|  | 	unsigned long rx_ptp_type_pdelay_follow_up; | ||||||
|  | 	unsigned long rx_ptp_announce; | ||||||
|  | 	unsigned long rx_ptp_mgmt; | ||||||
|  | 	unsigned long rx_ptp_signal; | ||||||
|  | 	unsigned long rx_ptp_resv_msg_type; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct mac_link { | ||||||
|  | 	int port; | ||||||
|  | 	int duplex; | ||||||
|  | 	int speed; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct mii_regs { | ||||||
|  | 	unsigned int addr;	/* MII Address */ | ||||||
|  | 	unsigned int data;	/* MII Data */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_core_ops { | ||||||
|  | 	/* MAC core initialization */ | ||||||
|  | 	void (*core_init)(void __iomem *ioaddr); | ||||||
|  | 	/* Dump MAC registers */ | ||||||
|  | 	void (*dump_regs)(void __iomem *ioaddr); | ||||||
|  | 	/* Handle extra events on specific interrupts hw dependent */ | ||||||
|  | 	int (*host_irq_status)(void __iomem *ioaddr, | ||||||
|  | 			       struct sxgbe_extra_stats *x); | ||||||
|  | 	/* Set power management mode (e.g. magic frame) */ | ||||||
|  | 	void (*pmt)(void __iomem *ioaddr, unsigned long mode); | ||||||
|  | 	/* Set/Get Unicast MAC addresses */ | ||||||
|  | 	void (*set_umac_addr)(void __iomem *ioaddr, unsigned char *addr, | ||||||
|  | 			      unsigned int reg_n); | ||||||
|  | 	void (*get_umac_addr)(void __iomem *ioaddr, unsigned char *addr, | ||||||
|  | 			      unsigned int reg_n); | ||||||
|  | 	void (*enable_rx)(void __iomem *ioaddr, bool enable); | ||||||
|  | 	void (*enable_tx)(void __iomem *ioaddr, bool enable); | ||||||
|  | 
 | ||||||
|  | 	/* controller version specific operations */ | ||||||
|  | 	int (*get_controller_version)(void __iomem *ioaddr); | ||||||
|  | 
 | ||||||
|  | 	/* If supported then get the optional core features */ | ||||||
|  | 	unsigned int (*get_hw_feature)(void __iomem *ioaddr, | ||||||
|  | 				       unsigned char feature_index); | ||||||
|  | 	/* adjust SXGBE speed */ | ||||||
|  | 	void (*set_speed)(void __iomem *ioaddr, unsigned char speed); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_core_ops *sxgbe_get_core_ops(void); | ||||||
|  | 
 | ||||||
|  | struct sxgbe_ops { | ||||||
|  | 	const struct sxgbe_core_ops *mac; | ||||||
|  | 	const struct sxgbe_desc_ops *desc; | ||||||
|  | 	const struct sxgbe_dma_ops *dma; | ||||||
|  | 	const struct sxgbe_mtl_ops *mtl; | ||||||
|  | 	struct mii_regs mii;	/* MII register Addresses */ | ||||||
|  | 	struct mac_link link; | ||||||
|  | 	unsigned int ctrl_uid; | ||||||
|  | 	unsigned int ctrl_id; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* SXGBE private data structures */ | ||||||
|  | struct sxgbe_tx_queue { | ||||||
|  | 	unsigned int irq_no; | ||||||
|  | 	struct sxgbe_priv_data *priv_ptr; | ||||||
|  | 	struct sxgbe_tx_norm_desc *dma_tx; | ||||||
|  | 	dma_addr_t dma_tx_phy; | ||||||
|  | 	dma_addr_t *tx_skbuff_dma; | ||||||
|  | 	struct sk_buff **tx_skbuff; | ||||||
|  | 	struct timer_list txtimer; | ||||||
|  | 	spinlock_t tx_lock;	/* lock for tx queues */ | ||||||
|  | 	unsigned int cur_tx; | ||||||
|  | 	unsigned int dirty_tx; | ||||||
|  | 	u32 tx_count_frames; | ||||||
|  | 	u32 tx_coal_frames; | ||||||
|  | 	u32 tx_coal_timer; | ||||||
|  | 	int hwts_tx_en; | ||||||
|  | 	u8 queue_no; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_rx_queue { | ||||||
|  | 	struct sxgbe_priv_data *priv_ptr; | ||||||
|  | 	struct sxgbe_rx_norm_desc *dma_rx; | ||||||
|  | 	struct sk_buff **rx_skbuff; | ||||||
|  | 	unsigned int cur_rx; | ||||||
|  | 	unsigned int dirty_rx; | ||||||
|  | 	unsigned int irq_no; | ||||||
|  | 	u32 rx_riwt; | ||||||
|  | 	dma_addr_t *rx_skbuff_dma; | ||||||
|  | 	dma_addr_t dma_rx_phy; | ||||||
|  | 	u8 queue_no; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* SXGBE HW capabilities */ | ||||||
|  | struct sxgbe_hw_features { | ||||||
|  | 	/****** CAP [0] *******/ | ||||||
|  | 	unsigned int pmt_remote_wake_up; | ||||||
|  | 	unsigned int pmt_magic_frame; | ||||||
|  | 	/* IEEE 1588-2008 */ | ||||||
|  | 	unsigned int atime_stamp; | ||||||
|  | 
 | ||||||
|  | 	unsigned int tx_csum_offload; | ||||||
|  | 	unsigned int rx_csum_offload; | ||||||
|  | 	unsigned int multi_macaddr; | ||||||
|  | 	unsigned int tstamp_srcselect; | ||||||
|  | 	unsigned int sa_vlan_insert; | ||||||
|  | 
 | ||||||
|  | 	/****** CAP [1] *******/ | ||||||
|  | 	unsigned int rxfifo_size; | ||||||
|  | 	unsigned int txfifo_size; | ||||||
|  | 	unsigned int atstmap_hword; | ||||||
|  | 	unsigned int dcb_enable; | ||||||
|  | 	unsigned int splithead_enable; | ||||||
|  | 	unsigned int tcpseg_offload; | ||||||
|  | 	unsigned int debug_mem; | ||||||
|  | 	unsigned int rss_enable; | ||||||
|  | 	unsigned int hash_tsize; | ||||||
|  | 	unsigned int l3l4_filer_size; | ||||||
|  | 
 | ||||||
|  | 	/* This value is in bytes and
 | ||||||
|  | 	 * as mentioned in HW features | ||||||
|  | 	 * of SXGBE data book | ||||||
|  | 	 */ | ||||||
|  | 	unsigned int rx_mtl_qsize; | ||||||
|  | 	unsigned int tx_mtl_qsize; | ||||||
|  | 
 | ||||||
|  | 	/****** CAP [2] *******/ | ||||||
|  | 	/* TX and RX number of channels */ | ||||||
|  | 	unsigned int rx_mtl_queues; | ||||||
|  | 	unsigned int tx_mtl_queues; | ||||||
|  | 	unsigned int rx_dma_channels; | ||||||
|  | 	unsigned int tx_dma_channels; | ||||||
|  | 	unsigned int pps_output_count; | ||||||
|  | 	unsigned int aux_input_count; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_priv_data { | ||||||
|  | 	/* DMA descriptos */ | ||||||
|  | 	struct sxgbe_tx_queue *txq[SXGBE_TX_QUEUES]; | ||||||
|  | 	struct sxgbe_rx_queue *rxq[SXGBE_RX_QUEUES]; | ||||||
|  | 	u8 cur_rx_qnum; | ||||||
|  | 
 | ||||||
|  | 	unsigned int dma_tx_size; | ||||||
|  | 	unsigned int dma_rx_size; | ||||||
|  | 	unsigned int dma_buf_sz; | ||||||
|  | 	u32 rx_riwt; | ||||||
|  | 
 | ||||||
|  | 	struct napi_struct napi; | ||||||
|  | 
 | ||||||
|  | 	void __iomem *ioaddr; | ||||||
|  | 	struct net_device *dev; | ||||||
|  | 	struct device *device; | ||||||
|  | 	struct sxgbe_ops *hw;	/* sxgbe specific ops */ | ||||||
|  | 	int no_csum_insertion; | ||||||
|  | 	int irq; | ||||||
|  | 	spinlock_t stats_lock;	/* lock for tx/rx statatics */ | ||||||
|  | 
 | ||||||
|  | 	struct phy_device *phydev; | ||||||
|  | 	int oldlink; | ||||||
|  | 	int speed; | ||||||
|  | 	int oldduplex; | ||||||
|  | 	struct mii_bus *mii; | ||||||
|  | 	int mii_irq[PHY_MAX_ADDR]; | ||||||
|  | 	u8 rx_pause; | ||||||
|  | 	u8 tx_pause; | ||||||
|  | 
 | ||||||
|  | 	struct sxgbe_extra_stats xstats; | ||||||
|  | 	struct sxgbe_plat_data *plat; | ||||||
|  | 	struct sxgbe_hw_features hw_cap; | ||||||
|  | 
 | ||||||
|  | 	u32 msg_enable; | ||||||
|  | 
 | ||||||
|  | 	struct clk *sxgbe_clk; | ||||||
|  | 	int clk_csr; | ||||||
|  | 	unsigned int mode; | ||||||
|  | 	unsigned int default_addend; | ||||||
|  | 
 | ||||||
|  | 	/* advanced time stamp support */ | ||||||
|  | 	u32 adv_ts; | ||||||
|  | 	int use_riwt; | ||||||
|  | 
 | ||||||
|  | 	/* tc control */ | ||||||
|  | 	int tx_tc; | ||||||
|  | 	int rx_tc; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* Function prototypes */ | ||||||
|  | struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, | ||||||
|  | 					struct sxgbe_plat_data *plat_dat, | ||||||
|  | 					void __iomem *addr); | ||||||
|  | int sxgbe_drv_remove(struct net_device *ndev); | ||||||
|  | void sxgbe_set_ethtool_ops(struct net_device *netdev); | ||||||
|  | int sxgbe_mdio_unregister(struct net_device *ndev); | ||||||
|  | int sxgbe_mdio_register(struct net_device *ndev); | ||||||
|  | int sxgbe_register_platform(void); | ||||||
|  | void sxgbe_unregister_platform(void); | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_PM | ||||||
|  | int sxgbe_suspend(struct net_device *ndev); | ||||||
|  | int sxgbe_resume(struct net_device *ndev); | ||||||
|  | int sxgbe_freeze(struct net_device *ndev); | ||||||
|  | int sxgbe_restore(struct net_device *ndev); | ||||||
|  | #endif /* CONFIG_PM */ | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void); | ||||||
|  | 
 | ||||||
|  | #endif /* __SXGBE_COMMON_H__ */ | ||||||
							
								
								
									
										158
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,158 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||||||
|  | 
 | ||||||
|  | #include <linux/export.h> | ||||||
|  | #include <linux/io.h> | ||||||
|  | #include <linux/netdevice.h> | ||||||
|  | #include <linux/phy.h> | ||||||
|  | 
 | ||||||
|  | #include "sxgbe_common.h" | ||||||
|  | #include "sxgbe_reg.h" | ||||||
|  | 
 | ||||||
|  | /* MAC core initialization */ | ||||||
|  | static void sxgbe_core_init(void __iomem *ioaddr) | ||||||
|  | { | ||||||
|  | 	u32 regval; | ||||||
|  | 
 | ||||||
|  | 	/* TX configuration */ | ||||||
|  | 	regval = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||||||
|  | 	/* Other configurable parameters IFP, IPG, ISR, ISM
 | ||||||
|  | 	 * needs to be set if needed | ||||||
|  | 	 */ | ||||||
|  | 	regval |= SXGBE_TX_JABBER_DISABLE; | ||||||
|  | 	writel(regval, ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||||||
|  | 
 | ||||||
|  | 	/* RX configuration */ | ||||||
|  | 	regval = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||||||
|  | 	/* Other configurable parameters CST, SPEN, USP, GPSLCE
 | ||||||
|  | 	 * WD, LM, S2KP, HDSMS, GPSL, ELEN, ARPEN needs to be | ||||||
|  | 	 * set if needed | ||||||
|  | 	 */ | ||||||
|  | 	regval |= SXGBE_RX_JUMBPKT_ENABLE | SXGBE_RX_ACS_ENABLE; | ||||||
|  | 	writel(regval, ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Dump MAC registers */ | ||||||
|  | static void sxgbe_core_dump_regs(void __iomem *ioaddr) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Handle extra events on specific interrupts hw dependent */ | ||||||
|  | static int sxgbe_core_host_irq_status(void __iomem *ioaddr, | ||||||
|  | 				      struct sxgbe_extra_stats *x) | ||||||
|  | { | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set power management mode (e.g. magic frame) */ | ||||||
|  | static void sxgbe_core_pmt(void __iomem *ioaddr, unsigned long mode) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set/Get Unicast MAC addresses */ | ||||||
|  | static void sxgbe_core_set_umac_addr(void __iomem *ioaddr, unsigned char *addr, | ||||||
|  | 				     unsigned int reg_n) | ||||||
|  | { | ||||||
|  | 	u32 high_word, low_word; | ||||||
|  | 
 | ||||||
|  | 	high_word = (addr[5] << 8) || (addr[4]); | ||||||
|  | 	low_word = ((addr[3] << 24) || (addr[2] << 16) || | ||||||
|  | 		    (addr[1] << 8) || (addr[0])); | ||||||
|  | 	writel(high_word, ioaddr + SXGBE_CORE_ADD_HIGHOFFSET(reg_n)); | ||||||
|  | 	writel(low_word, ioaddr + SXGBE_CORE_ADD_LOWOFFSET(reg_n)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_core_get_umac_addr(void __iomem *ioaddr, unsigned char *addr, | ||||||
|  | 				     unsigned int reg_n) | ||||||
|  | { | ||||||
|  | 	u32 high_word, low_word; | ||||||
|  | 
 | ||||||
|  | 	high_word = readl(ioaddr + SXGBE_CORE_ADD_HIGHOFFSET(reg_n)); | ||||||
|  | 	low_word = readl(ioaddr + SXGBE_CORE_ADD_LOWOFFSET(reg_n)); | ||||||
|  | 
 | ||||||
|  | 	/* extract and assign address */ | ||||||
|  | 	addr[5] = (high_word & 0x0000FF00) >> 8; | ||||||
|  | 	addr[4] = (high_word & 0x000000FF); | ||||||
|  | 	addr[3] = (low_word & 0xFF000000) >> 24; | ||||||
|  | 	addr[2] = (low_word & 0x00FF0000) >> 16; | ||||||
|  | 	addr[1] = (low_word & 0x0000FF00) >> 8; | ||||||
|  | 	addr[0] = (low_word & 0x000000FF); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_enable_tx(void __iomem *ioaddr, bool enable) | ||||||
|  | { | ||||||
|  | 	u32 tx_config; | ||||||
|  | 
 | ||||||
|  | 	tx_config = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||||||
|  | 	tx_config &= ~SXGBE_TX_ENABLE; | ||||||
|  | 
 | ||||||
|  | 	if (enable) | ||||||
|  | 		tx_config |= SXGBE_TX_ENABLE; | ||||||
|  | 	writel(tx_config, ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_enable_rx(void __iomem *ioaddr, bool enable) | ||||||
|  | { | ||||||
|  | 	u32 rx_config; | ||||||
|  | 
 | ||||||
|  | 	rx_config = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||||||
|  | 	rx_config &= ~SXGBE_RX_ENABLE; | ||||||
|  | 
 | ||||||
|  | 	if (enable) | ||||||
|  | 		rx_config |= SXGBE_RX_ENABLE; | ||||||
|  | 	writel(rx_config, ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sxgbe_get_controller_version(void __iomem *ioaddr) | ||||||
|  | { | ||||||
|  | 	return readl(ioaddr + SXGBE_CORE_VERSION_REG); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* If supported then get the optional core features */ | ||||||
|  | static unsigned int sxgbe_get_hw_feature(void __iomem *ioaddr, | ||||||
|  | 					 unsigned char feature_index) | ||||||
|  | { | ||||||
|  | 	return readl(ioaddr + (SXGBE_CORE_HW_FEA_REG(feature_index))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_core_set_speed(void __iomem *ioaddr, unsigned char speed) | ||||||
|  | { | ||||||
|  | 	u32 tx_cfg = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||||||
|  | 
 | ||||||
|  | 	/* clear the speed bits */ | ||||||
|  | 	tx_cfg &= ~0x60000000; | ||||||
|  | 	tx_cfg |= (speed << SXGBE_SPEED_LSHIFT); | ||||||
|  | 
 | ||||||
|  | 	/* set the speed */ | ||||||
|  | 	writel(tx_cfg, ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_core_ops core_ops = { | ||||||
|  | 	.core_init		= sxgbe_core_init, | ||||||
|  | 	.dump_regs		= sxgbe_core_dump_regs, | ||||||
|  | 	.host_irq_status	= sxgbe_core_host_irq_status, | ||||||
|  | 	.pmt			= sxgbe_core_pmt, | ||||||
|  | 	.set_umac_addr		= sxgbe_core_set_umac_addr, | ||||||
|  | 	.get_umac_addr		= sxgbe_core_get_umac_addr, | ||||||
|  | 	.enable_rx		= sxgbe_enable_rx, | ||||||
|  | 	.enable_tx		= sxgbe_enable_tx, | ||||||
|  | 	.get_controller_version	= sxgbe_get_controller_version, | ||||||
|  | 	.get_hw_feature		= sxgbe_get_hw_feature, | ||||||
|  | 	.set_speed		= sxgbe_core_set_speed, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_core_ops *sxgbe_get_core_ops(void) | ||||||
|  | { | ||||||
|  | 	return &core_ops; | ||||||
|  | } | ||||||
							
								
								
									
										515
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										515
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,515 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||||||
|  | 
 | ||||||
|  | #include <linux/bitops.h> | ||||||
|  | #include <linux/export.h> | ||||||
|  | #include <linux/io.h> | ||||||
|  | #include <linux/netdevice.h> | ||||||
|  | #include <linux/phy.h> | ||||||
|  | 
 | ||||||
|  | #include "sxgbe_common.h" | ||||||
|  | #include "sxgbe_dma.h" | ||||||
|  | #include "sxgbe_desc.h" | ||||||
|  | 
 | ||||||
|  | /* DMA TX descriptor ring initialization */ | ||||||
|  | static void sxgbe_init_tx_desc(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	p->tdes23.tx_rd_des23.own_bit = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_tx_desc_enable_tse(struct sxgbe_tx_norm_desc *p, u8 is_tse, | ||||||
|  | 				     u32 total_hdr_len, u32 tcp_hdr_len, | ||||||
|  | 				     u32 tcp_payload_len) | ||||||
|  | { | ||||||
|  | 	p->tdes23.tx_rd_des23.tse_bit = is_tse; | ||||||
|  | 	p->tdes23.tx_rd_des23.buf1_size = total_hdr_len; | ||||||
|  | 	p->tdes23.tx_rd_des23.tcp_hdr_len = tcp_hdr_len / 4; | ||||||
|  | 	p->tdes23.tx_rd_des23.tx_pkt_len.tcp_payload_len  = tcp_payload_len; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Assign buffer lengths for descriptor */ | ||||||
|  | static void sxgbe_prepare_tx_desc(struct sxgbe_tx_norm_desc *p, u8 is_fd, | ||||||
|  | 				  int buf1_len, int pkt_len, int cksum) | ||||||
|  | { | ||||||
|  | 	p->tdes23.tx_rd_des23.first_desc = is_fd; | ||||||
|  | 	p->tdes23.tx_rd_des23.buf1_size = buf1_len; | ||||||
|  | 
 | ||||||
|  | 	p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.total_pkt_len = pkt_len; | ||||||
|  | 
 | ||||||
|  | 	if (cksum) | ||||||
|  | 		p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.cksum_ctl = cic_full; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set VLAN control information */ | ||||||
|  | static void sxgbe_tx_vlanctl_desc(struct sxgbe_tx_norm_desc *p, int vlan_ctl) | ||||||
|  | { | ||||||
|  | 	p->tdes23.tx_rd_des23.vlan_tag_ctl = vlan_ctl; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set the owner of Normal descriptor */ | ||||||
|  | static void sxgbe_set_tx_owner(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	p->tdes23.tx_rd_des23.own_bit = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Get the owner of Normal descriptor */ | ||||||
|  | static int sxgbe_get_tx_owner(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->tdes23.tx_rd_des23.own_bit; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Invoked by the xmit function to close the tx descriptor */ | ||||||
|  | static void sxgbe_close_tx_desc(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	p->tdes23.tx_rd_des23.last_desc = 1; | ||||||
|  | 	p->tdes23.tx_rd_des23.int_on_com = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Clean the tx descriptor as soon as the tx irq is received */ | ||||||
|  | static void sxgbe_release_tx_desc(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	memset(p, 0, sizeof(*p)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Clear interrupt on tx frame completion. When this bit is
 | ||||||
|  |  * set an interrupt happens as soon as the frame is transmitted | ||||||
|  |  */ | ||||||
|  | static void sxgbe_clear_tx_ic(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	p->tdes23.tx_rd_des23.int_on_com = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Last tx segment reports the transmit status */ | ||||||
|  | static int sxgbe_get_tx_ls(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->tdes23.tx_rd_des23.last_desc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Get the buffer size from the descriptor */ | ||||||
|  | static int sxgbe_get_tx_len(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->tdes23.tx_rd_des23.buf1_size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set tx timestamp enable bit */ | ||||||
|  | static void sxgbe_tx_enable_tstamp(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	p->tdes23.tx_rd_des23.timestmp_enable = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* get tx timestamp status */ | ||||||
|  | static int sxgbe_get_tx_timestamp_status(struct sxgbe_tx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->tdes23.tx_rd_des23.timestmp_enable; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* TX Context Descripto Specific */ | ||||||
|  | static void sxgbe_tx_ctxt_desc_set_ctxt(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	p->ctxt_bit = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set the owner of TX context descriptor */ | ||||||
|  | static void sxgbe_tx_ctxt_desc_set_owner(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	p->own_bit = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Get the owner of TX context descriptor */ | ||||||
|  | static int sxgbe_tx_ctxt_desc_get_owner(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->own_bit; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set TX mss in TX context Descriptor */ | ||||||
|  | static void sxgbe_tx_ctxt_desc_set_mss(struct sxgbe_tx_ctxt_desc *p, int mss) | ||||||
|  | { | ||||||
|  | 	p->maxseg_size = mss; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Get TX mss from TX context Descriptor */ | ||||||
|  | static int sxgbe_tx_ctxt_desc_get_mss(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->maxseg_size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set TX tcmssv in TX context Descriptor */ | ||||||
|  | static void sxgbe_tx_ctxt_desc_set_tcmssv(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	p->tcmssv = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Reset TX ostc in TX context Descriptor */ | ||||||
|  | static void sxgbe_tx_ctxt_desc_reset_ostc(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	p->ostc = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set IVLAN information */ | ||||||
|  | static void sxgbe_tx_ctxt_desc_set_ivlantag(struct sxgbe_tx_ctxt_desc *p, | ||||||
|  | 					    int is_ivlanvalid, int ivlan_tag, | ||||||
|  | 					    int ivlan_ctl) | ||||||
|  | { | ||||||
|  | 	if (is_ivlanvalid) { | ||||||
|  | 		p->ivlan_tag_valid = is_ivlanvalid; | ||||||
|  | 		p->ivlan_tag = ivlan_tag; | ||||||
|  | 		p->ivlan_tag_ctl = ivlan_ctl; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Return IVLAN Tag */ | ||||||
|  | static int sxgbe_tx_ctxt_desc_get_ivlantag(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->ivlan_tag; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set VLAN Tag */ | ||||||
|  | static void sxgbe_tx_ctxt_desc_set_vlantag(struct sxgbe_tx_ctxt_desc *p, | ||||||
|  | 					   int is_vlanvalid, int vlan_tag) | ||||||
|  | { | ||||||
|  | 	if (is_vlanvalid) { | ||||||
|  | 		p->vltag_valid = is_vlanvalid; | ||||||
|  | 		p->vlan_tag = vlan_tag; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Return VLAN Tag */ | ||||||
|  | static int sxgbe_tx_ctxt_desc_get_vlantag(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->vlan_tag; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set Time stamp */ | ||||||
|  | static void sxgbe_tx_ctxt_desc_set_tstamp(struct sxgbe_tx_ctxt_desc *p, | ||||||
|  | 					  u8 ostc_enable, u64 tstamp) | ||||||
|  | { | ||||||
|  | 	if (ostc_enable) { | ||||||
|  | 		p->ostc = ostc_enable; | ||||||
|  | 		p->tstamp_lo = (u32) tstamp; | ||||||
|  | 		p->tstamp_hi = (u32) (tstamp>>32); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | /* Close TX context descriptor */ | ||||||
|  | static void sxgbe_tx_ctxt_desc_close(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	p->own_bit = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* WB status of context descriptor */ | ||||||
|  | static int sxgbe_tx_ctxt_desc_get_cde(struct sxgbe_tx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->ctxt_desc_err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* DMA RX descriptor ring initialization */ | ||||||
|  | static void sxgbe_init_rx_desc(struct sxgbe_rx_norm_desc *p, int disable_rx_ic, | ||||||
|  | 			       int mode, int end) | ||||||
|  | { | ||||||
|  | 	p->rdes23.rx_rd_des23.own_bit = 1; | ||||||
|  | 	if (disable_rx_ic) | ||||||
|  | 		p->rdes23.rx_rd_des23.int_on_com = disable_rx_ic; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Get RX own bit */ | ||||||
|  | static int sxgbe_get_rx_owner(struct sxgbe_rx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->rdes23.rx_rd_des23.own_bit; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set RX own bit */ | ||||||
|  | static void sxgbe_set_rx_owner(struct sxgbe_rx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	p->rdes23.rx_rd_des23.own_bit = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Get the receive frame size */ | ||||||
|  | static int sxgbe_get_rx_frame_len(struct sxgbe_rx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->rdes23.rx_wb_des23.pkt_len; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Return first Descriptor status */ | ||||||
|  | static int sxgbe_get_rx_fd_status(struct sxgbe_rx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->rdes23.rx_wb_des23.first_desc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Return Last Descriptor status */ | ||||||
|  | static int sxgbe_get_rx_ld_status(struct sxgbe_rx_norm_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->rdes23.rx_wb_des23.last_desc; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Return the RX status looking at the WB fields */ | ||||||
|  | static int sxgbe_rx_wbstatus(struct sxgbe_rx_norm_desc *p, | ||||||
|  | 			     struct sxgbe_extra_stats *x, int *checksum) | ||||||
|  | { | ||||||
|  | 	int status = 0; | ||||||
|  | 
 | ||||||
|  | 	*checksum = CHECKSUM_UNNECESSARY; | ||||||
|  | 	if (p->rdes23.rx_wb_des23.err_summary) { | ||||||
|  | 		switch (p->rdes23.rx_wb_des23.err_l2_type) { | ||||||
|  | 		case RX_GMII_ERR: | ||||||
|  | 			status = -EINVAL; | ||||||
|  | 			x->rx_code_gmii_err++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_WATCHDOG_ERR: | ||||||
|  | 			status = -EINVAL; | ||||||
|  | 			x->rx_watchdog_err++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_CRC_ERR: | ||||||
|  | 			status = -EINVAL; | ||||||
|  | 			x->rx_crc_err++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_GAINT_ERR: | ||||||
|  | 			status = -EINVAL; | ||||||
|  | 			x->rx_gaint_pkt_err++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_IP_HDR_ERR: | ||||||
|  | 			*checksum = CHECKSUM_NONE; | ||||||
|  | 			x->ip_hdr_err++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_PAYLOAD_ERR: | ||||||
|  | 			*checksum = CHECKSUM_NONE; | ||||||
|  | 			x->ip_payload_err++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_OVERFLOW_ERR: | ||||||
|  | 			status = -EINVAL; | ||||||
|  | 			x->overflow_error++; | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			pr_err("Invalid Error type\n"); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		switch (p->rdes23.rx_wb_des23.err_l2_type) { | ||||||
|  | 		case RX_LEN_PKT: | ||||||
|  | 			x->len_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_MACCTL_PKT: | ||||||
|  | 			x->mac_ctl_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_DCBCTL_PKT: | ||||||
|  | 			x->dcb_ctl_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_ARP_PKT: | ||||||
|  | 			x->arp_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_OAM_PKT: | ||||||
|  | 			x->oam_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_UNTAG_PKT: | ||||||
|  | 			x->untag_okt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_OTHER_PKT: | ||||||
|  | 			x->other_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_SVLAN_PKT: | ||||||
|  | 			x->svlan_tag_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_CVLAN_PKT: | ||||||
|  | 			x->cvlan_tag_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_DVLAN_OCVLAN_ICVLAN_PKT: | ||||||
|  | 			x->dvlan_ocvlan_icvlan_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_DVLAN_OSVLAN_ISVLAN_PKT: | ||||||
|  | 			x->dvlan_osvlan_isvlan_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_DVLAN_OSVLAN_ICVLAN_PKT: | ||||||
|  | 			x->dvlan_osvlan_icvlan_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		case RX_DVLAN_OCVLAN_ISVLAN_PKT: | ||||||
|  | 			x->dvlan_ocvlan_icvlan_pkt++; | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			pr_err("Invalid L2 Packet type\n"); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* L3/L4 Pkt type */ | ||||||
|  | 	switch (p->rdes23.rx_wb_des23.layer34_pkt_type) { | ||||||
|  | 	case RX_NOT_IP_PKT: | ||||||
|  | 		x->not_ip_pkt++; | ||||||
|  | 		break; | ||||||
|  | 	case RX_IPV4_TCP_PKT: | ||||||
|  | 		x->ip4_tcp_pkt++; | ||||||
|  | 		break; | ||||||
|  | 	case RX_IPV4_UDP_PKT: | ||||||
|  | 		x->ip4_udp_pkt++; | ||||||
|  | 		break; | ||||||
|  | 	case RX_IPV4_ICMP_PKT: | ||||||
|  | 		x->ip4_icmp_pkt++; | ||||||
|  | 		break; | ||||||
|  | 	case RX_IPV4_UNKNOWN_PKT: | ||||||
|  | 		x->ip4_unknown_pkt++; | ||||||
|  | 		break; | ||||||
|  | 	case RX_IPV6_TCP_PKT: | ||||||
|  | 		x->ip6_tcp_pkt++; | ||||||
|  | 		break; | ||||||
|  | 	case RX_IPV6_UDP_PKT: | ||||||
|  | 		x->ip6_udp_pkt++; | ||||||
|  | 		break; | ||||||
|  | 	case RX_IPV6_ICMP_PKT: | ||||||
|  | 		x->ip6_icmp_pkt++; | ||||||
|  | 		break; | ||||||
|  | 	case RX_IPV6_UNKNOWN_PKT: | ||||||
|  | 		x->ip6_unknown_pkt++; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		pr_err("Invalid L3/L4 Packet type\n"); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Filter */ | ||||||
|  | 	if (p->rdes23.rx_wb_des23.vlan_filter_match) | ||||||
|  | 		x->vlan_filter_match++; | ||||||
|  | 
 | ||||||
|  | 	if (p->rdes23.rx_wb_des23.sa_filter_fail) { | ||||||
|  | 		status = -EINVAL; | ||||||
|  | 		x->sa_filter_fail++; | ||||||
|  | 	} | ||||||
|  | 	if (p->rdes23.rx_wb_des23.da_filter_fail) { | ||||||
|  | 		status = -EINVAL; | ||||||
|  | 		x->da_filter_fail++; | ||||||
|  | 	} | ||||||
|  | 	if (p->rdes23.rx_wb_des23.hash_filter_pass) | ||||||
|  | 		x->hash_filter_pass++; | ||||||
|  | 
 | ||||||
|  | 	if (p->rdes23.rx_wb_des23.l3_filter_match) | ||||||
|  | 		x->l3_filter_match++; | ||||||
|  | 
 | ||||||
|  | 	if (p->rdes23.rx_wb_des23.l4_filter_match) | ||||||
|  | 		x->l4_filter_match++; | ||||||
|  | 
 | ||||||
|  | 	return status; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Get own bit of context descriptor */ | ||||||
|  | static int sxgbe_get_rx_ctxt_owner(struct sxgbe_rx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	return p->own_bit; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Set own bit for context descriptor */ | ||||||
|  | static void sxgbe_set_ctxt_rx_owner(struct sxgbe_rx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	p->own_bit = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* Return the reception status looking at Context control information */ | ||||||
|  | static void sxgbe_rx_ctxt_wbstatus(struct sxgbe_rx_ctxt_desc *p, | ||||||
|  | 				   struct sxgbe_extra_stats *x) | ||||||
|  | { | ||||||
|  | 	if (p->tstamp_dropped) | ||||||
|  | 		x->timestamp_dropped++; | ||||||
|  | 
 | ||||||
|  | 	/* ptp */ | ||||||
|  | 	if (p->ptp_msgtype == RX_NO_PTP) | ||||||
|  | 		x->rx_msg_type_no_ptp++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_SYNC) | ||||||
|  | 		x->rx_ptp_type_sync++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_FOLLOW_UP) | ||||||
|  | 		x->rx_ptp_type_follow_up++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_DELAY_REQ) | ||||||
|  | 		x->rx_ptp_type_delay_req++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_DELAY_RESP) | ||||||
|  | 		x->rx_ptp_type_delay_resp++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_PDELAY_REQ) | ||||||
|  | 		x->rx_ptp_type_pdelay_req++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_PDELAY_RESP) | ||||||
|  | 		x->rx_ptp_type_pdelay_resp++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_PDELAY_FOLLOW_UP) | ||||||
|  | 		x->rx_ptp_type_pdelay_follow_up++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_ANNOUNCE) | ||||||
|  | 		x->rx_ptp_announce++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_MGMT) | ||||||
|  | 		x->rx_ptp_mgmt++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_SIGNAL) | ||||||
|  | 		x->rx_ptp_signal++; | ||||||
|  | 	else if (p->ptp_msgtype == RX_PTP_RESV_MSG) | ||||||
|  | 		x->rx_ptp_resv_msg_type++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Get rx timestamp status */ | ||||||
|  | static int sxgbe_get_rx_ctxt_tstamp_status(struct sxgbe_rx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	if ((p->tstamp_hi == 0xffffffff) && (p->tstamp_lo == 0xffffffff)) { | ||||||
|  | 		pr_err("Time stamp corrupted\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return p->tstamp_available; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static u64 sxgbe_get_rx_timestamp(struct sxgbe_rx_ctxt_desc *p) | ||||||
|  | { | ||||||
|  | 	u64 ns; | ||||||
|  | 
 | ||||||
|  | 	ns = p->tstamp_lo; | ||||||
|  | 	ns |= ((u64)p->tstamp_hi) << 32; | ||||||
|  | 
 | ||||||
|  | 	return ns; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct sxgbe_desc_ops desc_ops = { | ||||||
|  | 	.init_tx_desc			= sxgbe_init_tx_desc, | ||||||
|  | 	.tx_desc_enable_tse		= sxgbe_tx_desc_enable_tse, | ||||||
|  | 	.prepare_tx_desc		= sxgbe_prepare_tx_desc, | ||||||
|  | 	.tx_vlanctl_desc		= sxgbe_tx_vlanctl_desc, | ||||||
|  | 	.set_tx_owner			= sxgbe_set_tx_owner, | ||||||
|  | 	.get_tx_owner			= sxgbe_get_tx_owner, | ||||||
|  | 	.close_tx_desc			= sxgbe_close_tx_desc, | ||||||
|  | 	.release_tx_desc		= sxgbe_release_tx_desc, | ||||||
|  | 	.clear_tx_ic			= sxgbe_clear_tx_ic, | ||||||
|  | 	.get_tx_ls			= sxgbe_get_tx_ls, | ||||||
|  | 	.get_tx_len			= sxgbe_get_tx_len, | ||||||
|  | 	.tx_enable_tstamp		= sxgbe_tx_enable_tstamp, | ||||||
|  | 	.get_tx_timestamp_status	= sxgbe_get_tx_timestamp_status, | ||||||
|  | 	.tx_ctxt_desc_set_ctxt		= sxgbe_tx_ctxt_desc_set_ctxt, | ||||||
|  | 	.tx_ctxt_desc_set_owner		= sxgbe_tx_ctxt_desc_set_owner, | ||||||
|  | 	.get_tx_ctxt_owner		= sxgbe_tx_ctxt_desc_get_owner, | ||||||
|  | 	.tx_ctxt_desc_set_mss		= sxgbe_tx_ctxt_desc_set_mss, | ||||||
|  | 	.tx_ctxt_desc_get_mss		= sxgbe_tx_ctxt_desc_get_mss, | ||||||
|  | 	.tx_ctxt_desc_set_tcmssv	= sxgbe_tx_ctxt_desc_set_tcmssv, | ||||||
|  | 	.tx_ctxt_desc_reset_ostc	= sxgbe_tx_ctxt_desc_reset_ostc, | ||||||
|  | 	.tx_ctxt_desc_set_ivlantag	= sxgbe_tx_ctxt_desc_set_ivlantag, | ||||||
|  | 	.tx_ctxt_desc_get_ivlantag	= sxgbe_tx_ctxt_desc_get_ivlantag, | ||||||
|  | 	.tx_ctxt_desc_set_vlantag	= sxgbe_tx_ctxt_desc_set_vlantag, | ||||||
|  | 	.tx_ctxt_desc_get_vlantag	= sxgbe_tx_ctxt_desc_get_vlantag, | ||||||
|  | 	.tx_ctxt_set_tstamp		= sxgbe_tx_ctxt_desc_set_tstamp, | ||||||
|  | 	.close_tx_ctxt_desc		= sxgbe_tx_ctxt_desc_close, | ||||||
|  | 	.get_tx_ctxt_cde		= sxgbe_tx_ctxt_desc_get_cde, | ||||||
|  | 	.init_rx_desc			= sxgbe_init_rx_desc, | ||||||
|  | 	.get_rx_owner			= sxgbe_get_rx_owner, | ||||||
|  | 	.set_rx_owner			= sxgbe_set_rx_owner, | ||||||
|  | 	.get_rx_frame_len		= sxgbe_get_rx_frame_len, | ||||||
|  | 	.get_rx_fd_status		= sxgbe_get_rx_fd_status, | ||||||
|  | 	.get_rx_ld_status		= sxgbe_get_rx_ld_status, | ||||||
|  | 	.rx_wbstatus			= sxgbe_rx_wbstatus, | ||||||
|  | 	.get_rx_ctxt_owner		= sxgbe_get_rx_ctxt_owner, | ||||||
|  | 	.set_rx_ctxt_owner		= sxgbe_set_ctxt_rx_owner, | ||||||
|  | 	.rx_ctxt_wbstatus		= sxgbe_rx_ctxt_wbstatus, | ||||||
|  | 	.get_rx_ctxt_tstamp_status	= sxgbe_get_rx_ctxt_tstamp_status, | ||||||
|  | 	.get_timestamp			= sxgbe_get_rx_timestamp, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_desc_ops *sxgbe_get_desc_ops(void) | ||||||
|  | { | ||||||
|  | 	return &desc_ops; | ||||||
|  | } | ||||||
							
								
								
									
										298
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,298 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #ifndef __SXGBE_DESC_H__ | ||||||
|  | #define __SXGBE_DESC_H__ | ||||||
|  | 
 | ||||||
|  | #define SXGBE_DESC_SIZE_BYTES	16 | ||||||
|  | 
 | ||||||
|  | /* forward declaration */ | ||||||
|  | struct sxgbe_extra_stats; | ||||||
|  | 
 | ||||||
|  | /* Transmit checksum insertion control */ | ||||||
|  | enum tdes_csum_insertion { | ||||||
|  | 	cic_disabled		= 0,	/* Checksum Insertion Control */ | ||||||
|  | 	cic_only_ip		= 1,	/* Only IP header */ | ||||||
|  | 	/* IP header but pseudoheader is not calculated */ | ||||||
|  | 	cic_no_pseudoheader	= 2, | ||||||
|  | 	cic_full		= 3,	/* IP header and pseudoheader */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_tx_norm_desc { | ||||||
|  | 	u64 tdes01; /* buf1 address */ | ||||||
|  | 	union { | ||||||
|  | 		/* TX Read-Format Desc 2,3 */ | ||||||
|  | 		struct { | ||||||
|  | 			/* TDES2 */ | ||||||
|  | 			u32 buf1_size:14; | ||||||
|  | 			u32 vlan_tag_ctl:2; | ||||||
|  | 			u32 buf2_size:14; | ||||||
|  | 			u32 timestmp_enable:1; | ||||||
|  | 			u32 int_on_com:1; | ||||||
|  | 			/* TDES3 */ | ||||||
|  | 			union { | ||||||
|  | 				u32 tcp_payload_len:18; | ||||||
|  | 				struct { | ||||||
|  | 					u32 total_pkt_len:15; | ||||||
|  | 					u32 reserved1:1; | ||||||
|  | 					u32 cksum_ctl:2; | ||||||
|  | 				} cksum_pktlen; | ||||||
|  | 			} tx_pkt_len; | ||||||
|  | 
 | ||||||
|  | 			u32 tse_bit:1; | ||||||
|  | 			u32 tcp_hdr_len:4; | ||||||
|  | 			u32 sa_insert_ctl:3; | ||||||
|  | 			u32 crc_pad_ctl:2; | ||||||
|  | 			u32 last_desc:1; | ||||||
|  | 			u32 first_desc:1; | ||||||
|  | 			u32 ctxt_bit:1; | ||||||
|  | 			u32 own_bit:1; | ||||||
|  | 		} tx_rd_des23; | ||||||
|  | 
 | ||||||
|  | 		/* tx write back Desc 2,3 */ | ||||||
|  | 		struct { | ||||||
|  | 			/* WB TES2 */ | ||||||
|  | 			u32 reserved1; | ||||||
|  | 			/* WB TES3 */ | ||||||
|  | 			u32 reserved2:31; | ||||||
|  | 			u32 own_bit:1; | ||||||
|  | 		} tx_wb_des23; | ||||||
|  | 	} tdes23; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_rx_norm_desc { | ||||||
|  | 	union { | ||||||
|  | 		u32 rdes0; /* buf1 address */ | ||||||
|  | 		struct { | ||||||
|  | 			u32 out_vlan_tag:16; | ||||||
|  | 			u32 in_vlan_tag:16; | ||||||
|  | 		} wb_rx_des0; | ||||||
|  | 	} rd_wb_des0; | ||||||
|  | 
 | ||||||
|  | 	union { | ||||||
|  | 		u32 rdes1;	/* buf2 address or buf1[63:32] */ | ||||||
|  | 		u32 rss_hash;	/* Write-back RX */ | ||||||
|  | 	} rd_wb_des1; | ||||||
|  | 
 | ||||||
|  | 	union { | ||||||
|  | 		/* RX Read format Desc 2,3 */ | ||||||
|  | 		struct{ | ||||||
|  | 			/* RDES2 */ | ||||||
|  | 			u32 buf2_addr; | ||||||
|  | 			/* RDES3 */ | ||||||
|  | 			u32 buf2_hi_addr:30; | ||||||
|  | 			u32 int_on_com:1; | ||||||
|  | 			u32 own_bit:1; | ||||||
|  | 		} rx_rd_des23; | ||||||
|  | 
 | ||||||
|  | 		/* RX write back */ | ||||||
|  | 		struct{ | ||||||
|  | 			/* WB RDES2 */ | ||||||
|  | 			u32 hdr_len:10; | ||||||
|  | 			u32 rdes2_reserved:2; | ||||||
|  | 			u32 elrd_val:1; | ||||||
|  | 			u32 iovt_sel:1; | ||||||
|  | 			u32 res_pkt:1; | ||||||
|  | 			u32 vlan_filter_match:1; | ||||||
|  | 			u32 sa_filter_fail:1; | ||||||
|  | 			u32 da_filter_fail:1; | ||||||
|  | 			u32 hash_filter_pass:1; | ||||||
|  | 			u32 macaddr_filter_match:8; | ||||||
|  | 			u32 l3_filter_match:1; | ||||||
|  | 			u32 l4_filter_match:1; | ||||||
|  | 			u32 l34_filter_num:3; | ||||||
|  | 
 | ||||||
|  | 			/* WB RDES3 */ | ||||||
|  | 			u32 pkt_len:14; | ||||||
|  | 			u32 rdes3_reserved:1; | ||||||
|  | 			u32 err_summary:15; | ||||||
|  | 			u32 err_l2_type:4; | ||||||
|  | 			u32 layer34_pkt_type:4; | ||||||
|  | 			u32 no_coagulation_pkt:1; | ||||||
|  | 			u32 in_seq_pkt:1; | ||||||
|  | 			u32 rss_valid:1; | ||||||
|  | 			u32 context_des_avail:1; | ||||||
|  | 			u32 last_desc:1; | ||||||
|  | 			u32 first_desc:1; | ||||||
|  | 			u32 recv_context_desc:1; | ||||||
|  | 			u32 own_bit:1; | ||||||
|  | 		} rx_wb_des23; | ||||||
|  | 	} rdes23; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* Context descriptor structure */ | ||||||
|  | struct sxgbe_tx_ctxt_desc { | ||||||
|  | 	u32 tstamp_lo; | ||||||
|  | 	u32 tstamp_hi; | ||||||
|  | 	u32 maxseg_size:15; | ||||||
|  | 	u32 reserved1:1; | ||||||
|  | 	u32 ivlan_tag:16; | ||||||
|  | 	u32 vlan_tag:16; | ||||||
|  | 	u32 vltag_valid:1; | ||||||
|  | 	u32 ivlan_tag_valid:1; | ||||||
|  | 	u32 ivlan_tag_ctl:2; | ||||||
|  | 	u32 reserved2:3; | ||||||
|  | 	u32 ctxt_desc_err:1; | ||||||
|  | 	u32 reserved3:2; | ||||||
|  | 	u32 ostc:1; | ||||||
|  | 	u32 tcmssv:1; | ||||||
|  | 	u32 reserved4:2; | ||||||
|  | 	u32 ctxt_bit:1; | ||||||
|  | 	u32 own_bit:1; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_rx_ctxt_desc { | ||||||
|  | 	u32 tstamp_lo; | ||||||
|  | 	u32 tstamp_hi; | ||||||
|  | 	u32 reserved1; | ||||||
|  | 	u32 ptp_msgtype:4; | ||||||
|  | 	u32 tstamp_available:1; | ||||||
|  | 	u32 ptp_rsp_err:1; | ||||||
|  | 	u32 tstamp_dropped:1; | ||||||
|  | 	u32 reserved2:23; | ||||||
|  | 	u32 rx_ctxt_desc:1; | ||||||
|  | 	u32 own_bit:1; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_desc_ops { | ||||||
|  | 	/* DMA TX descriptor ring initialization */ | ||||||
|  | 	void (*init_tx_desc)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Invoked by the xmit function to prepare the tx descriptor */ | ||||||
|  | 	void (*tx_desc_enable_tse)(struct sxgbe_tx_norm_desc *p, u8 is_tse, | ||||||
|  | 				   u32 total_hdr_len, u32 payload_len, | ||||||
|  | 				   u32 tcp_payload_len); | ||||||
|  | 
 | ||||||
|  | 	/* Assign buffer lengths for descriptor */ | ||||||
|  | 	void (*prepare_tx_desc)(struct sxgbe_tx_norm_desc *p, u8 is_fd, | ||||||
|  | 				int buf1_len, int pkt_len, int cksum); | ||||||
|  | 
 | ||||||
|  | 	/* Set VLAN control information */ | ||||||
|  | 	void (*tx_vlanctl_desc)(struct sxgbe_tx_norm_desc *p, int vlan_ctl); | ||||||
|  | 
 | ||||||
|  | 	/* Set the owner of the descriptor */ | ||||||
|  | 	void (*set_tx_owner)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Get the owner of the descriptor */ | ||||||
|  | 	int (*get_tx_owner)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Invoked by the xmit function to close the tx descriptor */ | ||||||
|  | 	void (*close_tx_desc)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Clean the tx descriptor as soon as the tx irq is received */ | ||||||
|  | 	void (*release_tx_desc)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Clear interrupt on tx frame completion. When this bit is
 | ||||||
|  | 	 * set an interrupt happens as soon as the frame is transmitted | ||||||
|  | 	 */ | ||||||
|  | 	void (*clear_tx_ic)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Last tx segment reports the transmit status */ | ||||||
|  | 	int (*get_tx_ls)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Get the buffer size from the descriptor */ | ||||||
|  | 	int (*get_tx_len)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Set tx timestamp enable bit */ | ||||||
|  | 	void (*tx_enable_tstamp)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* get tx timestamp status */ | ||||||
|  | 	int (*get_tx_timestamp_status)(struct sxgbe_tx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* TX Context Descripto Specific */ | ||||||
|  | 	void (*tx_ctxt_desc_set_ctxt)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Set the owner of the TX context descriptor */ | ||||||
|  | 	void (*tx_ctxt_desc_set_owner)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Get the owner of the TX context descriptor */ | ||||||
|  | 	int (*get_tx_ctxt_owner)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Set TX mss */ | ||||||
|  | 	void (*tx_ctxt_desc_set_mss)(struct sxgbe_tx_ctxt_desc *p, int mss); | ||||||
|  | 
 | ||||||
|  | 	/* Set TX mss */ | ||||||
|  | 	int (*tx_ctxt_desc_get_mss)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Set TX tcmssv */ | ||||||
|  | 	void (*tx_ctxt_desc_set_tcmssv)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Reset TX ostc */ | ||||||
|  | 	void (*tx_ctxt_desc_reset_ostc)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Set IVLAN information */ | ||||||
|  | 	void (*tx_ctxt_desc_set_ivlantag)(struct sxgbe_tx_ctxt_desc *p, | ||||||
|  | 					  int is_ivlanvalid, int ivlan_tag, | ||||||
|  | 					  int ivlan_ctl); | ||||||
|  | 
 | ||||||
|  | 	/* Return IVLAN Tag */ | ||||||
|  | 	int (*tx_ctxt_desc_get_ivlantag)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Set VLAN Tag */ | ||||||
|  | 	void (*tx_ctxt_desc_set_vlantag)(struct sxgbe_tx_ctxt_desc *p, | ||||||
|  | 					 int is_vlanvalid, int vlan_tag); | ||||||
|  | 
 | ||||||
|  | 	/* Return VLAN Tag */ | ||||||
|  | 	int (*tx_ctxt_desc_get_vlantag)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Set Time stamp */ | ||||||
|  | 	void (*tx_ctxt_set_tstamp)(struct sxgbe_tx_ctxt_desc *p, | ||||||
|  | 				   u8 ostc_enable, u64 tstamp); | ||||||
|  | 
 | ||||||
|  | 	/* Close TX context descriptor */ | ||||||
|  | 	void (*close_tx_ctxt_desc)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* WB status of context descriptor */ | ||||||
|  | 	int (*get_tx_ctxt_cde)(struct sxgbe_tx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* DMA RX descriptor ring initialization */ | ||||||
|  | 	void (*init_rx_desc)(struct sxgbe_rx_norm_desc *p, int disable_rx_ic, | ||||||
|  | 			     int mode, int end); | ||||||
|  | 
 | ||||||
|  | 	/* Get own bit */ | ||||||
|  | 	int (*get_rx_owner)(struct sxgbe_rx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Set own bit */ | ||||||
|  | 	void (*set_rx_owner)(struct sxgbe_rx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Get the receive frame size */ | ||||||
|  | 	int (*get_rx_frame_len)(struct sxgbe_rx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Return first Descriptor status */ | ||||||
|  | 	int (*get_rx_fd_status)(struct sxgbe_rx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Return first Descriptor status */ | ||||||
|  | 	int (*get_rx_ld_status)(struct sxgbe_rx_norm_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Return the reception status looking at the RDES1 */ | ||||||
|  | 	int (*rx_wbstatus)(struct sxgbe_rx_norm_desc *p, | ||||||
|  | 			   struct sxgbe_extra_stats *x, int *checksum); | ||||||
|  | 
 | ||||||
|  | 	/* Get own bit */ | ||||||
|  | 	int (*get_rx_ctxt_owner)(struct sxgbe_rx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Set own bit */ | ||||||
|  | 	void (*set_rx_ctxt_owner)(struct sxgbe_rx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Return the reception status looking at Context control information */ | ||||||
|  | 	void (*rx_ctxt_wbstatus)(struct sxgbe_rx_ctxt_desc *p, | ||||||
|  | 				 struct sxgbe_extra_stats *x); | ||||||
|  | 
 | ||||||
|  | 	/* Get rx timestamp status */ | ||||||
|  | 	int (*get_rx_ctxt_tstamp_status)(struct sxgbe_rx_ctxt_desc *p); | ||||||
|  | 
 | ||||||
|  | 	/* Get timestamp value for rx, need to check this */ | ||||||
|  | 	u64 (*get_timestamp)(struct sxgbe_rx_ctxt_desc *p); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_desc_ops *sxgbe_get_desc_ops(void); | ||||||
|  | 
 | ||||||
|  | #endif /* __SXGBE_DESC_H__ */ | ||||||
							
								
								
									
										372
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										372
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,372 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #include <linux/io.h> | ||||||
|  | #include <linux/delay.h> | ||||||
|  | #include <linux/export.h> | ||||||
|  | #include <linux/io.h> | ||||||
|  | #include <linux/netdevice.h> | ||||||
|  | #include <linux/phy.h> | ||||||
|  | 
 | ||||||
|  | #include "sxgbe_common.h" | ||||||
|  | #include "sxgbe_dma.h" | ||||||
|  | #include "sxgbe_reg.h" | ||||||
|  | #include "sxgbe_desc.h" | ||||||
|  | 
 | ||||||
|  | /* DMA core initialization */ | ||||||
|  | static int sxgbe_dma_init(void __iomem *ioaddr, int fix_burst, int burst_map) | ||||||
|  | { | ||||||
|  | 	int retry_count = 10; | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	/* reset the DMA */ | ||||||
|  | 	writel(SXGBE_DMA_SOFT_RESET, ioaddr + SXGBE_DMA_MODE_REG); | ||||||
|  | 	while (retry_count--) { | ||||||
|  | 		if (!(readl(ioaddr + SXGBE_DMA_MODE_REG) & | ||||||
|  | 		      SXGBE_DMA_SOFT_RESET)) | ||||||
|  | 			break; | ||||||
|  | 		mdelay(10); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (retry_count < 0) | ||||||
|  | 		return -EBUSY; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_DMA_SYSBUS_MODE_REG); | ||||||
|  | 
 | ||||||
|  | 	/* if fix_burst = 0, Set UNDEF = 1 of DMA_Sys_Mode Register.
 | ||||||
|  | 	 * if fix_burst = 1, Set UNDEF = 0 of DMA_Sys_Mode Register. | ||||||
|  | 	 * burst_map is bitmap for  BLEN[4, 8, 16, 32, 64, 128 and 256]. | ||||||
|  | 	 * Set burst_map irrespective of fix_burst value. | ||||||
|  | 	 */ | ||||||
|  | 	if (!fix_burst) | ||||||
|  | 		reg_val |= SXGBE_DMA_AXI_UNDEF_BURST; | ||||||
|  | 
 | ||||||
|  | 	/* write burst len map */ | ||||||
|  | 	reg_val |= (burst_map << SXGBE_DMA_BLENMAP_LSHIFT); | ||||||
|  | 
 | ||||||
|  | 	writel(reg_val,	ioaddr + SXGBE_DMA_SYSBUS_MODE_REG); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_dma_channel_init(void __iomem *ioaddr, int cha_num, | ||||||
|  | 				   int fix_burst, int pbl, dma_addr_t dma_tx, | ||||||
|  | 				   dma_addr_t dma_rx, int t_rsize, int r_rsize) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 	dma_addr_t dma_addr; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_DMA_CHA_CTL_REG(cha_num)); | ||||||
|  | 	/* set the pbl */ | ||||||
|  | 	if (fix_burst) { | ||||||
|  | 		reg_val |= SXGBE_DMA_PBL_X8MODE; | ||||||
|  | 		writel(reg_val, ioaddr + SXGBE_DMA_CHA_CTL_REG(cha_num)); | ||||||
|  | 		/* program the TX pbl */ | ||||||
|  | 		reg_val = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num)); | ||||||
|  | 		reg_val |= (pbl << SXGBE_DMA_TXPBL_LSHIFT); | ||||||
|  | 		writel(reg_val, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num)); | ||||||
|  | 		/* program the RX pbl */ | ||||||
|  | 		reg_val = readl(ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cha_num)); | ||||||
|  | 		reg_val |= (pbl << SXGBE_DMA_RXPBL_LSHIFT); | ||||||
|  | 		writel(reg_val, ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cha_num)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* program desc registers */ | ||||||
|  | 	writel(upper_32_bits(dma_tx), | ||||||
|  | 	       ioaddr + SXGBE_DMA_CHA_TXDESC_HADD_REG(cha_num)); | ||||||
|  | 	writel(lower_32_bits(dma_tx), | ||||||
|  | 	       ioaddr + SXGBE_DMA_CHA_TXDESC_LADD_REG(cha_num)); | ||||||
|  | 
 | ||||||
|  | 	writel(upper_32_bits(dma_rx), | ||||||
|  | 	       ioaddr + SXGBE_DMA_CHA_RXDESC_HADD_REG(cha_num)); | ||||||
|  | 	writel(lower_32_bits(dma_rx), | ||||||
|  | 	       ioaddr + SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num)); | ||||||
|  | 
 | ||||||
|  | 	/* program tail pointers */ | ||||||
|  | 	/* assumption: upper 32 bits are constant and
 | ||||||
|  | 	 * same as TX/RX desc list | ||||||
|  | 	 */ | ||||||
|  | 	dma_addr = dma_tx + ((t_rsize - 1) * SXGBE_DESC_SIZE_BYTES); | ||||||
|  | 	writel(lower_32_bits(dma_addr), | ||||||
|  | 	       ioaddr + SXGBE_DMA_CHA_TXDESC_TAILPTR_REG(cha_num)); | ||||||
|  | 
 | ||||||
|  | 	dma_addr = dma_rx + ((r_rsize - 1) * SXGBE_DESC_SIZE_BYTES); | ||||||
|  | 	writel(lower_32_bits(dma_addr), | ||||||
|  | 	       ioaddr + SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num)); | ||||||
|  | 	/* program the ring sizes */ | ||||||
|  | 	writel(t_rsize - 1, ioaddr + SXGBE_DMA_CHA_TXDESC_RINGLEN_REG(cha_num)); | ||||||
|  | 	writel(r_rsize - 1, ioaddr + SXGBE_DMA_CHA_RXDESC_RINGLEN_REG(cha_num)); | ||||||
|  | 
 | ||||||
|  | 	/* Enable TX/RX interrupts */ | ||||||
|  | 	writel(SXGBE_DMA_ENA_INT, | ||||||
|  | 	       ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(cha_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_enable_dma_transmission(void __iomem *ioaddr, int cha_num) | ||||||
|  | { | ||||||
|  | 	u32 tx_config; | ||||||
|  | 
 | ||||||
|  | 	tx_config = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num)); | ||||||
|  | 	tx_config |= SXGBE_TX_START_DMA; | ||||||
|  | 	writel(tx_config, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_enable_dma_irq(void __iomem *ioaddr, int dma_cnum) | ||||||
|  | { | ||||||
|  | 	/* Enable TX/RX interrupts */ | ||||||
|  | 	writel(SXGBE_DMA_ENA_INT, | ||||||
|  | 	       ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(dma_cnum)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_disable_dma_irq(void __iomem *ioaddr, int dma_cnum) | ||||||
|  | { | ||||||
|  | 	/* Disable TX/RX interrupts */ | ||||||
|  | 	writel(0, ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(dma_cnum)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_dma_start_tx(void __iomem *ioaddr, int tchannels) | ||||||
|  | { | ||||||
|  | 	int cnum; | ||||||
|  | 	u32 tx_ctl_reg; | ||||||
|  | 
 | ||||||
|  | 	for (cnum = 0; cnum < tchannels; cnum++) { | ||||||
|  | 		tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum)); | ||||||
|  | 		tx_ctl_reg |= SXGBE_TX_ENABLE; | ||||||
|  | 		writel(tx_ctl_reg, | ||||||
|  | 		       ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_dma_start_tx_queue(void __iomem *ioaddr, int dma_cnum) | ||||||
|  | { | ||||||
|  | 	u32 tx_ctl_reg; | ||||||
|  | 
 | ||||||
|  | 	tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum)); | ||||||
|  | 	tx_ctl_reg |= SXGBE_TX_ENABLE; | ||||||
|  | 	writel(tx_ctl_reg, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_dma_stop_tx_queue(void __iomem *ioaddr, int dma_cnum) | ||||||
|  | { | ||||||
|  | 	u32 tx_ctl_reg; | ||||||
|  | 
 | ||||||
|  | 	tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum)); | ||||||
|  | 	tx_ctl_reg &= ~(SXGBE_TX_ENABLE); | ||||||
|  | 	writel(tx_ctl_reg, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_dma_stop_tx(void __iomem *ioaddr, int tchannels) | ||||||
|  | { | ||||||
|  | 	int cnum; | ||||||
|  | 	u32 tx_ctl_reg; | ||||||
|  | 
 | ||||||
|  | 	for (cnum = 0; cnum < tchannels; cnum++) { | ||||||
|  | 		tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum)); | ||||||
|  | 		tx_ctl_reg &= ~(SXGBE_TX_ENABLE); | ||||||
|  | 		writel(tx_ctl_reg, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_dma_start_rx(void __iomem *ioaddr, int rchannels) | ||||||
|  | { | ||||||
|  | 	int cnum; | ||||||
|  | 	u32 rx_ctl_reg; | ||||||
|  | 
 | ||||||
|  | 	for (cnum = 0; cnum < rchannels; cnum++) { | ||||||
|  | 		rx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum)); | ||||||
|  | 		rx_ctl_reg |= SXGBE_RX_ENABLE; | ||||||
|  | 		writel(rx_ctl_reg, | ||||||
|  | 		       ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_dma_stop_rx(void __iomem *ioaddr, int rchannels) | ||||||
|  | { | ||||||
|  | 	int cnum; | ||||||
|  | 	u32 rx_ctl_reg; | ||||||
|  | 
 | ||||||
|  | 	for (cnum = 0; cnum < rchannels; cnum++) { | ||||||
|  | 		rx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum)); | ||||||
|  | 		rx_ctl_reg &= ~(SXGBE_RX_ENABLE); | ||||||
|  | 		writel(rx_ctl_reg, ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sxgbe_tx_dma_int_status(void __iomem *ioaddr, int channel_no, | ||||||
|  | 				   struct sxgbe_extra_stats *x) | ||||||
|  | { | ||||||
|  | 	u32 int_status = readl(ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no)); | ||||||
|  | 	u32 clear_val = 0; | ||||||
|  | 	u32 ret_val = 0; | ||||||
|  | 
 | ||||||
|  | 	/* TX Normal Interrupt Summary */ | ||||||
|  | 	if (likely(int_status & SXGBE_DMA_INT_STATUS_NIS)) { | ||||||
|  | 		x->normal_irq_n++; | ||||||
|  | 		if (int_status & SXGBE_DMA_INT_STATUS_TI) { | ||||||
|  | 			ret_val |= handle_tx; | ||||||
|  | 			x->tx_normal_irq_n++; | ||||||
|  | 			clear_val |= SXGBE_DMA_INT_STATUS_TI; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (int_status & SXGBE_DMA_INT_STATUS_TBU) { | ||||||
|  | 			x->tx_underflow_irq++; | ||||||
|  | 			ret_val |= tx_bump_tc; | ||||||
|  | 			clear_val |= SXGBE_DMA_INT_STATUS_TBU; | ||||||
|  | 		} | ||||||
|  | 	} else if (unlikely(int_status & SXGBE_DMA_INT_STATUS_AIS)) { | ||||||
|  | 		/* TX Abnormal Interrupt Summary */ | ||||||
|  | 		if (int_status & SXGBE_DMA_INT_STATUS_TPS) { | ||||||
|  | 			ret_val |= tx_hard_error; | ||||||
|  | 			clear_val |= SXGBE_DMA_INT_STATUS_TPS; | ||||||
|  | 			x->tx_process_stopped_irq++; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (int_status & SXGBE_DMA_INT_STATUS_FBE) { | ||||||
|  | 			ret_val |= tx_hard_error; | ||||||
|  | 			x->fatal_bus_error_irq++; | ||||||
|  | 
 | ||||||
|  | 			/* Assumption: FBE bit is the combination of
 | ||||||
|  | 			 * all the bus access erros and cleared when | ||||||
|  | 			 * the respective error bits cleared | ||||||
|  | 			 */ | ||||||
|  | 
 | ||||||
|  | 			/* check for actual cause */ | ||||||
|  | 			if (int_status & SXGBE_DMA_INT_STATUS_TEB0) { | ||||||
|  | 				x->tx_read_transfer_err++; | ||||||
|  | 				clear_val |= SXGBE_DMA_INT_STATUS_TEB0; | ||||||
|  | 			} else { | ||||||
|  | 				x->tx_write_transfer_err++; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (int_status & SXGBE_DMA_INT_STATUS_TEB1) { | ||||||
|  | 				x->tx_desc_access_err++; | ||||||
|  | 				clear_val |= SXGBE_DMA_INT_STATUS_TEB1; | ||||||
|  | 			} else { | ||||||
|  | 				x->tx_buffer_access_err++; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (int_status & SXGBE_DMA_INT_STATUS_TEB2) { | ||||||
|  | 				x->tx_data_transfer_err++; | ||||||
|  | 				clear_val |= SXGBE_DMA_INT_STATUS_TEB2; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* context descriptor error */ | ||||||
|  | 		if (int_status & SXGBE_DMA_INT_STATUS_CTXTERR) { | ||||||
|  | 			x->tx_ctxt_desc_err++; | ||||||
|  | 			clear_val |= SXGBE_DMA_INT_STATUS_CTXTERR; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* clear the served bits */ | ||||||
|  | 	writel(clear_val, ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no)); | ||||||
|  | 
 | ||||||
|  | 	return ret_val; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sxgbe_rx_dma_int_status(void __iomem *ioaddr, int channel_no, | ||||||
|  | 				   struct sxgbe_extra_stats *x) | ||||||
|  | { | ||||||
|  | 	u32 int_status = readl(ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no)); | ||||||
|  | 	u32 clear_val = 0; | ||||||
|  | 	u32 ret_val = 0; | ||||||
|  | 
 | ||||||
|  | 	/* RX Normal Interrupt Summary */ | ||||||
|  | 	if (likely(int_status & SXGBE_DMA_INT_STATUS_NIS)) { | ||||||
|  | 		x->normal_irq_n++; | ||||||
|  | 		if (int_status & SXGBE_DMA_INT_STATUS_RI) { | ||||||
|  | 			ret_val |= handle_rx; | ||||||
|  | 			x->rx_normal_irq_n++; | ||||||
|  | 			clear_val |= SXGBE_DMA_INT_STATUS_RI; | ||||||
|  | 		} | ||||||
|  | 	} else if (unlikely(int_status & SXGBE_DMA_INT_STATUS_AIS)) { | ||||||
|  | 		/* RX Abnormal Interrupt Summary */ | ||||||
|  | 		if (int_status & SXGBE_DMA_INT_STATUS_RBU) { | ||||||
|  | 			ret_val |= rx_bump_tc; | ||||||
|  | 			clear_val |= SXGBE_DMA_INT_STATUS_RBU; | ||||||
|  | 			x->rx_underflow_irq++; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (int_status & SXGBE_DMA_INT_STATUS_RPS) { | ||||||
|  | 			ret_val |= rx_hard_error; | ||||||
|  | 			clear_val |= SXGBE_DMA_INT_STATUS_RPS; | ||||||
|  | 			x->rx_process_stopped_irq++; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (int_status & SXGBE_DMA_INT_STATUS_FBE) { | ||||||
|  | 			ret_val |= rx_hard_error; | ||||||
|  | 			x->fatal_bus_error_irq++; | ||||||
|  | 
 | ||||||
|  | 			/* Assumption: FBE bit is the combination of
 | ||||||
|  | 			 * all the bus access erros and cleared when | ||||||
|  | 			 * the respective error bits cleared | ||||||
|  | 			 */ | ||||||
|  | 
 | ||||||
|  | 			/* check for actual cause */ | ||||||
|  | 			if (int_status & SXGBE_DMA_INT_STATUS_REB0) { | ||||||
|  | 				x->rx_read_transfer_err++; | ||||||
|  | 				clear_val |= SXGBE_DMA_INT_STATUS_REB0; | ||||||
|  | 			} else { | ||||||
|  | 				x->rx_write_transfer_err++; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (int_status & SXGBE_DMA_INT_STATUS_REB1) { | ||||||
|  | 				x->rx_desc_access_err++; | ||||||
|  | 				clear_val |= SXGBE_DMA_INT_STATUS_REB1; | ||||||
|  | 			} else { | ||||||
|  | 				x->rx_buffer_access_err++; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (int_status & SXGBE_DMA_INT_STATUS_REB2) { | ||||||
|  | 				x->rx_data_transfer_err++; | ||||||
|  | 				clear_val |= SXGBE_DMA_INT_STATUS_REB2; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* clear the served bits */ | ||||||
|  | 	writel(clear_val, ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no)); | ||||||
|  | 
 | ||||||
|  | 	return ret_val; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Program the HW RX Watchdog */ | ||||||
|  | static void sxgbe_dma_rx_watchdog(void __iomem *ioaddr, u32 riwt) | ||||||
|  | { | ||||||
|  | 	u32 que_num; | ||||||
|  | 
 | ||||||
|  | 	SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, que_num) { | ||||||
|  | 		writel(riwt, | ||||||
|  | 		       ioaddr + SXGBE_DMA_CHA_INT_RXWATCHTMR_REG(que_num)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct sxgbe_dma_ops sxgbe_dma_ops = { | ||||||
|  | 	.init				= sxgbe_dma_init, | ||||||
|  | 	.cha_init			= sxgbe_dma_channel_init, | ||||||
|  | 	.enable_dma_transmission	= sxgbe_enable_dma_transmission, | ||||||
|  | 	.enable_dma_irq			= sxgbe_enable_dma_irq, | ||||||
|  | 	.disable_dma_irq		= sxgbe_disable_dma_irq, | ||||||
|  | 	.start_tx			= sxgbe_dma_start_tx, | ||||||
|  | 	.start_tx_queue			= sxgbe_dma_start_tx_queue, | ||||||
|  | 	.stop_tx			= sxgbe_dma_stop_tx, | ||||||
|  | 	.stop_tx_queue			= sxgbe_dma_stop_tx_queue, | ||||||
|  | 	.start_rx			= sxgbe_dma_start_rx, | ||||||
|  | 	.stop_rx			= sxgbe_dma_stop_rx, | ||||||
|  | 	.tx_dma_int_status		= sxgbe_tx_dma_int_status, | ||||||
|  | 	.rx_dma_int_status		= sxgbe_rx_dma_int_status, | ||||||
|  | 	.rx_watchdog			= sxgbe_dma_rx_watchdog, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_dma_ops *sxgbe_get_dma_ops(void) | ||||||
|  | { | ||||||
|  | 	return &sxgbe_dma_ops; | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #ifndef __SXGBE_DMA_H__ | ||||||
|  | #define __SXGBE_DMA_H__ | ||||||
|  | 
 | ||||||
|  | /* forward declaration */ | ||||||
|  | struct sxgbe_extra_stats; | ||||||
|  | 
 | ||||||
|  | #define SXGBE_DMA_BLENMAP_LSHIFT	1 | ||||||
|  | #define SXGBE_DMA_TXPBL_LSHIFT		16 | ||||||
|  | #define SXGBE_DMA_RXPBL_LSHIFT		16 | ||||||
|  | #define DEFAULT_DMA_PBL			8 | ||||||
|  | 
 | ||||||
|  | struct sxgbe_dma_ops { | ||||||
|  | 	/* DMA core initialization */ | ||||||
|  | 	int (*init)(void __iomem *ioaddr, int fix_burst, int burst_map); | ||||||
|  | 	void (*cha_init)(void __iomem *ioaddr, int cha_num, int fix_burst, | ||||||
|  | 			 int pbl, dma_addr_t dma_tx, dma_addr_t dma_rx, | ||||||
|  | 			 int t_rzie, int r_rsize); | ||||||
|  | 	void (*enable_dma_transmission)(void __iomem *ioaddr, int dma_cnum); | ||||||
|  | 	void (*enable_dma_irq)(void __iomem *ioaddr, int dma_cnum); | ||||||
|  | 	void (*disable_dma_irq)(void __iomem *ioaddr, int dma_cnum); | ||||||
|  | 	void (*start_tx)(void __iomem *ioaddr, int tchannels); | ||||||
|  | 	void (*start_tx_queue)(void __iomem *ioaddr, int dma_cnum); | ||||||
|  | 	void (*stop_tx)(void __iomem *ioaddr, int tchannels); | ||||||
|  | 	void (*stop_tx_queue)(void __iomem *ioaddr, int dma_cnum); | ||||||
|  | 	void (*start_rx)(void __iomem *ioaddr, int rchannels); | ||||||
|  | 	void (*stop_rx)(void __iomem *ioaddr, int rchannels); | ||||||
|  | 	int (*tx_dma_int_status)(void __iomem *ioaddr, int channel_no, | ||||||
|  | 				 struct sxgbe_extra_stats *x); | ||||||
|  | 	int (*rx_dma_int_status)(void __iomem *ioaddr, int channel_no, | ||||||
|  | 				 struct sxgbe_extra_stats *x); | ||||||
|  | 	/* Program the HW RX Watchdog */ | ||||||
|  | 	void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_dma_ops *sxgbe_get_dma_ops(void); | ||||||
|  | 
 | ||||||
|  | #endif /* __SXGBE_CORE_H__ */ | ||||||
							
								
								
									
										44
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||||||
|  | 
 | ||||||
|  | #include <linux/kernel.h> | ||||||
|  | #include <linux/netdevice.h> | ||||||
|  | #include <linux/phy.h> | ||||||
|  | 
 | ||||||
|  | #include "sxgbe_common.h" | ||||||
|  | 
 | ||||||
|  | struct sxgbe_stats { | ||||||
|  | 	char stat_string[ETH_GSTRING_LEN]; | ||||||
|  | 	int sizeof_stat; | ||||||
|  | 	int stat_offset; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define SXGBE_STAT(m)						\ | ||||||
|  | {								\ | ||||||
|  | 	#m,							\ | ||||||
|  | 	FIELD_SIZEOF(struct sxgbe_extra_stats, m),		\ | ||||||
|  | 	offsetof(struct sxgbe_priv_data, xstats.m)		\ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct sxgbe_stats sxgbe_gstrings_stats[] = { | ||||||
|  | }; | ||||||
|  | #define SXGBE_STATS_LEN ARRAY_SIZE(sxgbe_gstrings_stats) | ||||||
|  | 
 | ||||||
|  | static const struct ethtool_ops sxgbe_ethtool_ops = { | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void sxgbe_set_ethtool_ops(struct net_device *netdev) | ||||||
|  | { | ||||||
|  | 	SET_ETHTOOL_OPS(netdev, &sxgbe_ethtool_ops); | ||||||
|  | } | ||||||
							
								
								
									
										2052
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2052
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										251
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,251 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||||||
|  | 
 | ||||||
|  | #include <linux/io.h> | ||||||
|  | #include <linux/mii.h> | ||||||
|  | #include <linux/netdevice.h> | ||||||
|  | #include <linux/platform_device.h> | ||||||
|  | #include <linux/phy.h> | ||||||
|  | #include <linux/slab.h> | ||||||
|  | #include <linux/sxgbe_platform.h> | ||||||
|  | 
 | ||||||
|  | #include "sxgbe_common.h" | ||||||
|  | #include "sxgbe_reg.h" | ||||||
|  | 
 | ||||||
|  | #define SXGBE_SMA_WRITE_CMD	0x01 /* write command */ | ||||||
|  | #define SXGBE_SMA_PREAD_CMD	0x02 /* post read  increament address */ | ||||||
|  | #define SXGBE_SMA_READ_CMD	0x03 /* read command */ | ||||||
|  | #define SXGBE_SMA_SKIP_ADDRFRM	0x00040000 /* skip the address frame */ | ||||||
|  | #define SXGBE_MII_BUSY		0x00800000 /* mii busy */ | ||||||
|  | 
 | ||||||
|  | static int sxgbe_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_data) | ||||||
|  | { | ||||||
|  | 	unsigned long fin_time = jiffies + 3 * HZ; /* 3 seconds */ | ||||||
|  | 
 | ||||||
|  | 	while (!time_after(jiffies, fin_time)) { | ||||||
|  | 		if (!(readl(ioaddr + mii_data) & SXGBE_MII_BUSY)) | ||||||
|  | 			return 0; | ||||||
|  | 		cpu_relax(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return -EBUSY; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mdio_ctrl_data(struct sxgbe_priv_data *sp, u32 cmd, | ||||||
|  | 				 u16 phydata) | ||||||
|  | { | ||||||
|  | 	u32 reg = phydata; | ||||||
|  | 
 | ||||||
|  | 	reg |= (cmd << 16) | SXGBE_SMA_SKIP_ADDRFRM | | ||||||
|  | 	       ((sp->clk_csr & 0x7) << 19) | SXGBE_MII_BUSY; | ||||||
|  | 	writel(reg, sp->ioaddr + sp->hw->mii.data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mdio_c45(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, | ||||||
|  | 			   int phyreg, u16 phydata) | ||||||
|  | { | ||||||
|  | 	u32 reg; | ||||||
|  | 
 | ||||||
|  | 	/* set mdio address register */ | ||||||
|  | 	reg = ((phyreg >> 16) & 0x1f) << 21; | ||||||
|  | 	reg |= (phyaddr << 16) | (phyreg & 0xffff); | ||||||
|  | 	writel(reg, sp->ioaddr + sp->hw->mii.addr); | ||||||
|  | 
 | ||||||
|  | 	sxgbe_mdio_ctrl_data(sp, cmd, phydata); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mdio_c22(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, | ||||||
|  | 			   int phyreg, u16 phydata) | ||||||
|  | { | ||||||
|  | 	u32 reg; | ||||||
|  | 
 | ||||||
|  | 	writel(1 << phyaddr, sp->ioaddr + SXGBE_MDIO_CLAUSE22_PORT_REG); | ||||||
|  | 
 | ||||||
|  | 	/* set mdio address register */ | ||||||
|  | 	reg = (phyaddr << 16) | (phyreg & 0x1f); | ||||||
|  | 	writel(reg, sp->ioaddr + sp->hw->mii.addr); | ||||||
|  | 
 | ||||||
|  | 	sxgbe_mdio_ctrl_data(sp, cmd, phydata); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sxgbe_mdio_access(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, | ||||||
|  | 			     int phyreg, u16 phydata) | ||||||
|  | { | ||||||
|  | 	const struct mii_regs *mii = &sp->hw->mii; | ||||||
|  | 	int rc; | ||||||
|  | 
 | ||||||
|  | 	rc = sxgbe_mdio_busy_wait(sp->ioaddr, mii->data); | ||||||
|  | 	if (rc < 0) | ||||||
|  | 		return rc; | ||||||
|  | 
 | ||||||
|  | 	if (phyreg & MII_ADDR_C45) { | ||||||
|  | 		sxgbe_mdio_c45(sp, cmd, phyaddr, phyreg, phydata); | ||||||
|  | 	} else { | ||||||
|  | 		 /* Ports 0-3 only support C22. */ | ||||||
|  | 		if (phyaddr >= 4) | ||||||
|  | 			return -ENODEV; | ||||||
|  | 
 | ||||||
|  | 		sxgbe_mdio_c22(sp, cmd, phyaddr, phyreg, phydata); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sxgbe_mdio_busy_wait(sp->ioaddr, mii->data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * sxgbe_mdio_read | ||||||
|  |  * @bus: points to the mii_bus structure | ||||||
|  |  * @phyaddr: address of phy port | ||||||
|  |  * @phyreg: address of register with in phy register | ||||||
|  |  * Description: this function used for C45 and C22 MDIO Read | ||||||
|  |  */ | ||||||
|  | static int sxgbe_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) | ||||||
|  | { | ||||||
|  | 	struct net_device *ndev = bus->priv; | ||||||
|  | 	struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||||||
|  | 	int rc; | ||||||
|  | 
 | ||||||
|  | 	rc = sxgbe_mdio_access(priv, SXGBE_SMA_READ_CMD, phyaddr, phyreg, 0); | ||||||
|  | 	if (rc < 0) | ||||||
|  | 		return rc; | ||||||
|  | 
 | ||||||
|  | 	return readl(priv->ioaddr + priv->hw->mii.data) & 0xffff; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * sxgbe_mdio_write | ||||||
|  |  * @bus: points to the mii_bus structure | ||||||
|  |  * @phyaddr: address of phy port | ||||||
|  |  * @phyreg: address of phy registers | ||||||
|  |  * @phydata: data to be written into phy register | ||||||
|  |  * Description: this function is used for C45 and C22 MDIO write | ||||||
|  |  */ | ||||||
|  | static int sxgbe_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, | ||||||
|  | 			     u16 phydata) | ||||||
|  | { | ||||||
|  | 	struct net_device *ndev = bus->priv; | ||||||
|  | 	struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||||||
|  | 
 | ||||||
|  | 	return sxgbe_mdio_access(priv, SXGBE_SMA_WRITE_CMD, phyaddr, phyreg, | ||||||
|  | 				 phydata); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sxgbe_mdio_register(struct net_device *ndev) | ||||||
|  | { | ||||||
|  | 	struct mii_bus *mdio_bus; | ||||||
|  | 	struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||||||
|  | 	struct sxgbe_mdio_bus_data *mdio_data = priv->plat->mdio_bus_data; | ||||||
|  | 	int err, phy_addr; | ||||||
|  | 	int *irqlist; | ||||||
|  | 	bool act; | ||||||
|  | 
 | ||||||
|  | 	/* allocate the new mdio bus */ | ||||||
|  | 	mdio_bus = mdiobus_alloc(); | ||||||
|  | 	if (!mdio_bus) { | ||||||
|  | 		netdev_err(ndev, "%s: mii bus allocation failed\n", __func__); | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (mdio_data->irqs) | ||||||
|  | 		irqlist = mdio_data->irqs; | ||||||
|  | 	else | ||||||
|  | 		irqlist = priv->mii_irq; | ||||||
|  | 
 | ||||||
|  | 	/* assign mii bus fields */ | ||||||
|  | 	mdio_bus->name = "samsxgbe"; | ||||||
|  | 	mdio_bus->read = &sxgbe_mdio_read; | ||||||
|  | 	mdio_bus->write = &sxgbe_mdio_write; | ||||||
|  | 	snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%x", | ||||||
|  | 		 mdio_bus->name, priv->plat->bus_id); | ||||||
|  | 	mdio_bus->priv = ndev; | ||||||
|  | 	mdio_bus->phy_mask = mdio_data->phy_mask; | ||||||
|  | 	mdio_bus->parent = priv->device; | ||||||
|  | 
 | ||||||
|  | 	/* register with kernel subsystem */ | ||||||
|  | 	err = mdiobus_register(mdio_bus); | ||||||
|  | 	if (err != 0) { | ||||||
|  | 		netdev_err(ndev, "mdiobus register failed\n"); | ||||||
|  | 		goto mdiobus_err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { | ||||||
|  | 		struct phy_device *phy = mdio_bus->phy_map[phy_addr]; | ||||||
|  | 
 | ||||||
|  | 		if (phy) { | ||||||
|  | 			char irq_num[4]; | ||||||
|  | 			char *irq_str; | ||||||
|  | 			/* If an IRQ was provided to be assigned after
 | ||||||
|  | 			 * the bus probe, do it here. | ||||||
|  | 			 */ | ||||||
|  | 			if ((mdio_data->irqs == NULL) && | ||||||
|  | 			    (mdio_data->probed_phy_irq > 0)) { | ||||||
|  | 				irqlist[phy_addr] = mdio_data->probed_phy_irq; | ||||||
|  | 				phy->irq = mdio_data->probed_phy_irq; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			/* If we're  going to bind the MAC to this PHY bus,
 | ||||||
|  | 			 * and no PHY number was provided to the MAC, | ||||||
|  | 			 * use the one probed here. | ||||||
|  | 			 */ | ||||||
|  | 			if (priv->plat->phy_addr == -1) | ||||||
|  | 				priv->plat->phy_addr = phy_addr; | ||||||
|  | 
 | ||||||
|  | 			act = (priv->plat->phy_addr == phy_addr); | ||||||
|  | 			switch (phy->irq) { | ||||||
|  | 			case PHY_POLL: | ||||||
|  | 				irq_str = "POLL"; | ||||||
|  | 				break; | ||||||
|  | 			case PHY_IGNORE_INTERRUPT: | ||||||
|  | 				irq_str = "IGNORE"; | ||||||
|  | 				break; | ||||||
|  | 			default: | ||||||
|  | 				sprintf(irq_num, "%d", phy->irq); | ||||||
|  | 				irq_str = irq_num; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n", | ||||||
|  | 				    phy->phy_id, phy_addr, irq_str, | ||||||
|  | 				    dev_name(&phy->dev), act ? " active" : ""); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!err) { | ||||||
|  | 		netdev_err(ndev, "PHY not found\n"); | ||||||
|  | 		mdiobus_unregister(mdio_bus); | ||||||
|  | 		mdiobus_free(mdio_bus); | ||||||
|  | 		goto mdiobus_err; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	priv->mii = mdio_bus; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | mdiobus_err: | ||||||
|  | 	mdiobus_free(mdio_bus); | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sxgbe_mdio_unregister(struct net_device *ndev) | ||||||
|  | { | ||||||
|  | 	struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||||||
|  | 
 | ||||||
|  | 	if (!priv->mii) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	mdiobus_unregister(priv->mii); | ||||||
|  | 	priv->mii->priv = NULL; | ||||||
|  | 	mdiobus_free(priv->mii); | ||||||
|  | 	priv->mii = NULL; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										254
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,254 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||||||
|  | 
 | ||||||
|  | #include <linux/io.h> | ||||||
|  | #include <linux/errno.h> | ||||||
|  | #include <linux/export.h> | ||||||
|  | #include <linux/jiffies.h> | ||||||
|  | 
 | ||||||
|  | #include "sxgbe_mtl.h" | ||||||
|  | #include "sxgbe_reg.h" | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_init(void __iomem *ioaddr, unsigned int etsalg, | ||||||
|  | 			   unsigned int raa) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_OP_MODE_REG); | ||||||
|  | 	reg_val &= ETS_RST; | ||||||
|  | 
 | ||||||
|  | 	/* ETS Algorith */ | ||||||
|  | 	switch (etsalg & SXGBE_MTL_OPMODE_ESTMASK) { | ||||||
|  | 	case ETS_WRR: | ||||||
|  | 		reg_val &= ETS_WRR; | ||||||
|  | 		break; | ||||||
|  | 	case ETS_WFQ: | ||||||
|  | 		reg_val |= ETS_WFQ; | ||||||
|  | 		break; | ||||||
|  | 	case ETS_DWRR: | ||||||
|  | 		reg_val |= ETS_DWRR; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_OP_MODE_REG); | ||||||
|  | 
 | ||||||
|  | 	switch (raa & SXGBE_MTL_OPMODE_RAAMASK) { | ||||||
|  | 	case RAA_SP: | ||||||
|  | 		reg_val &= RAA_SP; | ||||||
|  | 		break; | ||||||
|  | 	case RAA_WSP: | ||||||
|  | 		reg_val |= RAA_WSP; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_OP_MODE_REG); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* For Dynamic DMA channel mapping for Rx queue */ | ||||||
|  | static void sxgbe_mtl_dma_dm_rxqueue(void __iomem *ioaddr) | ||||||
|  | { | ||||||
|  | 	writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP0_REG); | ||||||
|  | 	writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP1_REG); | ||||||
|  | 	writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP2_REG); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_set_txfifosize(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				     int queue_fifo) | ||||||
|  | { | ||||||
|  | 	u32 fifo_bits, reg_val; | ||||||
|  | 
 | ||||||
|  | 	/* 0 means 256 bytes */ | ||||||
|  | 	fifo_bits = (queue_fifo / SXGBE_MTL_TX_FIFO_DIV) - 1; | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT); | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_set_rxfifosize(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				     int queue_fifo) | ||||||
|  | { | ||||||
|  | 	u32 fifo_bits, reg_val; | ||||||
|  | 
 | ||||||
|  | 	/* 0 means 256 bytes */ | ||||||
|  | 	fifo_bits = (queue_fifo / SXGBE_MTL_RX_FIFO_DIV)-1; | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT); | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_enable_txqueue(void __iomem *ioaddr, int queue_num) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val |= SXGBE_MTL_ENABLE_QUEUE; | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_disable_txqueue(void __iomem *ioaddr, int queue_num) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val &= ~SXGBE_MTL_ENABLE_QUEUE; | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_fc_active(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				int threshold) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val &= ~(SXGBE_MTL_FCMASK << RX_FC_ACTIVE); | ||||||
|  | 	reg_val |= (threshold << RX_FC_ACTIVE); | ||||||
|  | 
 | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_fc_enable(void __iomem *ioaddr, int queue_num) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val |= SXGBE_MTL_ENABLE_FC; | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_fc_deactive(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				  int threshold) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val &= ~(SXGBE_MTL_FCMASK << RX_FC_DEACTIVE); | ||||||
|  | 	reg_val |= (threshold << RX_FC_DEACTIVE); | ||||||
|  | 
 | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_fep_enable(void __iomem *ioaddr, int queue_num) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val |= SXGBE_MTL_RXQ_OP_FEP; | ||||||
|  | 
 | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_fep_disable(void __iomem *ioaddr, int queue_num) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val &= ~(SXGBE_MTL_RXQ_OP_FEP); | ||||||
|  | 
 | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_fup_enable(void __iomem *ioaddr, int queue_num) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val |= SXGBE_MTL_RXQ_OP_FUP; | ||||||
|  | 
 | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_mtl_fup_disable(void __iomem *ioaddr, int queue_num) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	reg_val &= ~(SXGBE_MTL_RXQ_OP_FUP); | ||||||
|  | 
 | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static void sxgbe_set_tx_mtl_mode(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				  int tx_mode) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	/* TX specific MTL mode settings */ | ||||||
|  | 	if (tx_mode == SXGBE_MTL_SFMODE) { | ||||||
|  | 		reg_val |= SXGBE_MTL_SFMODE; | ||||||
|  | 	} else { | ||||||
|  | 		/* set the TTC values */ | ||||||
|  | 		if (tx_mode <= 64) | ||||||
|  | 			reg_val |= MTL_CONTROL_TTC_64; | ||||||
|  | 		else if (tx_mode <= 96) | ||||||
|  | 			reg_val |= MTL_CONTROL_TTC_96; | ||||||
|  | 		else if (tx_mode <= 128) | ||||||
|  | 			reg_val |= MTL_CONTROL_TTC_128; | ||||||
|  | 		else if (tx_mode <= 192) | ||||||
|  | 			reg_val |= MTL_CONTROL_TTC_192; | ||||||
|  | 		else if (tx_mode <= 256) | ||||||
|  | 			reg_val |= MTL_CONTROL_TTC_256; | ||||||
|  | 		else if (tx_mode <= 384) | ||||||
|  | 			reg_val |= MTL_CONTROL_TTC_384; | ||||||
|  | 		else | ||||||
|  | 			reg_val |= MTL_CONTROL_TTC_512; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* write into TXQ operation register */ | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void sxgbe_set_rx_mtl_mode(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				  int rx_mode) | ||||||
|  | { | ||||||
|  | 	u32 reg_val; | ||||||
|  | 
 | ||||||
|  | 	reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | 	/* RX specific MTL mode settings */ | ||||||
|  | 	if (rx_mode == SXGBE_RX_MTL_SFMODE) { | ||||||
|  | 		reg_val |= SXGBE_RX_MTL_SFMODE; | ||||||
|  | 	} else { | ||||||
|  | 		if (rx_mode <= 64) | ||||||
|  | 			reg_val |= MTL_CONTROL_RTC_64; | ||||||
|  | 		else if (rx_mode <= 96) | ||||||
|  | 			reg_val |= MTL_CONTROL_RTC_96; | ||||||
|  | 		else if (rx_mode <= 128) | ||||||
|  | 			reg_val |= MTL_CONTROL_RTC_128; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* write into RXQ operation register */ | ||||||
|  | 	writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct sxgbe_mtl_ops mtl_ops = { | ||||||
|  | 	.mtl_set_txfifosize		= sxgbe_mtl_set_txfifosize, | ||||||
|  | 	.mtl_set_rxfifosize		= sxgbe_mtl_set_rxfifosize, | ||||||
|  | 	.mtl_enable_txqueue		= sxgbe_mtl_enable_txqueue, | ||||||
|  | 	.mtl_disable_txqueue		= sxgbe_mtl_disable_txqueue, | ||||||
|  | 	.mtl_dynamic_dma_rxqueue	= sxgbe_mtl_dma_dm_rxqueue, | ||||||
|  | 	.set_tx_mtl_mode		= sxgbe_set_tx_mtl_mode, | ||||||
|  | 	.set_rx_mtl_mode		= sxgbe_set_rx_mtl_mode, | ||||||
|  | 	.mtl_init			= sxgbe_mtl_init, | ||||||
|  | 	.mtl_fc_active			= sxgbe_mtl_fc_active, | ||||||
|  | 	.mtl_fc_deactive		= sxgbe_mtl_fc_deactive, | ||||||
|  | 	.mtl_fc_enable			= sxgbe_mtl_fc_enable, | ||||||
|  | 	.mtl_fep_enable			= sxgbe_mtl_fep_enable, | ||||||
|  | 	.mtl_fep_disable		= sxgbe_mtl_fep_disable, | ||||||
|  | 	.mtl_fup_enable			= sxgbe_mtl_fup_enable, | ||||||
|  | 	.mtl_fup_disable		= sxgbe_mtl_fup_disable | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void) | ||||||
|  | { | ||||||
|  | 	return &mtl_ops; | ||||||
|  | } | ||||||
							
								
								
									
										104
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,104 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #ifndef __SXGBE_MTL_H__ | ||||||
|  | #define __SXGBE_MTL_H__ | ||||||
|  | 
 | ||||||
|  | #define SXGBE_MTL_OPMODE_ESTMASK	0x3 | ||||||
|  | #define SXGBE_MTL_OPMODE_RAAMASK	0x1 | ||||||
|  | #define SXGBE_MTL_FCMASK		0x7 | ||||||
|  | #define SXGBE_MTL_TX_FIFO_DIV		256 | ||||||
|  | #define SXGBE_MTL_RX_FIFO_DIV		256 | ||||||
|  | 
 | ||||||
|  | #define SXGBE_MTL_RXQ_OP_FEP		BIT(4) | ||||||
|  | #define SXGBE_MTL_RXQ_OP_FUP		BIT(3) | ||||||
|  | #define SXGBE_MTL_ENABLE_FC		0x80 | ||||||
|  | 
 | ||||||
|  | #define ETS_WRR				0xFFFFFF9F | ||||||
|  | #define ETS_RST				0xFFFFFF9F | ||||||
|  | #define ETS_WFQ				0x00000020 | ||||||
|  | #define ETS_DWRR			0x00000040 | ||||||
|  | #define RAA_SP				0xFFFFFFFB | ||||||
|  | #define RAA_WSP				0x00000004 | ||||||
|  | 
 | ||||||
|  | #define RX_QUEUE_DYNAMIC		0x80808080 | ||||||
|  | #define RX_FC_ACTIVE			8 | ||||||
|  | #define RX_FC_DEACTIVE			13 | ||||||
|  | 
 | ||||||
|  | enum ttc_control { | ||||||
|  | 	MTL_CONTROL_TTC_64 = 0x00000000, | ||||||
|  | 	MTL_CONTROL_TTC_96 = 0x00000020, | ||||||
|  | 	MTL_CONTROL_TTC_128 = 0x00000030, | ||||||
|  | 	MTL_CONTROL_TTC_192 = 0x00000040, | ||||||
|  | 	MTL_CONTROL_TTC_256 = 0x00000050, | ||||||
|  | 	MTL_CONTROL_TTC_384 = 0x00000060, | ||||||
|  | 	MTL_CONTROL_TTC_512 = 0x00000070, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum rtc_control { | ||||||
|  | 	MTL_CONTROL_RTC_64 = 0x00000000, | ||||||
|  | 	MTL_CONTROL_RTC_96 = 0x00000002, | ||||||
|  | 	MTL_CONTROL_RTC_128 = 0x00000003, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum flow_control_th { | ||||||
|  | 	MTL_FC_FULL_1K = 0x00000000, | ||||||
|  | 	MTL_FC_FULL_2K = 0x00000001, | ||||||
|  | 	MTL_FC_FULL_4K = 0x00000002, | ||||||
|  | 	MTL_FC_FULL_5K = 0x00000003, | ||||||
|  | 	MTL_FC_FULL_6K = 0x00000004, | ||||||
|  | 	MTL_FC_FULL_8K = 0x00000005, | ||||||
|  | 	MTL_FC_FULL_16K = 0x00000006, | ||||||
|  | 	MTL_FC_FULL_24K = 0x00000007, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_mtl_ops { | ||||||
|  | 	void (*mtl_init)(void __iomem *ioaddr, unsigned int etsalg, | ||||||
|  | 			 unsigned int raa); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_set_txfifosize)(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				   int mtl_fifo); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_set_rxfifosize)(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				   int queue_fifo); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_enable_txqueue)(void __iomem *ioaddr, int queue_num); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_disable_txqueue)(void __iomem *ioaddr, int queue_num); | ||||||
|  | 
 | ||||||
|  | 	void (*set_tx_mtl_mode)(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				int tx_mode); | ||||||
|  | 
 | ||||||
|  | 	void (*set_rx_mtl_mode)(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				int rx_mode); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_dynamic_dma_rxqueue)(void __iomem *ioaddr); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_fc_active)(void __iomem *ioaddr, int queue_num, | ||||||
|  | 			      int threshold); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_fc_deactive)(void __iomem *ioaddr, int queue_num, | ||||||
|  | 				int threshold); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_fc_enable)(void __iomem *ioaddr, int queue_num); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_fep_enable)(void __iomem *ioaddr, int queue_num); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_fep_disable)(void __iomem *ioaddr, int queue_num); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_fup_enable)(void __iomem *ioaddr, int queue_num); | ||||||
|  | 
 | ||||||
|  | 	void (*mtl_fup_disable)(void __iomem *ioaddr, int queue_num); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void); | ||||||
|  | 
 | ||||||
|  | #endif /* __SXGBE_MTL_H__ */ | ||||||
							
								
								
									
										253
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,253 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||||||
|  | 
 | ||||||
|  | #include <linux/etherdevice.h> | ||||||
|  | #include <linux/io.h> | ||||||
|  | #include <linux/module.h> | ||||||
|  | #include <linux/netdevice.h> | ||||||
|  | #include <linux/of.h> | ||||||
|  | #include <linux/of_irq.h> | ||||||
|  | #include <linux/of_net.h> | ||||||
|  | #include <linux/phy.h> | ||||||
|  | #include <linux/platform_device.h> | ||||||
|  | #include <linux/sxgbe_platform.h> | ||||||
|  | 
 | ||||||
|  | #include "sxgbe_common.h" | ||||||
|  | #include "sxgbe_reg.h" | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_OF | ||||||
|  | static int sxgbe_probe_config_dt(struct platform_device *pdev, | ||||||
|  | 				 struct sxgbe_plat_data *plat, | ||||||
|  | 				 const char **mac) | ||||||
|  | { | ||||||
|  | 	struct device_node *np = pdev->dev.of_node; | ||||||
|  | 	struct sxgbe_dma_cfg *dma_cfg; | ||||||
|  | 
 | ||||||
|  | 	if (!np) | ||||||
|  | 		return -ENODEV; | ||||||
|  | 
 | ||||||
|  | 	*mac = of_get_mac_address(np); | ||||||
|  | 	plat->interface = of_get_phy_mode(np); | ||||||
|  | 
 | ||||||
|  | 	plat->bus_id = of_alias_get_id(np, "ethernet"); | ||||||
|  | 	if (plat->bus_id < 0) | ||||||
|  | 		plat->bus_id = 0; | ||||||
|  | 
 | ||||||
|  | 	plat->mdio_bus_data = devm_kzalloc(&pdev->dev, | ||||||
|  | 					   sizeof(*plat->mdio_bus_data), | ||||||
|  | 					   GFP_KERNEL); | ||||||
|  | 
 | ||||||
|  | 	dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL); | ||||||
|  | 	if (!dma_cfg) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	plat->dma_cfg = dma_cfg; | ||||||
|  | 	of_property_read_u32(np, "samsung,pbl", &dma_cfg->pbl); | ||||||
|  | 	if (of_property_read_u32(np, "samsung,burst-map", &dma_cfg->burst_map) == 0) | ||||||
|  | 		dma_cfg->fixed_burst = true; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | static int sxgbe_probe_config_dt(struct platform_device *pdev, | ||||||
|  | 				 struct sxgbe_plat_data *plat, | ||||||
|  | 				 const char **mac) | ||||||
|  | { | ||||||
|  | 	return -ENOSYS; | ||||||
|  | } | ||||||
|  | #endif /* CONFIG_OF */ | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * sxgbe_platform_probe | ||||||
|  |  * @pdev: platform device pointer | ||||||
|  |  * Description: platform_device probe function. It allocates | ||||||
|  |  * the necessary resources and invokes the main to init | ||||||
|  |  * the net device, register the mdio bus etc. | ||||||
|  |  */ | ||||||
|  | static int sxgbe_platform_probe(struct platform_device *pdev) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	int i, chan; | ||||||
|  | 	struct resource *res; | ||||||
|  | 	struct device *dev = &pdev->dev; | ||||||
|  | 	void __iomem *addr; | ||||||
|  | 	struct sxgbe_priv_data *priv = NULL; | ||||||
|  | 	struct sxgbe_plat_data *plat_dat = NULL; | ||||||
|  | 	const char *mac = NULL; | ||||||
|  | 	struct net_device *ndev = platform_get_drvdata(pdev); | ||||||
|  | 	struct device_node *node = dev->of_node; | ||||||
|  | 
 | ||||||
|  | 	/* Get memory resource */ | ||||||
|  | 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||||
|  | 	if (!res) | ||||||
|  | 		goto err_out; | ||||||
|  | 
 | ||||||
|  | 	addr = devm_ioremap_resource(dev, res); | ||||||
|  | 	if (IS_ERR(addr)) | ||||||
|  | 		return PTR_ERR(addr); | ||||||
|  | 
 | ||||||
|  | 	if (pdev->dev.of_node) { | ||||||
|  | 		plat_dat = devm_kzalloc(&pdev->dev, | ||||||
|  | 					sizeof(struct sxgbe_plat_data), | ||||||
|  | 					GFP_KERNEL); | ||||||
|  | 		if (!plat_dat) | ||||||
|  | 			return  -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 		ret = sxgbe_probe_config_dt(pdev, plat_dat, &mac); | ||||||
|  | 		if (ret) { | ||||||
|  | 			pr_err("%s: main dt probe failed\n", __func__); | ||||||
|  | 			return ret; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Get MAC address if available (DT) */ | ||||||
|  | 	if (mac) | ||||||
|  | 		ether_addr_copy(priv->dev->dev_addr, mac); | ||||||
|  | 
 | ||||||
|  | 	priv = sxgbe_drv_probe(&(pdev->dev), plat_dat, addr); | ||||||
|  | 	if (!priv) { | ||||||
|  | 		pr_err("%s: main driver probe failed\n", __func__); | ||||||
|  | 		goto err_out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Get the SXGBE common INT information */ | ||||||
|  | 	priv->irq  = irq_of_parse_and_map(node, 0); | ||||||
|  | 	if (priv->irq <= 0) { | ||||||
|  | 		dev_err(dev, "sxgbe common irq parsing failed\n"); | ||||||
|  | 		goto err_drv_remove; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Get the TX/RX IRQ numbers */ | ||||||
|  | 	for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) { | ||||||
|  | 		priv->txq[i]->irq_no = irq_of_parse_and_map(node, chan++); | ||||||
|  | 		if (priv->txq[i]->irq_no <= 0) { | ||||||
|  | 			dev_err(dev, "sxgbe tx irq parsing failed\n"); | ||||||
|  | 			goto err_tx_irq_unmap; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < SXGBE_RX_QUEUES; i++) { | ||||||
|  | 		priv->rxq[i]->irq_no = irq_of_parse_and_map(node, chan++); | ||||||
|  | 		if (priv->rxq[i]->irq_no <= 0) { | ||||||
|  | 			dev_err(dev, "sxgbe rx irq parsing failed\n"); | ||||||
|  | 			goto err_rx_irq_unmap; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	platform_set_drvdata(pdev, priv->dev); | ||||||
|  | 
 | ||||||
|  | 	pr_debug("platform driver registration completed\n"); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  | err_rx_irq_unmap: | ||||||
|  | 	while (--i) | ||||||
|  | 		irq_dispose_mapping(priv->rxq[i]->irq_no); | ||||||
|  | 	i = SXGBE_TX_QUEUES; | ||||||
|  | err_tx_irq_unmap: | ||||||
|  | 	while (--i) | ||||||
|  | 		irq_dispose_mapping(priv->txq[i]->irq_no); | ||||||
|  | 	irq_dispose_mapping(priv->irq); | ||||||
|  | err_drv_remove: | ||||||
|  | 	sxgbe_drv_remove(ndev); | ||||||
|  | err_out: | ||||||
|  | 	return -ENODEV; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * sxgbe_platform_remove | ||||||
|  |  * @pdev: platform device pointer | ||||||
|  |  * Description: this function calls the main to free the net resources | ||||||
|  |  * and calls the platforms hook and release the resources (e.g. mem). | ||||||
|  |  */ | ||||||
|  | static int sxgbe_platform_remove(struct platform_device *pdev) | ||||||
|  | { | ||||||
|  | 	struct net_device *ndev = platform_get_drvdata(pdev); | ||||||
|  | 	int ret = sxgbe_drv_remove(ndev); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_PM | ||||||
|  | static int sxgbe_platform_suspend(struct device *dev) | ||||||
|  | { | ||||||
|  | 	struct net_device *ndev = dev_get_drvdata(dev); | ||||||
|  | 
 | ||||||
|  | 	return sxgbe_suspend(ndev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sxgbe_platform_resume(struct device *dev) | ||||||
|  | { | ||||||
|  | 	struct net_device *ndev = dev_get_drvdata(dev); | ||||||
|  | 
 | ||||||
|  | 	return sxgbe_resume(ndev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sxgbe_platform_freeze(struct device *dev) | ||||||
|  | { | ||||||
|  | 	struct net_device *ndev = dev_get_drvdata(dev); | ||||||
|  | 
 | ||||||
|  | 	return sxgbe_freeze(ndev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sxgbe_platform_restore(struct device *dev) | ||||||
|  | { | ||||||
|  | 	struct net_device *ndev = dev_get_drvdata(dev); | ||||||
|  | 
 | ||||||
|  | 	return sxgbe_restore(ndev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct dev_pm_ops sxgbe_platform_pm_ops = { | ||||||
|  | 	.suspend	= sxgbe_platform_suspend, | ||||||
|  | 	.resume		= sxgbe_platform_resume, | ||||||
|  | 	.freeze		= sxgbe_platform_freeze, | ||||||
|  | 	.thaw		= sxgbe_platform_restore, | ||||||
|  | 	.restore	= sxgbe_platform_restore, | ||||||
|  | }; | ||||||
|  | #else | ||||||
|  | static const struct dev_pm_ops sxgbe_platform_pm_ops; | ||||||
|  | #endif /* CONFIG_PM */ | ||||||
|  | 
 | ||||||
|  | static const struct of_device_id sxgbe_dt_ids[] = { | ||||||
|  | 	{ .compatible = "samsung,sxgbe-v2.0a"}, | ||||||
|  | 	{ /* sentinel */ } | ||||||
|  | }; | ||||||
|  | MODULE_DEVICE_TABLE(of, sxgbe_dt_ids); | ||||||
|  | 
 | ||||||
|  | struct platform_driver sxgbe_platform_driver = { | ||||||
|  | 	.probe	= sxgbe_platform_probe, | ||||||
|  | 	.remove	= sxgbe_platform_remove, | ||||||
|  | 	.driver	= { | ||||||
|  | 		.name		= SXGBE_RESOURCE_NAME, | ||||||
|  | 		.owner		= THIS_MODULE, | ||||||
|  | 		.pm		= &sxgbe_platform_pm_ops, | ||||||
|  | 		.of_match_table	= of_match_ptr(sxgbe_dt_ids), | ||||||
|  | 	}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | int sxgbe_register_platform(void) | ||||||
|  | { | ||||||
|  | 	int err; | ||||||
|  | 
 | ||||||
|  | 	err = platform_driver_register(&sxgbe_platform_driver); | ||||||
|  | 	if (err) | ||||||
|  | 		pr_err("failed to register the platform driver\n"); | ||||||
|  | 
 | ||||||
|  | 	return err; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void sxgbe_unregister_platform(void) | ||||||
|  | { | ||||||
|  | 	platform_driver_unregister(&sxgbe_platform_driver); | ||||||
|  | } | ||||||
							
								
								
									
										477
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										477
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,477 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #ifndef __SXGBE_REGMAP_H__ | ||||||
|  | #define __SXGBE_REGMAP_H__ | ||||||
|  | 
 | ||||||
|  | /* SXGBE MAC Registers */ | ||||||
|  | #define SXGBE_CORE_TX_CONFIG_REG	0x0000 | ||||||
|  | #define SXGBE_CORE_RX_CONFIG_REG	0x0004 | ||||||
|  | #define SXGBE_CORE_PKT_FILTER_REG	0x0008 | ||||||
|  | #define SXGBE_CORE_WATCHDOG_TIMEOUT_REG 0x000C | ||||||
|  | #define SXGBE_CORE_HASH_TABLE_REG0	0x0010 | ||||||
|  | #define SXGBE_CORE_HASH_TABLE_REG1	0x0014 | ||||||
|  | #define SXGBE_CORE_HASH_TABLE_REG2	0x0018 | ||||||
|  | #define SXGBE_CORE_HASH_TABLE_REG3	0x001C | ||||||
|  | #define SXGBE_CORE_HASH_TABLE_REG4	0x0020 | ||||||
|  | #define SXGBE_CORE_HASH_TABLE_REG5	0x0024 | ||||||
|  | #define SXGBE_CORE_HASH_TABLE_REG6	0x0028 | ||||||
|  | #define SXGBE_CORE_HASH_TABLE_REG7	0x002C | ||||||
|  | /* VLAN Specific Registers */ | ||||||
|  | #define SXGBE_CORE_VLAN_TAG_REG		0x0050 | ||||||
|  | #define SXGBE_CORE_VLAN_HASHTAB_REG	0x0058 | ||||||
|  | #define SXGBE_CORE_VLAN_INSCTL_REG	0x0060 | ||||||
|  | #define SXGBE_CORE_VLAN_INNERCTL_REG	0x0064 | ||||||
|  | #define SXGBE_CORE_RX_ETHTYPE_MATCH_REG 0x006C | ||||||
|  | 
 | ||||||
|  | /* Flow Contol Registers */ | ||||||
|  | #define SXGBE_CORE_TX_Q0_FLOWCTL_REG	0x0070 | ||||||
|  | #define SXGBE_CORE_TX_Q1_FLOWCTL_REG	0x0074 | ||||||
|  | #define SXGBE_CORE_TX_Q2_FLOWCTL_REG	0x0078 | ||||||
|  | #define SXGBE_CORE_TX_Q3_FLOWCTL_REG	0x007C | ||||||
|  | #define SXGBE_CORE_TX_Q4_FLOWCTL_REG	0x0080 | ||||||
|  | #define SXGBE_CORE_TX_Q5_FLOWCTL_REG	0x0084 | ||||||
|  | #define SXGBE_CORE_TX_Q6_FLOWCTL_REG	0x0088 | ||||||
|  | #define SXGBE_CORE_TX_Q7_FLOWCTL_REG	0x008C | ||||||
|  | #define SXGBE_CORE_RX_FLOWCTL_REG	0x0090 | ||||||
|  | #define SXGBE_CORE_RX_CTL0_REG		0x00A0 | ||||||
|  | #define SXGBE_CORE_RX_CTL1_REG		0x00A4 | ||||||
|  | #define SXGBE_CORE_RX_CTL2_REG		0x00A8 | ||||||
|  | #define SXGBE_CORE_RX_CTL3_REG		0x00AC | ||||||
|  | 
 | ||||||
|  | /* Interrupt Registers */ | ||||||
|  | #define SXGBE_CORE_INT_STATUS_REG	0x00B0 | ||||||
|  | #define SXGBE_CORE_INT_ENABLE_REG	0x00B4 | ||||||
|  | #define SXGBE_CORE_RXTX_ERR_STATUS_REG	0x00B8 | ||||||
|  | #define SXGBE_CORE_PMT_CTL_STATUS_REG	0x00C0 | ||||||
|  | #define SXGBE_CORE_RWK_PKT_FILTER_REG	0x00C4 | ||||||
|  | #define SXGBE_CORE_VERSION_REG		0x0110 | ||||||
|  | #define SXGBE_CORE_DEBUG_REG		0x0114 | ||||||
|  | #define SXGBE_CORE_HW_FEA_REG(index)	(0x011C + index * 4) | ||||||
|  | 
 | ||||||
|  | /* SMA(MDIO) module registers */ | ||||||
|  | #define SXGBE_MDIO_SCMD_ADD_REG		0x0200 | ||||||
|  | #define SXGBE_MDIO_SCMD_DATA_REG	0x0204 | ||||||
|  | #define SXGBE_MDIO_CCMD_WADD_REG	0x0208 | ||||||
|  | #define SXGBE_MDIO_CCMD_WDATA_REG	0x020C | ||||||
|  | #define SXGBE_MDIO_CSCAN_PORT_REG	0x0210 | ||||||
|  | #define SXGBE_MDIO_INT_STATUS_REG	0x0214 | ||||||
|  | #define SXGBE_MDIO_INT_ENABLE_REG	0x0218 | ||||||
|  | #define SXGBE_MDIO_PORT_CONDCON_REG	0x021C | ||||||
|  | #define SXGBE_MDIO_CLAUSE22_PORT_REG	0x0220 | ||||||
|  | 
 | ||||||
|  | /* port specific, addr = 0-3 */ | ||||||
|  | #define SXGBE_MDIO_DEV_BASE_REG		0x0230 | ||||||
|  | #define SXGBE_MDIO_PORT_DEV_REG(addr)			\ | ||||||
|  | 	(SXGBE_MDIO_DEV_BASE_REG + (0x10 * addr) + 0x0) | ||||||
|  | #define SXGBE_MDIO_PORT_LSTATUS_REG(addr)		\ | ||||||
|  | 	(SXGBE_MDIO_DEV_BASE_REG + (0x10 * addr) + 0x4) | ||||||
|  | #define SXGBE_MDIO_PORT_ALIVE_REG(addr)			\ | ||||||
|  | 	(SXGBE_MDIO_DEV_BASE_REG + (0x10 * addr) + 0x8) | ||||||
|  | 
 | ||||||
|  | #define SXGBE_CORE_GPIO_CTL_REG		0x0278 | ||||||
|  | #define SXGBE_CORE_GPIO_STATUS_REG	0x027C | ||||||
|  | 
 | ||||||
|  | /* Address registers for filtering */ | ||||||
|  | #define SXGBE_CORE_ADD_BASE_REG		0x0300 | ||||||
|  | 
 | ||||||
|  | /* addr = 0-31 */ | ||||||
|  | #define SXGBE_CORE_ADD_HIGHOFFSET(addr)			\ | ||||||
|  | 	(SXGBE_CORE_ADD_BASE_REG + (0x8 * addr) + 0x0) | ||||||
|  | #define SXGBE_CORE_ADD_LOWOFFSET(addr)			\ | ||||||
|  | 	(SXGBE_CORE_ADD_BASE_REG + (0x8 * addr) + 0x4) | ||||||
|  | 
 | ||||||
|  | /* SXGBE MMC registers */ | ||||||
|  | #define SXGBE_MMC_CTL_REG		0x0800 | ||||||
|  | #define SXGBE_MMC_RXINT_STATUS_REG	0x0804 | ||||||
|  | #define SXGBE_MMC_TXINT_STATUS_REG	0x0808 | ||||||
|  | #define SXGBE_MMC_RXINT_ENABLE_REG	0x080C | ||||||
|  | #define SXGBE_MMC_TXINT_ENABLE_REG	0x0810 | ||||||
|  | 
 | ||||||
|  | /* TX specific counters */ | ||||||
|  | #define SXGBE_MMC_TXOCTETHI_GBCNT_REG	0x0814 | ||||||
|  | #define SXGBE_MMC_TXOCTETLO_GBCNT_REG	0x0818 | ||||||
|  | #define SXGBE_MMC_TXFRAMELO_GBCNT_REG	0x081C | ||||||
|  | #define SXGBE_MMC_TXFRAMEHI_GBCNT_REG	0x0820 | ||||||
|  | #define SXGBE_MMC_TXBROADLO_GCNT_REG	0x0824 | ||||||
|  | #define SXGBE_MMC_TXBROADHI_GCNT_REG	0x0828 | ||||||
|  | #define SXGBE_MMC_TXMULTILO_GCNT_REG	0x082C | ||||||
|  | #define SXGBE_MMC_TXMULTIHI_GCNT_REG	0x0830 | ||||||
|  | #define SXGBE_MMC_TX64LO_GBCNT_REG	0x0834 | ||||||
|  | #define SXGBE_MMC_TX64HI_GBCNT_REG	0x0838 | ||||||
|  | #define SXGBE_MMC_TX65TO127LO_GBCNT_REG		0x083C | ||||||
|  | #define SXGBE_MMC_TX65TO127HI_GBCNT_REG		0x0840 | ||||||
|  | #define SXGBE_MMC_TX128TO255LO_GBCNT_REG	0x0844 | ||||||
|  | #define SXGBE_MMC_TX128TO255HI_GBCNT_REG	0x0848 | ||||||
|  | #define SXGBE_MMC_TX256TO511LO_GBCNT_REG	0x084C | ||||||
|  | #define SXGBE_MMC_TX256TO511HI_GBCNT_REG	0x0850 | ||||||
|  | #define SXGBE_MMC_TX512TO1023LO_GBCNT_REG	0x0854 | ||||||
|  | #define SXGBE_MMC_TX512TO1023HI_GBCNT_REG	0x0858 | ||||||
|  | #define SXGBE_MMC_TX1023TOMAXLO_GBCNT_REG	0x085C | ||||||
|  | #define SXGBE_MMC_TX1023TOMAXHI_GBCNT_REG	0x0860 | ||||||
|  | #define SXGBE_MMC_TXUNICASTLO_GBCNT_REG		0x0864 | ||||||
|  | #define SXGBE_MMC_TXUNICASTHI_GBCNT_REG		0x0868 | ||||||
|  | #define SXGBE_MMC_TXMULTILO_GBCNT_REG		0x086C | ||||||
|  | #define SXGBE_MMC_TXMULTIHI_GBCNT_REG		0x0870 | ||||||
|  | #define SXGBE_MMC_TXBROADLO_GBCNT_REG		0x0874 | ||||||
|  | #define SXGBE_MMC_TXBROADHI_GBCNT_REG		0x0878 | ||||||
|  | #define SXGBE_MMC_TXUFLWLO_GBCNT_REG		0x087C | ||||||
|  | #define SXGBE_MMC_TXUFLWHI_GBCNT_REG		0x0880 | ||||||
|  | #define SXGBE_MMC_TXOCTETLO_GCNT_REG	0x0884 | ||||||
|  | #define SXGBE_MMC_TXOCTETHI_GCNT_REG	0x0888 | ||||||
|  | #define SXGBE_MMC_TXFRAMELO_GCNT_REG	0x088C | ||||||
|  | #define SXGBE_MMC_TXFRAMEHI_GCNT_REG	0x0890 | ||||||
|  | #define SXGBE_MMC_TXPAUSELO_CNT_REG	0x0894 | ||||||
|  | #define SXGBE_MMC_TXPAUSEHI_CNT_REG	0x0898 | ||||||
|  | #define SXGBE_MMC_TXVLANLO_GCNT_REG	0x089C | ||||||
|  | #define SXGBE_MMC_TXVLANHI_GCNT_REG	0x08A0 | ||||||
|  | 
 | ||||||
|  | /* RX specific counters */ | ||||||
|  | #define SXGBE_MMC_RXFRAMELO_GBCNT_REG	0x0900 | ||||||
|  | #define SXGBE_MMC_RXFRAMEHI_GBCNT_REG	0x0904 | ||||||
|  | #define SXGBE_MMC_RXOCTETLO_GBCNT_REG	0x0908 | ||||||
|  | #define SXGBE_MMC_RXOCTETHI_GBCNT_REG	0x090C | ||||||
|  | #define SXGBE_MMC_RXOCTETLO_GCNT_REG	0x0910 | ||||||
|  | #define SXGBE_MMC_RXOCTETHI_GCNT_REG	0x0914 | ||||||
|  | #define SXGBE_MMC_RXBROADLO_GCNT_REG	0x0918 | ||||||
|  | #define SXGBE_MMC_RXBROADHI_GCNT_REG	0x091C | ||||||
|  | #define SXGBE_MMC_RXMULTILO_GCNT_REG	0x0920 | ||||||
|  | #define SXGBE_MMC_RXMULTIHI_GCNT_REG	0x0924 | ||||||
|  | #define SXGBE_MMC_RXCRCERRLO_REG	0x0928 | ||||||
|  | #define SXGBE_MMC_RXCRCERRHI_REG	0x092C | ||||||
|  | #define SXGBE_MMC_RXSHORT64BFRAME_ERR_REG	0x0930 | ||||||
|  | #define SXGBE_MMC_RXJABBERERR_REG		0x0934 | ||||||
|  | #define SXGBE_MMC_RXSHORT64BFRAME_COR_REG	0x0938 | ||||||
|  | #define SXGBE_MMC_RXOVERMAXFRAME_COR_REG	0x093C | ||||||
|  | #define SXGBE_MMC_RX64LO_GBCNT_REG		0x0940 | ||||||
|  | #define SXGBE_MMC_RX64HI_GBCNT_REG		0x0944 | ||||||
|  | #define SXGBE_MMC_RX65TO127LO_GBCNT_REG		0x0948 | ||||||
|  | #define SXGBE_MMC_RX65TO127HI_GBCNT_REG		0x094C | ||||||
|  | #define SXGBE_MMC_RX128TO255LO_GBCNT_REG	0x0950 | ||||||
|  | #define SXGBE_MMC_RX128TO255HI_GBCNT_REG	0x0954 | ||||||
|  | #define SXGBE_MMC_RX256TO511LO_GBCNT_REG	0x0958 | ||||||
|  | #define SXGBE_MMC_RX256TO511HI_GBCNT_REG	0x095C | ||||||
|  | #define SXGBE_MMC_RX512TO1023LO_GBCNT_REG	0x0960 | ||||||
|  | #define SXGBE_MMC_RX512TO1023HI_GBCNT_REG	0x0964 | ||||||
|  | #define SXGBE_MMC_RX1023TOMAXLO_GBCNT_REG	0x0968 | ||||||
|  | #define SXGBE_MMC_RX1023TOMAXHI_GBCNT_REG	0x096C | ||||||
|  | #define SXGBE_MMC_RXUNICASTLO_GCNT_REG		0x0970 | ||||||
|  | #define SXGBE_MMC_RXUNICASTHI_GCNT_REG		0x0974 | ||||||
|  | #define SXGBE_MMC_RXLENERRLO_REG		0x0978 | ||||||
|  | #define SXGBE_MMC_RXLENERRHI_REG		0x097C | ||||||
|  | #define SXGBE_MMC_RXOUTOFRANGETYPELO_REG	0x0980 | ||||||
|  | #define SXGBE_MMC_RXOUTOFRANGETYPEHI_REG	0x0984 | ||||||
|  | #define SXGBE_MMC_RXPAUSELO_CNT_REG		0x0988 | ||||||
|  | #define SXGBE_MMC_RXPAUSEHI_CNT_REG		0x098C | ||||||
|  | #define SXGBE_MMC_RXFIFOOVERFLOWLO_GBCNT_REG	0x0990 | ||||||
|  | #define SXGBE_MMC_RXFIFOOVERFLOWHI_GBCNT_REG	0x0994 | ||||||
|  | #define SXGBE_MMC_RXVLANLO_GBCNT_REG		0x0998 | ||||||
|  | #define SXGBE_MMC_RXVLANHI_GBCNT_REG		0x099C | ||||||
|  | #define SXGBE_MMC_RXWATCHDOG_ERR_REG		0x09A0 | ||||||
|  | 
 | ||||||
|  | /* L3/L4 function registers */ | ||||||
|  | #define SXGBE_CORE_L34_ADDCTL_REG	0x0C00 | ||||||
|  | #define SXGBE_CORE_L34_ADDCTL_REG	0x0C00 | ||||||
|  | #define SXGBE_CORE_L34_DATA_REG		0x0C04 | ||||||
|  | 
 | ||||||
|  | /* ARP registers */ | ||||||
|  | #define SXGBE_CORE_ARP_ADD_REG		0x0C10 | ||||||
|  | 
 | ||||||
|  | /* RSS registers */ | ||||||
|  | #define SXGBE_CORE_RSS_CTL_REG		0x0C80 | ||||||
|  | #define SXGBE_CORE_RSS_ADD_REG		0x0C88 | ||||||
|  | #define SXGBE_CORE_RSS_DATA_REG		0x0C8C | ||||||
|  | 
 | ||||||
|  | /* IEEE 1588 registers */ | ||||||
|  | #define SXGBE_CORE_TSTAMP_CTL_REG	0x0D00 | ||||||
|  | #define SXGBE_CORE_SUBSEC_INC_REG	0x0D04 | ||||||
|  | #define SXGBE_CORE_SYSTIME_SEC_REG	0x0D0C | ||||||
|  | #define SXGBE_CORE_SYSTIME_NSEC_REG	0x0D10 | ||||||
|  | #define SXGBE_CORE_SYSTIME_SECUP_REG	0x0D14 | ||||||
|  | #define SXGBE_CORE_TSTAMP_ADD_REG	0x0D18 | ||||||
|  | #define SXGBE_CORE_SYSTIME_HWORD_REG	0x0D1C | ||||||
|  | #define SXGBE_CORE_TSTAMP_STATUS_REG	0x0D20 | ||||||
|  | #define SXGBE_CORE_TXTIME_STATUSNSEC_REG 0x0D30 | ||||||
|  | #define SXGBE_CORE_TXTIME_STATUSSEC_REG	0x0D34 | ||||||
|  | 
 | ||||||
|  | /* Auxiliary registers */ | ||||||
|  | #define SXGBE_CORE_AUX_CTL_REG			 0x0D40 | ||||||
|  | #define SXGBE_CORE_AUX_TSTAMP_NSEC_REG		 0x0D48 | ||||||
|  | #define SXGBE_CORE_AUX_TSTAMP_SEC_REG		 0x0D4C | ||||||
|  | #define SXGBE_CORE_AUX_TSTAMP_INGCOR_REG	 0x0D50 | ||||||
|  | #define SXGBE_CORE_AUX_TSTAMP_ENGCOR_REG	 0x0D54 | ||||||
|  | #define SXGBE_CORE_AUX_TSTAMP_INGCOR_NSEC_REG	 0x0D58 | ||||||
|  | #define SXGBE_CORE_AUX_TSTAMP_INGCOR_SUBNSEC_REG 0x0D5C | ||||||
|  | #define SXGBE_CORE_AUX_TSTAMP_ENGCOR_NSEC_REG	 0x0D60 | ||||||
|  | #define SXGBE_CORE_AUX_TSTAMP_ENGCOR_SUBNSEC_REG 0x0D64 | ||||||
|  | 
 | ||||||
|  | /* PPS registers */ | ||||||
|  | #define SXGBE_CORE_PPS_CTL_REG		0x0D70 | ||||||
|  | #define SXGBE_CORE_PPS_BASE			0x0D80 | ||||||
|  | 
 | ||||||
|  | /* addr = 0 - 3 */ | ||||||
|  | #define SXGBE_CORE_PPS_TTIME_SEC_REG(addr)		\ | ||||||
|  | 	(SXGBE_CORE_PPS_BASE + (0x10 * addr) + 0x0) | ||||||
|  | #define SXGBE_CORE_PPS_TTIME_NSEC_REG(addr)		\ | ||||||
|  | 	(SXGBE_CORE_PPS_BASE + (0x10 * addr) + 0x4) | ||||||
|  | #define SXGBE_CORE_PPS_INTERVAL_REG(addr)		\ | ||||||
|  | 	(SXGBE_CORE_PPS_BASE + (0x10 * addr) + 0x8) | ||||||
|  | #define SXGBE_CORE_PPS_WIDTH_REG(addr)			\ | ||||||
|  | 	(SXGBE_CORE_PPS_BASE + (0x10 * addr) + 0xC) | ||||||
|  | #define SXGBE_CORE_PTO_CTL_REG		0x0DC0 | ||||||
|  | #define SXGBE_CORE_SRCPORT_ITY0_REG	0x0DC4 | ||||||
|  | #define SXGBE_CORE_SRCPORT_ITY1_REG	0x0DC8 | ||||||
|  | #define SXGBE_CORE_SRCPORT_ITY2_REG	0x0DCC | ||||||
|  | #define SXGBE_CORE_LOGMSG_LEVEL_REG	0x0DD0 | ||||||
|  | 
 | ||||||
|  | /* SXGBE MTL Registers */ | ||||||
|  | #define SXGBE_MTL_BASE_REG		0x1000 | ||||||
|  | #define SXGBE_MTL_OP_MODE_REG		(SXGBE_MTL_BASE_REG + 0x0000) | ||||||
|  | #define SXGBE_MTL_DEBUG_CTL_REG		(SXGBE_MTL_BASE_REG + 0x0008) | ||||||
|  | #define SXGBE_MTL_DEBUG_STATUS_REG	(SXGBE_MTL_BASE_REG + 0x000C) | ||||||
|  | #define SXGBE_MTL_FIFO_DEBUGDATA_REG	(SXGBE_MTL_BASE_REG + 0x0010) | ||||||
|  | #define SXGBE_MTL_INT_STATUS_REG	(SXGBE_MTL_BASE_REG + 0x0020) | ||||||
|  | #define SXGBE_MTL_RXQ_DMAMAP0_REG	(SXGBE_MTL_BASE_REG + 0x0030) | ||||||
|  | #define SXGBE_MTL_RXQ_DMAMAP1_REG	(SXGBE_MTL_BASE_REG + 0x0034) | ||||||
|  | #define SXGBE_MTL_RXQ_DMAMAP2_REG	(SXGBE_MTL_BASE_REG + 0x0038) | ||||||
|  | #define SXGBE_MTL_TX_PRTYMAP0_REG	(SXGBE_MTL_BASE_REG + 0x0040) | ||||||
|  | #define SXGBE_MTL_TX_PRTYMAP1_REG	(SXGBE_MTL_BASE_REG + 0x0044) | ||||||
|  | 
 | ||||||
|  | /* TC/Queue registers, qnum=0-15 */ | ||||||
|  | #define SXGBE_MTL_TC_TXBASE_REG		(SXGBE_MTL_BASE_REG + 0x0100) | ||||||
|  | #define SXGBE_MTL_TXQ_OPMODE_REG(qnum)				\ | ||||||
|  | 	(SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x00) | ||||||
|  | #define SXGBE_MTL_SFMODE		BIT(1) | ||||||
|  | #define SXGBE_MTL_FIFO_LSHIFT		16 | ||||||
|  | #define SXGBE_MTL_ENABLE_QUEUE		0x00000008 | ||||||
|  | #define SXGBE_MTL_TXQ_UNDERFLOW_REG(qnum)			\ | ||||||
|  | 	(SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x04) | ||||||
|  | #define SXGBE_MTL_TXQ_DEBUG_REG(qnum)				\ | ||||||
|  | 	(SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x08) | ||||||
|  | #define SXGBE_MTL_TXQ_ETSCTL_REG(qnum)				\ | ||||||
|  | 	(SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x10) | ||||||
|  | #define SXGBE_MTL_TXQ_ETSSTATUS_REG(qnum)			\ | ||||||
|  | 	(SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x14) | ||||||
|  | #define SXGBE_MTL_TXQ_QUANTWEIGHT_REG(qnum)			\ | ||||||
|  | 	(SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x18) | ||||||
|  | 
 | ||||||
|  | #define SXGBE_MTL_TC_RXBASE_REG		0x1140 | ||||||
|  | #define SXGBE_RX_MTL_SFMODE		BIT(5) | ||||||
|  | #define SXGBE_MTL_RXQ_OPMODE_REG(qnum)				\ | ||||||
|  | 	(SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x00) | ||||||
|  | #define SXGBE_MTL_RXQ_MISPKTOVERFLOW_REG(qnum)			\ | ||||||
|  | 	(SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x04) | ||||||
|  | #define SXGBE_MTL_RXQ_DEBUG_REG(qnum)				\ | ||||||
|  | 	(SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x08) | ||||||
|  | #define SXGBE_MTL_RXQ_CTL_REG(qnum)				\ | ||||||
|  | 	(SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x0C) | ||||||
|  | #define SXGBE_MTL_RXQ_INTENABLE_REG(qnum)			\ | ||||||
|  | 	(SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x30) | ||||||
|  | #define SXGBE_MTL_RXQ_INTSTATUS_REG(qnum)			\ | ||||||
|  | 	(SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x34) | ||||||
|  | 
 | ||||||
|  | /* SXGBE DMA Registers */ | ||||||
|  | #define SXGBE_DMA_BASE_REG		0x3000 | ||||||
|  | #define SXGBE_DMA_MODE_REG		(SXGBE_DMA_BASE_REG + 0x0000) | ||||||
|  | #define SXGBE_DMA_SOFT_RESET		BIT(0) | ||||||
|  | #define SXGBE_DMA_SYSBUS_MODE_REG	(SXGBE_DMA_BASE_REG + 0x0004) | ||||||
|  | #define SXGBE_DMA_AXI_UNDEF_BURST	BIT(0) | ||||||
|  | #define SXGBE_DMA_ENHACE_ADDR_MODE	BIT(11) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_REG	(SXGBE_DMA_BASE_REG + 0x0008) | ||||||
|  | #define SXGBE_DMA_AXI_ARCACHECTL_REG	(SXGBE_DMA_BASE_REG + 0x0010) | ||||||
|  | #define SXGBE_DMA_AXI_AWCACHECTL_REG	(SXGBE_DMA_BASE_REG + 0x0018) | ||||||
|  | #define SXGBE_DMA_DEBUG_STATUS0_REG	(SXGBE_DMA_BASE_REG + 0x0020) | ||||||
|  | #define SXGBE_DMA_DEBUG_STATUS1_REG	(SXGBE_DMA_BASE_REG + 0x0024) | ||||||
|  | #define SXGBE_DMA_DEBUG_STATUS2_REG	(SXGBE_DMA_BASE_REG + 0x0028) | ||||||
|  | #define SXGBE_DMA_DEBUG_STATUS3_REG	(SXGBE_DMA_BASE_REG + 0x002C) | ||||||
|  | #define SXGBE_DMA_DEBUG_STATUS4_REG	(SXGBE_DMA_BASE_REG + 0x0030) | ||||||
|  | #define SXGBE_DMA_DEBUG_STATUS5_REG	(SXGBE_DMA_BASE_REG + 0x0034) | ||||||
|  | 
 | ||||||
|  | /* Channel Registers, cha_num = 0-15 */ | ||||||
|  | #define SXGBE_DMA_CHA_BASE_REG			\ | ||||||
|  | 	(SXGBE_DMA_BASE_REG + 0x0100) | ||||||
|  | #define SXGBE_DMA_CHA_CTL_REG(cha_num)				\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x00) | ||||||
|  | #define SXGBE_DMA_PBL_X8MODE			BIT(16) | ||||||
|  | #define SXGBE_DMA_CHA_TXCTL_TSE_ENABLE		BIT(12) | ||||||
|  | #define SXGBE_DMA_CHA_TXCTL_REG(cha_num)			\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x04) | ||||||
|  | #define SXGBE_DMA_CHA_RXCTL_REG(cha_num)			\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x08) | ||||||
|  | #define SXGBE_DMA_CHA_TXDESC_HADD_REG(cha_num)			\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x10) | ||||||
|  | #define SXGBE_DMA_CHA_TXDESC_LADD_REG(cha_num)			\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x14) | ||||||
|  | #define SXGBE_DMA_CHA_RXDESC_HADD_REG(cha_num)			\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x18) | ||||||
|  | #define SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num)			\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x1C) | ||||||
|  | #define SXGBE_DMA_CHA_TXDESC_TAILPTR_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x24) | ||||||
|  | #define SXGBE_DMA_CHA_RXDESC_TAILPTR_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x2C) | ||||||
|  | #define SXGBE_DMA_CHA_TXDESC_RINGLEN_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x30) | ||||||
|  | #define SXGBE_DMA_CHA_RXDESC_RINGLEN_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x34) | ||||||
|  | #define SXGBE_DMA_CHA_INT_ENABLE_REG(cha_num)			\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x38) | ||||||
|  | #define SXGBE_DMA_CHA_INT_RXWATCHTMR_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x3C) | ||||||
|  | #define SXGBE_DMA_CHA_TXDESC_CURADDLO_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x44) | ||||||
|  | #define SXGBE_DMA_CHA_RXDESC_CURADDLO_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x4C) | ||||||
|  | #define SXGBE_DMA_CHA_CURTXBUF_ADDHI_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x50) | ||||||
|  | #define SXGBE_DMA_CHA_CURTXBUF_ADDLO_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x54) | ||||||
|  | #define SXGBE_DMA_CHA_CURRXBUF_ADDHI_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x58) | ||||||
|  | #define SXGBE_DMA_CHA_CURRXBUF_ADDLO_REG(cha_num)		\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x5C) | ||||||
|  | #define SXGBE_DMA_CHA_STATUS_REG(cha_num)			\ | ||||||
|  | 	(SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x60) | ||||||
|  | 
 | ||||||
|  | /* TX DMA control register specific */ | ||||||
|  | #define SXGBE_TX_START_DMA	BIT(0) | ||||||
|  | 
 | ||||||
|  | /* sxgbe tx configuration register bitfields */ | ||||||
|  | #define SXGBE_SPEED_10G		0x0 | ||||||
|  | #define SXGBE_SPEED_2_5G	0x1 | ||||||
|  | #define SXGBE_SPEED_1G		0x2 | ||||||
|  | #define SXGBE_SPEED_LSHIFT	29 | ||||||
|  | 
 | ||||||
|  | #define SXGBE_TX_ENABLE		BIT(0) | ||||||
|  | #define SXGBE_TX_DISDIC_ALGO	BIT(1) | ||||||
|  | #define SXGBE_TX_JABBER_DISABLE	BIT(16) | ||||||
|  | 
 | ||||||
|  | /* sxgbe rx configuration register bitfields */ | ||||||
|  | #define SXGBE_RX_ENABLE		BIT(0) | ||||||
|  | #define SXGBE_RX_ACS_ENABLE		BIT(1) | ||||||
|  | #define SXGBE_RX_WATCHDOG_DISABLE	BIT(7) | ||||||
|  | #define SXGBE_RX_JUMBPKT_ENABLE		BIT(8) | ||||||
|  | #define SXGBE_RX_CSUMOFFLOAD_ENABLE	BIT(9) | ||||||
|  | #define SXGBE_RX_LOOPBACK_ENABLE	BIT(10) | ||||||
|  | #define SXGBE_RX_ARPOFFLOAD_ENABLE	BIT(31) | ||||||
|  | 
 | ||||||
|  | /* sxgbe vlan Tag Register bitfields */ | ||||||
|  | #define SXGBE_VLAN_SVLAN_ENABLE		BIT(18) | ||||||
|  | #define SXGBE_VLAN_DOUBLEVLAN_ENABLE	BIT(26) | ||||||
|  | #define SXGBE_VLAN_INNERVLAN_ENABLE	BIT(27) | ||||||
|  | 
 | ||||||
|  | /* XMAC VLAN Tag Inclusion Register(0x0060) bitfields
 | ||||||
|  |  * Below fields same for  Inner VLAN Tag Inclusion | ||||||
|  |  * Register(0x0064) register | ||||||
|  |  */ | ||||||
|  | enum vlan_tag_ctl_tx { | ||||||
|  | 	VLAN_TAG_TX_NOP, | ||||||
|  | 	VLAN_TAG_TX_DEL, | ||||||
|  | 	VLAN_TAG_TX_INSERT, | ||||||
|  | 	VLAN_TAG_TX_REPLACE | ||||||
|  | }; | ||||||
|  | #define SXGBE_VLAN_PRTY_CTL	BIT(18) | ||||||
|  | #define SXGBE_VLAN_CSVL_CTL	BIT(19) | ||||||
|  | 
 | ||||||
|  | /* SXGBE TX Q Flow Control Register bitfields */ | ||||||
|  | #define SXGBE_TX_FLOW_CTL_FCB	BIT(0) | ||||||
|  | #define SXGBE_TX_FLOW_CTL_TFB	BIT(1) | ||||||
|  | 
 | ||||||
|  | /* SXGBE RX Q Flow Control Register bitfields */ | ||||||
|  | #define SXGBE_RX_FLOW_CTL_ENABLE	BIT(0) | ||||||
|  | #define SXGBE_RX_UNICAST_DETECT		BIT(1) | ||||||
|  | #define SXGBE_RX_PRTYFLOW_CTL_ENABLE	BIT(8) | ||||||
|  | 
 | ||||||
|  | /* sxgbe rx Q control0 register bitfields */ | ||||||
|  | #define SXGBE_RX_Q_ENABLE	0x2 | ||||||
|  | 
 | ||||||
|  | /* SXGBE hardware features bitfield specific */ | ||||||
|  | /* Capability Register 0 */ | ||||||
|  | #define SXGBE_HW_FEAT_GMII(cap)			((cap & 0x00000002) >> 1) | ||||||
|  | #define SXGBE_HW_FEAT_VLAN_HASH_FILTER(cap)	((cap & 0x00000010) >> 4) | ||||||
|  | #define SXGBE_HW_FEAT_SMA(cap)			((cap & 0x00000020) >> 5) | ||||||
|  | #define SXGBE_HW_FEAT_PMT_TEMOTE_WOP(cap)	((cap & 0x00000040) >> 6) | ||||||
|  | #define SXGBE_HW_FEAT_PMT_MAGIC_PKT(cap)	((cap & 0x00000080) >> 7) | ||||||
|  | #define SXGBE_HW_FEAT_RMON(cap)			((cap & 0x00000100) >> 8) | ||||||
|  | #define SXGBE_HW_FEAT_ARP_OFFLOAD(cap)		((cap & 0x00000200) >> 9) | ||||||
|  | #define SXGBE_HW_FEAT_IEEE1500_2008(cap)	((cap & 0x00001000) >> 12) | ||||||
|  | #define SXGBE_HW_FEAT_EEE(cap)			((cap & 0x00002000) >> 13) | ||||||
|  | #define SXGBE_HW_FEAT_TX_CSUM_OFFLOAD(cap)	((cap & 0x00004000) >> 14) | ||||||
|  | #define SXGBE_HW_FEAT_RX_CSUM_OFFLOAD(cap)	((cap & 0x00010000) >> 16) | ||||||
|  | #define SXGBE_HW_FEAT_MACADDR_COUNT(cap)	((cap & 0x007C0000) >> 18) | ||||||
|  | #define SXGBE_HW_FEAT_TSTMAP_SRC(cap)		((cap & 0x06000000) >> 25) | ||||||
|  | #define SXGBE_HW_FEAT_SRCADDR_VLAN(cap)		((cap & 0x08000000) >> 27) | ||||||
|  | 
 | ||||||
|  | /* Capability Register 1 */ | ||||||
|  | #define SXGBE_HW_FEAT_RX_FIFO_SIZE(cap)		((cap & 0x0000001F)) | ||||||
|  | #define SXGBE_HW_FEAT_TX_FIFO_SIZE(cap)		((cap & 0x000007C0) >> 6) | ||||||
|  | #define SXGBE_HW_FEAT_IEEE1588_HWORD(cap)	((cap & 0x00002000) >> 13) | ||||||
|  | #define SXGBE_HW_FEAT_DCB(cap)			((cap & 0x00010000) >> 16) | ||||||
|  | #define SXGBE_HW_FEAT_SPLIT_HDR(cap)		((cap & 0x00020000) >> 17) | ||||||
|  | #define SXGBE_HW_FEAT_TSO(cap)			((cap & 0x00040000) >> 18) | ||||||
|  | #define SXGBE_HW_FEAT_DEBUG_MEM_IFACE(cap)	((cap & 0x00080000) >> 19) | ||||||
|  | #define SXGBE_HW_FEAT_RSS(cap)			((cap & 0x00100000) >> 20) | ||||||
|  | #define SXGBE_HW_FEAT_HASH_TABLE_SIZE(cap)	((cap & 0x03000000) >> 24) | ||||||
|  | #define SXGBE_HW_FEAT_L3L4_FILTER_NUM(cap)	((cap & 0x78000000) >> 27) | ||||||
|  | 
 | ||||||
|  | /* Capability Register 2 */ | ||||||
|  | #define SXGBE_HW_FEAT_RX_MTL_QUEUES(cap)	((cap & 0x0000000F)) | ||||||
|  | #define SXGBE_HW_FEAT_TX_MTL_QUEUES(cap)	((cap & 0x000003C0) >> 6) | ||||||
|  | #define SXGBE_HW_FEAT_RX_DMA_CHANNELS(cap)	((cap & 0x0000F000) >> 12) | ||||||
|  | #define SXGBE_HW_FEAT_TX_DMA_CHANNELS(cap)	((cap & 0x003C0000) >> 18) | ||||||
|  | #define SXGBE_HW_FEAT_PPS_OUTPUTS(cap)		((cap & 0x07000000) >> 24) | ||||||
|  | #define SXGBE_HW_FEAT_AUX_SNAPSHOTS(cap)	((cap & 0x70000000) >> 28) | ||||||
|  | 
 | ||||||
|  | /* DMAchannel interrupt enable specific */ | ||||||
|  | /* DMA Normal interrupt */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_NIE	BIT(16)	/* Normal Summary */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_TIE	BIT(0)	/* Transmit Interrupt */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_TUE	BIT(2)	/* Transmit Buffer Unavailable */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_RIE	BIT(6)	/* Receive Interrupt */ | ||||||
|  | 
 | ||||||
|  | #define SXGBE_DMA_INT_NORMAL					\ | ||||||
|  | 	(SXGBE_DMA_INT_ENA_NIE | SXGBE_DMA_INT_ENA_RIE |	\ | ||||||
|  | 	 SXGBE_DMA_INT_ENA_TIE | SXGBE_DMA_INT_ENA_TUE) | ||||||
|  | 
 | ||||||
|  | /* DMA Abnormal interrupt */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_AIE	BIT(15)	/* Abnormal Summary */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_TSE	BIT(1)	/* Transmit Stopped */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_RUE	BIT(7)	/* Receive Buffer Unavailable */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_RSE	BIT(8)	/* Receive Stopped */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_FBE	BIT(12)	/* Fatal Bus Error */ | ||||||
|  | #define SXGBE_DMA_INT_ENA_CDEE	BIT(13)	/* Context Descriptor Error */ | ||||||
|  | 
 | ||||||
|  | #define SXGBE_DMA_INT_ABNORMAL					\ | ||||||
|  | 	(SXGBE_DMA_INT_ENA_AIE | SXGBE_DMA_INT_ENA_TSE |	\ | ||||||
|  | 	 SXGBE_DMA_INT_ENA_RUE | SXGBE_DMA_INT_ENA_RSE |	\ | ||||||
|  | 	 SXGBE_DMA_INT_ENA_FBE | SXGBE_DMA_INT_ENA_CDEE) | ||||||
|  | 
 | ||||||
|  | #define SXGBE_DMA_ENA_INT	(SXGBE_DMA_INT_NORMAL | SXGBE_DMA_INT_ABNORMAL) | ||||||
|  | 
 | ||||||
|  | /* DMA channel interrupt status specific */ | ||||||
|  | #define	SXGBE_DMA_INT_STATUS_REB2	BIT(21) | ||||||
|  | #define	SXGBE_DMA_INT_STATUS_REB1	BIT(20) | ||||||
|  | #define	SXGBE_DMA_INT_STATUS_REB0	BIT(19) | ||||||
|  | #define	SXGBE_DMA_INT_STATUS_TEB2	BIT(18) | ||||||
|  | #define	SXGBE_DMA_INT_STATUS_TEB1	BIT(17) | ||||||
|  | #define	SXGBE_DMA_INT_STATUS_TEB0	BIT(16) | ||||||
|  | #define	SXGBE_DMA_INT_STATUS_NIS	BIT(15) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_AIS	BIT(14) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_CTXTERR	BIT(13) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_FBE	BIT(12) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_RPS	BIT(8) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_RBU	BIT(7) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_RI		BIT(6) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_TBU	BIT(2) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_TPS	BIT(1) | ||||||
|  | #define SXGBE_DMA_INT_STATUS_TI		BIT(0) | ||||||
|  | 
 | ||||||
|  | #endif /* __SXGBE_REGMAP_H__ */ | ||||||
							
								
								
									
										91
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #include <linux/bitops.h> | ||||||
|  | #include <linux/kernel.h> | ||||||
|  | #include <linux/netdevice.h> | ||||||
|  | #include <linux/phy.h> | ||||||
|  | #include "sxgbe_common.h" | ||||||
|  | #include "sxgbe_xpcs.h" | ||||||
|  | 
 | ||||||
|  | static int sxgbe_xpcs_read(struct net_device *ndev, unsigned int reg) | ||||||
|  | { | ||||||
|  | 	u32 value; | ||||||
|  | 	struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||||||
|  | 
 | ||||||
|  | 	value = readl(priv->ioaddr + XPCS_OFFSET + reg); | ||||||
|  | 
 | ||||||
|  | 	return value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int sxgbe_xpcs_write(struct net_device *ndev, int reg, int data) | ||||||
|  | { | ||||||
|  | 	struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||||||
|  | 
 | ||||||
|  | 	writel(data, priv->ioaddr + XPCS_OFFSET + reg); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sxgbe_xpcs_init(struct net_device *ndev) | ||||||
|  | { | ||||||
|  | 	u32 value; | ||||||
|  | 
 | ||||||
|  | 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||||||
|  | 	/* 10G XAUI mode */ | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X); | ||||||
|  | 	sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE); | ||||||
|  | 	sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, value | BIT(13)); | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11)); | ||||||
|  | 
 | ||||||
|  | 	do { | ||||||
|  | 		value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS); | ||||||
|  | 	} while ((value & XPCS_QSEQ_STATE_MPLLOFF) == XPCS_QSEQ_STATE_STABLE); | ||||||
|  | 
 | ||||||
|  | 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11)); | ||||||
|  | 
 | ||||||
|  | 	do { | ||||||
|  | 		value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS); | ||||||
|  | 	} while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int sxgbe_xpcs_init_1G(struct net_device *ndev) | ||||||
|  | { | ||||||
|  | 	int value; | ||||||
|  | 
 | ||||||
|  | 	/* 10GBASE-X PCS (1G) mode */ | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X); | ||||||
|  | 	sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE); | ||||||
|  | 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(13)); | ||||||
|  | 
 | ||||||
|  | 	value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL); | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(6)); | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value & ~BIT(13)); | ||||||
|  | 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11)); | ||||||
|  | 
 | ||||||
|  | 	do { | ||||||
|  | 		value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS); | ||||||
|  | 	} while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE); | ||||||
|  | 
 | ||||||
|  | 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11)); | ||||||
|  | 
 | ||||||
|  | 	/* Auto Negotiation cluase 37 enable */ | ||||||
|  | 	value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL); | ||||||
|  | 	sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(12)); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | /* 10G controller driver for Samsung SoCs
 | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Byungho An <bh74.an@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #ifndef __SXGBE_XPCS_H__ | ||||||
|  | #define __SXGBE_XPCS_H__ | ||||||
|  | 
 | ||||||
|  | /* XPCS Registers */ | ||||||
|  | #define XPCS_OFFSET			0x1A060000 | ||||||
|  | #define SR_PCS_MMD_CONTROL1		0x030000 | ||||||
|  | #define SR_PCS_CONTROL2			0x030007 | ||||||
|  | #define VR_PCS_MMD_XAUI_MODE_CONTROL	0x038004 | ||||||
|  | #define VR_PCS_MMD_DIGITAL_STATUS	0x038010 | ||||||
|  | #define SR_MII_MMD_CONTROL		0x1F0000 | ||||||
|  | #define SR_MII_MMD_AN_ADV		0x1F0004 | ||||||
|  | #define SR_MII_MMD_AN_LINK_PARTNER_BA	0x1F0005 | ||||||
|  | #define VR_MII_MMD_AN_CONTROL		0x1F8001 | ||||||
|  | #define VR_MII_MMD_AN_INT_STATUS	0x1F8002 | ||||||
|  | 
 | ||||||
|  | #define XPCS_QSEQ_STATE_STABLE		0x10 | ||||||
|  | #define XPCS_QSEQ_STATE_MPLLOFF		0x1c | ||||||
|  | #define XPCS_TYPE_SEL_R			0x00 | ||||||
|  | #define XPCS_TYPE_SEL_X			0x01 | ||||||
|  | #define XPCS_TYPE_SEL_W			0x02 | ||||||
|  | #define XPCS_XAUI_MODE			0x00 | ||||||
|  | #define XPCS_RXAUI_MODE			0x01 | ||||||
|  | 
 | ||||||
|  | int sxgbe_xpcs_init(struct net_device *ndev); | ||||||
|  | int sxgbe_xpcs_init_1G(struct net_device *ndev); | ||||||
|  | 
 | ||||||
|  | #endif /* __SXGBE_XPCS_H__ */ | ||||||
							
								
								
									
										54
									
								
								include/linux/sxgbe_platform.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								include/linux/sxgbe_platform.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | ||||||
|  | /*
 | ||||||
|  |  * 10G controller driver for Samsung EXYNOS SoCs | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||||||
|  |  *		http://www.samsung.com
 | ||||||
|  |  * | ||||||
|  |  * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||||||
|  |  * | ||||||
|  |  * This program is free software; you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License version 2 as | ||||||
|  |  * published by the Free Software Foundation. | ||||||
|  |  */ | ||||||
|  | #ifndef __SXGBE_PLATFORM_H__ | ||||||
|  | #define __SXGBE_PLATFORM_H__ | ||||||
|  | 
 | ||||||
|  | /* MDC Clock Selection define*/ | ||||||
|  | #define SXGBE_CSR_100_150M	0x0	/* MDC = clk_scr_i/62 */ | ||||||
|  | #define SXGBE_CSR_150_250M	0x1	/* MDC = clk_scr_i/102 */ | ||||||
|  | #define SXGBE_CSR_250_300M	0x2	/* MDC = clk_scr_i/122 */ | ||||||
|  | #define SXGBE_CSR_300_350M	0x3	/* MDC = clk_scr_i/142 */ | ||||||
|  | #define SXGBE_CSR_350_400M	0x4	/* MDC = clk_scr_i/162 */ | ||||||
|  | #define SXGBE_CSR_400_500M	0x5	/* MDC = clk_scr_i/202 */ | ||||||
|  | 
 | ||||||
|  | /* Platfrom data for platform device structure's
 | ||||||
|  |  * platform_data field | ||||||
|  |  */ | ||||||
|  | struct sxgbe_mdio_bus_data { | ||||||
|  | 	unsigned int phy_mask; | ||||||
|  | 	int *irqs; | ||||||
|  | 	int probed_phy_irq; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_dma_cfg { | ||||||
|  | 	int pbl; | ||||||
|  | 	int fixed_burst; | ||||||
|  | 	int burst_map; | ||||||
|  | 	int adv_addr_mode; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct sxgbe_plat_data { | ||||||
|  | 	char *phy_bus_name; | ||||||
|  | 	int bus_id; | ||||||
|  | 	int phy_addr; | ||||||
|  | 	int interface; | ||||||
|  | 	struct sxgbe_mdio_bus_data *mdio_bus_data; | ||||||
|  | 	struct sxgbe_dma_cfg *dma_cfg; | ||||||
|  | 	int clk_csr; | ||||||
|  | 	int pmt; | ||||||
|  | 	int force_sf_dma_mode; | ||||||
|  | 	int force_thresh_dma_mode; | ||||||
|  | 	int riwt_off; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif /* __SXGBE_PLATFORM_H__ */ | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Siva Reddy
				Siva Reddy