diff options
| author | Siva Reddy <siva.kallam@samsung.com> | 2014-03-25 15:10:54 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-03-26 16:49:31 -0400 |
| commit | 1edb9ca69e8a7988900fc0283e10550b5592164d (patch) | |
| tree | 268691e0c432357fb1a55ff35cb215263a4db576 /drivers/net/ethernet/samsung | |
| parent | 5221d3e66d74e2c90cd9f94acfd957da1ab1df4d (diff) | |
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>
Diffstat (limited to 'drivers/net/ethernet/samsung')
19 files changed, 5451 insertions, 0 deletions
diff --git a/drivers/net/ethernet/samsung/Kconfig b/drivers/net/ethernet/samsung/Kconfig new file mode 100644 index 000000000000..7902341f2623 --- /dev/null +++ b/drivers/net/ethernet/samsung/Kconfig | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | # | ||
| 2 | # Samsung Ethernet device configuration | ||
| 3 | # | ||
| 4 | |||
| 5 | config NET_VENDOR_SAMSUNG | ||
| 6 | bool "Samsung Ethernet device" | ||
| 7 | default y | ||
| 8 | ---help--- | ||
| 9 | This is the driver for the SXGBE 10G Ethernet IP block found on Samsung | ||
| 10 | platforms. | ||
| 11 | |||
| 12 | if NET_VENDOR_SAMSUNG | ||
| 13 | |||
| 14 | source "drivers/net/ethernet/samsung/sxgbe/Kconfig" | ||
| 15 | |||
| 16 | endif # NET_VENDOR_SAMSUNG | ||
diff --git a/drivers/net/ethernet/samsung/Makefile b/drivers/net/ethernet/samsung/Makefile new file mode 100644 index 000000000000..1773c29b8d76 --- /dev/null +++ b/drivers/net/ethernet/samsung/Makefile | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the Samsung Ethernet device drivers. | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_SXGBE_ETH) += sxgbe/ | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/Kconfig b/drivers/net/ethernet/samsung/sxgbe/Kconfig new file mode 100644 index 000000000000..d79288c51d0a --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/Kconfig | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | config SXGBE_ETH | ||
| 2 | tristate "Samsung 10G/2.5G/1G SXGBE Ethernet driver" | ||
| 3 | depends on HAS_IOMEM && HAS_DMA | ||
| 4 | select PHYLIB | ||
| 5 | select CRC32 | ||
| 6 | select PTP_1588_CLOCK | ||
| 7 | ---help--- | ||
| 8 | This is the driver for the SXGBE 10G Ethernet IP block found on Samsung | ||
| 9 | platforms. | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/Makefile b/drivers/net/ethernet/samsung/sxgbe/Makefile new file mode 100644 index 000000000000..dcc80b9d4370 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/Makefile | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | obj-$(CONFIG_SXGBE_ETH) += samsung-sxgbe.o | ||
| 2 | samsung-sxgbe-objs:= sxgbe_platform.o sxgbe_main.o sxgbe_desc.o \ | ||
| 3 | sxgbe_dma.o sxgbe_core.o sxgbe_mtl.o sxgbe_mdio.o \ | ||
| 4 | sxgbe_ethtool.o sxgbe_xpcs.o $(samsung-sxgbe-y) | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h new file mode 100644 index 000000000000..c7803f199967 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h | |||
| @@ -0,0 +1,462 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __SXGBE_COMMON_H__ | ||
| 14 | #define __SXGBE_COMMON_H__ | ||
| 15 | |||
| 16 | /* forward references */ | ||
| 17 | struct sxgbe_desc_ops; | ||
| 18 | struct sxgbe_dma_ops; | ||
| 19 | struct sxgbe_mtl_ops; | ||
| 20 | |||
| 21 | #define SXGBE_RESOURCE_NAME "sam_sxgbeeth" | ||
| 22 | #define DRV_MODULE_VERSION "November_2013" | ||
| 23 | |||
| 24 | /* MAX HW feature words */ | ||
| 25 | #define SXGBE_HW_WORDS 3 | ||
| 26 | |||
| 27 | #define SXGBE_RX_COE_NONE 0 | ||
| 28 | |||
| 29 | /* CSR Frequency Access Defines*/ | ||
| 30 | #define SXGBE_CSR_F_150M 150000000 | ||
| 31 | #define SXGBE_CSR_F_250M 250000000 | ||
| 32 | #define SXGBE_CSR_F_300M 300000000 | ||
| 33 | #define SXGBE_CSR_F_350M 350000000 | ||
| 34 | #define SXGBE_CSR_F_400M 400000000 | ||
| 35 | #define SXGBE_CSR_F_500M 500000000 | ||
| 36 | |||
| 37 | /* pause time */ | ||
| 38 | #define SXGBE_PAUSE_TIME 0x200 | ||
| 39 | |||
| 40 | /* tx queues */ | ||
| 41 | #define SXGBE_TX_QUEUES 8 | ||
| 42 | #define SXGBE_RX_QUEUES 16 | ||
| 43 | |||
| 44 | /* Calculated based how much time does it take to fill 256KB Rx memory | ||
| 45 | * at 10Gb speed at 156MHz clock rate and considered little less then | ||
| 46 | * the actual value. | ||
| 47 | */ | ||
| 48 | #define SXGBE_MAX_DMA_RIWT 0x70 | ||
| 49 | #define SXGBE_MIN_DMA_RIWT 0x01 | ||
| 50 | |||
| 51 | /* Tx coalesce parameters */ | ||
| 52 | #define SXGBE_COAL_TX_TIMER 40000 | ||
| 53 | #define SXGBE_MAX_COAL_TX_TICK 100000 | ||
| 54 | #define SXGBE_TX_MAX_FRAMES 512 | ||
| 55 | #define SXGBE_TX_FRAMES 128 | ||
| 56 | |||
| 57 | /* SXGBE TX FIFO is 8K, Rx FIFO is 16K */ | ||
| 58 | #define BUF_SIZE_16KiB 16384 | ||
| 59 | #define BUF_SIZE_8KiB 8192 | ||
| 60 | #define BUF_SIZE_4KiB 4096 | ||
| 61 | #define BUF_SIZE_2KiB 2048 | ||
| 62 | |||
| 63 | #define SXGBE_DEFAULT_LIT_LS 0x3E8 | ||
| 64 | #define SXGBE_DEFAULT_TWT_LS 0x0 | ||
| 65 | |||
| 66 | /* Flow Control defines */ | ||
| 67 | #define SXGBE_FLOW_OFF 0 | ||
| 68 | #define SXGBE_FLOW_RX 1 | ||
| 69 | #define SXGBE_FLOW_TX 2 | ||
| 70 | #define SXGBE_FLOW_AUTO (SXGBE_FLOW_TX | SXGBE_FLOW_RX) | ||
| 71 | |||
| 72 | #define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */ | ||
| 73 | |||
| 74 | /* errors */ | ||
| 75 | #define RX_GMII_ERR 0x01 | ||
| 76 | #define RX_WATCHDOG_ERR 0x02 | ||
| 77 | #define RX_CRC_ERR 0x03 | ||
| 78 | #define RX_GAINT_ERR 0x04 | ||
| 79 | #define RX_IP_HDR_ERR 0x05 | ||
| 80 | #define RX_PAYLOAD_ERR 0x06 | ||
| 81 | #define RX_OVERFLOW_ERR 0x07 | ||
| 82 | |||
| 83 | /* pkt type */ | ||
| 84 | #define RX_LEN_PKT 0x00 | ||
| 85 | #define RX_MACCTL_PKT 0x01 | ||
| 86 | #define RX_DCBCTL_PKT 0x02 | ||
| 87 | #define RX_ARP_PKT 0x03 | ||
| 88 | #define RX_OAM_PKT 0x04 | ||
| 89 | #define RX_UNTAG_PKT 0x05 | ||
| 90 | #define RX_OTHER_PKT 0x07 | ||
| 91 | #define RX_SVLAN_PKT 0x08 | ||
| 92 | #define RX_CVLAN_PKT 0x09 | ||
| 93 | #define RX_DVLAN_OCVLAN_ICVLAN_PKT 0x0A | ||
| 94 | #define RX_DVLAN_OSVLAN_ISVLAN_PKT 0x0B | ||
| 95 | #define RX_DVLAN_OSVLAN_ICVLAN_PKT 0x0C | ||
| 96 | #define RX_DVLAN_OCVLAN_ISVLAN_PKT 0x0D | ||
| 97 | |||
| 98 | #define RX_NOT_IP_PKT 0x00 | ||
| 99 | #define RX_IPV4_TCP_PKT 0x01 | ||
| 100 | #define RX_IPV4_UDP_PKT 0x02 | ||
| 101 | #define RX_IPV4_ICMP_PKT 0x03 | ||
| 102 | #define RX_IPV4_UNKNOWN_PKT 0x07 | ||
| 103 | #define RX_IPV6_TCP_PKT 0x09 | ||
| 104 | #define RX_IPV6_UDP_PKT 0x0A | ||
| 105 | #define RX_IPV6_ICMP_PKT 0x0B | ||
| 106 | #define RX_IPV6_UNKNOWN_PKT 0x0F | ||
| 107 | |||
| 108 | #define RX_NO_PTP 0x00 | ||
| 109 | #define RX_PTP_SYNC 0x01 | ||
| 110 | #define RX_PTP_FOLLOW_UP 0x02 | ||
| 111 | #define RX_PTP_DELAY_REQ 0x03 | ||
| 112 | #define RX_PTP_DELAY_RESP 0x04 | ||
| 113 | #define RX_PTP_PDELAY_REQ 0x05 | ||
| 114 | #define RX_PTP_PDELAY_RESP 0x06 | ||
| 115 | #define RX_PTP_PDELAY_FOLLOW_UP 0x07 | ||
| 116 | #define RX_PTP_ANNOUNCE 0x08 | ||
| 117 | #define RX_PTP_MGMT 0x09 | ||
| 118 | #define RX_PTP_SIGNAL 0x0A | ||
| 119 | #define RX_PTP_RESV_MSG 0x0F | ||
| 120 | |||
| 121 | enum dma_irq_status { | ||
| 122 | tx_hard_error = BIT(0), | ||
| 123 | tx_bump_tc = BIT(1), | ||
| 124 | handle_tx = BIT(2), | ||
| 125 | rx_hard_error = BIT(3), | ||
| 126 | rx_bump_tc = BIT(4), | ||
| 127 | handle_rx = BIT(5), | ||
| 128 | }; | ||
| 129 | |||
| 130 | #define NETIF_F_HW_VLAN_ALL (NETIF_F_HW_VLAN_CTAG_RX | \ | ||
| 131 | NETIF_F_HW_VLAN_STAG_RX | \ | ||
| 132 | NETIF_F_HW_VLAN_CTAG_TX | \ | ||
| 133 | NETIF_F_HW_VLAN_STAG_TX | \ | ||
| 134 | NETIF_F_HW_VLAN_CTAG_FILTER | \ | ||
| 135 | NETIF_F_HW_VLAN_STAG_FILTER) | ||
| 136 | |||
| 137 | /* MMC control defines */ | ||
| 138 | #define SXGBE_MMC_CTRL_CNT_FRZ 0x00000008 | ||
| 139 | |||
| 140 | /* SXGBE HW ADDR regs */ | ||
| 141 | #define SXGBE_ADDR_HIGH(reg) (((reg > 15) ? 0x00000800 : 0x00000040) + \ | ||
| 142 | (reg * 8)) | ||
| 143 | #define SXGBE_ADDR_LOW(reg) (((reg > 15) ? 0x00000804 : 0x00000044) + \ | ||
| 144 | (reg * 8)) | ||
| 145 | #define SXGBE_MAX_PERFECT_ADDRESSES 32 /* Maximum unicast perfect filtering */ | ||
| 146 | #define SXGBE_FRAME_FILTER 0x00000004 /* Frame Filter */ | ||
| 147 | |||
| 148 | /* SXGBE Frame Filter defines */ | ||
| 149 | #define SXGBE_FRAME_FILTER_PR 0x00000001 /* Promiscuous Mode */ | ||
| 150 | #define SXGBE_FRAME_FILTER_HUC 0x00000002 /* Hash Unicast */ | ||
| 151 | #define SXGBE_FRAME_FILTER_HMC 0x00000004 /* Hash Multicast */ | ||
| 152 | #define SXGBE_FRAME_FILTER_DAIF 0x00000008 /* DA Inverse Filtering */ | ||
| 153 | #define SXGBE_FRAME_FILTER_PM 0x00000010 /* Pass all multicast */ | ||
| 154 | #define SXGBE_FRAME_FILTER_DBF 0x00000020 /* Disable Broadcast frames */ | ||
| 155 | #define SXGBE_FRAME_FILTER_SAIF 0x00000100 /* Inverse Filtering */ | ||
| 156 | #define SXGBE_FRAME_FILTER_SAF 0x00000200 /* Source Address Filter */ | ||
| 157 | #define SXGBE_FRAME_FILTER_HPF 0x00000400 /* Hash or perfect Filter */ | ||
| 158 | #define SXGBE_FRAME_FILTER_RA 0x80000000 /* Receive all mode */ | ||
| 159 | |||
| 160 | #define SXGBE_HASH_TABLE_SIZE 64 | ||
| 161 | #define SXGBE_HASH_HIGH 0x00000008 /* Multicast Hash Table High */ | ||
| 162 | #define SXGBE_HASH_LOW 0x0000000c /* Multicast Hash Table Low */ | ||
| 163 | |||
| 164 | #define SXGBE_HI_REG_AE 0x80000000 | ||
| 165 | |||
| 166 | /* Minimum and maximum MTU */ | ||
| 167 | #define MIN_MTU 68 | ||
| 168 | #define MAX_MTU 9000 | ||
| 169 | |||
| 170 | #define SXGBE_FOR_EACH_QUEUE(max_queues, queue_num) \ | ||
| 171 | for (queue_num = 0; queue_num < max_queues; queue_num++) | ||
| 172 | |||
| 173 | /* sxgbe statistics counters */ | ||
| 174 | struct sxgbe_extra_stats { | ||
| 175 | /* TX/RX IRQ events */ | ||
| 176 | unsigned long tx_underflow_irq; | ||
| 177 | unsigned long tx_process_stopped_irq; | ||
| 178 | unsigned long tx_ctxt_desc_err; | ||
| 179 | unsigned long tx_threshold; | ||
| 180 | unsigned long rx_threshold; | ||
| 181 | unsigned long tx_pkt_n; | ||
| 182 | unsigned long rx_pkt_n; | ||
| 183 | unsigned long normal_irq_n; | ||
| 184 | unsigned long tx_normal_irq_n; | ||
| 185 | unsigned long rx_normal_irq_n; | ||
| 186 | unsigned long napi_poll; | ||
| 187 | unsigned long tx_clean; | ||
| 188 | unsigned long tx_reset_ic_bit; | ||
| 189 | unsigned long rx_process_stopped_irq; | ||
| 190 | unsigned long rx_underflow_irq; | ||
| 191 | |||
| 192 | /* Bus access errors */ | ||
| 193 | unsigned long fatal_bus_error_irq; | ||
| 194 | unsigned long tx_read_transfer_err; | ||
| 195 | unsigned long tx_write_transfer_err; | ||
| 196 | unsigned long tx_desc_access_err; | ||
| 197 | unsigned long tx_buffer_access_err; | ||
| 198 | unsigned long tx_data_transfer_err; | ||
| 199 | unsigned long rx_read_transfer_err; | ||
| 200 | unsigned long rx_write_transfer_err; | ||
| 201 | unsigned long rx_desc_access_err; | ||
| 202 | unsigned long rx_buffer_access_err; | ||
| 203 | unsigned long rx_data_transfer_err; | ||
| 204 | |||
| 205 | /* RX specific */ | ||
| 206 | /* L2 error */ | ||
| 207 | unsigned long rx_code_gmii_err; | ||
| 208 | unsigned long rx_watchdog_err; | ||
| 209 | unsigned long rx_crc_err; | ||
| 210 | unsigned long rx_gaint_pkt_err; | ||
| 211 | unsigned long ip_hdr_err; | ||
| 212 | unsigned long ip_payload_err; | ||
| 213 | unsigned long overflow_error; | ||
| 214 | |||
| 215 | /* L2 Pkt type */ | ||
| 216 | unsigned long len_pkt; | ||
| 217 | unsigned long mac_ctl_pkt; | ||
| 218 | unsigned long dcb_ctl_pkt; | ||
| 219 | unsigned long arp_pkt; | ||
| 220 | unsigned long oam_pkt; | ||
| 221 | unsigned long untag_okt; | ||
| 222 | unsigned long other_pkt; | ||
| 223 | unsigned long svlan_tag_pkt; | ||
| 224 | unsigned long cvlan_tag_pkt; | ||
| 225 | unsigned long dvlan_ocvlan_icvlan_pkt; | ||
| 226 | unsigned long dvlan_osvlan_isvlan_pkt; | ||
| 227 | unsigned long dvlan_osvlan_icvlan_pkt; | ||
| 228 | unsigned long dvan_ocvlan_icvlan_pkt; | ||
| 229 | |||
| 230 | /* L3/L4 Pkt type */ | ||
| 231 | unsigned long not_ip_pkt; | ||
| 232 | unsigned long ip4_tcp_pkt; | ||
| 233 | unsigned long ip4_udp_pkt; | ||
| 234 | unsigned long ip4_icmp_pkt; | ||
| 235 | unsigned long ip4_unknown_pkt; | ||
| 236 | unsigned long ip6_tcp_pkt; | ||
| 237 | unsigned long ip6_udp_pkt; | ||
| 238 | unsigned long ip6_icmp_pkt; | ||
| 239 | unsigned long ip6_unknown_pkt; | ||
| 240 | |||
| 241 | /* Filter specific */ | ||
| 242 | unsigned long vlan_filter_match; | ||
| 243 | unsigned long sa_filter_fail; | ||
| 244 | unsigned long da_filter_fail; | ||
| 245 | unsigned long hash_filter_pass; | ||
| 246 | unsigned long l3_filter_match; | ||
| 247 | unsigned long l4_filter_match; | ||
| 248 | |||
| 249 | /* RX context specific */ | ||
| 250 | unsigned long timestamp_dropped; | ||
| 251 | unsigned long rx_msg_type_no_ptp; | ||
| 252 | unsigned long rx_ptp_type_sync; | ||
| 253 | unsigned long rx_ptp_type_follow_up; | ||
| 254 | unsigned long rx_ptp_type_delay_req; | ||
| 255 | unsigned long rx_ptp_type_delay_resp; | ||
| 256 | unsigned long rx_ptp_type_pdelay_req; | ||
| 257 | unsigned long rx_ptp_type_pdelay_resp; | ||
| 258 | unsigned long rx_ptp_type_pdelay_follow_up; | ||
| 259 | unsigned long rx_ptp_announce; | ||
| 260 | unsigned long rx_ptp_mgmt; | ||
| 261 | unsigned long rx_ptp_signal; | ||
| 262 | unsigned long rx_ptp_resv_msg_type; | ||
| 263 | }; | ||
| 264 | |||
| 265 | struct mac_link { | ||
| 266 | int port; | ||
| 267 | int duplex; | ||
| 268 | int speed; | ||
| 269 | }; | ||
| 270 | |||
| 271 | struct mii_regs { | ||
| 272 | unsigned int addr; /* MII Address */ | ||
| 273 | unsigned int data; /* MII Data */ | ||
| 274 | }; | ||
| 275 | |||
| 276 | struct sxgbe_core_ops { | ||
| 277 | /* MAC core initialization */ | ||
| 278 | void (*core_init)(void __iomem *ioaddr); | ||
| 279 | /* Dump MAC registers */ | ||
| 280 | void (*dump_regs)(void __iomem *ioaddr); | ||
| 281 | /* Handle extra events on specific interrupts hw dependent */ | ||
| 282 | int (*host_irq_status)(void __iomem *ioaddr, | ||
| 283 | struct sxgbe_extra_stats *x); | ||
| 284 | /* Set power management mode (e.g. magic frame) */ | ||
| 285 | void (*pmt)(void __iomem *ioaddr, unsigned long mode); | ||
| 286 | /* Set/Get Unicast MAC addresses */ | ||
| 287 | void (*set_umac_addr)(void __iomem *ioaddr, unsigned char *addr, | ||
| 288 | unsigned int reg_n); | ||
| 289 | void (*get_umac_addr)(void __iomem *ioaddr, unsigned char *addr, | ||
| 290 | unsigned int reg_n); | ||
| 291 | void (*enable_rx)(void __iomem *ioaddr, bool enable); | ||
| 292 | void (*enable_tx)(void __iomem *ioaddr, bool enable); | ||
| 293 | |||
| 294 | /* controller version specific operations */ | ||
| 295 | int (*get_controller_version)(void __iomem *ioaddr); | ||
| 296 | |||
| 297 | /* If supported then get the optional core features */ | ||
| 298 | unsigned int (*get_hw_feature)(void __iomem *ioaddr, | ||
| 299 | unsigned char feature_index); | ||
| 300 | /* adjust SXGBE speed */ | ||
| 301 | void (*set_speed)(void __iomem *ioaddr, unsigned char speed); | ||
| 302 | }; | ||
| 303 | |||
| 304 | const struct sxgbe_core_ops *sxgbe_get_core_ops(void); | ||
| 305 | |||
| 306 | struct sxgbe_ops { | ||
| 307 | const struct sxgbe_core_ops *mac; | ||
| 308 | const struct sxgbe_desc_ops *desc; | ||
| 309 | const struct sxgbe_dma_ops *dma; | ||
| 310 | const struct sxgbe_mtl_ops *mtl; | ||
| 311 | struct mii_regs mii; /* MII register Addresses */ | ||
| 312 | struct mac_link link; | ||
| 313 | unsigned int ctrl_uid; | ||
| 314 | unsigned int ctrl_id; | ||
| 315 | }; | ||
| 316 | |||
| 317 | /* SXGBE private data structures */ | ||
| 318 | struct sxgbe_tx_queue { | ||
| 319 | unsigned int irq_no; | ||
| 320 | struct sxgbe_priv_data *priv_ptr; | ||
| 321 | struct sxgbe_tx_norm_desc *dma_tx; | ||
| 322 | dma_addr_t dma_tx_phy; | ||
| 323 | dma_addr_t *tx_skbuff_dma; | ||
| 324 | struct sk_buff **tx_skbuff; | ||
| 325 | struct timer_list txtimer; | ||
| 326 | spinlock_t tx_lock; /* lock for tx queues */ | ||
| 327 | unsigned int cur_tx; | ||
| 328 | unsigned int dirty_tx; | ||
| 329 | u32 tx_count_frames; | ||
| 330 | u32 tx_coal_frames; | ||
| 331 | u32 tx_coal_timer; | ||
| 332 | int hwts_tx_en; | ||
| 333 | u8 queue_no; | ||
| 334 | }; | ||
| 335 | |||
| 336 | struct sxgbe_rx_queue { | ||
| 337 | struct sxgbe_priv_data *priv_ptr; | ||
| 338 | struct sxgbe_rx_norm_desc *dma_rx; | ||
| 339 | struct sk_buff **rx_skbuff; | ||
| 340 | unsigned int cur_rx; | ||
| 341 | unsigned int dirty_rx; | ||
| 342 | unsigned int irq_no; | ||
| 343 | u32 rx_riwt; | ||
| 344 | dma_addr_t *rx_skbuff_dma; | ||
| 345 | dma_addr_t dma_rx_phy; | ||
| 346 | u8 queue_no; | ||
| 347 | }; | ||
| 348 | |||
| 349 | /* SXGBE HW capabilities */ | ||
| 350 | struct sxgbe_hw_features { | ||
| 351 | /****** CAP [0] *******/ | ||
| 352 | unsigned int pmt_remote_wake_up; | ||
| 353 | unsigned int pmt_magic_frame; | ||
| 354 | /* IEEE 1588-2008 */ | ||
| 355 | unsigned int atime_stamp; | ||
| 356 | |||
| 357 | unsigned int tx_csum_offload; | ||
| 358 | unsigned int rx_csum_offload; | ||
| 359 | unsigned int multi_macaddr; | ||
| 360 | unsigned int tstamp_srcselect; | ||
| 361 | unsigned int sa_vlan_insert; | ||
| 362 | |||
| 363 | /****** CAP [1] *******/ | ||
| 364 | unsigned int rxfifo_size; | ||
| 365 | unsigned int txfifo_size; | ||
| 366 | unsigned int atstmap_hword; | ||
| 367 | unsigned int dcb_enable; | ||
| 368 | unsigned int splithead_enable; | ||
| 369 | unsigned int tcpseg_offload; | ||
| 370 | unsigned int debug_mem; | ||
| 371 | unsigned int rss_enable; | ||
| 372 | unsigned int hash_tsize; | ||
| 373 | unsigned int l3l4_filer_size; | ||
| 374 | |||
| 375 | /* This value is in bytes and | ||
| 376 | * as mentioned in HW features | ||
| 377 | * of SXGBE data book | ||
| 378 | */ | ||
| 379 | unsigned int rx_mtl_qsize; | ||
| 380 | unsigned int tx_mtl_qsize; | ||
| 381 | |||
| 382 | /****** CAP [2] *******/ | ||
| 383 | /* TX and RX number of channels */ | ||
| 384 | unsigned int rx_mtl_queues; | ||
| 385 | unsigned int tx_mtl_queues; | ||
| 386 | unsigned int rx_dma_channels; | ||
| 387 | unsigned int tx_dma_channels; | ||
| 388 | unsigned int pps_output_count; | ||
| 389 | unsigned int aux_input_count; | ||
| 390 | }; | ||
| 391 | |||
| 392 | struct sxgbe_priv_data { | ||
| 393 | /* DMA descriptos */ | ||
| 394 | struct sxgbe_tx_queue *txq[SXGBE_TX_QUEUES]; | ||
| 395 | struct sxgbe_rx_queue *rxq[SXGBE_RX_QUEUES]; | ||
| 396 | u8 cur_rx_qnum; | ||
| 397 | |||
| 398 | unsigned int dma_tx_size; | ||
| 399 | unsigned int dma_rx_size; | ||
| 400 | unsigned int dma_buf_sz; | ||
| 401 | u32 rx_riwt; | ||
| 402 | |||
| 403 | struct napi_struct napi; | ||
| 404 | |||
| 405 | void __iomem *ioaddr; | ||
| 406 | struct net_device *dev; | ||
| 407 | struct device *device; | ||
| 408 | struct sxgbe_ops *hw; /* sxgbe specific ops */ | ||
| 409 | int no_csum_insertion; | ||
| 410 | int irq; | ||
| 411 | spinlock_t stats_lock; /* lock for tx/rx statatics */ | ||
| 412 | |||
| 413 | struct phy_device *phydev; | ||
| 414 | int oldlink; | ||
| 415 | int speed; | ||
| 416 | int oldduplex; | ||
| 417 | struct mii_bus *mii; | ||
| 418 | int mii_irq[PHY_MAX_ADDR]; | ||
| 419 | u8 rx_pause; | ||
| 420 | u8 tx_pause; | ||
| 421 | |||
| 422 | struct sxgbe_extra_stats xstats; | ||
| 423 | struct sxgbe_plat_data *plat; | ||
| 424 | struct sxgbe_hw_features hw_cap; | ||
| 425 | |||
| 426 | u32 msg_enable; | ||
| 427 | |||
| 428 | struct clk *sxgbe_clk; | ||
| 429 | int clk_csr; | ||
| 430 | unsigned int mode; | ||
| 431 | unsigned int default_addend; | ||
| 432 | |||
| 433 | /* advanced time stamp support */ | ||
| 434 | u32 adv_ts; | ||
| 435 | int use_riwt; | ||
| 436 | |||
| 437 | /* tc control */ | ||
| 438 | int tx_tc; | ||
| 439 | int rx_tc; | ||
| 440 | }; | ||
| 441 | |||
| 442 | /* Function prototypes */ | ||
| 443 | struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, | ||
| 444 | struct sxgbe_plat_data *plat_dat, | ||
| 445 | void __iomem *addr); | ||
| 446 | int sxgbe_drv_remove(struct net_device *ndev); | ||
| 447 | void sxgbe_set_ethtool_ops(struct net_device *netdev); | ||
| 448 | int sxgbe_mdio_unregister(struct net_device *ndev); | ||
| 449 | int sxgbe_mdio_register(struct net_device *ndev); | ||
| 450 | int sxgbe_register_platform(void); | ||
| 451 | void sxgbe_unregister_platform(void); | ||
| 452 | |||
| 453 | #ifdef CONFIG_PM | ||
| 454 | int sxgbe_suspend(struct net_device *ndev); | ||
| 455 | int sxgbe_resume(struct net_device *ndev); | ||
| 456 | int sxgbe_freeze(struct net_device *ndev); | ||
| 457 | int sxgbe_restore(struct net_device *ndev); | ||
| 458 | #endif /* CONFIG_PM */ | ||
| 459 | |||
| 460 | const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void); | ||
| 461 | |||
| 462 | #endif /* __SXGBE_COMMON_H__ */ | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c new file mode 100644 index 000000000000..4ad31bbc42c9 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 14 | |||
| 15 | #include <linux/export.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/netdevice.h> | ||
| 18 | #include <linux/phy.h> | ||
| 19 | |||
| 20 | #include "sxgbe_common.h" | ||
| 21 | #include "sxgbe_reg.h" | ||
| 22 | |||
| 23 | /* MAC core initialization */ | ||
| 24 | static void sxgbe_core_init(void __iomem *ioaddr) | ||
| 25 | { | ||
| 26 | u32 regval; | ||
| 27 | |||
| 28 | /* TX configuration */ | ||
| 29 | regval = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||
| 30 | /* Other configurable parameters IFP, IPG, ISR, ISM | ||
| 31 | * needs to be set if needed | ||
| 32 | */ | ||
| 33 | regval |= SXGBE_TX_JABBER_DISABLE; | ||
| 34 | writel(regval, ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||
| 35 | |||
| 36 | /* RX configuration */ | ||
| 37 | regval = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||
| 38 | /* Other configurable parameters CST, SPEN, USP, GPSLCE | ||
| 39 | * WD, LM, S2KP, HDSMS, GPSL, ELEN, ARPEN needs to be | ||
| 40 | * set if needed | ||
| 41 | */ | ||
| 42 | regval |= SXGBE_RX_JUMBPKT_ENABLE | SXGBE_RX_ACS_ENABLE; | ||
| 43 | writel(regval, ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||
| 44 | } | ||
| 45 | |||
| 46 | /* Dump MAC registers */ | ||
| 47 | static void sxgbe_core_dump_regs(void __iomem *ioaddr) | ||
| 48 | { | ||
| 49 | } | ||
| 50 | |||
| 51 | /* Handle extra events on specific interrupts hw dependent */ | ||
| 52 | static int sxgbe_core_host_irq_status(void __iomem *ioaddr, | ||
| 53 | struct sxgbe_extra_stats *x) | ||
| 54 | { | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | /* Set power management mode (e.g. magic frame) */ | ||
| 59 | static void sxgbe_core_pmt(void __iomem *ioaddr, unsigned long mode) | ||
| 60 | { | ||
| 61 | } | ||
| 62 | |||
| 63 | /* Set/Get Unicast MAC addresses */ | ||
| 64 | static void sxgbe_core_set_umac_addr(void __iomem *ioaddr, unsigned char *addr, | ||
| 65 | unsigned int reg_n) | ||
| 66 | { | ||
| 67 | u32 high_word, low_word; | ||
| 68 | |||
| 69 | high_word = (addr[5] << 8) || (addr[4]); | ||
| 70 | low_word = ((addr[3] << 24) || (addr[2] << 16) || | ||
| 71 | (addr[1] << 8) || (addr[0])); | ||
| 72 | writel(high_word, ioaddr + SXGBE_CORE_ADD_HIGHOFFSET(reg_n)); | ||
| 73 | writel(low_word, ioaddr + SXGBE_CORE_ADD_LOWOFFSET(reg_n)); | ||
| 74 | } | ||
| 75 | |||
| 76 | static void sxgbe_core_get_umac_addr(void __iomem *ioaddr, unsigned char *addr, | ||
| 77 | unsigned int reg_n) | ||
| 78 | { | ||
| 79 | u32 high_word, low_word; | ||
| 80 | |||
| 81 | high_word = readl(ioaddr + SXGBE_CORE_ADD_HIGHOFFSET(reg_n)); | ||
| 82 | low_word = readl(ioaddr + SXGBE_CORE_ADD_LOWOFFSET(reg_n)); | ||
| 83 | |||
| 84 | /* extract and assign address */ | ||
| 85 | addr[5] = (high_word & 0x0000FF00) >> 8; | ||
| 86 | addr[4] = (high_word & 0x000000FF); | ||
| 87 | addr[3] = (low_word & 0xFF000000) >> 24; | ||
| 88 | addr[2] = (low_word & 0x00FF0000) >> 16; | ||
| 89 | addr[1] = (low_word & 0x0000FF00) >> 8; | ||
| 90 | addr[0] = (low_word & 0x000000FF); | ||
| 91 | } | ||
| 92 | |||
| 93 | static void sxgbe_enable_tx(void __iomem *ioaddr, bool enable) | ||
| 94 | { | ||
| 95 | u32 tx_config; | ||
| 96 | |||
| 97 | tx_config = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||
| 98 | tx_config &= ~SXGBE_TX_ENABLE; | ||
| 99 | |||
| 100 | if (enable) | ||
| 101 | tx_config |= SXGBE_TX_ENABLE; | ||
| 102 | writel(tx_config, ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||
| 103 | } | ||
| 104 | |||
| 105 | static void sxgbe_enable_rx(void __iomem *ioaddr, bool enable) | ||
| 106 | { | ||
| 107 | u32 rx_config; | ||
| 108 | |||
| 109 | rx_config = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||
| 110 | rx_config &= ~SXGBE_RX_ENABLE; | ||
| 111 | |||
| 112 | if (enable) | ||
| 113 | rx_config |= SXGBE_RX_ENABLE; | ||
| 114 | writel(rx_config, ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||
| 115 | } | ||
| 116 | |||
| 117 | static int sxgbe_get_controller_version(void __iomem *ioaddr) | ||
| 118 | { | ||
| 119 | return readl(ioaddr + SXGBE_CORE_VERSION_REG); | ||
| 120 | } | ||
| 121 | |||
| 122 | /* If supported then get the optional core features */ | ||
| 123 | static unsigned int sxgbe_get_hw_feature(void __iomem *ioaddr, | ||
| 124 | unsigned char feature_index) | ||
| 125 | { | ||
| 126 | return readl(ioaddr + (SXGBE_CORE_HW_FEA_REG(feature_index))); | ||
| 127 | } | ||
| 128 | |||
| 129 | static void sxgbe_core_set_speed(void __iomem *ioaddr, unsigned char speed) | ||
| 130 | { | ||
| 131 | u32 tx_cfg = readl(ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||
| 132 | |||
| 133 | /* clear the speed bits */ | ||
| 134 | tx_cfg &= ~0x60000000; | ||
| 135 | tx_cfg |= (speed << SXGBE_SPEED_LSHIFT); | ||
| 136 | |||
| 137 | /* set the speed */ | ||
| 138 | writel(tx_cfg, ioaddr + SXGBE_CORE_TX_CONFIG_REG); | ||
| 139 | } | ||
| 140 | |||
| 141 | const struct sxgbe_core_ops core_ops = { | ||
| 142 | .core_init = sxgbe_core_init, | ||
| 143 | .dump_regs = sxgbe_core_dump_regs, | ||
| 144 | .host_irq_status = sxgbe_core_host_irq_status, | ||
| 145 | .pmt = sxgbe_core_pmt, | ||
| 146 | .set_umac_addr = sxgbe_core_set_umac_addr, | ||
| 147 | .get_umac_addr = sxgbe_core_get_umac_addr, | ||
| 148 | .enable_rx = sxgbe_enable_rx, | ||
| 149 | .enable_tx = sxgbe_enable_tx, | ||
| 150 | .get_controller_version = sxgbe_get_controller_version, | ||
| 151 | .get_hw_feature = sxgbe_get_hw_feature, | ||
| 152 | .set_speed = sxgbe_core_set_speed, | ||
| 153 | }; | ||
| 154 | |||
| 155 | const struct sxgbe_core_ops *sxgbe_get_core_ops(void) | ||
| 156 | { | ||
| 157 | return &core_ops; | ||
| 158 | } | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c new file mode 100644 index 000000000000..7cb5520475b7 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.c | |||
| @@ -0,0 +1,515 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 14 | |||
| 15 | #include <linux/bitops.h> | ||
| 16 | #include <linux/export.h> | ||
| 17 | #include <linux/io.h> | ||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/phy.h> | ||
| 20 | |||
| 21 | #include "sxgbe_common.h" | ||
| 22 | #include "sxgbe_dma.h" | ||
| 23 | #include "sxgbe_desc.h" | ||
| 24 | |||
| 25 | /* DMA TX descriptor ring initialization */ | ||
| 26 | static void sxgbe_init_tx_desc(struct sxgbe_tx_norm_desc *p) | ||
| 27 | { | ||
| 28 | p->tdes23.tx_rd_des23.own_bit = 0; | ||
| 29 | } | ||
| 30 | |||
| 31 | static void sxgbe_tx_desc_enable_tse(struct sxgbe_tx_norm_desc *p, u8 is_tse, | ||
| 32 | u32 total_hdr_len, u32 tcp_hdr_len, | ||
| 33 | u32 tcp_payload_len) | ||
| 34 | { | ||
| 35 | p->tdes23.tx_rd_des23.tse_bit = is_tse; | ||
| 36 | p->tdes23.tx_rd_des23.buf1_size = total_hdr_len; | ||
| 37 | p->tdes23.tx_rd_des23.tcp_hdr_len = tcp_hdr_len / 4; | ||
| 38 | p->tdes23.tx_rd_des23.tx_pkt_len.tcp_payload_len = tcp_payload_len; | ||
| 39 | } | ||
| 40 | |||
| 41 | /* Assign buffer lengths for descriptor */ | ||
| 42 | static void sxgbe_prepare_tx_desc(struct sxgbe_tx_norm_desc *p, u8 is_fd, | ||
| 43 | int buf1_len, int pkt_len, int cksum) | ||
| 44 | { | ||
| 45 | p->tdes23.tx_rd_des23.first_desc = is_fd; | ||
| 46 | p->tdes23.tx_rd_des23.buf1_size = buf1_len; | ||
| 47 | |||
| 48 | p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.total_pkt_len = pkt_len; | ||
| 49 | |||
| 50 | if (cksum) | ||
| 51 | p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.cksum_ctl = cic_full; | ||
| 52 | } | ||
| 53 | |||
| 54 | /* Set VLAN control information */ | ||
| 55 | static void sxgbe_tx_vlanctl_desc(struct sxgbe_tx_norm_desc *p, int vlan_ctl) | ||
| 56 | { | ||
| 57 | p->tdes23.tx_rd_des23.vlan_tag_ctl = vlan_ctl; | ||
| 58 | } | ||
| 59 | |||
| 60 | /* Set the owner of Normal descriptor */ | ||
| 61 | static void sxgbe_set_tx_owner(struct sxgbe_tx_norm_desc *p) | ||
| 62 | { | ||
| 63 | p->tdes23.tx_rd_des23.own_bit = 1; | ||
| 64 | } | ||
| 65 | |||
| 66 | /* Get the owner of Normal descriptor */ | ||
| 67 | static int sxgbe_get_tx_owner(struct sxgbe_tx_norm_desc *p) | ||
| 68 | { | ||
| 69 | return p->tdes23.tx_rd_des23.own_bit; | ||
| 70 | } | ||
| 71 | |||
| 72 | /* Invoked by the xmit function to close the tx descriptor */ | ||
| 73 | static void sxgbe_close_tx_desc(struct sxgbe_tx_norm_desc *p) | ||
| 74 | { | ||
| 75 | p->tdes23.tx_rd_des23.last_desc = 1; | ||
| 76 | p->tdes23.tx_rd_des23.int_on_com = 1; | ||
| 77 | } | ||
| 78 | |||
| 79 | /* Clean the tx descriptor as soon as the tx irq is received */ | ||
| 80 | static void sxgbe_release_tx_desc(struct sxgbe_tx_norm_desc *p) | ||
| 81 | { | ||
| 82 | memset(p, 0, sizeof(*p)); | ||
| 83 | } | ||
| 84 | |||
| 85 | /* Clear interrupt on tx frame completion. When this bit is | ||
| 86 | * set an interrupt happens as soon as the frame is transmitted | ||
| 87 | */ | ||
| 88 | static void sxgbe_clear_tx_ic(struct sxgbe_tx_norm_desc *p) | ||
| 89 | { | ||
| 90 | p->tdes23.tx_rd_des23.int_on_com = 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | /* Last tx segment reports the transmit status */ | ||
| 94 | static int sxgbe_get_tx_ls(struct sxgbe_tx_norm_desc *p) | ||
| 95 | { | ||
| 96 | return p->tdes23.tx_rd_des23.last_desc; | ||
| 97 | } | ||
| 98 | |||
| 99 | /* Get the buffer size from the descriptor */ | ||
| 100 | static int sxgbe_get_tx_len(struct sxgbe_tx_norm_desc *p) | ||
| 101 | { | ||
| 102 | return p->tdes23.tx_rd_des23.buf1_size; | ||
| 103 | } | ||
| 104 | |||
| 105 | /* Set tx timestamp enable bit */ | ||
| 106 | static void sxgbe_tx_enable_tstamp(struct sxgbe_tx_norm_desc *p) | ||
| 107 | { | ||
| 108 | p->tdes23.tx_rd_des23.timestmp_enable = 1; | ||
| 109 | } | ||
| 110 | |||
| 111 | /* get tx timestamp status */ | ||
| 112 | static int sxgbe_get_tx_timestamp_status(struct sxgbe_tx_norm_desc *p) | ||
| 113 | { | ||
| 114 | return p->tdes23.tx_rd_des23.timestmp_enable; | ||
| 115 | } | ||
| 116 | |||
| 117 | /* TX Context Descripto Specific */ | ||
| 118 | static void sxgbe_tx_ctxt_desc_set_ctxt(struct sxgbe_tx_ctxt_desc *p) | ||
| 119 | { | ||
| 120 | p->ctxt_bit = 1; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* Set the owner of TX context descriptor */ | ||
| 124 | static void sxgbe_tx_ctxt_desc_set_owner(struct sxgbe_tx_ctxt_desc *p) | ||
| 125 | { | ||
| 126 | p->own_bit = 1; | ||
| 127 | } | ||
| 128 | |||
| 129 | /* Get the owner of TX context descriptor */ | ||
| 130 | static int sxgbe_tx_ctxt_desc_get_owner(struct sxgbe_tx_ctxt_desc *p) | ||
| 131 | { | ||
| 132 | return p->own_bit; | ||
| 133 | } | ||
| 134 | |||
| 135 | /* Set TX mss in TX context Descriptor */ | ||
| 136 | static void sxgbe_tx_ctxt_desc_set_mss(struct sxgbe_tx_ctxt_desc *p, int mss) | ||
| 137 | { | ||
| 138 | p->maxseg_size = mss; | ||
| 139 | } | ||
| 140 | |||
| 141 | /* Get TX mss from TX context Descriptor */ | ||
| 142 | static int sxgbe_tx_ctxt_desc_get_mss(struct sxgbe_tx_ctxt_desc *p) | ||
| 143 | { | ||
| 144 | return p->maxseg_size; | ||
| 145 | } | ||
| 146 | |||
| 147 | /* Set TX tcmssv in TX context Descriptor */ | ||
| 148 | static void sxgbe_tx_ctxt_desc_set_tcmssv(struct sxgbe_tx_ctxt_desc *p) | ||
| 149 | { | ||
| 150 | p->tcmssv = 1; | ||
| 151 | } | ||
| 152 | |||
| 153 | /* Reset TX ostc in TX context Descriptor */ | ||
| 154 | static void sxgbe_tx_ctxt_desc_reset_ostc(struct sxgbe_tx_ctxt_desc *p) | ||
| 155 | { | ||
| 156 | p->ostc = 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | /* Set IVLAN information */ | ||
| 160 | static void sxgbe_tx_ctxt_desc_set_ivlantag(struct sxgbe_tx_ctxt_desc *p, | ||
| 161 | int is_ivlanvalid, int ivlan_tag, | ||
| 162 | int ivlan_ctl) | ||
| 163 | { | ||
| 164 | if (is_ivlanvalid) { | ||
| 165 | p->ivlan_tag_valid = is_ivlanvalid; | ||
| 166 | p->ivlan_tag = ivlan_tag; | ||
| 167 | p->ivlan_tag_ctl = ivlan_ctl; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | /* Return IVLAN Tag */ | ||
| 172 | static int sxgbe_tx_ctxt_desc_get_ivlantag(struct sxgbe_tx_ctxt_desc *p) | ||
| 173 | { | ||
| 174 | return p->ivlan_tag; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* Set VLAN Tag */ | ||
| 178 | static void sxgbe_tx_ctxt_desc_set_vlantag(struct sxgbe_tx_ctxt_desc *p, | ||
| 179 | int is_vlanvalid, int vlan_tag) | ||
| 180 | { | ||
| 181 | if (is_vlanvalid) { | ||
| 182 | p->vltag_valid = is_vlanvalid; | ||
| 183 | p->vlan_tag = vlan_tag; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | /* Return VLAN Tag */ | ||
| 188 | static int sxgbe_tx_ctxt_desc_get_vlantag(struct sxgbe_tx_ctxt_desc *p) | ||
| 189 | { | ||
| 190 | return p->vlan_tag; | ||
| 191 | } | ||
| 192 | |||
| 193 | /* Set Time stamp */ | ||
| 194 | static void sxgbe_tx_ctxt_desc_set_tstamp(struct sxgbe_tx_ctxt_desc *p, | ||
| 195 | u8 ostc_enable, u64 tstamp) | ||
| 196 | { | ||
| 197 | if (ostc_enable) { | ||
| 198 | p->ostc = ostc_enable; | ||
| 199 | p->tstamp_lo = (u32) tstamp; | ||
| 200 | p->tstamp_hi = (u32) (tstamp>>32); | ||
| 201 | } | ||
| 202 | } | ||
| 203 | /* Close TX context descriptor */ | ||
| 204 | static void sxgbe_tx_ctxt_desc_close(struct sxgbe_tx_ctxt_desc *p) | ||
| 205 | { | ||
| 206 | p->own_bit = 1; | ||
| 207 | } | ||
| 208 | |||
| 209 | /* WB status of context descriptor */ | ||
| 210 | static int sxgbe_tx_ctxt_desc_get_cde(struct sxgbe_tx_ctxt_desc *p) | ||
| 211 | { | ||
| 212 | return p->ctxt_desc_err; | ||
| 213 | } | ||
| 214 | |||
| 215 | /* DMA RX descriptor ring initialization */ | ||
| 216 | static void sxgbe_init_rx_desc(struct sxgbe_rx_norm_desc *p, int disable_rx_ic, | ||
| 217 | int mode, int end) | ||
| 218 | { | ||
| 219 | p->rdes23.rx_rd_des23.own_bit = 1; | ||
| 220 | if (disable_rx_ic) | ||
| 221 | p->rdes23.rx_rd_des23.int_on_com = disable_rx_ic; | ||
| 222 | } | ||
| 223 | |||
| 224 | /* Get RX own bit */ | ||
| 225 | static int sxgbe_get_rx_owner(struct sxgbe_rx_norm_desc *p) | ||
| 226 | { | ||
| 227 | return p->rdes23.rx_rd_des23.own_bit; | ||
| 228 | } | ||
| 229 | |||
| 230 | /* Set RX own bit */ | ||
| 231 | static void sxgbe_set_rx_owner(struct sxgbe_rx_norm_desc *p) | ||
| 232 | { | ||
| 233 | p->rdes23.rx_rd_des23.own_bit = 1; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* Get the receive frame size */ | ||
| 237 | static int sxgbe_get_rx_frame_len(struct sxgbe_rx_norm_desc *p) | ||
| 238 | { | ||
| 239 | return p->rdes23.rx_wb_des23.pkt_len; | ||
| 240 | } | ||
| 241 | |||
| 242 | /* Return first Descriptor status */ | ||
| 243 | static int sxgbe_get_rx_fd_status(struct sxgbe_rx_norm_desc *p) | ||
| 244 | { | ||
| 245 | return p->rdes23.rx_wb_des23.first_desc; | ||
| 246 | } | ||
| 247 | |||
| 248 | /* Return Last Descriptor status */ | ||
| 249 | static int sxgbe_get_rx_ld_status(struct sxgbe_rx_norm_desc *p) | ||
| 250 | { | ||
| 251 | return p->rdes23.rx_wb_des23.last_desc; | ||
| 252 | } | ||
| 253 | |||
| 254 | |||
| 255 | /* Return the RX status looking at the WB fields */ | ||
| 256 | static int sxgbe_rx_wbstatus(struct sxgbe_rx_norm_desc *p, | ||
| 257 | struct sxgbe_extra_stats *x, int *checksum) | ||
| 258 | { | ||
| 259 | int status = 0; | ||
| 260 | |||
| 261 | *checksum = CHECKSUM_UNNECESSARY; | ||
| 262 | if (p->rdes23.rx_wb_des23.err_summary) { | ||
| 263 | switch (p->rdes23.rx_wb_des23.err_l2_type) { | ||
| 264 | case RX_GMII_ERR: | ||
| 265 | status = -EINVAL; | ||
| 266 | x->rx_code_gmii_err++; | ||
| 267 | break; | ||
| 268 | case RX_WATCHDOG_ERR: | ||
| 269 | status = -EINVAL; | ||
| 270 | x->rx_watchdog_err++; | ||
| 271 | break; | ||
| 272 | case RX_CRC_ERR: | ||
| 273 | status = -EINVAL; | ||
| 274 | x->rx_crc_err++; | ||
| 275 | break; | ||
| 276 | case RX_GAINT_ERR: | ||
| 277 | status = -EINVAL; | ||
| 278 | x->rx_gaint_pkt_err++; | ||
| 279 | break; | ||
| 280 | case RX_IP_HDR_ERR: | ||
| 281 | *checksum = CHECKSUM_NONE; | ||
| 282 | x->ip_hdr_err++; | ||
| 283 | break; | ||
| 284 | case RX_PAYLOAD_ERR: | ||
| 285 | *checksum = CHECKSUM_NONE; | ||
| 286 | x->ip_payload_err++; | ||
| 287 | break; | ||
| 288 | case RX_OVERFLOW_ERR: | ||
| 289 | status = -EINVAL; | ||
| 290 | x->overflow_error++; | ||
| 291 | break; | ||
| 292 | default: | ||
| 293 | pr_err("Invalid Error type\n"); | ||
| 294 | break; | ||
| 295 | } | ||
| 296 | } else { | ||
| 297 | switch (p->rdes23.rx_wb_des23.err_l2_type) { | ||
| 298 | case RX_LEN_PKT: | ||
| 299 | x->len_pkt++; | ||
| 300 | break; | ||
| 301 | case RX_MACCTL_PKT: | ||
| 302 | x->mac_ctl_pkt++; | ||
| 303 | break; | ||
| 304 | case RX_DCBCTL_PKT: | ||
| 305 | x->dcb_ctl_pkt++; | ||
| 306 | break; | ||
| 307 | case RX_ARP_PKT: | ||
| 308 | x->arp_pkt++; | ||
| 309 | break; | ||
| 310 | case RX_OAM_PKT: | ||
| 311 | x->oam_pkt++; | ||
| 312 | break; | ||
| 313 | case RX_UNTAG_PKT: | ||
| 314 | x->untag_okt++; | ||
| 315 | break; | ||
| 316 | case RX_OTHER_PKT: | ||
| 317 | x->other_pkt++; | ||
| 318 | break; | ||
| 319 | case RX_SVLAN_PKT: | ||
| 320 | x->svlan_tag_pkt++; | ||
| 321 | break; | ||
| 322 | case RX_CVLAN_PKT: | ||
| 323 | x->cvlan_tag_pkt++; | ||
| 324 | break; | ||
| 325 | case RX_DVLAN_OCVLAN_ICVLAN_PKT: | ||
| 326 | x->dvlan_ocvlan_icvlan_pkt++; | ||
| 327 | break; | ||
| 328 | case RX_DVLAN_OSVLAN_ISVLAN_PKT: | ||
| 329 | x->dvlan_osvlan_isvlan_pkt++; | ||
| 330 | break; | ||
| 331 | case RX_DVLAN_OSVLAN_ICVLAN_PKT: | ||
| 332 | x->dvlan_osvlan_icvlan_pkt++; | ||
| 333 | break; | ||
| 334 | case RX_DVLAN_OCVLAN_ISVLAN_PKT: | ||
| 335 | x->dvlan_ocvlan_icvlan_pkt++; | ||
| 336 | break; | ||
| 337 | default: | ||
| 338 | pr_err("Invalid L2 Packet type\n"); | ||
| 339 | break; | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | /* L3/L4 Pkt type */ | ||
| 344 | switch (p->rdes23.rx_wb_des23.layer34_pkt_type) { | ||
| 345 | case RX_NOT_IP_PKT: | ||
| 346 | x->not_ip_pkt++; | ||
| 347 | break; | ||
| 348 | case RX_IPV4_TCP_PKT: | ||
| 349 | x->ip4_tcp_pkt++; | ||
| 350 | break; | ||
| 351 | case RX_IPV4_UDP_PKT: | ||
| 352 | x->ip4_udp_pkt++; | ||
| 353 | break; | ||
| 354 | case RX_IPV4_ICMP_PKT: | ||
| 355 | x->ip4_icmp_pkt++; | ||
| 356 | break; | ||
| 357 | case RX_IPV4_UNKNOWN_PKT: | ||
| 358 | x->ip4_unknown_pkt++; | ||
| 359 | break; | ||
| 360 | case RX_IPV6_TCP_PKT: | ||
| 361 | x->ip6_tcp_pkt++; | ||
| 362 | break; | ||
| 363 | case RX_IPV6_UDP_PKT: | ||
| 364 | x->ip6_udp_pkt++; | ||
| 365 | break; | ||
| 366 | case RX_IPV6_ICMP_PKT: | ||
| 367 | x->ip6_icmp_pkt++; | ||
| 368 | break; | ||
| 369 | case RX_IPV6_UNKNOWN_PKT: | ||
| 370 | x->ip6_unknown_pkt++; | ||
| 371 | break; | ||
| 372 | default: | ||
| 373 | pr_err("Invalid L3/L4 Packet type\n"); | ||
| 374 | break; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* Filter */ | ||
| 378 | if (p->rdes23.rx_wb_des23.vlan_filter_match) | ||
| 379 | x->vlan_filter_match++; | ||
| 380 | |||
| 381 | if (p->rdes23.rx_wb_des23.sa_filter_fail) { | ||
| 382 | status = -EINVAL; | ||
| 383 | x->sa_filter_fail++; | ||
| 384 | } | ||
| 385 | if (p->rdes23.rx_wb_des23.da_filter_fail) { | ||
| 386 | status = -EINVAL; | ||
| 387 | x->da_filter_fail++; | ||
| 388 | } | ||
| 389 | if (p->rdes23.rx_wb_des23.hash_filter_pass) | ||
| 390 | x->hash_filter_pass++; | ||
| 391 | |||
| 392 | if (p->rdes23.rx_wb_des23.l3_filter_match) | ||
| 393 | x->l3_filter_match++; | ||
| 394 | |||
| 395 | if (p->rdes23.rx_wb_des23.l4_filter_match) | ||
| 396 | x->l4_filter_match++; | ||
| 397 | |||
| 398 | return status; | ||
| 399 | } | ||
| 400 | |||
| 401 | /* Get own bit of context descriptor */ | ||
| 402 | static int sxgbe_get_rx_ctxt_owner(struct sxgbe_rx_ctxt_desc *p) | ||
| 403 | { | ||
| 404 | return p->own_bit; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* Set own bit for context descriptor */ | ||
| 408 | static void sxgbe_set_ctxt_rx_owner(struct sxgbe_rx_ctxt_desc *p) | ||
| 409 | { | ||
| 410 | p->own_bit = 1; | ||
| 411 | } | ||
| 412 | |||
| 413 | |||
| 414 | /* Return the reception status looking at Context control information */ | ||
| 415 | static void sxgbe_rx_ctxt_wbstatus(struct sxgbe_rx_ctxt_desc *p, | ||
| 416 | struct sxgbe_extra_stats *x) | ||
| 417 | { | ||
| 418 | if (p->tstamp_dropped) | ||
| 419 | x->timestamp_dropped++; | ||
| 420 | |||
| 421 | /* ptp */ | ||
| 422 | if (p->ptp_msgtype == RX_NO_PTP) | ||
| 423 | x->rx_msg_type_no_ptp++; | ||
| 424 | else if (p->ptp_msgtype == RX_PTP_SYNC) | ||
| 425 | x->rx_ptp_type_sync++; | ||
| 426 | else if (p->ptp_msgtype == RX_PTP_FOLLOW_UP) | ||
| 427 | x->rx_ptp_type_follow_up++; | ||
| 428 | else if (p->ptp_msgtype == RX_PTP_DELAY_REQ) | ||
| 429 | x->rx_ptp_type_delay_req++; | ||
| 430 | else if (p->ptp_msgtype == RX_PTP_DELAY_RESP) | ||
| 431 | x->rx_ptp_type_delay_resp++; | ||
| 432 | else if (p->ptp_msgtype == RX_PTP_PDELAY_REQ) | ||
| 433 | x->rx_ptp_type_pdelay_req++; | ||
| 434 | else if (p->ptp_msgtype == RX_PTP_PDELAY_RESP) | ||
| 435 | x->rx_ptp_type_pdelay_resp++; | ||
| 436 | else if (p->ptp_msgtype == RX_PTP_PDELAY_FOLLOW_UP) | ||
| 437 | x->rx_ptp_type_pdelay_follow_up++; | ||
| 438 | else if (p->ptp_msgtype == RX_PTP_ANNOUNCE) | ||
| 439 | x->rx_ptp_announce++; | ||
| 440 | else if (p->ptp_msgtype == RX_PTP_MGMT) | ||
| 441 | x->rx_ptp_mgmt++; | ||
| 442 | else if (p->ptp_msgtype == RX_PTP_SIGNAL) | ||
| 443 | x->rx_ptp_signal++; | ||
| 444 | else if (p->ptp_msgtype == RX_PTP_RESV_MSG) | ||
| 445 | x->rx_ptp_resv_msg_type++; | ||
| 446 | } | ||
| 447 | |||
| 448 | /* Get rx timestamp status */ | ||
| 449 | static int sxgbe_get_rx_ctxt_tstamp_status(struct sxgbe_rx_ctxt_desc *p) | ||
| 450 | { | ||
| 451 | if ((p->tstamp_hi == 0xffffffff) && (p->tstamp_lo == 0xffffffff)) { | ||
| 452 | pr_err("Time stamp corrupted\n"); | ||
| 453 | return 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | return p->tstamp_available; | ||
| 457 | } | ||
| 458 | |||
| 459 | |||
| 460 | static u64 sxgbe_get_rx_timestamp(struct sxgbe_rx_ctxt_desc *p) | ||
| 461 | { | ||
| 462 | u64 ns; | ||
| 463 | |||
| 464 | ns = p->tstamp_lo; | ||
| 465 | ns |= ((u64)p->tstamp_hi) << 32; | ||
| 466 | |||
| 467 | return ns; | ||
| 468 | } | ||
| 469 | |||
| 470 | static const struct sxgbe_desc_ops desc_ops = { | ||
| 471 | .init_tx_desc = sxgbe_init_tx_desc, | ||
| 472 | .tx_desc_enable_tse = sxgbe_tx_desc_enable_tse, | ||
| 473 | .prepare_tx_desc = sxgbe_prepare_tx_desc, | ||
| 474 | .tx_vlanctl_desc = sxgbe_tx_vlanctl_desc, | ||
| 475 | .set_tx_owner = sxgbe_set_tx_owner, | ||
| 476 | .get_tx_owner = sxgbe_get_tx_owner, | ||
| 477 | .close_tx_desc = sxgbe_close_tx_desc, | ||
| 478 | .release_tx_desc = sxgbe_release_tx_desc, | ||
| 479 | .clear_tx_ic = sxgbe_clear_tx_ic, | ||
| 480 | .get_tx_ls = sxgbe_get_tx_ls, | ||
| 481 | .get_tx_len = sxgbe_get_tx_len, | ||
| 482 | .tx_enable_tstamp = sxgbe_tx_enable_tstamp, | ||
| 483 | .get_tx_timestamp_status = sxgbe_get_tx_timestamp_status, | ||
| 484 | .tx_ctxt_desc_set_ctxt = sxgbe_tx_ctxt_desc_set_ctxt, | ||
| 485 | .tx_ctxt_desc_set_owner = sxgbe_tx_ctxt_desc_set_owner, | ||
| 486 | .get_tx_ctxt_owner = sxgbe_tx_ctxt_desc_get_owner, | ||
| 487 | .tx_ctxt_desc_set_mss = sxgbe_tx_ctxt_desc_set_mss, | ||
| 488 | .tx_ctxt_desc_get_mss = sxgbe_tx_ctxt_desc_get_mss, | ||
| 489 | .tx_ctxt_desc_set_tcmssv = sxgbe_tx_ctxt_desc_set_tcmssv, | ||
| 490 | .tx_ctxt_desc_reset_ostc = sxgbe_tx_ctxt_desc_reset_ostc, | ||
| 491 | .tx_ctxt_desc_set_ivlantag = sxgbe_tx_ctxt_desc_set_ivlantag, | ||
| 492 | .tx_ctxt_desc_get_ivlantag = sxgbe_tx_ctxt_desc_get_ivlantag, | ||
| 493 | .tx_ctxt_desc_set_vlantag = sxgbe_tx_ctxt_desc_set_vlantag, | ||
| 494 | .tx_ctxt_desc_get_vlantag = sxgbe_tx_ctxt_desc_get_vlantag, | ||
| 495 | .tx_ctxt_set_tstamp = sxgbe_tx_ctxt_desc_set_tstamp, | ||
| 496 | .close_tx_ctxt_desc = sxgbe_tx_ctxt_desc_close, | ||
| 497 | .get_tx_ctxt_cde = sxgbe_tx_ctxt_desc_get_cde, | ||
| 498 | .init_rx_desc = sxgbe_init_rx_desc, | ||
| 499 | .get_rx_owner = sxgbe_get_rx_owner, | ||
| 500 | .set_rx_owner = sxgbe_set_rx_owner, | ||
| 501 | .get_rx_frame_len = sxgbe_get_rx_frame_len, | ||
| 502 | .get_rx_fd_status = sxgbe_get_rx_fd_status, | ||
| 503 | .get_rx_ld_status = sxgbe_get_rx_ld_status, | ||
| 504 | .rx_wbstatus = sxgbe_rx_wbstatus, | ||
| 505 | .get_rx_ctxt_owner = sxgbe_get_rx_ctxt_owner, | ||
| 506 | .set_rx_ctxt_owner = sxgbe_set_ctxt_rx_owner, | ||
| 507 | .rx_ctxt_wbstatus = sxgbe_rx_ctxt_wbstatus, | ||
| 508 | .get_rx_ctxt_tstamp_status = sxgbe_get_rx_ctxt_tstamp_status, | ||
| 509 | .get_timestamp = sxgbe_get_rx_timestamp, | ||
| 510 | }; | ||
| 511 | |||
| 512 | const struct sxgbe_desc_ops *sxgbe_get_desc_ops(void) | ||
| 513 | { | ||
| 514 | return &desc_ops; | ||
| 515 | } | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h new file mode 100644 index 000000000000..2caef1ae1ac5 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h | |||
| @@ -0,0 +1,298 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #ifndef __SXGBE_DESC_H__ | ||
| 13 | #define __SXGBE_DESC_H__ | ||
| 14 | |||
| 15 | #define SXGBE_DESC_SIZE_BYTES 16 | ||
| 16 | |||
| 17 | /* forward declaration */ | ||
| 18 | struct sxgbe_extra_stats; | ||
| 19 | |||
| 20 | /* Transmit checksum insertion control */ | ||
| 21 | enum tdes_csum_insertion { | ||
| 22 | cic_disabled = 0, /* Checksum Insertion Control */ | ||
| 23 | cic_only_ip = 1, /* Only IP header */ | ||
| 24 | /* IP header but pseudoheader is not calculated */ | ||
| 25 | cic_no_pseudoheader = 2, | ||
| 26 | cic_full = 3, /* IP header and pseudoheader */ | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct sxgbe_tx_norm_desc { | ||
| 30 | u64 tdes01; /* buf1 address */ | ||
| 31 | union { | ||
| 32 | /* TX Read-Format Desc 2,3 */ | ||
| 33 | struct { | ||
| 34 | /* TDES2 */ | ||
| 35 | u32 buf1_size:14; | ||
| 36 | u32 vlan_tag_ctl:2; | ||
| 37 | u32 buf2_size:14; | ||
| 38 | u32 timestmp_enable:1; | ||
| 39 | u32 int_on_com:1; | ||
| 40 | /* TDES3 */ | ||
| 41 | union { | ||
| 42 | u32 tcp_payload_len:18; | ||
| 43 | struct { | ||
| 44 | u32 total_pkt_len:15; | ||
| 45 | u32 reserved1:1; | ||
| 46 | u32 cksum_ctl:2; | ||
| 47 | } cksum_pktlen; | ||
| 48 | } tx_pkt_len; | ||
| 49 | |||
| 50 | u32 tse_bit:1; | ||
| 51 | u32 tcp_hdr_len:4; | ||
| 52 | u32 sa_insert_ctl:3; | ||
| 53 | u32 crc_pad_ctl:2; | ||
| 54 | u32 last_desc:1; | ||
| 55 | u32 first_desc:1; | ||
| 56 | u32 ctxt_bit:1; | ||
| 57 | u32 own_bit:1; | ||
| 58 | } tx_rd_des23; | ||
| 59 | |||
| 60 | /* tx write back Desc 2,3 */ | ||
| 61 | struct { | ||
| 62 | /* WB TES2 */ | ||
| 63 | u32 reserved1; | ||
| 64 | /* WB TES3 */ | ||
| 65 | u32 reserved2:31; | ||
| 66 | u32 own_bit:1; | ||
| 67 | } tx_wb_des23; | ||
| 68 | } tdes23; | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct sxgbe_rx_norm_desc { | ||
| 72 | union { | ||
| 73 | u32 rdes0; /* buf1 address */ | ||
| 74 | struct { | ||
| 75 | u32 out_vlan_tag:16; | ||
| 76 | u32 in_vlan_tag:16; | ||
| 77 | } wb_rx_des0; | ||
| 78 | } rd_wb_des0; | ||
| 79 | |||
| 80 | union { | ||
| 81 | u32 rdes1; /* buf2 address or buf1[63:32] */ | ||
| 82 | u32 rss_hash; /* Write-back RX */ | ||
| 83 | } rd_wb_des1; | ||
| 84 | |||
| 85 | union { | ||
| 86 | /* RX Read format Desc 2,3 */ | ||
| 87 | struct{ | ||
| 88 | /* RDES2 */ | ||
| 89 | u32 buf2_addr; | ||
| 90 | /* RDES3 */ | ||
| 91 | u32 buf2_hi_addr:30; | ||
| 92 | u32 int_on_com:1; | ||
| 93 | u32 own_bit:1; | ||
| 94 | } rx_rd_des23; | ||
| 95 | |||
| 96 | /* RX write back */ | ||
| 97 | struct{ | ||
| 98 | /* WB RDES2 */ | ||
| 99 | u32 hdr_len:10; | ||
| 100 | u32 rdes2_reserved:2; | ||
| 101 | u32 elrd_val:1; | ||
| 102 | u32 iovt_sel:1; | ||
| 103 | u32 res_pkt:1; | ||
| 104 | u32 vlan_filter_match:1; | ||
| 105 | u32 sa_filter_fail:1; | ||
| 106 | u32 da_filter_fail:1; | ||
| 107 | u32 hash_filter_pass:1; | ||
| 108 | u32 macaddr_filter_match:8; | ||
| 109 | u32 l3_filter_match:1; | ||
| 110 | u32 l4_filter_match:1; | ||
| 111 | u32 l34_filter_num:3; | ||
| 112 | |||
| 113 | /* WB RDES3 */ | ||
| 114 | u32 pkt_len:14; | ||
| 115 | u32 rdes3_reserved:1; | ||
| 116 | u32 err_summary:15; | ||
| 117 | u32 err_l2_type:4; | ||
| 118 | u32 layer34_pkt_type:4; | ||
| 119 | u32 no_coagulation_pkt:1; | ||
| 120 | u32 in_seq_pkt:1; | ||
| 121 | u32 rss_valid:1; | ||
| 122 | u32 context_des_avail:1; | ||
| 123 | u32 last_desc:1; | ||
| 124 | u32 first_desc:1; | ||
| 125 | u32 recv_context_desc:1; | ||
| 126 | u32 own_bit:1; | ||
| 127 | } rx_wb_des23; | ||
| 128 | } rdes23; | ||
| 129 | }; | ||
| 130 | |||
| 131 | /* Context descriptor structure */ | ||
| 132 | struct sxgbe_tx_ctxt_desc { | ||
| 133 | u32 tstamp_lo; | ||
| 134 | u32 tstamp_hi; | ||
| 135 | u32 maxseg_size:15; | ||
| 136 | u32 reserved1:1; | ||
| 137 | u32 ivlan_tag:16; | ||
| 138 | u32 vlan_tag:16; | ||
| 139 | u32 vltag_valid:1; | ||
| 140 | u32 ivlan_tag_valid:1; | ||
| 141 | u32 ivlan_tag_ctl:2; | ||
| 142 | u32 reserved2:3; | ||
| 143 | u32 ctxt_desc_err:1; | ||
| 144 | u32 reserved3:2; | ||
| 145 | u32 ostc:1; | ||
| 146 | u32 tcmssv:1; | ||
| 147 | u32 reserved4:2; | ||
| 148 | u32 ctxt_bit:1; | ||
| 149 | u32 own_bit:1; | ||
| 150 | }; | ||
| 151 | |||
| 152 | struct sxgbe_rx_ctxt_desc { | ||
| 153 | u32 tstamp_lo; | ||
| 154 | u32 tstamp_hi; | ||
| 155 | u32 reserved1; | ||
| 156 | u32 ptp_msgtype:4; | ||
| 157 | u32 tstamp_available:1; | ||
| 158 | u32 ptp_rsp_err:1; | ||
| 159 | u32 tstamp_dropped:1; | ||
| 160 | u32 reserved2:23; | ||
| 161 | u32 rx_ctxt_desc:1; | ||
| 162 | u32 own_bit:1; | ||
| 163 | }; | ||
| 164 | |||
| 165 | struct sxgbe_desc_ops { | ||
| 166 | /* DMA TX descriptor ring initialization */ | ||
| 167 | void (*init_tx_desc)(struct sxgbe_tx_norm_desc *p); | ||
| 168 | |||
| 169 | /* Invoked by the xmit function to prepare the tx descriptor */ | ||
| 170 | void (*tx_desc_enable_tse)(struct sxgbe_tx_norm_desc *p, u8 is_tse, | ||
| 171 | u32 total_hdr_len, u32 payload_len, | ||
| 172 | u32 tcp_payload_len); | ||
| 173 | |||
| 174 | /* Assign buffer lengths for descriptor */ | ||
| 175 | void (*prepare_tx_desc)(struct sxgbe_tx_norm_desc *p, u8 is_fd, | ||
| 176 | int buf1_len, int pkt_len, int cksum); | ||
| 177 | |||
| 178 | /* Set VLAN control information */ | ||
| 179 | void (*tx_vlanctl_desc)(struct sxgbe_tx_norm_desc *p, int vlan_ctl); | ||
| 180 | |||
| 181 | /* Set the owner of the descriptor */ | ||
| 182 | void (*set_tx_owner)(struct sxgbe_tx_norm_desc *p); | ||
| 183 | |||
| 184 | /* Get the owner of the descriptor */ | ||
| 185 | int (*get_tx_owner)(struct sxgbe_tx_norm_desc *p); | ||
| 186 | |||
| 187 | /* Invoked by the xmit function to close the tx descriptor */ | ||
| 188 | void (*close_tx_desc)(struct sxgbe_tx_norm_desc *p); | ||
| 189 | |||
| 190 | /* Clean the tx descriptor as soon as the tx irq is received */ | ||
| 191 | void (*release_tx_desc)(struct sxgbe_tx_norm_desc *p); | ||
| 192 | |||
| 193 | /* Clear interrupt on tx frame completion. When this bit is | ||
| 194 | * set an interrupt happens as soon as the frame is transmitted | ||
| 195 | */ | ||
| 196 | void (*clear_tx_ic)(struct sxgbe_tx_norm_desc *p); | ||
| 197 | |||
| 198 | /* Last tx segment reports the transmit status */ | ||
| 199 | int (*get_tx_ls)(struct sxgbe_tx_norm_desc *p); | ||
| 200 | |||
| 201 | /* Get the buffer size from the descriptor */ | ||
| 202 | int (*get_tx_len)(struct sxgbe_tx_norm_desc *p); | ||
| 203 | |||
| 204 | /* Set tx timestamp enable bit */ | ||
| 205 | void (*tx_enable_tstamp)(struct sxgbe_tx_norm_desc *p); | ||
| 206 | |||
| 207 | /* get tx timestamp status */ | ||
| 208 | int (*get_tx_timestamp_status)(struct sxgbe_tx_norm_desc *p); | ||
| 209 | |||
| 210 | /* TX Context Descripto Specific */ | ||
| 211 | void (*tx_ctxt_desc_set_ctxt)(struct sxgbe_tx_ctxt_desc *p); | ||
| 212 | |||
| 213 | /* Set the owner of the TX context descriptor */ | ||
| 214 | void (*tx_ctxt_desc_set_owner)(struct sxgbe_tx_ctxt_desc *p); | ||
| 215 | |||
| 216 | /* Get the owner of the TX context descriptor */ | ||
| 217 | int (*get_tx_ctxt_owner)(struct sxgbe_tx_ctxt_desc *p); | ||
| 218 | |||
| 219 | /* Set TX mss */ | ||
| 220 | void (*tx_ctxt_desc_set_mss)(struct sxgbe_tx_ctxt_desc *p, int mss); | ||
| 221 | |||
| 222 | /* Set TX mss */ | ||
| 223 | int (*tx_ctxt_desc_get_mss)(struct sxgbe_tx_ctxt_desc *p); | ||
| 224 | |||
| 225 | /* Set TX tcmssv */ | ||
| 226 | void (*tx_ctxt_desc_set_tcmssv)(struct sxgbe_tx_ctxt_desc *p); | ||
| 227 | |||
| 228 | /* Reset TX ostc */ | ||
| 229 | void (*tx_ctxt_desc_reset_ostc)(struct sxgbe_tx_ctxt_desc *p); | ||
| 230 | |||
| 231 | /* Set IVLAN information */ | ||
| 232 | void (*tx_ctxt_desc_set_ivlantag)(struct sxgbe_tx_ctxt_desc *p, | ||
| 233 | int is_ivlanvalid, int ivlan_tag, | ||
| 234 | int ivlan_ctl); | ||
| 235 | |||
| 236 | /* Return IVLAN Tag */ | ||
| 237 | int (*tx_ctxt_desc_get_ivlantag)(struct sxgbe_tx_ctxt_desc *p); | ||
| 238 | |||
| 239 | /* Set VLAN Tag */ | ||
| 240 | void (*tx_ctxt_desc_set_vlantag)(struct sxgbe_tx_ctxt_desc *p, | ||
| 241 | int is_vlanvalid, int vlan_tag); | ||
| 242 | |||
| 243 | /* Return VLAN Tag */ | ||
| 244 | int (*tx_ctxt_desc_get_vlantag)(struct sxgbe_tx_ctxt_desc *p); | ||
| 245 | |||
| 246 | /* Set Time stamp */ | ||
| 247 | void (*tx_ctxt_set_tstamp)(struct sxgbe_tx_ctxt_desc *p, | ||
| 248 | u8 ostc_enable, u64 tstamp); | ||
| 249 | |||
| 250 | /* Close TX context descriptor */ | ||
| 251 | void (*close_tx_ctxt_desc)(struct sxgbe_tx_ctxt_desc *p); | ||
| 252 | |||
| 253 | /* WB status of context descriptor */ | ||
| 254 | int (*get_tx_ctxt_cde)(struct sxgbe_tx_ctxt_desc *p); | ||
| 255 | |||
| 256 | /* DMA RX descriptor ring initialization */ | ||
| 257 | void (*init_rx_desc)(struct sxgbe_rx_norm_desc *p, int disable_rx_ic, | ||
| 258 | int mode, int end); | ||
| 259 | |||
| 260 | /* Get own bit */ | ||
| 261 | int (*get_rx_owner)(struct sxgbe_rx_norm_desc *p); | ||
| 262 | |||
| 263 | /* Set own bit */ | ||
| 264 | void (*set_rx_owner)(struct sxgbe_rx_norm_desc *p); | ||
| 265 | |||
| 266 | /* Get the receive frame size */ | ||
| 267 | int (*get_rx_frame_len)(struct sxgbe_rx_norm_desc *p); | ||
| 268 | |||
| 269 | /* Return first Descriptor status */ | ||
| 270 | int (*get_rx_fd_status)(struct sxgbe_rx_norm_desc *p); | ||
| 271 | |||
| 272 | /* Return first Descriptor status */ | ||
| 273 | int (*get_rx_ld_status)(struct sxgbe_rx_norm_desc *p); | ||
| 274 | |||
| 275 | /* Return the reception status looking at the RDES1 */ | ||
| 276 | int (*rx_wbstatus)(struct sxgbe_rx_norm_desc *p, | ||
| 277 | struct sxgbe_extra_stats *x, int *checksum); | ||
| 278 | |||
| 279 | /* Get own bit */ | ||
| 280 | int (*get_rx_ctxt_owner)(struct sxgbe_rx_ctxt_desc *p); | ||
| 281 | |||
| 282 | /* Set own bit */ | ||
| 283 | void (*set_rx_ctxt_owner)(struct sxgbe_rx_ctxt_desc *p); | ||
| 284 | |||
| 285 | /* Return the reception status looking at Context control information */ | ||
| 286 | void (*rx_ctxt_wbstatus)(struct sxgbe_rx_ctxt_desc *p, | ||
| 287 | struct sxgbe_extra_stats *x); | ||
| 288 | |||
| 289 | /* Get rx timestamp status */ | ||
| 290 | int (*get_rx_ctxt_tstamp_status)(struct sxgbe_rx_ctxt_desc *p); | ||
| 291 | |||
| 292 | /* Get timestamp value for rx, need to check this */ | ||
| 293 | u64 (*get_timestamp)(struct sxgbe_rx_ctxt_desc *p); | ||
| 294 | }; | ||
| 295 | |||
| 296 | const struct sxgbe_desc_ops *sxgbe_get_desc_ops(void); | ||
| 297 | |||
| 298 | #endif /* __SXGBE_DESC_H__ */ | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c new file mode 100644 index 000000000000..59d2d3976277 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.c | |||
| @@ -0,0 +1,372 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #include <linux/io.h> | ||
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/export.h> | ||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/netdevice.h> | ||
| 17 | #include <linux/phy.h> | ||
| 18 | |||
| 19 | #include "sxgbe_common.h" | ||
| 20 | #include "sxgbe_dma.h" | ||
| 21 | #include "sxgbe_reg.h" | ||
| 22 | #include "sxgbe_desc.h" | ||
| 23 | |||
| 24 | /* DMA core initialization */ | ||
| 25 | static int sxgbe_dma_init(void __iomem *ioaddr, int fix_burst, int burst_map) | ||
| 26 | { | ||
| 27 | int retry_count = 10; | ||
| 28 | u32 reg_val; | ||
| 29 | |||
| 30 | /* reset the DMA */ | ||
| 31 | writel(SXGBE_DMA_SOFT_RESET, ioaddr + SXGBE_DMA_MODE_REG); | ||
| 32 | while (retry_count--) { | ||
| 33 | if (!(readl(ioaddr + SXGBE_DMA_MODE_REG) & | ||
| 34 | SXGBE_DMA_SOFT_RESET)) | ||
| 35 | break; | ||
| 36 | mdelay(10); | ||
| 37 | } | ||
| 38 | |||
| 39 | if (retry_count < 0) | ||
| 40 | return -EBUSY; | ||
| 41 | |||
| 42 | reg_val = readl(ioaddr + SXGBE_DMA_SYSBUS_MODE_REG); | ||
| 43 | |||
| 44 | /* if fix_burst = 0, Set UNDEF = 1 of DMA_Sys_Mode Register. | ||
| 45 | * if fix_burst = 1, Set UNDEF = 0 of DMA_Sys_Mode Register. | ||
| 46 | * burst_map is bitmap for BLEN[4, 8, 16, 32, 64, 128 and 256]. | ||
| 47 | * Set burst_map irrespective of fix_burst value. | ||
| 48 | */ | ||
| 49 | if (!fix_burst) | ||
| 50 | reg_val |= SXGBE_DMA_AXI_UNDEF_BURST; | ||
| 51 | |||
| 52 | /* write burst len map */ | ||
| 53 | reg_val |= (burst_map << SXGBE_DMA_BLENMAP_LSHIFT); | ||
| 54 | |||
| 55 | writel(reg_val, ioaddr + SXGBE_DMA_SYSBUS_MODE_REG); | ||
| 56 | |||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | static void sxgbe_dma_channel_init(void __iomem *ioaddr, int cha_num, | ||
| 61 | int fix_burst, int pbl, dma_addr_t dma_tx, | ||
| 62 | dma_addr_t dma_rx, int t_rsize, int r_rsize) | ||
| 63 | { | ||
| 64 | u32 reg_val; | ||
| 65 | dma_addr_t dma_addr; | ||
| 66 | |||
| 67 | reg_val = readl(ioaddr + SXGBE_DMA_CHA_CTL_REG(cha_num)); | ||
| 68 | /* set the pbl */ | ||
| 69 | if (fix_burst) { | ||
| 70 | reg_val |= SXGBE_DMA_PBL_X8MODE; | ||
| 71 | writel(reg_val, ioaddr + SXGBE_DMA_CHA_CTL_REG(cha_num)); | ||
| 72 | /* program the TX pbl */ | ||
| 73 | reg_val = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num)); | ||
| 74 | reg_val |= (pbl << SXGBE_DMA_TXPBL_LSHIFT); | ||
| 75 | writel(reg_val, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num)); | ||
| 76 | /* program the RX pbl */ | ||
| 77 | reg_val = readl(ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cha_num)); | ||
| 78 | reg_val |= (pbl << SXGBE_DMA_RXPBL_LSHIFT); | ||
| 79 | writel(reg_val, ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cha_num)); | ||
| 80 | } | ||
| 81 | |||
| 82 | /* program desc registers */ | ||
| 83 | writel(upper_32_bits(dma_tx), | ||
| 84 | ioaddr + SXGBE_DMA_CHA_TXDESC_HADD_REG(cha_num)); | ||
| 85 | writel(lower_32_bits(dma_tx), | ||
| 86 | ioaddr + SXGBE_DMA_CHA_TXDESC_LADD_REG(cha_num)); | ||
| 87 | |||
| 88 | writel(upper_32_bits(dma_rx), | ||
| 89 | ioaddr + SXGBE_DMA_CHA_RXDESC_HADD_REG(cha_num)); | ||
| 90 | writel(lower_32_bits(dma_rx), | ||
| 91 | ioaddr + SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num)); | ||
| 92 | |||
| 93 | /* program tail pointers */ | ||
| 94 | /* assumption: upper 32 bits are constant and | ||
| 95 | * same as TX/RX desc list | ||
| 96 | */ | ||
| 97 | dma_addr = dma_tx + ((t_rsize - 1) * SXGBE_DESC_SIZE_BYTES); | ||
| 98 | writel(lower_32_bits(dma_addr), | ||
| 99 | ioaddr + SXGBE_DMA_CHA_TXDESC_TAILPTR_REG(cha_num)); | ||
| 100 | |||
| 101 | dma_addr = dma_rx + ((r_rsize - 1) * SXGBE_DESC_SIZE_BYTES); | ||
| 102 | writel(lower_32_bits(dma_addr), | ||
| 103 | ioaddr + SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num)); | ||
| 104 | /* program the ring sizes */ | ||
| 105 | writel(t_rsize - 1, ioaddr + SXGBE_DMA_CHA_TXDESC_RINGLEN_REG(cha_num)); | ||
| 106 | writel(r_rsize - 1, ioaddr + SXGBE_DMA_CHA_RXDESC_RINGLEN_REG(cha_num)); | ||
| 107 | |||
| 108 | /* Enable TX/RX interrupts */ | ||
| 109 | writel(SXGBE_DMA_ENA_INT, | ||
| 110 | ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(cha_num)); | ||
| 111 | } | ||
| 112 | |||
| 113 | static void sxgbe_enable_dma_transmission(void __iomem *ioaddr, int cha_num) | ||
| 114 | { | ||
| 115 | u32 tx_config; | ||
| 116 | |||
| 117 | tx_config = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num)); | ||
| 118 | tx_config |= SXGBE_TX_START_DMA; | ||
| 119 | writel(tx_config, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cha_num)); | ||
| 120 | } | ||
| 121 | |||
| 122 | static void sxgbe_enable_dma_irq(void __iomem *ioaddr, int dma_cnum) | ||
| 123 | { | ||
| 124 | /* Enable TX/RX interrupts */ | ||
| 125 | writel(SXGBE_DMA_ENA_INT, | ||
| 126 | ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(dma_cnum)); | ||
| 127 | } | ||
| 128 | |||
| 129 | static void sxgbe_disable_dma_irq(void __iomem *ioaddr, int dma_cnum) | ||
| 130 | { | ||
| 131 | /* Disable TX/RX interrupts */ | ||
| 132 | writel(0, ioaddr + SXGBE_DMA_CHA_INT_ENABLE_REG(dma_cnum)); | ||
| 133 | } | ||
| 134 | |||
| 135 | static void sxgbe_dma_start_tx(void __iomem *ioaddr, int tchannels) | ||
| 136 | { | ||
| 137 | int cnum; | ||
| 138 | u32 tx_ctl_reg; | ||
| 139 | |||
| 140 | for (cnum = 0; cnum < tchannels; cnum++) { | ||
| 141 | tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum)); | ||
| 142 | tx_ctl_reg |= SXGBE_TX_ENABLE; | ||
| 143 | writel(tx_ctl_reg, | ||
| 144 | ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum)); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | static void sxgbe_dma_start_tx_queue(void __iomem *ioaddr, int dma_cnum) | ||
| 149 | { | ||
| 150 | u32 tx_ctl_reg; | ||
| 151 | |||
| 152 | tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum)); | ||
| 153 | tx_ctl_reg |= SXGBE_TX_ENABLE; | ||
| 154 | writel(tx_ctl_reg, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum)); | ||
| 155 | } | ||
| 156 | |||
| 157 | static void sxgbe_dma_stop_tx_queue(void __iomem *ioaddr, int dma_cnum) | ||
| 158 | { | ||
| 159 | u32 tx_ctl_reg; | ||
| 160 | |||
| 161 | tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum)); | ||
| 162 | tx_ctl_reg &= ~(SXGBE_TX_ENABLE); | ||
| 163 | writel(tx_ctl_reg, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(dma_cnum)); | ||
| 164 | } | ||
| 165 | |||
| 166 | static void sxgbe_dma_stop_tx(void __iomem *ioaddr, int tchannels) | ||
| 167 | { | ||
| 168 | int cnum; | ||
| 169 | u32 tx_ctl_reg; | ||
| 170 | |||
| 171 | for (cnum = 0; cnum < tchannels; cnum++) { | ||
| 172 | tx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum)); | ||
| 173 | tx_ctl_reg &= ~(SXGBE_TX_ENABLE); | ||
| 174 | writel(tx_ctl_reg, ioaddr + SXGBE_DMA_CHA_TXCTL_REG(cnum)); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | static void sxgbe_dma_start_rx(void __iomem *ioaddr, int rchannels) | ||
| 179 | { | ||
| 180 | int cnum; | ||
| 181 | u32 rx_ctl_reg; | ||
| 182 | |||
| 183 | for (cnum = 0; cnum < rchannels; cnum++) { | ||
| 184 | rx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum)); | ||
| 185 | rx_ctl_reg |= SXGBE_RX_ENABLE; | ||
| 186 | writel(rx_ctl_reg, | ||
| 187 | ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum)); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | static void sxgbe_dma_stop_rx(void __iomem *ioaddr, int rchannels) | ||
| 192 | { | ||
| 193 | int cnum; | ||
| 194 | u32 rx_ctl_reg; | ||
| 195 | |||
| 196 | for (cnum = 0; cnum < rchannels; cnum++) { | ||
| 197 | rx_ctl_reg = readl(ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum)); | ||
| 198 | rx_ctl_reg &= ~(SXGBE_RX_ENABLE); | ||
| 199 | writel(rx_ctl_reg, ioaddr + SXGBE_DMA_CHA_RXCTL_REG(cnum)); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | static int sxgbe_tx_dma_int_status(void __iomem *ioaddr, int channel_no, | ||
| 204 | struct sxgbe_extra_stats *x) | ||
| 205 | { | ||
| 206 | u32 int_status = readl(ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no)); | ||
| 207 | u32 clear_val = 0; | ||
| 208 | u32 ret_val = 0; | ||
| 209 | |||
| 210 | /* TX Normal Interrupt Summary */ | ||
| 211 | if (likely(int_status & SXGBE_DMA_INT_STATUS_NIS)) { | ||
| 212 | x->normal_irq_n++; | ||
| 213 | if (int_status & SXGBE_DMA_INT_STATUS_TI) { | ||
| 214 | ret_val |= handle_tx; | ||
| 215 | x->tx_normal_irq_n++; | ||
| 216 | clear_val |= SXGBE_DMA_INT_STATUS_TI; | ||
| 217 | } | ||
| 218 | |||
| 219 | if (int_status & SXGBE_DMA_INT_STATUS_TBU) { | ||
| 220 | x->tx_underflow_irq++; | ||
| 221 | ret_val |= tx_bump_tc; | ||
| 222 | clear_val |= SXGBE_DMA_INT_STATUS_TBU; | ||
| 223 | } | ||
| 224 | } else if (unlikely(int_status & SXGBE_DMA_INT_STATUS_AIS)) { | ||
| 225 | /* TX Abnormal Interrupt Summary */ | ||
| 226 | if (int_status & SXGBE_DMA_INT_STATUS_TPS) { | ||
| 227 | ret_val |= tx_hard_error; | ||
| 228 | clear_val |= SXGBE_DMA_INT_STATUS_TPS; | ||
| 229 | x->tx_process_stopped_irq++; | ||
| 230 | } | ||
| 231 | |||
| 232 | if (int_status & SXGBE_DMA_INT_STATUS_FBE) { | ||
| 233 | ret_val |= tx_hard_error; | ||
| 234 | x->fatal_bus_error_irq++; | ||
| 235 | |||
| 236 | /* Assumption: FBE bit is the combination of | ||
| 237 | * all the bus access erros and cleared when | ||
| 238 | * the respective error bits cleared | ||
| 239 | */ | ||
| 240 | |||
| 241 | /* check for actual cause */ | ||
| 242 | if (int_status & SXGBE_DMA_INT_STATUS_TEB0) { | ||
| 243 | x->tx_read_transfer_err++; | ||
| 244 | clear_val |= SXGBE_DMA_INT_STATUS_TEB0; | ||
| 245 | } else { | ||
| 246 | x->tx_write_transfer_err++; | ||
| 247 | } | ||
| 248 | |||
| 249 | if (int_status & SXGBE_DMA_INT_STATUS_TEB1) { | ||
| 250 | x->tx_desc_access_err++; | ||
| 251 | clear_val |= SXGBE_DMA_INT_STATUS_TEB1; | ||
| 252 | } else { | ||
| 253 | x->tx_buffer_access_err++; | ||
| 254 | } | ||
| 255 | |||
| 256 | if (int_status & SXGBE_DMA_INT_STATUS_TEB2) { | ||
| 257 | x->tx_data_transfer_err++; | ||
| 258 | clear_val |= SXGBE_DMA_INT_STATUS_TEB2; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | /* context descriptor error */ | ||
| 263 | if (int_status & SXGBE_DMA_INT_STATUS_CTXTERR) { | ||
| 264 | x->tx_ctxt_desc_err++; | ||
| 265 | clear_val |= SXGBE_DMA_INT_STATUS_CTXTERR; | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | /* clear the served bits */ | ||
| 270 | writel(clear_val, ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no)); | ||
| 271 | |||
| 272 | return ret_val; | ||
| 273 | } | ||
| 274 | |||
| 275 | static int sxgbe_rx_dma_int_status(void __iomem *ioaddr, int channel_no, | ||
| 276 | struct sxgbe_extra_stats *x) | ||
| 277 | { | ||
| 278 | u32 int_status = readl(ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no)); | ||
| 279 | u32 clear_val = 0; | ||
| 280 | u32 ret_val = 0; | ||
| 281 | |||
| 282 | /* RX Normal Interrupt Summary */ | ||
| 283 | if (likely(int_status & SXGBE_DMA_INT_STATUS_NIS)) { | ||
| 284 | x->normal_irq_n++; | ||
| 285 | if (int_status & SXGBE_DMA_INT_STATUS_RI) { | ||
| 286 | ret_val |= handle_rx; | ||
| 287 | x->rx_normal_irq_n++; | ||
| 288 | clear_val |= SXGBE_DMA_INT_STATUS_RI; | ||
| 289 | } | ||
| 290 | } else if (unlikely(int_status & SXGBE_DMA_INT_STATUS_AIS)) { | ||
| 291 | /* RX Abnormal Interrupt Summary */ | ||
| 292 | if (int_status & SXGBE_DMA_INT_STATUS_RBU) { | ||
| 293 | ret_val |= rx_bump_tc; | ||
| 294 | clear_val |= SXGBE_DMA_INT_STATUS_RBU; | ||
| 295 | x->rx_underflow_irq++; | ||
| 296 | } | ||
| 297 | |||
| 298 | if (int_status & SXGBE_DMA_INT_STATUS_RPS) { | ||
| 299 | ret_val |= rx_hard_error; | ||
| 300 | clear_val |= SXGBE_DMA_INT_STATUS_RPS; | ||
| 301 | x->rx_process_stopped_irq++; | ||
| 302 | } | ||
| 303 | |||
| 304 | if (int_status & SXGBE_DMA_INT_STATUS_FBE) { | ||
| 305 | ret_val |= rx_hard_error; | ||
| 306 | x->fatal_bus_error_irq++; | ||
| 307 | |||
| 308 | /* Assumption: FBE bit is the combination of | ||
| 309 | * all the bus access erros and cleared when | ||
| 310 | * the respective error bits cleared | ||
| 311 | */ | ||
| 312 | |||
| 313 | /* check for actual cause */ | ||
| 314 | if (int_status & SXGBE_DMA_INT_STATUS_REB0) { | ||
| 315 | x->rx_read_transfer_err++; | ||
| 316 | clear_val |= SXGBE_DMA_INT_STATUS_REB0; | ||
| 317 | } else { | ||
| 318 | x->rx_write_transfer_err++; | ||
| 319 | } | ||
| 320 | |||
| 321 | if (int_status & SXGBE_DMA_INT_STATUS_REB1) { | ||
| 322 | x->rx_desc_access_err++; | ||
| 323 | clear_val |= SXGBE_DMA_INT_STATUS_REB1; | ||
| 324 | } else { | ||
| 325 | x->rx_buffer_access_err++; | ||
| 326 | } | ||
| 327 | |||
| 328 | if (int_status & SXGBE_DMA_INT_STATUS_REB2) { | ||
| 329 | x->rx_data_transfer_err++; | ||
| 330 | clear_val |= SXGBE_DMA_INT_STATUS_REB2; | ||
| 331 | } | ||
| 332 | } | ||
| 333 | } | ||
| 334 | |||
| 335 | /* clear the served bits */ | ||
| 336 | writel(clear_val, ioaddr + SXGBE_DMA_CHA_STATUS_REG(channel_no)); | ||
| 337 | |||
| 338 | return ret_val; | ||
| 339 | } | ||
| 340 | |||
| 341 | /* Program the HW RX Watchdog */ | ||
| 342 | static void sxgbe_dma_rx_watchdog(void __iomem *ioaddr, u32 riwt) | ||
| 343 | { | ||
| 344 | u32 que_num; | ||
| 345 | |||
| 346 | SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, que_num) { | ||
| 347 | writel(riwt, | ||
| 348 | ioaddr + SXGBE_DMA_CHA_INT_RXWATCHTMR_REG(que_num)); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | static const struct sxgbe_dma_ops sxgbe_dma_ops = { | ||
| 353 | .init = sxgbe_dma_init, | ||
| 354 | .cha_init = sxgbe_dma_channel_init, | ||
| 355 | .enable_dma_transmission = sxgbe_enable_dma_transmission, | ||
| 356 | .enable_dma_irq = sxgbe_enable_dma_irq, | ||
| 357 | .disable_dma_irq = sxgbe_disable_dma_irq, | ||
| 358 | .start_tx = sxgbe_dma_start_tx, | ||
| 359 | .start_tx_queue = sxgbe_dma_start_tx_queue, | ||
| 360 | .stop_tx = sxgbe_dma_stop_tx, | ||
| 361 | .stop_tx_queue = sxgbe_dma_stop_tx_queue, | ||
| 362 | .start_rx = sxgbe_dma_start_rx, | ||
| 363 | .stop_rx = sxgbe_dma_stop_rx, | ||
| 364 | .tx_dma_int_status = sxgbe_tx_dma_int_status, | ||
| 365 | .rx_dma_int_status = sxgbe_rx_dma_int_status, | ||
| 366 | .rx_watchdog = sxgbe_dma_rx_watchdog, | ||
| 367 | }; | ||
| 368 | |||
| 369 | const struct sxgbe_dma_ops *sxgbe_get_dma_ops(void) | ||
| 370 | { | ||
| 371 | return &sxgbe_dma_ops; | ||
| 372 | } | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.h new file mode 100644 index 000000000000..bbf167efb60c --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_dma.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #ifndef __SXGBE_DMA_H__ | ||
| 13 | #define __SXGBE_DMA_H__ | ||
| 14 | |||
| 15 | /* forward declaration */ | ||
| 16 | struct sxgbe_extra_stats; | ||
| 17 | |||
| 18 | #define SXGBE_DMA_BLENMAP_LSHIFT 1 | ||
| 19 | #define SXGBE_DMA_TXPBL_LSHIFT 16 | ||
| 20 | #define SXGBE_DMA_RXPBL_LSHIFT 16 | ||
| 21 | #define DEFAULT_DMA_PBL 8 | ||
| 22 | |||
| 23 | struct sxgbe_dma_ops { | ||
| 24 | /* DMA core initialization */ | ||
| 25 | int (*init)(void __iomem *ioaddr, int fix_burst, int burst_map); | ||
| 26 | void (*cha_init)(void __iomem *ioaddr, int cha_num, int fix_burst, | ||
| 27 | int pbl, dma_addr_t dma_tx, dma_addr_t dma_rx, | ||
| 28 | int t_rzie, int r_rsize); | ||
| 29 | void (*enable_dma_transmission)(void __iomem *ioaddr, int dma_cnum); | ||
| 30 | void (*enable_dma_irq)(void __iomem *ioaddr, int dma_cnum); | ||
| 31 | void (*disable_dma_irq)(void __iomem *ioaddr, int dma_cnum); | ||
| 32 | void (*start_tx)(void __iomem *ioaddr, int tchannels); | ||
| 33 | void (*start_tx_queue)(void __iomem *ioaddr, int dma_cnum); | ||
| 34 | void (*stop_tx)(void __iomem *ioaddr, int tchannels); | ||
| 35 | void (*stop_tx_queue)(void __iomem *ioaddr, int dma_cnum); | ||
| 36 | void (*start_rx)(void __iomem *ioaddr, int rchannels); | ||
| 37 | void (*stop_rx)(void __iomem *ioaddr, int rchannels); | ||
| 38 | int (*tx_dma_int_status)(void __iomem *ioaddr, int channel_no, | ||
| 39 | struct sxgbe_extra_stats *x); | ||
| 40 | int (*rx_dma_int_status)(void __iomem *ioaddr, int channel_no, | ||
| 41 | struct sxgbe_extra_stats *x); | ||
| 42 | /* Program the HW RX Watchdog */ | ||
| 43 | void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt); | ||
| 44 | }; | ||
| 45 | |||
| 46 | const struct sxgbe_dma_ops *sxgbe_get_dma_ops(void); | ||
| 47 | |||
| 48 | #endif /* __SXGBE_CORE_H__ */ | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c new file mode 100644 index 000000000000..1dce2b2e045b --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/netdevice.h> | ||
| 17 | #include <linux/phy.h> | ||
| 18 | |||
| 19 | #include "sxgbe_common.h" | ||
| 20 | |||
| 21 | struct sxgbe_stats { | ||
| 22 | char stat_string[ETH_GSTRING_LEN]; | ||
| 23 | int sizeof_stat; | ||
| 24 | int stat_offset; | ||
| 25 | }; | ||
| 26 | |||
| 27 | #define SXGBE_STAT(m) \ | ||
| 28 | { \ | ||
| 29 | #m, \ | ||
| 30 | FIELD_SIZEOF(struct sxgbe_extra_stats, m), \ | ||
| 31 | offsetof(struct sxgbe_priv_data, xstats.m) \ | ||
| 32 | } | ||
| 33 | |||
| 34 | static const struct sxgbe_stats sxgbe_gstrings_stats[] = { | ||
| 35 | }; | ||
| 36 | #define SXGBE_STATS_LEN ARRAY_SIZE(sxgbe_gstrings_stats) | ||
| 37 | |||
| 38 | static const struct ethtool_ops sxgbe_ethtool_ops = { | ||
| 39 | }; | ||
| 40 | |||
| 41 | void sxgbe_set_ethtool_ops(struct net_device *netdev) | ||
| 42 | { | ||
| 43 | SET_ETHTOOL_OPS(netdev, &sxgbe_ethtool_ops); | ||
| 44 | } | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c new file mode 100644 index 000000000000..75ba57cfe7c0 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | |||
| @@ -0,0 +1,2052 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 14 | |||
| 15 | #include <linux/clk.h> | ||
| 16 | #include <linux/crc32.h> | ||
| 17 | #include <linux/dma-mapping.h> | ||
| 18 | #include <linux/etherdevice.h> | ||
| 19 | #include <linux/ethtool.h> | ||
| 20 | #include <linux/if.h> | ||
| 21 | #include <linux/if_ether.h> | ||
| 22 | #include <linux/if_vlan.h> | ||
| 23 | #include <linux/init.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/ip.h> | ||
| 26 | #include <linux/kernel.h> | ||
| 27 | #include <linux/mii.h> | ||
| 28 | #include <linux/module.h> | ||
| 29 | #include <linux/net_tstamp.h> | ||
| 30 | #include <linux/netdevice.h> | ||
| 31 | #include <linux/phy.h> | ||
| 32 | #include <linux/platform_device.h> | ||
| 33 | #include <linux/prefetch.h> | ||
| 34 | #include <linux/skbuff.h> | ||
| 35 | #include <linux/slab.h> | ||
| 36 | #include <linux/tcp.h> | ||
| 37 | #include <linux/sxgbe_platform.h> | ||
| 38 | |||
| 39 | #include "sxgbe_common.h" | ||
| 40 | #include "sxgbe_desc.h" | ||
| 41 | #include "sxgbe_dma.h" | ||
| 42 | #include "sxgbe_mtl.h" | ||
| 43 | #include "sxgbe_reg.h" | ||
| 44 | |||
| 45 | #define SXGBE_ALIGN(x) L1_CACHE_ALIGN(x) | ||
| 46 | #define JUMBO_LEN 9000 | ||
| 47 | |||
| 48 | /* Module parameters */ | ||
| 49 | #define TX_TIMEO 5000 | ||
| 50 | #define DMA_TX_SIZE 512 | ||
| 51 | #define DMA_RX_SIZE 1024 | ||
| 52 | #define TC_DEFAULT 64 | ||
| 53 | #define DMA_BUFFER_SIZE BUF_SIZE_2KiB | ||
| 54 | /* The default timer value as per the sxgbe specification 1 sec(1000 ms) */ | ||
| 55 | #define SXGBE_DEFAULT_LPI_TIMER 1000 | ||
| 56 | |||
| 57 | static int debug = -1; | ||
| 58 | |||
| 59 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
| 60 | static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | | ||
| 61 | NETIF_MSG_LINK | NETIF_MSG_IFUP | | ||
| 62 | NETIF_MSG_IFDOWN | NETIF_MSG_TIMER); | ||
| 63 | |||
| 64 | static irqreturn_t sxgbe_common_interrupt(int irq, void *dev_id); | ||
| 65 | static irqreturn_t sxgbe_tx_interrupt(int irq, void *dev_id); | ||
| 66 | static irqreturn_t sxgbe_rx_interrupt(int irq, void *dev_id); | ||
| 67 | |||
| 68 | #define SXGBE_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) | ||
| 69 | |||
| 70 | /** | ||
| 71 | * sxgbe_clk_csr_set - dynamically set the MDC clock | ||
| 72 | * @priv: driver private structure | ||
| 73 | * Description: this is to dynamically set the MDC clock according to the csr | ||
| 74 | * clock input. | ||
| 75 | */ | ||
| 76 | static void sxgbe_clk_csr_set(struct sxgbe_priv_data *priv) | ||
| 77 | { | ||
| 78 | u32 clk_rate = clk_get_rate(priv->sxgbe_clk); | ||
| 79 | |||
| 80 | /* assign the proper divider, this will be used during | ||
| 81 | * mdio communication | ||
| 82 | */ | ||
| 83 | if (clk_rate < SXGBE_CSR_F_150M) | ||
| 84 | priv->clk_csr = SXGBE_CSR_100_150M; | ||
| 85 | else if (clk_rate <= SXGBE_CSR_F_250M) | ||
| 86 | priv->clk_csr = SXGBE_CSR_150_250M; | ||
| 87 | else if (clk_rate <= SXGBE_CSR_F_300M) | ||
| 88 | priv->clk_csr = SXGBE_CSR_250_300M; | ||
| 89 | else if (clk_rate <= SXGBE_CSR_F_350M) | ||
| 90 | priv->clk_csr = SXGBE_CSR_300_350M; | ||
| 91 | else if (clk_rate <= SXGBE_CSR_F_400M) | ||
| 92 | priv->clk_csr = SXGBE_CSR_350_400M; | ||
| 93 | else if (clk_rate <= SXGBE_CSR_F_500M) | ||
| 94 | priv->clk_csr = SXGBE_CSR_400_500M; | ||
| 95 | } | ||
| 96 | |||
| 97 | /* minimum number of free TX descriptors required to wake up TX process */ | ||
| 98 | #define SXGBE_TX_THRESH(x) (x->dma_tx_size/4) | ||
| 99 | |||
| 100 | static inline u32 sxgbe_tx_avail(struct sxgbe_tx_queue *queue, int tx_qsize) | ||
| 101 | { | ||
| 102 | return queue->dirty_tx + tx_qsize - queue->cur_tx - 1; | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * sxgbe_adjust_link | ||
| 107 | * @dev: net device structure | ||
| 108 | * Description: it adjusts the link parameters. | ||
| 109 | */ | ||
| 110 | static void sxgbe_adjust_link(struct net_device *dev) | ||
| 111 | { | ||
| 112 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 113 | struct phy_device *phydev = priv->phydev; | ||
| 114 | u8 new_state = 0; | ||
| 115 | u8 speed = 0xff; | ||
| 116 | |||
| 117 | if (!phydev) | ||
| 118 | return; | ||
| 119 | |||
| 120 | /* SXGBE is not supporting auto-negotiation and | ||
| 121 | * half duplex mode. so, not handling duplex change | ||
| 122 | * in this function. only handling speed and link status | ||
| 123 | */ | ||
| 124 | if (phydev->link) { | ||
| 125 | if (phydev->speed != priv->speed) { | ||
| 126 | new_state = 1; | ||
| 127 | switch (phydev->speed) { | ||
| 128 | case SPEED_10000: | ||
| 129 | speed = SXGBE_SPEED_10G; | ||
| 130 | break; | ||
| 131 | case SPEED_2500: | ||
| 132 | speed = SXGBE_SPEED_2_5G; | ||
| 133 | break; | ||
| 134 | case SPEED_1000: | ||
| 135 | speed = SXGBE_SPEED_1G; | ||
| 136 | break; | ||
| 137 | default: | ||
| 138 | netif_err(priv, link, dev, | ||
| 139 | "Speed (%d) not supported\n", | ||
| 140 | phydev->speed); | ||
| 141 | } | ||
| 142 | |||
| 143 | priv->speed = phydev->speed; | ||
| 144 | priv->hw->mac->set_speed(priv->ioaddr, speed); | ||
| 145 | } | ||
| 146 | |||
| 147 | if (!priv->oldlink) { | ||
| 148 | new_state = 1; | ||
| 149 | priv->oldlink = 1; | ||
| 150 | } | ||
| 151 | } else if (priv->oldlink) { | ||
| 152 | new_state = 1; | ||
| 153 | priv->oldlink = 0; | ||
| 154 | priv->speed = SPEED_UNKNOWN; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (new_state & netif_msg_link(priv)) | ||
| 158 | phy_print_status(phydev); | ||
| 159 | } | ||
| 160 | |||
| 161 | /** | ||
| 162 | * sxgbe_init_phy - PHY initialization | ||
| 163 | * @dev: net device structure | ||
| 164 | * Description: it initializes the driver's PHY state, and attaches the PHY | ||
| 165 | * to the mac driver. | ||
| 166 | * Return value: | ||
| 167 | * 0 on success | ||
| 168 | */ | ||
| 169 | static int sxgbe_init_phy(struct net_device *ndev) | ||
| 170 | { | ||
| 171 | char phy_id_fmt[MII_BUS_ID_SIZE + 3]; | ||
| 172 | char bus_id[MII_BUS_ID_SIZE]; | ||
| 173 | struct phy_device *phydev; | ||
| 174 | struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||
| 175 | int phy_iface = priv->plat->interface; | ||
| 176 | |||
| 177 | /* assign default link status */ | ||
| 178 | priv->oldlink = 0; | ||
| 179 | priv->speed = SPEED_UNKNOWN; | ||
| 180 | priv->oldduplex = DUPLEX_UNKNOWN; | ||
| 181 | |||
| 182 | if (priv->plat->phy_bus_name) | ||
| 183 | snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x", | ||
| 184 | priv->plat->phy_bus_name, priv->plat->bus_id); | ||
| 185 | else | ||
| 186 | snprintf(bus_id, MII_BUS_ID_SIZE, "sxgbe-%x", | ||
| 187 | priv->plat->bus_id); | ||
| 188 | |||
| 189 | snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, | ||
| 190 | priv->plat->phy_addr); | ||
| 191 | netdev_dbg(ndev, "%s: trying to attach to %s\n", __func__, phy_id_fmt); | ||
| 192 | |||
| 193 | phydev = phy_connect(ndev, phy_id_fmt, &sxgbe_adjust_link, phy_iface); | ||
| 194 | |||
| 195 | if (IS_ERR(phydev)) { | ||
| 196 | netdev_err(ndev, "Could not attach to PHY\n"); | ||
| 197 | return PTR_ERR(phydev); | ||
| 198 | } | ||
| 199 | |||
| 200 | /* Stop Advertising 1000BASE Capability if interface is not GMII */ | ||
| 201 | if ((phy_iface == PHY_INTERFACE_MODE_MII) || | ||
| 202 | (phy_iface == PHY_INTERFACE_MODE_RMII)) | ||
| 203 | phydev->advertising &= ~(SUPPORTED_1000baseT_Half | | ||
| 204 | SUPPORTED_1000baseT_Full); | ||
| 205 | if (phydev->phy_id == 0) { | ||
| 206 | phy_disconnect(phydev); | ||
| 207 | return -ENODEV; | ||
| 208 | } | ||
| 209 | |||
| 210 | netdev_dbg(ndev, "%s: attached to PHY (UID 0x%x) Link = %d\n", | ||
| 211 | __func__, phydev->phy_id, phydev->link); | ||
| 212 | |||
| 213 | /* save phy device in private structure */ | ||
| 214 | priv->phydev = phydev; | ||
| 215 | |||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | /** | ||
| 220 | * sxgbe_clear_descriptors: clear descriptors | ||
| 221 | * @priv: driver private structure | ||
| 222 | * Description: this function is called to clear the tx and rx descriptors | ||
| 223 | * in case of both basic and extended descriptors are used. | ||
| 224 | */ | ||
| 225 | static void sxgbe_clear_descriptors(struct sxgbe_priv_data *priv) | ||
| 226 | { | ||
| 227 | int i, j; | ||
| 228 | unsigned int txsize = priv->dma_tx_size; | ||
| 229 | unsigned int rxsize = priv->dma_rx_size; | ||
| 230 | |||
| 231 | /* Clear the Rx/Tx descriptors */ | ||
| 232 | for (j = 0; j < SXGBE_RX_QUEUES; j++) { | ||
| 233 | for (i = 0; i < rxsize; i++) | ||
| 234 | priv->hw->desc->init_rx_desc(&priv->rxq[j]->dma_rx[i], | ||
| 235 | priv->use_riwt, priv->mode, | ||
| 236 | (i == rxsize - 1)); | ||
| 237 | } | ||
| 238 | |||
| 239 | for (j = 0; j < SXGBE_TX_QUEUES; j++) { | ||
| 240 | for (i = 0; i < txsize; i++) | ||
| 241 | priv->hw->desc->init_tx_desc(&priv->txq[j]->dma_tx[i]); | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | static int sxgbe_init_rx_buffers(struct net_device *dev, | ||
| 246 | struct sxgbe_rx_norm_desc *p, int i, | ||
| 247 | unsigned int dma_buf_sz, | ||
| 248 | struct sxgbe_rx_queue *rx_ring) | ||
| 249 | { | ||
| 250 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 251 | struct sk_buff *skb; | ||
| 252 | |||
| 253 | skb = __netdev_alloc_skb_ip_align(dev, dma_buf_sz, GFP_KERNEL); | ||
| 254 | if (!skb) | ||
| 255 | return -ENOMEM; | ||
| 256 | |||
| 257 | rx_ring->rx_skbuff[i] = skb; | ||
| 258 | rx_ring->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, | ||
| 259 | dma_buf_sz, DMA_FROM_DEVICE); | ||
| 260 | |||
| 261 | if (dma_mapping_error(priv->device, rx_ring->rx_skbuff_dma[i])) { | ||
| 262 | netdev_err(dev, "%s: DMA mapping error\n", __func__); | ||
| 263 | dev_kfree_skb_any(skb); | ||
| 264 | return -EINVAL; | ||
| 265 | } | ||
| 266 | |||
| 267 | p->rdes23.rx_rd_des23.buf2_addr = rx_ring->rx_skbuff_dma[i]; | ||
| 268 | |||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | /** | ||
| 272 | * init_tx_ring - init the TX descriptor ring | ||
| 273 | * @dev: net device structure | ||
| 274 | * @tx_ring: ring to be intialised | ||
| 275 | * @tx_rsize: ring size | ||
| 276 | * Description: this function initializes the DMA TX descriptor | ||
| 277 | */ | ||
| 278 | static int init_tx_ring(struct device *dev, u8 queue_no, | ||
| 279 | struct sxgbe_tx_queue *tx_ring, int tx_rsize) | ||
| 280 | { | ||
| 281 | /* TX ring is not allcoated */ | ||
| 282 | if (!tx_ring) { | ||
| 283 | dev_err(dev, "No memory for TX queue of SXGBE\n"); | ||
| 284 | return -ENOMEM; | ||
| 285 | } | ||
| 286 | |||
| 287 | /* allocate memory for TX descriptors */ | ||
| 288 | tx_ring->dma_tx = dma_zalloc_coherent(dev, | ||
| 289 | tx_rsize * sizeof(struct sxgbe_tx_norm_desc), | ||
| 290 | &tx_ring->dma_tx_phy, GFP_KERNEL); | ||
| 291 | if (!tx_ring->dma_tx) | ||
| 292 | return -ENOMEM; | ||
| 293 | |||
| 294 | /* allocate memory for TX skbuff array */ | ||
| 295 | tx_ring->tx_skbuff_dma = devm_kcalloc(dev, tx_rsize, | ||
| 296 | sizeof(dma_addr_t), GFP_KERNEL); | ||
| 297 | if (!tx_ring->tx_skbuff_dma) | ||
| 298 | goto dmamem_err; | ||
| 299 | |||
| 300 | tx_ring->tx_skbuff = devm_kcalloc(dev, tx_rsize, | ||
| 301 | sizeof(struct sk_buff *), GFP_KERNEL); | ||
| 302 | |||
| 303 | if (!tx_ring->tx_skbuff) | ||
| 304 | goto dmamem_err; | ||
| 305 | |||
| 306 | /* assign queue number */ | ||
| 307 | tx_ring->queue_no = queue_no; | ||
| 308 | |||
| 309 | /* initalise counters */ | ||
| 310 | tx_ring->dirty_tx = 0; | ||
| 311 | tx_ring->cur_tx = 0; | ||
| 312 | |||
| 313 | /* initalise TX queue lock */ | ||
| 314 | spin_lock_init(&tx_ring->tx_lock); | ||
| 315 | |||
| 316 | return 0; | ||
| 317 | |||
| 318 | dmamem_err: | ||
| 319 | dma_free_coherent(dev, tx_rsize * sizeof(struct sxgbe_tx_norm_desc), | ||
| 320 | tx_ring->dma_tx, tx_ring->dma_tx_phy); | ||
| 321 | return -ENOMEM; | ||
| 322 | } | ||
| 323 | |||
| 324 | /** | ||
| 325 | * free_rx_ring - free the RX descriptor ring | ||
| 326 | * @dev: net device structure | ||
| 327 | * @rx_ring: ring to be intialised | ||
| 328 | * @rx_rsize: ring size | ||
| 329 | * Description: this function initializes the DMA RX descriptor | ||
| 330 | */ | ||
| 331 | void free_rx_ring(struct device *dev, struct sxgbe_rx_queue *rx_ring, | ||
| 332 | int rx_rsize) | ||
| 333 | { | ||
| 334 | dma_free_coherent(dev, rx_rsize * sizeof(struct sxgbe_rx_norm_desc), | ||
| 335 | rx_ring->dma_rx, rx_ring->dma_rx_phy); | ||
| 336 | kfree(rx_ring->rx_skbuff_dma); | ||
| 337 | kfree(rx_ring->rx_skbuff); | ||
| 338 | } | ||
| 339 | |||
| 340 | /** | ||
| 341 | * init_rx_ring - init the RX descriptor ring | ||
| 342 | * @dev: net device structure | ||
| 343 | * @rx_ring: ring to be intialised | ||
| 344 | * @rx_rsize: ring size | ||
| 345 | * Description: this function initializes the DMA RX descriptor | ||
| 346 | */ | ||
| 347 | static int init_rx_ring(struct net_device *dev, u8 queue_no, | ||
| 348 | struct sxgbe_rx_queue *rx_ring, int rx_rsize) | ||
| 349 | { | ||
| 350 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 351 | int desc_index; | ||
| 352 | unsigned int bfsize = 0; | ||
| 353 | unsigned int ret = 0; | ||
| 354 | |||
| 355 | /* Set the max buffer size according to the MTU. */ | ||
| 356 | bfsize = ALIGN(dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN, 8); | ||
| 357 | |||
| 358 | netif_dbg(priv, probe, dev, "%s: bfsize %d\n", __func__, bfsize); | ||
| 359 | |||
| 360 | /* RX ring is not allcoated */ | ||
| 361 | if (rx_ring == NULL) { | ||
| 362 | netdev_err(dev, "No memory for RX queue\n"); | ||
| 363 | goto error; | ||
| 364 | } | ||
| 365 | |||
| 366 | /* assign queue number */ | ||
| 367 | rx_ring->queue_no = queue_no; | ||
| 368 | |||
| 369 | /* allocate memory for RX descriptors */ | ||
| 370 | rx_ring->dma_rx = dma_zalloc_coherent(priv->device, | ||
| 371 | rx_rsize * sizeof(struct sxgbe_rx_norm_desc), | ||
| 372 | &rx_ring->dma_rx_phy, GFP_KERNEL); | ||
| 373 | |||
| 374 | if (rx_ring->dma_rx == NULL) | ||
| 375 | goto error; | ||
| 376 | |||
| 377 | /* allocate memory for RX skbuff array */ | ||
| 378 | rx_ring->rx_skbuff_dma = kmalloc_array(rx_rsize, | ||
| 379 | sizeof(dma_addr_t), GFP_KERNEL); | ||
| 380 | if (rx_ring->rx_skbuff_dma == NULL) | ||
| 381 | goto dmamem_err; | ||
| 382 | |||
| 383 | rx_ring->rx_skbuff = kmalloc_array(rx_rsize, | ||
| 384 | sizeof(struct sk_buff *), GFP_KERNEL); | ||
| 385 | if (rx_ring->rx_skbuff == NULL) | ||
| 386 | goto rxbuff_err; | ||
| 387 | |||
| 388 | /* initialise the buffers */ | ||
| 389 | for (desc_index = 0; desc_index < rx_rsize; desc_index++) { | ||
| 390 | struct sxgbe_rx_norm_desc *p; | ||
| 391 | p = rx_ring->dma_rx + desc_index; | ||
| 392 | ret = sxgbe_init_rx_buffers(dev, p, desc_index, | ||
| 393 | bfsize, rx_ring); | ||
| 394 | if (ret) | ||
| 395 | goto err_init_rx_buffers; | ||
| 396 | } | ||
| 397 | |||
| 398 | /* initalise counters */ | ||
| 399 | rx_ring->cur_rx = 0; | ||
| 400 | rx_ring->dirty_rx = (unsigned int)(desc_index - rx_rsize); | ||
| 401 | priv->dma_buf_sz = bfsize; | ||
| 402 | |||
| 403 | return 0; | ||
| 404 | |||
| 405 | err_init_rx_buffers: | ||
| 406 | while (--desc_index >= 0) | ||
| 407 | free_rx_ring(priv->device, rx_ring, desc_index); | ||
| 408 | kfree(rx_ring->rx_skbuff); | ||
| 409 | rxbuff_err: | ||
| 410 | kfree(rx_ring->rx_skbuff_dma); | ||
| 411 | dmamem_err: | ||
| 412 | dma_free_coherent(priv->device, | ||
| 413 | rx_rsize * sizeof(struct sxgbe_rx_norm_desc), | ||
| 414 | rx_ring->dma_rx, rx_ring->dma_rx_phy); | ||
| 415 | error: | ||
| 416 | return -ENOMEM; | ||
| 417 | } | ||
| 418 | /** | ||
| 419 | * free_tx_ring - free the TX descriptor ring | ||
| 420 | * @dev: net device structure | ||
| 421 | * @tx_ring: ring to be intialised | ||
| 422 | * @tx_rsize: ring size | ||
| 423 | * Description: this function initializes the DMA TX descriptor | ||
| 424 | */ | ||
| 425 | void free_tx_ring(struct device *dev, struct sxgbe_tx_queue *tx_ring, | ||
| 426 | int tx_rsize) | ||
| 427 | { | ||
| 428 | dma_free_coherent(dev, tx_rsize * sizeof(struct sxgbe_tx_norm_desc), | ||
| 429 | tx_ring->dma_tx, tx_ring->dma_tx_phy); | ||
| 430 | } | ||
| 431 | |||
| 432 | /** | ||
| 433 | * init_dma_desc_rings - init the RX/TX descriptor rings | ||
| 434 | * @dev: net device structure | ||
| 435 | * Description: this function initializes the DMA RX/TX descriptors | ||
| 436 | * and allocates the socket buffers. It suppors the chained and ring | ||
| 437 | * modes. | ||
| 438 | */ | ||
| 439 | static int init_dma_desc_rings(struct net_device *netd) | ||
| 440 | { | ||
| 441 | int queue_num, ret; | ||
| 442 | struct sxgbe_priv_data *priv = netdev_priv(netd); | ||
| 443 | int tx_rsize = priv->dma_tx_size; | ||
| 444 | int rx_rsize = priv->dma_rx_size; | ||
| 445 | |||
| 446 | /* Allocate memory for queue structures and TX descs */ | ||
| 447 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { | ||
| 448 | ret = init_tx_ring(priv->device, queue_num, | ||
| 449 | priv->txq[queue_num], tx_rsize); | ||
| 450 | if (ret) { | ||
| 451 | dev_err(&netd->dev, "TX DMA ring allocation failed!\n"); | ||
| 452 | goto txalloc_err; | ||
| 453 | } | ||
| 454 | |||
| 455 | /* save private pointer in each ring this | ||
| 456 | * pointer is needed during cleaing TX queue | ||
| 457 | */ | ||
| 458 | priv->txq[queue_num]->priv_ptr = priv; | ||
| 459 | } | ||
| 460 | |||
| 461 | /* Allocate memory for queue structures and RX descs */ | ||
| 462 | SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) { | ||
| 463 | ret = init_rx_ring(netd, queue_num, | ||
| 464 | priv->rxq[queue_num], rx_rsize); | ||
| 465 | if (ret) { | ||
| 466 | netdev_err(netd, "RX DMA ring allocation failed!!\n"); | ||
| 467 | goto rxalloc_err; | ||
| 468 | } | ||
| 469 | |||
| 470 | /* save private pointer in each ring this | ||
| 471 | * pointer is needed during cleaing TX queue | ||
| 472 | */ | ||
| 473 | priv->rxq[queue_num]->priv_ptr = priv; | ||
| 474 | } | ||
| 475 | |||
| 476 | sxgbe_clear_descriptors(priv); | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | |||
| 480 | txalloc_err: | ||
| 481 | while (queue_num--) | ||
| 482 | free_tx_ring(priv->device, priv->txq[queue_num], tx_rsize); | ||
| 483 | return ret; | ||
| 484 | |||
| 485 | rxalloc_err: | ||
| 486 | while (queue_num--) | ||
| 487 | free_rx_ring(priv->device, priv->rxq[queue_num], rx_rsize); | ||
| 488 | return ret; | ||
| 489 | } | ||
| 490 | |||
| 491 | static void tx_free_ring_skbufs(struct sxgbe_tx_queue *txqueue) | ||
| 492 | { | ||
| 493 | int dma_desc; | ||
| 494 | struct sxgbe_priv_data *priv = txqueue->priv_ptr; | ||
| 495 | int tx_rsize = priv->dma_tx_size; | ||
| 496 | |||
| 497 | for (dma_desc = 0; dma_desc < tx_rsize; dma_desc++) { | ||
| 498 | struct sxgbe_tx_norm_desc *tdesc = txqueue->dma_tx + dma_desc; | ||
| 499 | |||
| 500 | if (txqueue->tx_skbuff_dma[dma_desc]) | ||
| 501 | dma_unmap_single(priv->device, | ||
| 502 | txqueue->tx_skbuff_dma[dma_desc], | ||
| 503 | priv->hw->desc->get_tx_len(tdesc), | ||
| 504 | DMA_TO_DEVICE); | ||
| 505 | |||
| 506 | dev_kfree_skb_any(txqueue->tx_skbuff[dma_desc]); | ||
| 507 | txqueue->tx_skbuff[dma_desc] = NULL; | ||
| 508 | txqueue->tx_skbuff_dma[dma_desc] = 0; | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | |||
| 513 | static void dma_free_tx_skbufs(struct sxgbe_priv_data *priv) | ||
| 514 | { | ||
| 515 | int queue_num; | ||
| 516 | |||
| 517 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { | ||
| 518 | struct sxgbe_tx_queue *tqueue = priv->txq[queue_num]; | ||
| 519 | tx_free_ring_skbufs(tqueue); | ||
| 520 | } | ||
| 521 | } | ||
| 522 | |||
| 523 | static void free_dma_desc_resources(struct sxgbe_priv_data *priv) | ||
| 524 | { | ||
| 525 | int queue_num; | ||
| 526 | int tx_rsize = priv->dma_tx_size; | ||
| 527 | int rx_rsize = priv->dma_rx_size; | ||
| 528 | |||
| 529 | /* Release the DMA TX buffers */ | ||
| 530 | dma_free_tx_skbufs(priv); | ||
| 531 | |||
| 532 | /* Release the TX ring memory also */ | ||
| 533 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { | ||
| 534 | free_tx_ring(priv->device, priv->txq[queue_num], tx_rsize); | ||
| 535 | } | ||
| 536 | |||
| 537 | /* Release the RX ring memory also */ | ||
| 538 | SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) { | ||
| 539 | free_rx_ring(priv->device, priv->rxq[queue_num], rx_rsize); | ||
| 540 | } | ||
| 541 | } | ||
| 542 | |||
| 543 | static int txring_mem_alloc(struct sxgbe_priv_data *priv) | ||
| 544 | { | ||
| 545 | int queue_num; | ||
| 546 | |||
| 547 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { | ||
| 548 | priv->txq[queue_num] = devm_kmalloc(priv->device, | ||
| 549 | sizeof(struct sxgbe_tx_queue), GFP_KERNEL); | ||
| 550 | if (!priv->txq[queue_num]) | ||
| 551 | return -ENOMEM; | ||
| 552 | } | ||
| 553 | |||
| 554 | return 0; | ||
| 555 | } | ||
| 556 | |||
| 557 | static int rxring_mem_alloc(struct sxgbe_priv_data *priv) | ||
| 558 | { | ||
| 559 | int queue_num; | ||
| 560 | |||
| 561 | SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) { | ||
| 562 | priv->rxq[queue_num] = devm_kmalloc(priv->device, | ||
| 563 | sizeof(struct sxgbe_rx_queue), GFP_KERNEL); | ||
| 564 | if (!priv->rxq[queue_num]) | ||
| 565 | return -ENOMEM; | ||
| 566 | } | ||
| 567 | |||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | /** | ||
| 572 | * sxgbe_mtl_operation_mode - HW MTL operation mode | ||
| 573 | * @priv: driver private structure | ||
| 574 | * Description: it sets the MTL operation mode: tx/rx MTL thresholds | ||
| 575 | * or Store-And-Forward capability. | ||
| 576 | */ | ||
| 577 | static void sxgbe_mtl_operation_mode(struct sxgbe_priv_data *priv) | ||
| 578 | { | ||
| 579 | int queue_num; | ||
| 580 | |||
| 581 | /* TX/RX threshold control */ | ||
| 582 | if (likely(priv->plat->force_sf_dma_mode)) { | ||
| 583 | /* set TC mode for TX QUEUES */ | ||
| 584 | SXGBE_FOR_EACH_QUEUE(priv->hw_cap.tx_mtl_queues, queue_num) | ||
| 585 | priv->hw->mtl->set_tx_mtl_mode(priv->ioaddr, queue_num, | ||
| 586 | SXGBE_MTL_SFMODE); | ||
| 587 | priv->tx_tc = SXGBE_MTL_SFMODE; | ||
| 588 | |||
| 589 | /* set TC mode for RX QUEUES */ | ||
| 590 | SXGBE_FOR_EACH_QUEUE(priv->hw_cap.rx_mtl_queues, queue_num) | ||
| 591 | priv->hw->mtl->set_rx_mtl_mode(priv->ioaddr, queue_num, | ||
| 592 | SXGBE_MTL_SFMODE); | ||
| 593 | priv->rx_tc = SXGBE_MTL_SFMODE; | ||
| 594 | } else if (unlikely(priv->plat->force_thresh_dma_mode)) { | ||
| 595 | /* set TC mode for TX QUEUES */ | ||
| 596 | SXGBE_FOR_EACH_QUEUE(priv->hw_cap.tx_mtl_queues, queue_num) | ||
| 597 | priv->hw->mtl->set_tx_mtl_mode(priv->ioaddr, queue_num, | ||
| 598 | priv->tx_tc); | ||
| 599 | /* set TC mode for RX QUEUES */ | ||
| 600 | SXGBE_FOR_EACH_QUEUE(priv->hw_cap.rx_mtl_queues, queue_num) | ||
| 601 | priv->hw->mtl->set_rx_mtl_mode(priv->ioaddr, queue_num, | ||
| 602 | priv->rx_tc); | ||
| 603 | } else { | ||
| 604 | pr_err("ERROR: %s: Invalid TX threshold mode\n", __func__); | ||
| 605 | } | ||
| 606 | } | ||
| 607 | |||
| 608 | /** | ||
| 609 | * sxgbe_tx_queue_clean: | ||
| 610 | * @priv: driver private structure | ||
| 611 | * Description: it reclaims resources after transmission completes. | ||
| 612 | */ | ||
| 613 | static void sxgbe_tx_queue_clean(struct sxgbe_tx_queue *tqueue) | ||
| 614 | { | ||
| 615 | struct sxgbe_priv_data *priv = tqueue->priv_ptr; | ||
| 616 | unsigned int tx_rsize = priv->dma_tx_size; | ||
| 617 | struct netdev_queue *dev_txq; | ||
| 618 | u8 queue_no = tqueue->queue_no; | ||
| 619 | |||
| 620 | dev_txq = netdev_get_tx_queue(priv->dev, queue_no); | ||
| 621 | |||
| 622 | spin_lock(&tqueue->tx_lock); | ||
| 623 | |||
| 624 | priv->xstats.tx_clean++; | ||
| 625 | while (tqueue->dirty_tx != tqueue->cur_tx) { | ||
| 626 | unsigned int entry = tqueue->dirty_tx % tx_rsize; | ||
| 627 | struct sk_buff *skb = tqueue->tx_skbuff[entry]; | ||
| 628 | struct sxgbe_tx_norm_desc *p; | ||
| 629 | |||
| 630 | p = tqueue->dma_tx + entry; | ||
| 631 | |||
| 632 | /* Check if the descriptor is owned by the DMA. */ | ||
| 633 | if (priv->hw->desc->get_tx_owner(p)) | ||
| 634 | break; | ||
| 635 | |||
| 636 | if (netif_msg_tx_done(priv)) | ||
| 637 | pr_debug("%s: curr %d, dirty %d\n", | ||
| 638 | __func__, tqueue->cur_tx, tqueue->dirty_tx); | ||
| 639 | |||
| 640 | if (likely(tqueue->tx_skbuff_dma[entry])) { | ||
| 641 | dma_unmap_single(priv->device, | ||
| 642 | tqueue->tx_skbuff_dma[entry], | ||
| 643 | priv->hw->desc->get_tx_len(p), | ||
| 644 | DMA_TO_DEVICE); | ||
| 645 | tqueue->tx_skbuff_dma[entry] = 0; | ||
| 646 | } | ||
| 647 | |||
| 648 | if (likely(skb)) { | ||
| 649 | dev_kfree_skb(skb); | ||
| 650 | tqueue->tx_skbuff[entry] = NULL; | ||
| 651 | } | ||
| 652 | |||
| 653 | priv->hw->desc->release_tx_desc(p); | ||
| 654 | |||
| 655 | tqueue->dirty_tx++; | ||
| 656 | } | ||
| 657 | |||
| 658 | /* wake up queue */ | ||
| 659 | if (unlikely(netif_tx_queue_stopped(dev_txq) && | ||
| 660 | sxgbe_tx_avail(tqueue, tx_rsize) > SXGBE_TX_THRESH(priv))) { | ||
| 661 | netif_tx_lock(priv->dev); | ||
| 662 | if (netif_tx_queue_stopped(dev_txq) && | ||
| 663 | sxgbe_tx_avail(tqueue, tx_rsize) > SXGBE_TX_THRESH(priv)) { | ||
| 664 | if (netif_msg_tx_done(priv)) | ||
| 665 | pr_debug("%s: restart transmit\n", __func__); | ||
| 666 | netif_tx_wake_queue(dev_txq); | ||
| 667 | } | ||
| 668 | netif_tx_unlock(priv->dev); | ||
| 669 | } | ||
| 670 | |||
| 671 | spin_unlock(&tqueue->tx_lock); | ||
| 672 | } | ||
| 673 | |||
| 674 | /** | ||
| 675 | * sxgbe_tx_clean: | ||
| 676 | * @priv: driver private structure | ||
| 677 | * Description: it reclaims resources after transmission completes. | ||
| 678 | */ | ||
| 679 | static void sxgbe_tx_all_clean(struct sxgbe_priv_data *priv) | ||
| 680 | { | ||
| 681 | u8 queue_num; | ||
| 682 | |||
| 683 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { | ||
| 684 | struct sxgbe_tx_queue *tqueue = priv->txq[queue_num]; | ||
| 685 | |||
| 686 | sxgbe_tx_queue_clean(tqueue); | ||
| 687 | } | ||
| 688 | } | ||
| 689 | |||
| 690 | /** | ||
| 691 | * sxgbe_restart_tx_queue: irq tx error mng function | ||
| 692 | * @priv: driver private structure | ||
| 693 | * Description: it cleans the descriptors and restarts the transmission | ||
| 694 | * in case of errors. | ||
| 695 | */ | ||
| 696 | static void sxgbe_restart_tx_queue(struct sxgbe_priv_data *priv, int queue_num) | ||
| 697 | { | ||
| 698 | struct sxgbe_tx_queue *tx_ring = priv->txq[queue_num]; | ||
| 699 | struct netdev_queue *dev_txq = netdev_get_tx_queue(priv->dev, | ||
| 700 | queue_num); | ||
| 701 | |||
| 702 | /* stop the queue */ | ||
| 703 | netif_tx_stop_queue(dev_txq); | ||
| 704 | |||
| 705 | /* stop the tx dma */ | ||
| 706 | priv->hw->dma->stop_tx_queue(priv->ioaddr, queue_num); | ||
| 707 | |||
| 708 | /* free the skbuffs of the ring */ | ||
| 709 | tx_free_ring_skbufs(tx_ring); | ||
| 710 | |||
| 711 | /* initalise counters */ | ||
| 712 | tx_ring->cur_tx = 0; | ||
| 713 | tx_ring->dirty_tx = 0; | ||
| 714 | |||
| 715 | /* start the tx dma */ | ||
| 716 | priv->hw->dma->start_tx_queue(priv->ioaddr, queue_num); | ||
| 717 | |||
| 718 | priv->dev->stats.tx_errors++; | ||
| 719 | |||
| 720 | /* wakeup the queue */ | ||
| 721 | netif_tx_wake_queue(dev_txq); | ||
| 722 | } | ||
| 723 | |||
| 724 | /** | ||
| 725 | * sxgbe_reset_all_tx_queues: irq tx error mng function | ||
| 726 | * @priv: driver private structure | ||
| 727 | * Description: it cleans all the descriptors and | ||
| 728 | * restarts the transmission on all queues in case of errors. | ||
| 729 | */ | ||
| 730 | static void sxgbe_reset_all_tx_queues(struct sxgbe_priv_data *priv) | ||
| 731 | { | ||
| 732 | int queue_num; | ||
| 733 | |||
| 734 | /* On TX timeout of net device, resetting of all queues | ||
| 735 | * may not be proper way, revisit this later if needed | ||
| 736 | */ | ||
| 737 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) | ||
| 738 | sxgbe_restart_tx_queue(priv, queue_num); | ||
| 739 | } | ||
| 740 | |||
| 741 | /** | ||
| 742 | * sxgbe_get_hw_features: get XMAC capabilities from the HW cap. register. | ||
| 743 | * @priv: driver private structure | ||
| 744 | * Description: | ||
| 745 | * new GMAC chip generations have a new register to indicate the | ||
| 746 | * presence of the optional feature/functions. | ||
| 747 | * This can be also used to override the value passed through the | ||
| 748 | * platform and necessary for old MAC10/100 and GMAC chips. | ||
| 749 | */ | ||
| 750 | static int sxgbe_get_hw_features(struct sxgbe_priv_data * const priv) | ||
| 751 | { | ||
| 752 | int rval = 0; | ||
| 753 | struct sxgbe_hw_features *features = &priv->hw_cap; | ||
| 754 | |||
| 755 | /* Read First Capability Register CAP[0] */ | ||
| 756 | rval = priv->hw->mac->get_hw_feature(priv->ioaddr, 0); | ||
| 757 | if (rval) { | ||
| 758 | features->pmt_remote_wake_up = | ||
| 759 | SXGBE_HW_FEAT_PMT_TEMOTE_WOP(rval); | ||
| 760 | features->pmt_magic_frame = SXGBE_HW_FEAT_PMT_MAGIC_PKT(rval); | ||
| 761 | features->atime_stamp = SXGBE_HW_FEAT_IEEE1500_2008(rval); | ||
| 762 | features->tx_csum_offload = | ||
| 763 | SXGBE_HW_FEAT_TX_CSUM_OFFLOAD(rval); | ||
| 764 | features->rx_csum_offload = | ||
| 765 | SXGBE_HW_FEAT_RX_CSUM_OFFLOAD(rval); | ||
| 766 | features->multi_macaddr = SXGBE_HW_FEAT_MACADDR_COUNT(rval); | ||
| 767 | features->tstamp_srcselect = SXGBE_HW_FEAT_TSTMAP_SRC(rval); | ||
| 768 | features->sa_vlan_insert = SXGBE_HW_FEAT_SRCADDR_VLAN(rval); | ||
| 769 | } | ||
| 770 | |||
| 771 | /* Read First Capability Register CAP[1] */ | ||
| 772 | rval = priv->hw->mac->get_hw_feature(priv->ioaddr, 1); | ||
| 773 | if (rval) { | ||
| 774 | features->rxfifo_size = SXGBE_HW_FEAT_RX_FIFO_SIZE(rval); | ||
| 775 | features->txfifo_size = SXGBE_HW_FEAT_TX_FIFO_SIZE(rval); | ||
| 776 | features->atstmap_hword = SXGBE_HW_FEAT_TX_FIFO_SIZE(rval); | ||
| 777 | features->dcb_enable = SXGBE_HW_FEAT_DCB(rval); | ||
| 778 | features->splithead_enable = SXGBE_HW_FEAT_SPLIT_HDR(rval); | ||
| 779 | features->tcpseg_offload = SXGBE_HW_FEAT_TSO(rval); | ||
| 780 | features->debug_mem = SXGBE_HW_FEAT_DEBUG_MEM_IFACE(rval); | ||
| 781 | features->rss_enable = SXGBE_HW_FEAT_RSS(rval); | ||
| 782 | features->hash_tsize = SXGBE_HW_FEAT_HASH_TABLE_SIZE(rval); | ||
| 783 | features->l3l4_filer_size = SXGBE_HW_FEAT_L3L4_FILTER_NUM(rval); | ||
| 784 | } | ||
| 785 | |||
| 786 | /* Read First Capability Register CAP[2] */ | ||
| 787 | rval = priv->hw->mac->get_hw_feature(priv->ioaddr, 2); | ||
| 788 | if (rval) { | ||
| 789 | features->rx_mtl_queues = SXGBE_HW_FEAT_RX_MTL_QUEUES(rval); | ||
| 790 | features->tx_mtl_queues = SXGBE_HW_FEAT_TX_MTL_QUEUES(rval); | ||
| 791 | features->rx_dma_channels = SXGBE_HW_FEAT_RX_DMA_CHANNELS(rval); | ||
| 792 | features->tx_dma_channels = SXGBE_HW_FEAT_TX_DMA_CHANNELS(rval); | ||
| 793 | features->pps_output_count = SXGBE_HW_FEAT_PPS_OUTPUTS(rval); | ||
| 794 | features->aux_input_count = SXGBE_HW_FEAT_AUX_SNAPSHOTS(rval); | ||
| 795 | } | ||
| 796 | |||
| 797 | return rval; | ||
| 798 | } | ||
| 799 | |||
| 800 | /** | ||
| 801 | * sxgbe_check_ether_addr: check if the MAC addr is valid | ||
| 802 | * @priv: driver private structure | ||
| 803 | * Description: | ||
| 804 | * it is to verify if the MAC address is valid, in case of failures it | ||
| 805 | * generates a random MAC address | ||
| 806 | */ | ||
| 807 | static void sxgbe_check_ether_addr(struct sxgbe_priv_data *priv) | ||
| 808 | { | ||
| 809 | if (!is_valid_ether_addr(priv->dev->dev_addr)) { | ||
| 810 | priv->hw->mac->get_umac_addr((void __iomem *) | ||
| 811 | priv->ioaddr, | ||
| 812 | priv->dev->dev_addr, 0); | ||
| 813 | if (!is_valid_ether_addr(priv->dev->dev_addr)) | ||
| 814 | eth_hw_addr_random(priv->dev); | ||
| 815 | } | ||
| 816 | dev_info(priv->device, "device MAC address %pM\n", | ||
| 817 | priv->dev->dev_addr); | ||
| 818 | } | ||
| 819 | |||
| 820 | /** | ||
| 821 | * sxgbe_init_dma_engine: DMA init. | ||
| 822 | * @priv: driver private structure | ||
| 823 | * Description: | ||
| 824 | * It inits the DMA invoking the specific SXGBE callback. | ||
| 825 | * Some DMA parameters can be passed from the platform; | ||
| 826 | * in case of these are not passed a default is kept for the MAC or GMAC. | ||
| 827 | */ | ||
| 828 | static int sxgbe_init_dma_engine(struct sxgbe_priv_data *priv) | ||
| 829 | { | ||
| 830 | int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_map = 0; | ||
| 831 | int queue_num; | ||
| 832 | |||
| 833 | if (priv->plat->dma_cfg) { | ||
| 834 | pbl = priv->plat->dma_cfg->pbl; | ||
| 835 | fixed_burst = priv->plat->dma_cfg->fixed_burst; | ||
| 836 | burst_map = priv->plat->dma_cfg->burst_map; | ||
| 837 | } | ||
| 838 | |||
| 839 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) | ||
| 840 | priv->hw->dma->cha_init(priv->ioaddr, queue_num, | ||
| 841 | fixed_burst, pbl, | ||
| 842 | (priv->txq[queue_num])->dma_tx_phy, | ||
| 843 | (priv->rxq[queue_num])->dma_rx_phy, | ||
| 844 | priv->dma_tx_size, priv->dma_rx_size); | ||
| 845 | |||
| 846 | return priv->hw->dma->init(priv->ioaddr, fixed_burst, burst_map); | ||
| 847 | } | ||
| 848 | |||
| 849 | /** | ||
| 850 | * sxgbe_init_mtl_engine: MTL init. | ||
| 851 | * @priv: driver private structure | ||
| 852 | * Description: | ||
| 853 | * It inits the MTL invoking the specific SXGBE callback. | ||
| 854 | */ | ||
| 855 | static void sxgbe_init_mtl_engine(struct sxgbe_priv_data *priv) | ||
| 856 | { | ||
| 857 | int queue_num; | ||
| 858 | |||
| 859 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { | ||
| 860 | priv->hw->mtl->mtl_set_txfifosize(priv->ioaddr, queue_num, | ||
| 861 | priv->hw_cap.tx_mtl_qsize); | ||
| 862 | priv->hw->mtl->mtl_enable_txqueue(priv->ioaddr, queue_num); | ||
| 863 | } | ||
| 864 | } | ||
| 865 | |||
| 866 | /** | ||
| 867 | * sxgbe_disable_mtl_engine: MTL disable. | ||
| 868 | * @priv: driver private structure | ||
| 869 | * Description: | ||
| 870 | * It disables the MTL queues by invoking the specific SXGBE callback. | ||
| 871 | */ | ||
| 872 | static void sxgbe_disable_mtl_engine(struct sxgbe_priv_data *priv) | ||
| 873 | { | ||
| 874 | int queue_num; | ||
| 875 | |||
| 876 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) | ||
| 877 | priv->hw->mtl->mtl_disable_txqueue(priv->ioaddr, queue_num); | ||
| 878 | } | ||
| 879 | |||
| 880 | |||
| 881 | /** | ||
| 882 | * sxgbe_tx_timer: mitigation sw timer for tx. | ||
| 883 | * @data: data pointer | ||
| 884 | * Description: | ||
| 885 | * This is the timer handler to directly invoke the sxgbe_tx_clean. | ||
| 886 | */ | ||
| 887 | static void sxgbe_tx_timer(unsigned long data) | ||
| 888 | { | ||
| 889 | struct sxgbe_tx_queue *p = (struct sxgbe_tx_queue *)data; | ||
| 890 | sxgbe_tx_queue_clean(p); | ||
| 891 | } | ||
| 892 | |||
| 893 | /** | ||
| 894 | * sxgbe_init_tx_coalesce: init tx mitigation options. | ||
| 895 | * @priv: driver private structure | ||
| 896 | * Description: | ||
| 897 | * This inits the transmit coalesce parameters: i.e. timer rate, | ||
| 898 | * timer handler and default threshold used for enabling the | ||
| 899 | * interrupt on completion bit. | ||
| 900 | */ | ||
| 901 | static void sxgbe_tx_init_coalesce(struct sxgbe_priv_data *priv) | ||
| 902 | { | ||
| 903 | u8 queue_num; | ||
| 904 | |||
| 905 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { | ||
| 906 | struct sxgbe_tx_queue *p = priv->txq[queue_num]; | ||
| 907 | p->tx_coal_frames = SXGBE_TX_FRAMES; | ||
| 908 | p->tx_coal_timer = SXGBE_COAL_TX_TIMER; | ||
| 909 | init_timer(&p->txtimer); | ||
| 910 | p->txtimer.expires = SXGBE_COAL_TIMER(p->tx_coal_timer); | ||
| 911 | p->txtimer.data = (unsigned long)&priv->txq[queue_num]; | ||
| 912 | p->txtimer.function = sxgbe_tx_timer; | ||
| 913 | add_timer(&p->txtimer); | ||
| 914 | } | ||
| 915 | } | ||
| 916 | |||
| 917 | static void sxgbe_tx_del_timer(struct sxgbe_priv_data *priv) | ||
| 918 | { | ||
| 919 | u8 queue_num; | ||
| 920 | |||
| 921 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { | ||
| 922 | struct sxgbe_tx_queue *p = priv->txq[queue_num]; | ||
| 923 | del_timer_sync(&p->txtimer); | ||
| 924 | } | ||
| 925 | } | ||
| 926 | |||
| 927 | /** | ||
| 928 | * sxgbe_open - open entry point of the driver | ||
| 929 | * @dev : pointer to the device structure. | ||
| 930 | * Description: | ||
| 931 | * This function is the open entry point of the driver. | ||
| 932 | * Return value: | ||
| 933 | * 0 on success and an appropriate (-)ve integer as defined in errno.h | ||
| 934 | * file on failure. | ||
| 935 | */ | ||
| 936 | static int sxgbe_open(struct net_device *dev) | ||
| 937 | { | ||
| 938 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 939 | int ret, queue_num; | ||
| 940 | |||
| 941 | clk_prepare_enable(priv->sxgbe_clk); | ||
| 942 | |||
| 943 | sxgbe_check_ether_addr(priv); | ||
| 944 | |||
| 945 | /* Init the phy */ | ||
| 946 | ret = sxgbe_init_phy(dev); | ||
| 947 | if (ret) { | ||
| 948 | netdev_err(dev, "%s: Cannot attach to PHY (error: %d)\n", | ||
| 949 | __func__, ret); | ||
| 950 | goto phy_error; | ||
| 951 | } | ||
| 952 | |||
| 953 | /* Create and initialize the TX/RX descriptors chains. */ | ||
| 954 | priv->dma_tx_size = SXGBE_ALIGN(DMA_TX_SIZE); | ||
| 955 | priv->dma_rx_size = SXGBE_ALIGN(DMA_RX_SIZE); | ||
| 956 | priv->dma_buf_sz = SXGBE_ALIGN(DMA_BUFFER_SIZE); | ||
| 957 | priv->tx_tc = TC_DEFAULT; | ||
| 958 | priv->rx_tc = TC_DEFAULT; | ||
| 959 | init_dma_desc_rings(dev); | ||
| 960 | |||
| 961 | /* DMA initialization and SW reset */ | ||
| 962 | ret = sxgbe_init_dma_engine(priv); | ||
| 963 | if (ret < 0) { | ||
| 964 | netdev_err(dev, "%s: DMA initialization failed\n", __func__); | ||
| 965 | goto init_error; | ||
| 966 | } | ||
| 967 | |||
| 968 | /* MTL initialization */ | ||
| 969 | sxgbe_init_mtl_engine(priv); | ||
| 970 | |||
| 971 | /* Copy the MAC addr into the HW */ | ||
| 972 | priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0); | ||
| 973 | |||
| 974 | /* Initialize the MAC Core */ | ||
| 975 | priv->hw->mac->core_init(priv->ioaddr); | ||
| 976 | |||
| 977 | /* Request the IRQ lines */ | ||
| 978 | ret = devm_request_irq(priv->device, priv->irq, sxgbe_common_interrupt, | ||
| 979 | IRQF_SHARED, dev->name, dev); | ||
| 980 | if (unlikely(ret < 0)) { | ||
| 981 | netdev_err(dev, "%s: ERROR: allocating the IRQ %d (error: %d)\n", | ||
| 982 | __func__, priv->irq, ret); | ||
| 983 | goto init_error; | ||
| 984 | } | ||
| 985 | |||
| 986 | /* Request TX DMA irq lines */ | ||
| 987 | SXGBE_FOR_EACH_QUEUE(SXGBE_TX_QUEUES, queue_num) { | ||
| 988 | ret = devm_request_irq(priv->device, | ||
| 989 | (priv->txq[queue_num])->irq_no, | ||
| 990 | sxgbe_tx_interrupt, 0, | ||
| 991 | dev->name, priv->txq[queue_num]); | ||
| 992 | if (unlikely(ret < 0)) { | ||
| 993 | netdev_err(dev, "%s: ERROR: allocating TX IRQ %d (error: %d)\n", | ||
| 994 | __func__, priv->irq, ret); | ||
| 995 | goto init_error; | ||
| 996 | } | ||
| 997 | } | ||
| 998 | |||
| 999 | /* Request RX DMA irq lines */ | ||
| 1000 | SXGBE_FOR_EACH_QUEUE(SXGBE_RX_QUEUES, queue_num) { | ||
| 1001 | ret = devm_request_irq(priv->device, | ||
| 1002 | (priv->rxq[queue_num])->irq_no, | ||
| 1003 | sxgbe_rx_interrupt, 0, | ||
| 1004 | dev->name, priv->rxq[queue_num]); | ||
| 1005 | if (unlikely(ret < 0)) { | ||
| 1006 | netdev_err(dev, "%s: ERROR: allocating TX IRQ %d (error: %d)\n", | ||
| 1007 | __func__, priv->irq, ret); | ||
| 1008 | goto init_error; | ||
| 1009 | } | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | /* Enable the MAC Rx/Tx */ | ||
| 1013 | priv->hw->mac->enable_tx(priv->ioaddr, true); | ||
| 1014 | priv->hw->mac->enable_rx(priv->ioaddr, true); | ||
| 1015 | |||
| 1016 | /* Set the HW DMA mode and the COE */ | ||
| 1017 | sxgbe_mtl_operation_mode(priv); | ||
| 1018 | |||
| 1019 | /* Extra statistics */ | ||
| 1020 | memset(&priv->xstats, 0, sizeof(struct sxgbe_extra_stats)); | ||
| 1021 | |||
| 1022 | priv->xstats.tx_threshold = priv->tx_tc; | ||
| 1023 | priv->xstats.rx_threshold = priv->rx_tc; | ||
| 1024 | |||
| 1025 | /* Start the ball rolling... */ | ||
| 1026 | netdev_dbg(dev, "DMA RX/TX processes started...\n"); | ||
| 1027 | priv->hw->dma->start_tx(priv->ioaddr, SXGBE_TX_QUEUES); | ||
| 1028 | priv->hw->dma->start_rx(priv->ioaddr, SXGBE_RX_QUEUES); | ||
| 1029 | |||
| 1030 | if (priv->phydev) | ||
| 1031 | phy_start(priv->phydev); | ||
| 1032 | |||
| 1033 | /* initalise TX coalesce parameters */ | ||
| 1034 | sxgbe_tx_init_coalesce(priv); | ||
| 1035 | |||
| 1036 | if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { | ||
| 1037 | priv->rx_riwt = SXGBE_MAX_DMA_RIWT; | ||
| 1038 | priv->hw->dma->rx_watchdog(priv->ioaddr, SXGBE_MAX_DMA_RIWT); | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | napi_enable(&priv->napi); | ||
| 1042 | netif_start_queue(dev); | ||
| 1043 | |||
| 1044 | return 0; | ||
| 1045 | |||
| 1046 | init_error: | ||
| 1047 | free_dma_desc_resources(priv); | ||
| 1048 | if (priv->phydev) | ||
| 1049 | phy_disconnect(priv->phydev); | ||
| 1050 | phy_error: | ||
| 1051 | clk_disable_unprepare(priv->sxgbe_clk); | ||
| 1052 | |||
| 1053 | return ret; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | /** | ||
| 1057 | * sxgbe_release - close entry point of the driver | ||
| 1058 | * @dev : device pointer. | ||
| 1059 | * Description: | ||
| 1060 | * This is the stop entry point of the driver. | ||
| 1061 | */ | ||
| 1062 | static int sxgbe_release(struct net_device *dev) | ||
| 1063 | { | ||
| 1064 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 1065 | |||
| 1066 | /* Stop and disconnect the PHY */ | ||
| 1067 | if (priv->phydev) { | ||
| 1068 | phy_stop(priv->phydev); | ||
| 1069 | phy_disconnect(priv->phydev); | ||
| 1070 | priv->phydev = NULL; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | netif_tx_stop_all_queues(dev); | ||
| 1074 | |||
| 1075 | napi_disable(&priv->napi); | ||
| 1076 | |||
| 1077 | /* delete TX timers */ | ||
| 1078 | sxgbe_tx_del_timer(priv); | ||
| 1079 | |||
| 1080 | /* Stop TX/RX DMA and clear the descriptors */ | ||
| 1081 | priv->hw->dma->stop_tx(priv->ioaddr, SXGBE_TX_QUEUES); | ||
| 1082 | priv->hw->dma->stop_rx(priv->ioaddr, SXGBE_RX_QUEUES); | ||
| 1083 | |||
| 1084 | /* disable MTL queue */ | ||
| 1085 | sxgbe_disable_mtl_engine(priv); | ||
| 1086 | |||
| 1087 | /* Release and free the Rx/Tx resources */ | ||
| 1088 | free_dma_desc_resources(priv); | ||
| 1089 | |||
| 1090 | /* Disable the MAC Rx/Tx */ | ||
| 1091 | priv->hw->mac->enable_tx(priv->ioaddr, false); | ||
| 1092 | priv->hw->mac->enable_rx(priv->ioaddr, false); | ||
| 1093 | |||
| 1094 | clk_disable_unprepare(priv->sxgbe_clk); | ||
| 1095 | |||
| 1096 | return 0; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | /** | ||
| 1100 | * sxgbe_xmit: Tx entry point of the driver | ||
| 1101 | * @skb : the socket buffer | ||
| 1102 | * @dev : device pointer | ||
| 1103 | * Description : this is the tx entry point of the driver. | ||
| 1104 | * It programs the chain or the ring and supports oversized frames | ||
| 1105 | * and SG feature. | ||
| 1106 | */ | ||
| 1107 | static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 1108 | { | ||
| 1109 | unsigned int entry, frag_num; | ||
| 1110 | struct netdev_queue *dev_txq; | ||
| 1111 | unsigned txq_index = skb_get_queue_mapping(skb); | ||
| 1112 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 1113 | unsigned int tx_rsize = priv->dma_tx_size; | ||
| 1114 | struct sxgbe_tx_queue *tqueue = priv->txq[txq_index]; | ||
| 1115 | struct sxgbe_tx_norm_desc *tx_desc, *first_desc; | ||
| 1116 | int nr_frags = skb_shinfo(skb)->nr_frags; | ||
| 1117 | int no_pagedlen = skb_headlen(skb); | ||
| 1118 | int is_jumbo = 0; | ||
| 1119 | |||
| 1120 | /* get the TX queue handle */ | ||
| 1121 | dev_txq = netdev_get_tx_queue(dev, txq_index); | ||
| 1122 | |||
| 1123 | /* get the spinlock */ | ||
| 1124 | spin_lock(&tqueue->tx_lock); | ||
| 1125 | |||
| 1126 | if (unlikely(sxgbe_tx_avail(tqueue, tx_rsize) < nr_frags + 1)) { | ||
| 1127 | if (!netif_tx_queue_stopped(dev_txq)) { | ||
| 1128 | netif_tx_stop_queue(dev_txq); | ||
| 1129 | netdev_err(dev, "%s: Tx Ring is full when %d queue is awake\n", | ||
| 1130 | __func__, txq_index); | ||
| 1131 | } | ||
| 1132 | /* release the spin lock in case of BUSY */ | ||
| 1133 | spin_unlock(&tqueue->tx_lock); | ||
| 1134 | return NETDEV_TX_BUSY; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | entry = tqueue->cur_tx % tx_rsize; | ||
| 1138 | tx_desc = tqueue->dma_tx + entry; | ||
| 1139 | |||
| 1140 | first_desc = tx_desc; | ||
| 1141 | |||
| 1142 | /* save the skb address */ | ||
| 1143 | tqueue->tx_skbuff[entry] = skb; | ||
| 1144 | |||
| 1145 | if (!is_jumbo) { | ||
| 1146 | tx_desc->tdes01 = dma_map_single(priv->device, skb->data, | ||
| 1147 | no_pagedlen, DMA_TO_DEVICE); | ||
| 1148 | if (dma_mapping_error(priv->device, tx_desc->tdes01)) | ||
| 1149 | pr_err("%s: TX dma mapping failed!!\n", __func__); | ||
| 1150 | |||
| 1151 | priv->hw->desc->prepare_tx_desc(tx_desc, 1, no_pagedlen, | ||
| 1152 | no_pagedlen, 0); | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | for (frag_num = 0; frag_num < nr_frags; frag_num++) { | ||
| 1156 | const skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_num]; | ||
| 1157 | int len = skb_frag_size(frag); | ||
| 1158 | |||
| 1159 | entry = (++tqueue->cur_tx) % tx_rsize; | ||
| 1160 | tx_desc = tqueue->dma_tx + entry; | ||
| 1161 | tx_desc->tdes01 = skb_frag_dma_map(priv->device, frag, 0, len, | ||
| 1162 | DMA_TO_DEVICE); | ||
| 1163 | |||
| 1164 | tqueue->tx_skbuff_dma[entry] = tx_desc->tdes01; | ||
| 1165 | tqueue->tx_skbuff[entry] = NULL; | ||
| 1166 | |||
| 1167 | /* prepare the descriptor */ | ||
| 1168 | priv->hw->desc->prepare_tx_desc(tx_desc, 0, len, | ||
| 1169 | len, 0); | ||
| 1170 | /* memory barrier to flush descriptor */ | ||
| 1171 | wmb(); | ||
| 1172 | |||
| 1173 | /* set the owner */ | ||
| 1174 | priv->hw->desc->set_tx_owner(tx_desc); | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | /* close the descriptors */ | ||
| 1178 | priv->hw->desc->close_tx_desc(tx_desc); | ||
| 1179 | |||
| 1180 | /* memory barrier to flush descriptor */ | ||
| 1181 | wmb(); | ||
| 1182 | |||
| 1183 | tqueue->tx_count_frames += nr_frags + 1; | ||
| 1184 | if (tqueue->tx_count_frames > tqueue->tx_coal_frames) { | ||
| 1185 | priv->hw->desc->clear_tx_ic(tx_desc); | ||
| 1186 | priv->xstats.tx_reset_ic_bit++; | ||
| 1187 | mod_timer(&tqueue->txtimer, | ||
| 1188 | SXGBE_COAL_TIMER(tqueue->tx_coal_timer)); | ||
| 1189 | } else { | ||
| 1190 | tqueue->tx_count_frames = 0; | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | /* set owner for first desc */ | ||
| 1194 | priv->hw->desc->set_tx_owner(first_desc); | ||
| 1195 | |||
| 1196 | /* memory barrier to flush descriptor */ | ||
| 1197 | wmb(); | ||
| 1198 | |||
| 1199 | tqueue->cur_tx++; | ||
| 1200 | |||
| 1201 | /* display current ring */ | ||
| 1202 | netif_dbg(priv, pktdata, dev, "%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d\n", | ||
| 1203 | __func__, tqueue->cur_tx % tx_rsize, | ||
| 1204 | tqueue->dirty_tx % tx_rsize, entry, | ||
| 1205 | first_desc, nr_frags); | ||
| 1206 | |||
| 1207 | if (unlikely(sxgbe_tx_avail(tqueue, tx_rsize) <= (MAX_SKB_FRAGS + 1))) { | ||
| 1208 | netif_dbg(priv, hw, dev, "%s: stop transmitted packets\n", | ||
| 1209 | __func__); | ||
| 1210 | netif_tx_stop_queue(dev_txq); | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | dev->stats.tx_bytes += skb->len; | ||
| 1214 | |||
| 1215 | if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && | ||
| 1216 | tqueue->hwts_tx_en)) { | ||
| 1217 | /* declare that device is doing timestamping */ | ||
| 1218 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | ||
| 1219 | priv->hw->desc->tx_enable_tstamp(first_desc); | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | if (!tqueue->hwts_tx_en) | ||
| 1223 | skb_tx_timestamp(skb); | ||
| 1224 | |||
| 1225 | priv->hw->dma->enable_dma_transmission(priv->ioaddr, txq_index); | ||
| 1226 | |||
| 1227 | spin_unlock(&tqueue->tx_lock); | ||
| 1228 | |||
| 1229 | return NETDEV_TX_OK; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | /** | ||
| 1233 | * sxgbe_rx_refill: refill used skb preallocated buffers | ||
| 1234 | * @priv: driver private structure | ||
| 1235 | * Description : this is to reallocate the skb for the reception process | ||
| 1236 | * that is based on zero-copy. | ||
| 1237 | */ | ||
| 1238 | static void sxgbe_rx_refill(struct sxgbe_priv_data *priv) | ||
| 1239 | { | ||
| 1240 | unsigned int rxsize = priv->dma_rx_size; | ||
| 1241 | int bfsize = priv->dma_buf_sz; | ||
| 1242 | u8 qnum = priv->cur_rx_qnum; | ||
| 1243 | |||
| 1244 | for (; priv->rxq[qnum]->cur_rx - priv->rxq[qnum]->dirty_rx > 0; | ||
| 1245 | priv->rxq[qnum]->dirty_rx++) { | ||
| 1246 | unsigned int entry = priv->rxq[qnum]->dirty_rx % rxsize; | ||
| 1247 | struct sxgbe_rx_norm_desc *p; | ||
| 1248 | |||
| 1249 | p = priv->rxq[qnum]->dma_rx + entry; | ||
| 1250 | |||
| 1251 | if (likely(priv->rxq[qnum]->rx_skbuff[entry] == NULL)) { | ||
| 1252 | struct sk_buff *skb; | ||
| 1253 | |||
| 1254 | skb = netdev_alloc_skb_ip_align(priv->dev, bfsize); | ||
| 1255 | |||
| 1256 | if (unlikely(skb == NULL)) | ||
| 1257 | break; | ||
| 1258 | |||
| 1259 | priv->rxq[qnum]->rx_skbuff[entry] = skb; | ||
| 1260 | priv->rxq[qnum]->rx_skbuff_dma[entry] = | ||
| 1261 | dma_map_single(priv->device, skb->data, bfsize, | ||
| 1262 | DMA_FROM_DEVICE); | ||
| 1263 | |||
| 1264 | p->rdes23.rx_rd_des23.buf2_addr = | ||
| 1265 | priv->rxq[qnum]->rx_skbuff_dma[entry]; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | /* Added memory barrier for RX descriptor modification */ | ||
| 1269 | wmb(); | ||
| 1270 | priv->hw->desc->set_rx_owner(p); | ||
| 1271 | /* Added memory barrier for RX descriptor modification */ | ||
| 1272 | wmb(); | ||
| 1273 | } | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | /** | ||
| 1277 | * sxgbe_rx: receive the frames from the remote host | ||
| 1278 | * @priv: driver private structure | ||
| 1279 | * @limit: napi bugget. | ||
| 1280 | * Description : this the function called by the napi poll method. | ||
| 1281 | * It gets all the frames inside the ring. | ||
| 1282 | */ | ||
| 1283 | static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) | ||
| 1284 | { | ||
| 1285 | u8 qnum = priv->cur_rx_qnum; | ||
| 1286 | unsigned int rxsize = priv->dma_rx_size; | ||
| 1287 | unsigned int entry = priv->rxq[qnum]->cur_rx; | ||
| 1288 | unsigned int next_entry = 0; | ||
| 1289 | unsigned int count = 0; | ||
| 1290 | |||
| 1291 | while (count < limit) { | ||
| 1292 | struct sxgbe_rx_norm_desc *p; | ||
| 1293 | struct sk_buff *skb; | ||
| 1294 | int frame_len; | ||
| 1295 | |||
| 1296 | p = priv->rxq[qnum]->dma_rx + entry; | ||
| 1297 | |||
| 1298 | if (priv->hw->desc->get_rx_owner(p)) | ||
| 1299 | break; | ||
| 1300 | |||
| 1301 | count++; | ||
| 1302 | |||
| 1303 | next_entry = (++priv->rxq[qnum]->cur_rx) % rxsize; | ||
| 1304 | prefetch(priv->rxq[qnum]->dma_rx + next_entry); | ||
| 1305 | |||
| 1306 | /*TO DO read the status of the incoming frame */ | ||
| 1307 | |||
| 1308 | skb = priv->rxq[qnum]->rx_skbuff[entry]; | ||
| 1309 | |||
| 1310 | if (unlikely(!skb)) | ||
| 1311 | netdev_err(priv->dev, "rx descriptor is not consistent\n"); | ||
| 1312 | |||
| 1313 | prefetch(skb->data - NET_IP_ALIGN); | ||
| 1314 | priv->rxq[qnum]->rx_skbuff[entry] = NULL; | ||
| 1315 | |||
| 1316 | frame_len = priv->hw->desc->get_rx_frame_len(p); | ||
| 1317 | |||
| 1318 | skb_put(skb, frame_len); | ||
| 1319 | |||
| 1320 | netif_receive_skb(skb); | ||
| 1321 | |||
| 1322 | entry = next_entry; | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | sxgbe_rx_refill(priv); | ||
| 1326 | |||
| 1327 | return count; | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | /** | ||
| 1331 | * sxgbe_poll - sxgbe poll method (NAPI) | ||
| 1332 | * @napi : pointer to the napi structure. | ||
| 1333 | * @budget : maximum number of packets that the current CPU can receive from | ||
| 1334 | * all interfaces. | ||
| 1335 | * Description : | ||
| 1336 | * To look at the incoming frames and clear the tx resources. | ||
| 1337 | */ | ||
| 1338 | static int sxgbe_poll(struct napi_struct *napi, int budget) | ||
| 1339 | { | ||
| 1340 | struct sxgbe_priv_data *priv = container_of(napi, | ||
| 1341 | struct sxgbe_priv_data, napi); | ||
| 1342 | int work_done = 0; | ||
| 1343 | u8 qnum = priv->cur_rx_qnum; | ||
| 1344 | |||
| 1345 | priv->xstats.napi_poll++; | ||
| 1346 | /* first, clean the tx queues */ | ||
| 1347 | sxgbe_tx_all_clean(priv); | ||
| 1348 | |||
| 1349 | work_done = sxgbe_rx(priv, budget); | ||
| 1350 | if (work_done < budget) { | ||
| 1351 | napi_complete(napi); | ||
| 1352 | priv->hw->dma->enable_dma_irq(priv->ioaddr, qnum); | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | return work_done; | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | /** | ||
| 1359 | * sxgbe_tx_timeout | ||
| 1360 | * @dev : Pointer to net device structure | ||
| 1361 | * Description: this function is called when a packet transmission fails to | ||
| 1362 | * complete within a reasonable time. The driver will mark the error in the | ||
| 1363 | * netdev structure and arrange for the device to be reset to a sane state | ||
| 1364 | * in order to transmit a new packet. | ||
| 1365 | */ | ||
| 1366 | static void sxgbe_tx_timeout(struct net_device *dev) | ||
| 1367 | { | ||
| 1368 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 1369 | |||
| 1370 | sxgbe_reset_all_tx_queues(priv); | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | /** | ||
| 1374 | * sxgbe_common_interrupt - main ISR | ||
| 1375 | * @irq: interrupt number. | ||
| 1376 | * @dev_id: to pass the net device pointer. | ||
| 1377 | * Description: this is the main driver interrupt service routine. | ||
| 1378 | * It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI | ||
| 1379 | * interrupts. | ||
| 1380 | */ | ||
| 1381 | static irqreturn_t sxgbe_common_interrupt(int irq, void *dev_id) | ||
| 1382 | { | ||
| 1383 | return IRQ_HANDLED; | ||
| 1384 | } | ||
| 1385 | |||
| 1386 | /** | ||
| 1387 | * sxgbe_tx_interrupt - TX DMA ISR | ||
| 1388 | * @irq: interrupt number. | ||
| 1389 | * @dev_id: to pass the net device pointer. | ||
| 1390 | * Description: this is the tx dma interrupt service routine. | ||
| 1391 | */ | ||
| 1392 | static irqreturn_t sxgbe_tx_interrupt(int irq, void *dev_id) | ||
| 1393 | { | ||
| 1394 | int status; | ||
| 1395 | struct sxgbe_tx_queue *txq = (struct sxgbe_tx_queue *)dev_id; | ||
| 1396 | struct sxgbe_priv_data *priv = txq->priv_ptr; | ||
| 1397 | |||
| 1398 | /* get the channel status */ | ||
| 1399 | status = priv->hw->dma->tx_dma_int_status(priv->ioaddr, txq->queue_no, | ||
| 1400 | &priv->xstats); | ||
| 1401 | /* check for normal path */ | ||
| 1402 | if (likely((status & handle_tx))) | ||
| 1403 | napi_schedule(&priv->napi); | ||
| 1404 | |||
| 1405 | /* check for unrecoverable error */ | ||
| 1406 | if (unlikely((status & tx_hard_error))) | ||
| 1407 | sxgbe_restart_tx_queue(priv, txq->queue_no); | ||
| 1408 | |||
| 1409 | /* check for TC configuration change */ | ||
| 1410 | if (unlikely((status & tx_bump_tc) && | ||
| 1411 | (priv->tx_tc != SXGBE_MTL_SFMODE) && | ||
| 1412 | (priv->tx_tc < 512))) { | ||
| 1413 | /* step of TX TC is 32 till 128, otherwise 64 */ | ||
| 1414 | priv->tx_tc += (priv->tx_tc < 128) ? 32 : 64; | ||
| 1415 | priv->hw->mtl->set_tx_mtl_mode(priv->ioaddr, | ||
| 1416 | txq->queue_no, priv->tx_tc); | ||
| 1417 | priv->xstats.tx_threshold = priv->tx_tc; | ||
| 1418 | } | ||
| 1419 | |||
| 1420 | return IRQ_HANDLED; | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | /** | ||
| 1424 | * sxgbe_rx_interrupt - RX DMA ISR | ||
| 1425 | * @irq: interrupt number. | ||
| 1426 | * @dev_id: to pass the net device pointer. | ||
| 1427 | * Description: this is the rx dma interrupt service routine. | ||
| 1428 | */ | ||
| 1429 | static irqreturn_t sxgbe_rx_interrupt(int irq, void *dev_id) | ||
| 1430 | { | ||
| 1431 | int status; | ||
| 1432 | struct sxgbe_rx_queue *rxq = (struct sxgbe_rx_queue *)dev_id; | ||
| 1433 | struct sxgbe_priv_data *priv = rxq->priv_ptr; | ||
| 1434 | |||
| 1435 | /* get the channel status */ | ||
| 1436 | status = priv->hw->dma->rx_dma_int_status(priv->ioaddr, rxq->queue_no, | ||
| 1437 | &priv->xstats); | ||
| 1438 | |||
| 1439 | if (likely((status & handle_rx) && (napi_schedule_prep(&priv->napi)))) { | ||
| 1440 | priv->hw->dma->disable_dma_irq(priv->ioaddr, rxq->queue_no); | ||
| 1441 | __napi_schedule(&priv->napi); | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | /* check for TC configuration change */ | ||
| 1445 | if (unlikely((status & rx_bump_tc) && | ||
| 1446 | (priv->rx_tc != SXGBE_MTL_SFMODE) && | ||
| 1447 | (priv->rx_tc < 128))) { | ||
| 1448 | /* step of TC is 32 */ | ||
| 1449 | priv->rx_tc += 32; | ||
| 1450 | priv->hw->mtl->set_rx_mtl_mode(priv->ioaddr, | ||
| 1451 | rxq->queue_no, priv->rx_tc); | ||
| 1452 | priv->xstats.rx_threshold = priv->rx_tc; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | return IRQ_HANDLED; | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | static inline u64 sxgbe_get_stat64(void __iomem *ioaddr, int reg_lo, int reg_hi) | ||
| 1459 | { | ||
| 1460 | u64 val = readl(ioaddr + reg_lo); | ||
| 1461 | |||
| 1462 | val |= ((u64)readl(ioaddr + reg_hi)) << 32; | ||
| 1463 | |||
| 1464 | return val; | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | |||
| 1468 | /* sxgbe_get_stats64 - entry point to see statistical information of device | ||
| 1469 | * @dev : device pointer. | ||
| 1470 | * @stats : pointer to hold all the statistical information of device. | ||
| 1471 | * Description: | ||
| 1472 | * This function is a driver entry point whenever ifconfig command gets | ||
| 1473 | * executed to see device statistics. Statistics are number of | ||
| 1474 | * bytes sent or received, errors occured etc. | ||
| 1475 | * Return value: | ||
| 1476 | * This function returns various statistical information of device. | ||
| 1477 | */ | ||
| 1478 | static struct rtnl_link_stats64 *sxgbe_get_stats64(struct net_device *dev, | ||
| 1479 | struct rtnl_link_stats64 *stats) | ||
| 1480 | { | ||
| 1481 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 1482 | void __iomem *ioaddr = priv->ioaddr; | ||
| 1483 | u64 count; | ||
| 1484 | |||
| 1485 | spin_lock(&priv->stats_lock); | ||
| 1486 | /* Freeze the counter registers before reading value otherwise it may | ||
| 1487 | * get updated by hardware while we are reading them | ||
| 1488 | */ | ||
| 1489 | writel(SXGBE_MMC_CTRL_CNT_FRZ, ioaddr + SXGBE_MMC_CTL_REG); | ||
| 1490 | |||
| 1491 | stats->rx_bytes = sxgbe_get_stat64(ioaddr, | ||
| 1492 | SXGBE_MMC_RXOCTETLO_GCNT_REG, | ||
| 1493 | SXGBE_MMC_RXOCTETHI_GCNT_REG); | ||
| 1494 | |||
| 1495 | stats->rx_packets = sxgbe_get_stat64(ioaddr, | ||
| 1496 | SXGBE_MMC_RXFRAMELO_GBCNT_REG, | ||
| 1497 | SXGBE_MMC_RXFRAMEHI_GBCNT_REG); | ||
| 1498 | |||
| 1499 | stats->multicast = sxgbe_get_stat64(ioaddr, | ||
| 1500 | SXGBE_MMC_RXMULTILO_GCNT_REG, | ||
| 1501 | SXGBE_MMC_RXMULTIHI_GCNT_REG); | ||
| 1502 | |||
| 1503 | stats->rx_crc_errors = sxgbe_get_stat64(ioaddr, | ||
| 1504 | SXGBE_MMC_RXCRCERRLO_REG, | ||
| 1505 | SXGBE_MMC_RXCRCERRHI_REG); | ||
| 1506 | |||
| 1507 | stats->rx_length_errors = sxgbe_get_stat64(ioaddr, | ||
| 1508 | SXGBE_MMC_RXLENERRLO_REG, | ||
| 1509 | SXGBE_MMC_RXLENERRHI_REG); | ||
| 1510 | |||
| 1511 | stats->rx_missed_errors = sxgbe_get_stat64(ioaddr, | ||
| 1512 | SXGBE_MMC_RXFIFOOVERFLOWLO_GBCNT_REG, | ||
| 1513 | SXGBE_MMC_RXFIFOOVERFLOWHI_GBCNT_REG); | ||
| 1514 | |||
| 1515 | stats->tx_bytes = sxgbe_get_stat64(ioaddr, | ||
| 1516 | SXGBE_MMC_TXOCTETLO_GCNT_REG, | ||
| 1517 | SXGBE_MMC_TXOCTETHI_GCNT_REG); | ||
| 1518 | |||
| 1519 | count = sxgbe_get_stat64(ioaddr, SXGBE_MMC_TXFRAMELO_GBCNT_REG, | ||
| 1520 | SXGBE_MMC_TXFRAMEHI_GBCNT_REG); | ||
| 1521 | |||
| 1522 | stats->tx_errors = sxgbe_get_stat64(ioaddr, SXGBE_MMC_TXFRAMELO_GCNT_REG, | ||
| 1523 | SXGBE_MMC_TXFRAMEHI_GCNT_REG); | ||
| 1524 | stats->tx_errors = count - stats->tx_errors; | ||
| 1525 | stats->tx_packets = count; | ||
| 1526 | stats->tx_fifo_errors = sxgbe_get_stat64(ioaddr, SXGBE_MMC_TXUFLWLO_GBCNT_REG, | ||
| 1527 | SXGBE_MMC_TXUFLWHI_GBCNT_REG); | ||
| 1528 | writel(0, ioaddr + SXGBE_MMC_CTL_REG); | ||
| 1529 | spin_unlock(&priv->stats_lock); | ||
| 1530 | |||
| 1531 | return stats; | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | /* sxgbe_set_features - entry point to set offload features of the device. | ||
| 1535 | * @dev : device pointer. | ||
| 1536 | * @features : features which are required to be set. | ||
| 1537 | * Description: | ||
| 1538 | * This function is a driver entry point and called by Linux kernel whenever | ||
| 1539 | * any device features are set or reset by user. | ||
| 1540 | * Return value: | ||
| 1541 | * This function returns 0 after setting or resetting device features. | ||
| 1542 | */ | ||
| 1543 | static int sxgbe_set_features(struct net_device *dev, | ||
| 1544 | netdev_features_t features) | ||
| 1545 | { | ||
| 1546 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 1547 | netdev_features_t changed = dev->features ^ features; | ||
| 1548 | u32 ctrl; | ||
| 1549 | |||
| 1550 | if (changed & NETIF_F_RXCSUM) { | ||
| 1551 | ctrl = readl(priv->ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||
| 1552 | if (features & NETIF_F_RXCSUM) | ||
| 1553 | ctrl |= SXGBE_RX_CSUMOFFLOAD_ENABLE; | ||
| 1554 | else | ||
| 1555 | ctrl &= ~SXGBE_RX_CSUMOFFLOAD_ENABLE; | ||
| 1556 | writel(ctrl, priv->ioaddr + SXGBE_CORE_RX_CONFIG_REG); | ||
| 1557 | } | ||
| 1558 | |||
| 1559 | return 0; | ||
| 1560 | } | ||
| 1561 | |||
| 1562 | /* sxgbe_change_mtu - entry point to change MTU size for the device. | ||
| 1563 | * @dev : device pointer. | ||
| 1564 | * @new_mtu : the new MTU size for the device. | ||
| 1565 | * Description: the Maximum Transfer Unit (MTU) is used by the network layer | ||
| 1566 | * to drive packet transmission. Ethernet has an MTU of 1500 octets | ||
| 1567 | * (ETH_DATA_LEN). This value can be changed with ifconfig. | ||
| 1568 | * Return value: | ||
| 1569 | * 0 on success and an appropriate (-)ve integer as defined in errno.h | ||
| 1570 | * file on failure. | ||
| 1571 | */ | ||
| 1572 | static int sxgbe_change_mtu(struct net_device *dev, int new_mtu) | ||
| 1573 | { | ||
| 1574 | /* RFC 791, page 25, "Every internet module must be able to forward | ||
| 1575 | * a datagram of 68 octets without further fragmentation." | ||
| 1576 | */ | ||
| 1577 | if (new_mtu < MIN_MTU || (new_mtu > MAX_MTU)) { | ||
| 1578 | netdev_err(dev, "invalid MTU, MTU should be in between %d and %d\n", | ||
| 1579 | MIN_MTU, MAX_MTU); | ||
| 1580 | return -EINVAL; | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | /* Return if the buffer sizes will not change */ | ||
| 1584 | if (dev->mtu == new_mtu) | ||
| 1585 | return 0; | ||
| 1586 | |||
| 1587 | dev->mtu = new_mtu; | ||
| 1588 | |||
| 1589 | if (!netif_running(dev)) | ||
| 1590 | return 0; | ||
| 1591 | |||
| 1592 | /* Recevice ring buffer size is needed to be set based on MTU. If MTU is | ||
| 1593 | * changed then reinitilisation of the receive ring buffers need to be | ||
| 1594 | * done. Hence bring interface down and bring interface back up | ||
| 1595 | */ | ||
| 1596 | sxgbe_release(dev); | ||
| 1597 | return sxgbe_open(dev); | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | static void sxgbe_set_umac_addr(void __iomem *ioaddr, unsigned char *addr, | ||
| 1601 | unsigned int reg_n) | ||
| 1602 | { | ||
| 1603 | unsigned long data; | ||
| 1604 | |||
| 1605 | data = (addr[5] << 8) | addr[4]; | ||
| 1606 | /* For MAC Addr registers se have to set the Address Enable (AE) | ||
| 1607 | * bit that has no effect on the High Reg 0 where the bit 31 (MO) | ||
| 1608 | * is RO. | ||
| 1609 | */ | ||
| 1610 | writel(data | SXGBE_HI_REG_AE, ioaddr + SXGBE_ADDR_HIGH(reg_n)); | ||
| 1611 | data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; | ||
| 1612 | writel(data, ioaddr + SXGBE_ADDR_LOW(reg_n)); | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | /** | ||
| 1616 | * sxgbe_set_rx_mode - entry point for setting different receive mode of | ||
| 1617 | * a device. unicast, multicast addressing | ||
| 1618 | * @dev : pointer to the device structure | ||
| 1619 | * Description: | ||
| 1620 | * This function is a driver entry point which gets called by the kernel | ||
| 1621 | * whenever different receive mode like unicast, multicast and promiscuous | ||
| 1622 | * must be enabled/disabled. | ||
| 1623 | * Return value: | ||
| 1624 | * void. | ||
| 1625 | */ | ||
| 1626 | static void sxgbe_set_rx_mode(struct net_device *dev) | ||
| 1627 | { | ||
| 1628 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 1629 | void __iomem *ioaddr = (void __iomem *)priv->ioaddr; | ||
| 1630 | unsigned int value = 0; | ||
| 1631 | u32 mc_filter[2]; | ||
| 1632 | struct netdev_hw_addr *ha; | ||
| 1633 | int reg = 1; | ||
| 1634 | |||
| 1635 | netdev_dbg(dev, "%s: # mcasts %d, # unicast %d\n", | ||
| 1636 | __func__, netdev_mc_count(dev), netdev_uc_count(dev)); | ||
| 1637 | |||
| 1638 | if (dev->flags & IFF_PROMISC) { | ||
| 1639 | value = SXGBE_FRAME_FILTER_PR; | ||
| 1640 | |||
| 1641 | } else if ((netdev_mc_count(dev) > SXGBE_HASH_TABLE_SIZE) || | ||
| 1642 | (dev->flags & IFF_ALLMULTI)) { | ||
| 1643 | value = SXGBE_FRAME_FILTER_PM; /* pass all multi */ | ||
| 1644 | writel(0xffffffff, ioaddr + SXGBE_HASH_HIGH); | ||
| 1645 | writel(0xffffffff, ioaddr + SXGBE_HASH_LOW); | ||
| 1646 | |||
| 1647 | } else if (!netdev_mc_empty(dev)) { | ||
| 1648 | /* Hash filter for multicast */ | ||
| 1649 | value = SXGBE_FRAME_FILTER_HMC; | ||
| 1650 | |||
| 1651 | memset(mc_filter, 0, sizeof(mc_filter)); | ||
| 1652 | netdev_for_each_mc_addr(ha, dev) { | ||
| 1653 | /* The upper 6 bits of the calculated CRC are used to | ||
| 1654 | * index the contens of the hash table | ||
| 1655 | */ | ||
| 1656 | int bit_nr = bitrev32(~crc32_le(~0, ha->addr, 6)) >> 26; | ||
| 1657 | |||
| 1658 | /* The most significant bit determines the register to | ||
| 1659 | * use (H/L) while the other 5 bits determine the bit | ||
| 1660 | * within the register. | ||
| 1661 | */ | ||
| 1662 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); | ||
| 1663 | } | ||
| 1664 | writel(mc_filter[0], ioaddr + SXGBE_HASH_LOW); | ||
| 1665 | writel(mc_filter[1], ioaddr + SXGBE_HASH_HIGH); | ||
| 1666 | } | ||
| 1667 | |||
| 1668 | /* Handle multiple unicast addresses (perfect filtering) */ | ||
| 1669 | if (netdev_uc_count(dev) > SXGBE_MAX_PERFECT_ADDRESSES) | ||
| 1670 | /* Switch to promiscuous mode if more than 16 addrs | ||
| 1671 | * are required | ||
| 1672 | */ | ||
| 1673 | value |= SXGBE_FRAME_FILTER_PR; | ||
| 1674 | else { | ||
| 1675 | netdev_for_each_uc_addr(ha, dev) { | ||
| 1676 | sxgbe_set_umac_addr(ioaddr, ha->addr, reg); | ||
| 1677 | reg++; | ||
| 1678 | } | ||
| 1679 | } | ||
| 1680 | #ifdef FRAME_FILTER_DEBUG | ||
| 1681 | /* Enable Receive all mode (to debug filtering_fail errors) */ | ||
| 1682 | value |= SXGBE_FRAME_FILTER_RA; | ||
| 1683 | #endif | ||
| 1684 | writel(value, ioaddr + SXGBE_FRAME_FILTER); | ||
| 1685 | |||
| 1686 | netdev_dbg(dev, "Filter: 0x%08x\n\tHash: HI 0x%08x, LO 0x%08x\n", | ||
| 1687 | readl(ioaddr + SXGBE_FRAME_FILTER), | ||
| 1688 | readl(ioaddr + SXGBE_HASH_HIGH), | ||
| 1689 | readl(ioaddr + SXGBE_HASH_LOW)); | ||
| 1690 | } | ||
| 1691 | |||
| 1692 | /** | ||
| 1693 | * sxgbe_config - entry point for changing configuration mode passed on by | ||
| 1694 | * ifconfig | ||
| 1695 | * @dev : pointer to the device structure | ||
| 1696 | * @map : pointer to the device mapping structure | ||
| 1697 | * Description: | ||
| 1698 | * This function is a driver entry point which gets called by the kernel | ||
| 1699 | * whenever some device configuration is changed. | ||
| 1700 | * Return value: | ||
| 1701 | * This function returns 0 if success and appropriate error otherwise. | ||
| 1702 | */ | ||
| 1703 | static int sxgbe_config(struct net_device *dev, struct ifmap *map) | ||
| 1704 | { | ||
| 1705 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 1706 | |||
| 1707 | /* Can't act on a running interface */ | ||
| 1708 | if (dev->flags & IFF_UP) | ||
| 1709 | return -EBUSY; | ||
| 1710 | |||
| 1711 | /* Don't allow changing the I/O address */ | ||
| 1712 | if (map->base_addr != (unsigned long)priv->ioaddr) { | ||
| 1713 | netdev_warn(dev, "can't change I/O address\n"); | ||
| 1714 | return -EOPNOTSUPP; | ||
| 1715 | } | ||
| 1716 | |||
| 1717 | /* Don't allow changing the IRQ */ | ||
| 1718 | if (map->irq != priv->irq) { | ||
| 1719 | netdev_warn(dev, "not change IRQ number %d\n", priv->irq); | ||
| 1720 | return -EOPNOTSUPP; | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | return 0; | ||
| 1724 | } | ||
| 1725 | |||
| 1726 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 1727 | /** | ||
| 1728 | * sxgbe_poll_controller - entry point for polling receive by device | ||
| 1729 | * @dev : pointer to the device structure | ||
| 1730 | * Description: | ||
| 1731 | * This function is used by NETCONSOLE and other diagnostic tools | ||
| 1732 | * to allow network I/O with interrupts disabled. | ||
| 1733 | * Return value: | ||
| 1734 | * Void. | ||
| 1735 | */ | ||
| 1736 | static void sxgbe_poll_controller(struct net_device *dev) | ||
| 1737 | { | ||
| 1738 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 1739 | |||
| 1740 | disable_irq(priv->irq); | ||
| 1741 | sxgbe_rx_interrupt(priv->irq, dev); | ||
| 1742 | enable_irq(priv->irq); | ||
| 1743 | } | ||
| 1744 | #endif | ||
| 1745 | |||
| 1746 | /* sxgbe_ioctl - Entry point for the Ioctl | ||
| 1747 | * @dev: Device pointer. | ||
| 1748 | * @rq: An IOCTL specefic structure, that can contain a pointer to | ||
| 1749 | * a proprietary structure used to pass information to the driver. | ||
| 1750 | * @cmd: IOCTL command | ||
| 1751 | * Description: | ||
| 1752 | * Currently it supports the phy_mii_ioctl(...) and HW time stamping. | ||
| 1753 | */ | ||
| 1754 | static int sxgbe_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||
| 1755 | { | ||
| 1756 | struct sxgbe_priv_data *priv = netdev_priv(dev); | ||
| 1757 | int ret = -EOPNOTSUPP; | ||
| 1758 | |||
| 1759 | if (!netif_running(dev)) | ||
| 1760 | return -EINVAL; | ||
| 1761 | |||
| 1762 | switch (cmd) { | ||
| 1763 | case SIOCGMIIPHY: | ||
| 1764 | case SIOCGMIIREG: | ||
| 1765 | case SIOCSMIIREG: | ||
| 1766 | if (!priv->phydev) | ||
| 1767 | return -EINVAL; | ||
| 1768 | ret = phy_mii_ioctl(priv->phydev, rq, cmd); | ||
| 1769 | break; | ||
| 1770 | default: | ||
| 1771 | break; | ||
| 1772 | } | ||
| 1773 | |||
| 1774 | return ret; | ||
| 1775 | } | ||
| 1776 | |||
| 1777 | static const struct net_device_ops sxgbe_netdev_ops = { | ||
| 1778 | .ndo_open = sxgbe_open, | ||
| 1779 | .ndo_start_xmit = sxgbe_xmit, | ||
| 1780 | .ndo_stop = sxgbe_release, | ||
| 1781 | .ndo_get_stats64 = sxgbe_get_stats64, | ||
| 1782 | .ndo_change_mtu = sxgbe_change_mtu, | ||
| 1783 | .ndo_set_features = sxgbe_set_features, | ||
| 1784 | .ndo_set_rx_mode = sxgbe_set_rx_mode, | ||
| 1785 | .ndo_tx_timeout = sxgbe_tx_timeout, | ||
| 1786 | .ndo_do_ioctl = sxgbe_ioctl, | ||
| 1787 | .ndo_set_config = sxgbe_config, | ||
| 1788 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 1789 | .ndo_poll_controller = sxgbe_poll_controller, | ||
| 1790 | #endif | ||
| 1791 | .ndo_set_mac_address = eth_mac_addr, | ||
| 1792 | }; | ||
| 1793 | |||
| 1794 | /* Get the hardware ops */ | ||
| 1795 | void sxgbe_get_ops(struct sxgbe_ops * const ops_ptr) | ||
| 1796 | { | ||
| 1797 | ops_ptr->mac = sxgbe_get_core_ops(); | ||
| 1798 | ops_ptr->desc = sxgbe_get_desc_ops(); | ||
| 1799 | ops_ptr->dma = sxgbe_get_dma_ops(); | ||
| 1800 | ops_ptr->mtl = sxgbe_get_mtl_ops(); | ||
| 1801 | |||
| 1802 | /* set the MDIO communication Address/Data regisers */ | ||
| 1803 | ops_ptr->mii.addr = SXGBE_MDIO_SCMD_ADD_REG; | ||
| 1804 | ops_ptr->mii.data = SXGBE_MDIO_SCMD_DATA_REG; | ||
| 1805 | |||
| 1806 | /* Assigning the default link settings | ||
| 1807 | * no SXGBE defined default values to be set in registers, | ||
| 1808 | * so assigning as 0 for port and duplex | ||
| 1809 | */ | ||
| 1810 | ops_ptr->link.port = 0; | ||
| 1811 | ops_ptr->link.duplex = 0; | ||
| 1812 | ops_ptr->link.speed = SXGBE_SPEED_10G; | ||
| 1813 | } | ||
| 1814 | |||
| 1815 | /** | ||
| 1816 | * sxgbe_hw_init - Init the GMAC device | ||
| 1817 | * @priv: driver private structure | ||
| 1818 | * Description: this function checks the HW capability | ||
| 1819 | * (if supported) and sets the driver's features. | ||
| 1820 | */ | ||
| 1821 | static void sxgbe_hw_init(struct sxgbe_priv_data * const priv) | ||
| 1822 | { | ||
| 1823 | u32 ctrl_ids; | ||
| 1824 | |||
| 1825 | priv->hw = kmalloc(sizeof(*priv->hw), GFP_KERNEL); | ||
| 1826 | |||
| 1827 | /* get the hardware ops */ | ||
| 1828 | sxgbe_get_ops(priv->hw); | ||
| 1829 | |||
| 1830 | /* get the controller id */ | ||
| 1831 | ctrl_ids = priv->hw->mac->get_controller_version(priv->ioaddr); | ||
| 1832 | priv->hw->ctrl_uid = (ctrl_ids & 0x00ff0000) >> 16; | ||
| 1833 | priv->hw->ctrl_id = (ctrl_ids & 0x000000ff); | ||
| 1834 | pr_info("user ID: 0x%x, Controller ID: 0x%x\n", | ||
| 1835 | priv->hw->ctrl_uid, priv->hw->ctrl_id); | ||
| 1836 | |||
| 1837 | /* get the H/W features */ | ||
| 1838 | if (!sxgbe_get_hw_features(priv)) | ||
| 1839 | pr_info("Hardware features not found\n"); | ||
| 1840 | |||
| 1841 | if (priv->hw_cap.tx_csum_offload) | ||
| 1842 | pr_info("TX Checksum offload supported\n"); | ||
| 1843 | |||
| 1844 | if (priv->hw_cap.rx_csum_offload) | ||
| 1845 | pr_info("RX Checksum offload supported\n"); | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | /** | ||
| 1849 | * sxgbe_drv_probe | ||
| 1850 | * @device: device pointer | ||
| 1851 | * @plat_dat: platform data pointer | ||
| 1852 | * @addr: iobase memory address | ||
| 1853 | * Description: this is the main probe function used to | ||
| 1854 | * call the alloc_etherdev, allocate the priv structure. | ||
| 1855 | */ | ||
| 1856 | struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, | ||
| 1857 | struct sxgbe_plat_data *plat_dat, | ||
| 1858 | void __iomem *addr) | ||
| 1859 | { | ||
| 1860 | struct sxgbe_priv_data *priv; | ||
| 1861 | struct net_device *ndev; | ||
| 1862 | int ret; | ||
| 1863 | |||
| 1864 | ndev = alloc_etherdev_mqs(sizeof(struct sxgbe_priv_data), | ||
| 1865 | SXGBE_TX_QUEUES, SXGBE_RX_QUEUES); | ||
| 1866 | if (!ndev) | ||
| 1867 | return NULL; | ||
| 1868 | |||
| 1869 | SET_NETDEV_DEV(ndev, device); | ||
| 1870 | |||
| 1871 | priv = netdev_priv(ndev); | ||
| 1872 | priv->device = device; | ||
| 1873 | priv->dev = ndev; | ||
| 1874 | |||
| 1875 | sxgbe_set_ethtool_ops(ndev); | ||
| 1876 | priv->plat = plat_dat; | ||
| 1877 | priv->ioaddr = addr; | ||
| 1878 | |||
| 1879 | /* Init MAC and get the capabilities */ | ||
| 1880 | sxgbe_hw_init(priv); | ||
| 1881 | |||
| 1882 | /* allocate memory resources for Descriptor rings */ | ||
| 1883 | ret = txring_mem_alloc(priv); | ||
| 1884 | if (ret) | ||
| 1885 | goto error_free_netdev; | ||
| 1886 | |||
| 1887 | ret = rxring_mem_alloc(priv); | ||
| 1888 | if (ret) | ||
| 1889 | goto error_free_netdev; | ||
| 1890 | |||
| 1891 | ndev->netdev_ops = &sxgbe_netdev_ops; | ||
| 1892 | |||
| 1893 | ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM; | ||
| 1894 | ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; | ||
| 1895 | ndev->watchdog_timeo = msecs_to_jiffies(TX_TIMEO); | ||
| 1896 | |||
| 1897 | /* assign filtering support */ | ||
| 1898 | ndev->priv_flags |= IFF_UNICAST_FLT; | ||
| 1899 | |||
| 1900 | priv->msg_enable = netif_msg_init(debug, default_msg_level); | ||
| 1901 | |||
| 1902 | /* Rx Watchdog is available, enable depend on platform data */ | ||
| 1903 | if (!priv->plat->riwt_off) { | ||
| 1904 | priv->use_riwt = 1; | ||
| 1905 | pr_info("Enable RX Mitigation via HW Watchdog Timer\n"); | ||
| 1906 | } | ||
| 1907 | |||
| 1908 | netif_napi_add(ndev, &priv->napi, sxgbe_poll, 64); | ||
| 1909 | |||
| 1910 | spin_lock_init(&priv->stats_lock); | ||
| 1911 | |||
| 1912 | priv->sxgbe_clk = clk_get(priv->device, SXGBE_RESOURCE_NAME); | ||
| 1913 | if (IS_ERR(priv->sxgbe_clk)) { | ||
| 1914 | netdev_warn(ndev, "%s: warning: cannot get CSR clock\n", | ||
| 1915 | __func__); | ||
| 1916 | goto error_clk_get; | ||
| 1917 | } | ||
| 1918 | |||
| 1919 | /* If a specific clk_csr value is passed from the platform | ||
| 1920 | * this means that the CSR Clock Range selection cannot be | ||
| 1921 | * changed at run-time and it is fixed. Viceversa the driver'll try to | ||
| 1922 | * set the MDC clock dynamically according to the csr actual | ||
| 1923 | * clock input. | ||
| 1924 | */ | ||
| 1925 | if (!priv->plat->clk_csr) | ||
| 1926 | sxgbe_clk_csr_set(priv); | ||
| 1927 | else | ||
| 1928 | priv->clk_csr = priv->plat->clk_csr; | ||
| 1929 | |||
| 1930 | /* MDIO bus Registration */ | ||
| 1931 | ret = sxgbe_mdio_register(ndev); | ||
| 1932 | if (ret < 0) { | ||
| 1933 | netdev_dbg(ndev, "%s: MDIO bus (id: %d) registration failed\n", | ||
| 1934 | __func__, priv->plat->bus_id); | ||
| 1935 | goto error_mdio_register; | ||
| 1936 | } | ||
| 1937 | |||
| 1938 | ret = register_netdev(ndev); | ||
| 1939 | if (ret) { | ||
| 1940 | pr_err("%s: ERROR %i registering the device\n", __func__, ret); | ||
| 1941 | goto error_netdev_register; | ||
| 1942 | } | ||
| 1943 | |||
| 1944 | sxgbe_check_ether_addr(priv); | ||
| 1945 | |||
| 1946 | return priv; | ||
| 1947 | |||
| 1948 | error_mdio_register: | ||
| 1949 | clk_put(priv->sxgbe_clk); | ||
| 1950 | error_clk_get: | ||
| 1951 | error_netdev_register: | ||
| 1952 | netif_napi_del(&priv->napi); | ||
| 1953 | error_free_netdev: | ||
| 1954 | free_netdev(ndev); | ||
| 1955 | |||
| 1956 | return NULL; | ||
| 1957 | } | ||
| 1958 | |||
| 1959 | /** | ||
| 1960 | * sxgbe_drv_remove | ||
| 1961 | * @ndev: net device pointer | ||
| 1962 | * Description: this function resets the TX/RX processes, disables the MAC RX/TX | ||
| 1963 | * changes the link status, releases the DMA descriptor rings. | ||
| 1964 | */ | ||
| 1965 | int sxgbe_drv_remove(struct net_device *ndev) | ||
| 1966 | { | ||
| 1967 | struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||
| 1968 | |||
| 1969 | netdev_info(ndev, "%s: removing driver\n", __func__); | ||
| 1970 | |||
| 1971 | priv->hw->dma->stop_rx(priv->ioaddr, SXGBE_RX_QUEUES); | ||
| 1972 | priv->hw->dma->stop_tx(priv->ioaddr, SXGBE_TX_QUEUES); | ||
| 1973 | |||
| 1974 | priv->hw->mac->enable_tx(priv->ioaddr, false); | ||
| 1975 | priv->hw->mac->enable_rx(priv->ioaddr, false); | ||
| 1976 | |||
| 1977 | netif_napi_del(&priv->napi); | ||
| 1978 | |||
| 1979 | sxgbe_mdio_unregister(ndev); | ||
| 1980 | |||
| 1981 | unregister_netdev(ndev); | ||
| 1982 | |||
| 1983 | free_netdev(ndev); | ||
| 1984 | |||
| 1985 | return 0; | ||
| 1986 | } | ||
| 1987 | |||
| 1988 | #ifdef CONFIG_PM | ||
| 1989 | int sxgbe_suspend(struct net_device *ndev) | ||
| 1990 | { | ||
| 1991 | return 0; | ||
| 1992 | } | ||
| 1993 | |||
| 1994 | int sxgbe_resume(struct net_device *ndev) | ||
| 1995 | { | ||
| 1996 | return 0; | ||
| 1997 | } | ||
| 1998 | |||
| 1999 | int sxgbe_freeze(struct net_device *ndev) | ||
| 2000 | { | ||
| 2001 | return -ENOSYS; | ||
| 2002 | } | ||
| 2003 | |||
| 2004 | int sxgbe_restore(struct net_device *ndev) | ||
| 2005 | { | ||
| 2006 | return -ENOSYS; | ||
| 2007 | } | ||
| 2008 | #endif /* CONFIG_PM */ | ||
| 2009 | |||
| 2010 | /* Driver is configured as Platform driver */ | ||
| 2011 | static int __init sxgbe_init(void) | ||
| 2012 | { | ||
| 2013 | int ret; | ||
| 2014 | |||
| 2015 | ret = sxgbe_register_platform(); | ||
| 2016 | if (ret) | ||
| 2017 | goto err; | ||
| 2018 | return 0; | ||
| 2019 | err: | ||
| 2020 | pr_err("driver registration failed\n"); | ||
| 2021 | return ret; | ||
| 2022 | } | ||
| 2023 | |||
| 2024 | static void __exit sxgbe_exit(void) | ||
| 2025 | { | ||
| 2026 | sxgbe_unregister_platform(); | ||
| 2027 | } | ||
| 2028 | |||
| 2029 | module_init(sxgbe_init); | ||
| 2030 | module_exit(sxgbe_exit); | ||
| 2031 | |||
| 2032 | #ifndef MODULE | ||
| 2033 | static int __init sxgbe_cmdline_opt(char *str) | ||
| 2034 | { | ||
| 2035 | return 0; | ||
| 2036 | } | ||
| 2037 | |||
| 2038 | __setup("sxgbeeth=", sxgbe_cmdline_opt); | ||
| 2039 | #endif /* MODULE */ | ||
| 2040 | |||
| 2041 | |||
| 2042 | |||
| 2043 | MODULE_DESCRIPTION("SAMSUNG 10G/2.5G/1G Ethernet PLATFORM driver"); | ||
| 2044 | |||
| 2045 | MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)"); | ||
| 2046 | |||
| 2047 | MODULE_AUTHOR("Siva Reddy Kallam <siva.kallam@samsung.com>"); | ||
| 2048 | MODULE_AUTHOR("ByungHo An <bh74.an@samsung.com>"); | ||
| 2049 | MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>"); | ||
| 2050 | MODULE_AUTHOR("Vipul Pandya <vipul.pandya@samsung.com>"); | ||
| 2051 | |||
| 2052 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c new file mode 100644 index 000000000000..b0eb0a2c52ca --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c | |||
| @@ -0,0 +1,251 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 14 | |||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/mii.h> | ||
| 17 | #include <linux/netdevice.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/phy.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/sxgbe_platform.h> | ||
| 22 | |||
| 23 | #include "sxgbe_common.h" | ||
| 24 | #include "sxgbe_reg.h" | ||
| 25 | |||
| 26 | #define SXGBE_SMA_WRITE_CMD 0x01 /* write command */ | ||
| 27 | #define SXGBE_SMA_PREAD_CMD 0x02 /* post read increament address */ | ||
| 28 | #define SXGBE_SMA_READ_CMD 0x03 /* read command */ | ||
| 29 | #define SXGBE_SMA_SKIP_ADDRFRM 0x00040000 /* skip the address frame */ | ||
| 30 | #define SXGBE_MII_BUSY 0x00800000 /* mii busy */ | ||
| 31 | |||
| 32 | static int sxgbe_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_data) | ||
| 33 | { | ||
| 34 | unsigned long fin_time = jiffies + 3 * HZ; /* 3 seconds */ | ||
| 35 | |||
| 36 | while (!time_after(jiffies, fin_time)) { | ||
| 37 | if (!(readl(ioaddr + mii_data) & SXGBE_MII_BUSY)) | ||
| 38 | return 0; | ||
| 39 | cpu_relax(); | ||
| 40 | } | ||
| 41 | |||
| 42 | return -EBUSY; | ||
| 43 | } | ||
| 44 | |||
| 45 | static void sxgbe_mdio_ctrl_data(struct sxgbe_priv_data *sp, u32 cmd, | ||
| 46 | u16 phydata) | ||
| 47 | { | ||
| 48 | u32 reg = phydata; | ||
| 49 | |||
| 50 | reg |= (cmd << 16) | SXGBE_SMA_SKIP_ADDRFRM | | ||
| 51 | ((sp->clk_csr & 0x7) << 19) | SXGBE_MII_BUSY; | ||
| 52 | writel(reg, sp->ioaddr + sp->hw->mii.data); | ||
| 53 | } | ||
| 54 | |||
| 55 | static void sxgbe_mdio_c45(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, | ||
| 56 | int phyreg, u16 phydata) | ||
| 57 | { | ||
| 58 | u32 reg; | ||
| 59 | |||
| 60 | /* set mdio address register */ | ||
| 61 | reg = ((phyreg >> 16) & 0x1f) << 21; | ||
| 62 | reg |= (phyaddr << 16) | (phyreg & 0xffff); | ||
| 63 | writel(reg, sp->ioaddr + sp->hw->mii.addr); | ||
| 64 | |||
| 65 | sxgbe_mdio_ctrl_data(sp, cmd, phydata); | ||
| 66 | } | ||
| 67 | |||
| 68 | static void sxgbe_mdio_c22(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, | ||
| 69 | int phyreg, u16 phydata) | ||
| 70 | { | ||
| 71 | u32 reg; | ||
| 72 | |||
| 73 | writel(1 << phyaddr, sp->ioaddr + SXGBE_MDIO_CLAUSE22_PORT_REG); | ||
| 74 | |||
| 75 | /* set mdio address register */ | ||
| 76 | reg = (phyaddr << 16) | (phyreg & 0x1f); | ||
| 77 | writel(reg, sp->ioaddr + sp->hw->mii.addr); | ||
| 78 | |||
| 79 | sxgbe_mdio_ctrl_data(sp, cmd, phydata); | ||
| 80 | } | ||
| 81 | |||
| 82 | static int sxgbe_mdio_access(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, | ||
| 83 | int phyreg, u16 phydata) | ||
| 84 | { | ||
| 85 | const struct mii_regs *mii = &sp->hw->mii; | ||
| 86 | int rc; | ||
| 87 | |||
| 88 | rc = sxgbe_mdio_busy_wait(sp->ioaddr, mii->data); | ||
| 89 | if (rc < 0) | ||
| 90 | return rc; | ||
| 91 | |||
| 92 | if (phyreg & MII_ADDR_C45) { | ||
| 93 | sxgbe_mdio_c45(sp, cmd, phyaddr, phyreg, phydata); | ||
| 94 | } else { | ||
| 95 | /* Ports 0-3 only support C22. */ | ||
| 96 | if (phyaddr >= 4) | ||
| 97 | return -ENODEV; | ||
| 98 | |||
| 99 | sxgbe_mdio_c22(sp, cmd, phyaddr, phyreg, phydata); | ||
| 100 | } | ||
| 101 | |||
| 102 | return sxgbe_mdio_busy_wait(sp->ioaddr, mii->data); | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * sxgbe_mdio_read | ||
| 107 | * @bus: points to the mii_bus structure | ||
| 108 | * @phyaddr: address of phy port | ||
| 109 | * @phyreg: address of register with in phy register | ||
| 110 | * Description: this function used for C45 and C22 MDIO Read | ||
| 111 | */ | ||
| 112 | static int sxgbe_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) | ||
| 113 | { | ||
| 114 | struct net_device *ndev = bus->priv; | ||
| 115 | struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||
| 116 | int rc; | ||
| 117 | |||
| 118 | rc = sxgbe_mdio_access(priv, SXGBE_SMA_READ_CMD, phyaddr, phyreg, 0); | ||
| 119 | if (rc < 0) | ||
| 120 | return rc; | ||
| 121 | |||
| 122 | return readl(priv->ioaddr + priv->hw->mii.data) & 0xffff; | ||
| 123 | } | ||
| 124 | |||
| 125 | /** | ||
| 126 | * sxgbe_mdio_write | ||
| 127 | * @bus: points to the mii_bus structure | ||
| 128 | * @phyaddr: address of phy port | ||
| 129 | * @phyreg: address of phy registers | ||
| 130 | * @phydata: data to be written into phy register | ||
| 131 | * Description: this function is used for C45 and C22 MDIO write | ||
| 132 | */ | ||
| 133 | static int sxgbe_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, | ||
| 134 | u16 phydata) | ||
| 135 | { | ||
| 136 | struct net_device *ndev = bus->priv; | ||
| 137 | struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||
| 138 | |||
| 139 | return sxgbe_mdio_access(priv, SXGBE_SMA_WRITE_CMD, phyaddr, phyreg, | ||
| 140 | phydata); | ||
| 141 | } | ||
| 142 | |||
| 143 | int sxgbe_mdio_register(struct net_device *ndev) | ||
| 144 | { | ||
| 145 | struct mii_bus *mdio_bus; | ||
| 146 | struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||
| 147 | struct sxgbe_mdio_bus_data *mdio_data = priv->plat->mdio_bus_data; | ||
| 148 | int err, phy_addr; | ||
| 149 | int *irqlist; | ||
| 150 | bool act; | ||
| 151 | |||
| 152 | /* allocate the new mdio bus */ | ||
| 153 | mdio_bus = mdiobus_alloc(); | ||
| 154 | if (!mdio_bus) { | ||
| 155 | netdev_err(ndev, "%s: mii bus allocation failed\n", __func__); | ||
| 156 | return -ENOMEM; | ||
| 157 | } | ||
| 158 | |||
| 159 | if (mdio_data->irqs) | ||
| 160 | irqlist = mdio_data->irqs; | ||
| 161 | else | ||
| 162 | irqlist = priv->mii_irq; | ||
| 163 | |||
| 164 | /* assign mii bus fields */ | ||
| 165 | mdio_bus->name = "samsxgbe"; | ||
| 166 | mdio_bus->read = &sxgbe_mdio_read; | ||
| 167 | mdio_bus->write = &sxgbe_mdio_write; | ||
| 168 | snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%x", | ||
| 169 | mdio_bus->name, priv->plat->bus_id); | ||
| 170 | mdio_bus->priv = ndev; | ||
| 171 | mdio_bus->phy_mask = mdio_data->phy_mask; | ||
| 172 | mdio_bus->parent = priv->device; | ||
| 173 | |||
| 174 | /* register with kernel subsystem */ | ||
| 175 | err = mdiobus_register(mdio_bus); | ||
| 176 | if (err != 0) { | ||
| 177 | netdev_err(ndev, "mdiobus register failed\n"); | ||
| 178 | goto mdiobus_err; | ||
| 179 | } | ||
| 180 | |||
| 181 | for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { | ||
| 182 | struct phy_device *phy = mdio_bus->phy_map[phy_addr]; | ||
| 183 | |||
| 184 | if (phy) { | ||
| 185 | char irq_num[4]; | ||
| 186 | char *irq_str; | ||
| 187 | /* If an IRQ was provided to be assigned after | ||
| 188 | * the bus probe, do it here. | ||
| 189 | */ | ||
| 190 | if ((mdio_data->irqs == NULL) && | ||
| 191 | (mdio_data->probed_phy_irq > 0)) { | ||
| 192 | irqlist[phy_addr] = mdio_data->probed_phy_irq; | ||
| 193 | phy->irq = mdio_data->probed_phy_irq; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* If we're going to bind the MAC to this PHY bus, | ||
| 197 | * and no PHY number was provided to the MAC, | ||
| 198 | * use the one probed here. | ||
| 199 | */ | ||
| 200 | if (priv->plat->phy_addr == -1) | ||
| 201 | priv->plat->phy_addr = phy_addr; | ||
| 202 | |||
| 203 | act = (priv->plat->phy_addr == phy_addr); | ||
| 204 | switch (phy->irq) { | ||
| 205 | case PHY_POLL: | ||
| 206 | irq_str = "POLL"; | ||
| 207 | break; | ||
| 208 | case PHY_IGNORE_INTERRUPT: | ||
| 209 | irq_str = "IGNORE"; | ||
| 210 | break; | ||
| 211 | default: | ||
| 212 | sprintf(irq_num, "%d", phy->irq); | ||
| 213 | irq_str = irq_num; | ||
| 214 | break; | ||
| 215 | } | ||
| 216 | netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n", | ||
| 217 | phy->phy_id, phy_addr, irq_str, | ||
| 218 | dev_name(&phy->dev), act ? " active" : ""); | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | if (!err) { | ||
| 223 | netdev_err(ndev, "PHY not found\n"); | ||
| 224 | mdiobus_unregister(mdio_bus); | ||
| 225 | mdiobus_free(mdio_bus); | ||
| 226 | goto mdiobus_err; | ||
| 227 | } | ||
| 228 | |||
| 229 | priv->mii = mdio_bus; | ||
| 230 | |||
| 231 | return 0; | ||
| 232 | |||
| 233 | mdiobus_err: | ||
| 234 | mdiobus_free(mdio_bus); | ||
| 235 | return err; | ||
| 236 | } | ||
| 237 | |||
| 238 | int sxgbe_mdio_unregister(struct net_device *ndev) | ||
| 239 | { | ||
| 240 | struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||
| 241 | |||
| 242 | if (!priv->mii) | ||
| 243 | return 0; | ||
| 244 | |||
| 245 | mdiobus_unregister(priv->mii); | ||
| 246 | priv->mii->priv = NULL; | ||
| 247 | mdiobus_free(priv->mii); | ||
| 248 | priv->mii = NULL; | ||
| 249 | |||
| 250 | return 0; | ||
| 251 | } | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.c new file mode 100644 index 000000000000..324681c2bb74 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.c | |||
| @@ -0,0 +1,254 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 14 | |||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/errno.h> | ||
| 17 | #include <linux/export.h> | ||
| 18 | #include <linux/jiffies.h> | ||
| 19 | |||
| 20 | #include "sxgbe_mtl.h" | ||
| 21 | #include "sxgbe_reg.h" | ||
| 22 | |||
| 23 | static void sxgbe_mtl_init(void __iomem *ioaddr, unsigned int etsalg, | ||
| 24 | unsigned int raa) | ||
| 25 | { | ||
| 26 | u32 reg_val; | ||
| 27 | |||
| 28 | reg_val = readl(ioaddr + SXGBE_MTL_OP_MODE_REG); | ||
| 29 | reg_val &= ETS_RST; | ||
| 30 | |||
| 31 | /* ETS Algorith */ | ||
| 32 | switch (etsalg & SXGBE_MTL_OPMODE_ESTMASK) { | ||
| 33 | case ETS_WRR: | ||
| 34 | reg_val &= ETS_WRR; | ||
| 35 | break; | ||
| 36 | case ETS_WFQ: | ||
| 37 | reg_val |= ETS_WFQ; | ||
| 38 | break; | ||
| 39 | case ETS_DWRR: | ||
| 40 | reg_val |= ETS_DWRR; | ||
| 41 | break; | ||
| 42 | } | ||
| 43 | writel(reg_val, ioaddr + SXGBE_MTL_OP_MODE_REG); | ||
| 44 | |||
| 45 | switch (raa & SXGBE_MTL_OPMODE_RAAMASK) { | ||
| 46 | case RAA_SP: | ||
| 47 | reg_val &= RAA_SP; | ||
| 48 | break; | ||
| 49 | case RAA_WSP: | ||
| 50 | reg_val |= RAA_WSP; | ||
| 51 | break; | ||
| 52 | } | ||
| 53 | writel(reg_val, ioaddr + SXGBE_MTL_OP_MODE_REG); | ||
| 54 | } | ||
| 55 | |||
| 56 | /* For Dynamic DMA channel mapping for Rx queue */ | ||
| 57 | static void sxgbe_mtl_dma_dm_rxqueue(void __iomem *ioaddr) | ||
| 58 | { | ||
| 59 | writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP0_REG); | ||
| 60 | writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP1_REG); | ||
| 61 | writel(RX_QUEUE_DYNAMIC, ioaddr + SXGBE_MTL_RXQ_DMAMAP2_REG); | ||
| 62 | } | ||
| 63 | |||
| 64 | static void sxgbe_mtl_set_txfifosize(void __iomem *ioaddr, int queue_num, | ||
| 65 | int queue_fifo) | ||
| 66 | { | ||
| 67 | u32 fifo_bits, reg_val; | ||
| 68 | |||
| 69 | /* 0 means 256 bytes */ | ||
| 70 | fifo_bits = (queue_fifo / SXGBE_MTL_TX_FIFO_DIV) - 1; | ||
| 71 | reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||
| 72 | reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT); | ||
| 73 | writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||
| 74 | } | ||
| 75 | |||
| 76 | static void sxgbe_mtl_set_rxfifosize(void __iomem *ioaddr, int queue_num, | ||
| 77 | int queue_fifo) | ||
| 78 | { | ||
| 79 | u32 fifo_bits, reg_val; | ||
| 80 | |||
| 81 | /* 0 means 256 bytes */ | ||
| 82 | fifo_bits = (queue_fifo / SXGBE_MTL_RX_FIFO_DIV)-1; | ||
| 83 | reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 84 | reg_val |= (fifo_bits << SXGBE_MTL_FIFO_LSHIFT); | ||
| 85 | writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 86 | } | ||
| 87 | |||
| 88 | static void sxgbe_mtl_enable_txqueue(void __iomem *ioaddr, int queue_num) | ||
| 89 | { | ||
| 90 | u32 reg_val; | ||
| 91 | |||
| 92 | reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||
| 93 | reg_val |= SXGBE_MTL_ENABLE_QUEUE; | ||
| 94 | writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||
| 95 | } | ||
| 96 | |||
| 97 | static void sxgbe_mtl_disable_txqueue(void __iomem *ioaddr, int queue_num) | ||
| 98 | { | ||
| 99 | u32 reg_val; | ||
| 100 | |||
| 101 | reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||
| 102 | reg_val &= ~SXGBE_MTL_ENABLE_QUEUE; | ||
| 103 | writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||
| 104 | } | ||
| 105 | |||
| 106 | static void sxgbe_mtl_fc_active(void __iomem *ioaddr, int queue_num, | ||
| 107 | int threshold) | ||
| 108 | { | ||
| 109 | u32 reg_val; | ||
| 110 | |||
| 111 | reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 112 | reg_val &= ~(SXGBE_MTL_FCMASK << RX_FC_ACTIVE); | ||
| 113 | reg_val |= (threshold << RX_FC_ACTIVE); | ||
| 114 | |||
| 115 | writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 116 | } | ||
| 117 | |||
| 118 | static void sxgbe_mtl_fc_enable(void __iomem *ioaddr, int queue_num) | ||
| 119 | { | ||
| 120 | u32 reg_val; | ||
| 121 | |||
| 122 | reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 123 | reg_val |= SXGBE_MTL_ENABLE_FC; | ||
| 124 | writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 125 | } | ||
| 126 | |||
| 127 | static void sxgbe_mtl_fc_deactive(void __iomem *ioaddr, int queue_num, | ||
| 128 | int threshold) | ||
| 129 | { | ||
| 130 | u32 reg_val; | ||
| 131 | |||
| 132 | reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 133 | reg_val &= ~(SXGBE_MTL_FCMASK << RX_FC_DEACTIVE); | ||
| 134 | reg_val |= (threshold << RX_FC_DEACTIVE); | ||
| 135 | |||
| 136 | writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 137 | } | ||
| 138 | |||
| 139 | static void sxgbe_mtl_fep_enable(void __iomem *ioaddr, int queue_num) | ||
| 140 | { | ||
| 141 | u32 reg_val; | ||
| 142 | |||
| 143 | reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 144 | reg_val |= SXGBE_MTL_RXQ_OP_FEP; | ||
| 145 | |||
| 146 | writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 147 | } | ||
| 148 | |||
| 149 | static void sxgbe_mtl_fep_disable(void __iomem *ioaddr, int queue_num) | ||
| 150 | { | ||
| 151 | u32 reg_val; | ||
| 152 | |||
| 153 | reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 154 | reg_val &= ~(SXGBE_MTL_RXQ_OP_FEP); | ||
| 155 | |||
| 156 | writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 157 | } | ||
| 158 | |||
| 159 | static void sxgbe_mtl_fup_enable(void __iomem *ioaddr, int queue_num) | ||
| 160 | { | ||
| 161 | u32 reg_val; | ||
| 162 | |||
| 163 | reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 164 | reg_val |= SXGBE_MTL_RXQ_OP_FUP; | ||
| 165 | |||
| 166 | writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 167 | } | ||
| 168 | |||
| 169 | static void sxgbe_mtl_fup_disable(void __iomem *ioaddr, int queue_num) | ||
| 170 | { | ||
| 171 | u32 reg_val; | ||
| 172 | |||
| 173 | reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 174 | reg_val &= ~(SXGBE_MTL_RXQ_OP_FUP); | ||
| 175 | |||
| 176 | writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 177 | } | ||
| 178 | |||
| 179 | |||
| 180 | static void sxgbe_set_tx_mtl_mode(void __iomem *ioaddr, int queue_num, | ||
| 181 | int tx_mode) | ||
| 182 | { | ||
| 183 | u32 reg_val; | ||
| 184 | |||
| 185 | reg_val = readl(ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||
| 186 | /* TX specific MTL mode settings */ | ||
| 187 | if (tx_mode == SXGBE_MTL_SFMODE) { | ||
| 188 | reg_val |= SXGBE_MTL_SFMODE; | ||
| 189 | } else { | ||
| 190 | /* set the TTC values */ | ||
| 191 | if (tx_mode <= 64) | ||
| 192 | reg_val |= MTL_CONTROL_TTC_64; | ||
| 193 | else if (tx_mode <= 96) | ||
| 194 | reg_val |= MTL_CONTROL_TTC_96; | ||
| 195 | else if (tx_mode <= 128) | ||
| 196 | reg_val |= MTL_CONTROL_TTC_128; | ||
| 197 | else if (tx_mode <= 192) | ||
| 198 | reg_val |= MTL_CONTROL_TTC_192; | ||
| 199 | else if (tx_mode <= 256) | ||
| 200 | reg_val |= MTL_CONTROL_TTC_256; | ||
| 201 | else if (tx_mode <= 384) | ||
| 202 | reg_val |= MTL_CONTROL_TTC_384; | ||
| 203 | else | ||
| 204 | reg_val |= MTL_CONTROL_TTC_512; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* write into TXQ operation register */ | ||
| 208 | writel(reg_val, ioaddr + SXGBE_MTL_TXQ_OPMODE_REG(queue_num)); | ||
| 209 | } | ||
| 210 | |||
| 211 | static void sxgbe_set_rx_mtl_mode(void __iomem *ioaddr, int queue_num, | ||
| 212 | int rx_mode) | ||
| 213 | { | ||
| 214 | u32 reg_val; | ||
| 215 | |||
| 216 | reg_val = readl(ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 217 | /* RX specific MTL mode settings */ | ||
| 218 | if (rx_mode == SXGBE_RX_MTL_SFMODE) { | ||
| 219 | reg_val |= SXGBE_RX_MTL_SFMODE; | ||
| 220 | } else { | ||
| 221 | if (rx_mode <= 64) | ||
| 222 | reg_val |= MTL_CONTROL_RTC_64; | ||
| 223 | else if (rx_mode <= 96) | ||
| 224 | reg_val |= MTL_CONTROL_RTC_96; | ||
| 225 | else if (rx_mode <= 128) | ||
| 226 | reg_val |= MTL_CONTROL_RTC_128; | ||
| 227 | } | ||
| 228 | |||
| 229 | /* write into RXQ operation register */ | ||
| 230 | writel(reg_val, ioaddr + SXGBE_MTL_RXQ_OPMODE_REG(queue_num)); | ||
| 231 | } | ||
| 232 | |||
| 233 | static const struct sxgbe_mtl_ops mtl_ops = { | ||
| 234 | .mtl_set_txfifosize = sxgbe_mtl_set_txfifosize, | ||
| 235 | .mtl_set_rxfifosize = sxgbe_mtl_set_rxfifosize, | ||
| 236 | .mtl_enable_txqueue = sxgbe_mtl_enable_txqueue, | ||
| 237 | .mtl_disable_txqueue = sxgbe_mtl_disable_txqueue, | ||
| 238 | .mtl_dynamic_dma_rxqueue = sxgbe_mtl_dma_dm_rxqueue, | ||
| 239 | .set_tx_mtl_mode = sxgbe_set_tx_mtl_mode, | ||
| 240 | .set_rx_mtl_mode = sxgbe_set_rx_mtl_mode, | ||
| 241 | .mtl_init = sxgbe_mtl_init, | ||
| 242 | .mtl_fc_active = sxgbe_mtl_fc_active, | ||
| 243 | .mtl_fc_deactive = sxgbe_mtl_fc_deactive, | ||
| 244 | .mtl_fc_enable = sxgbe_mtl_fc_enable, | ||
| 245 | .mtl_fep_enable = sxgbe_mtl_fep_enable, | ||
| 246 | .mtl_fep_disable = sxgbe_mtl_fep_disable, | ||
| 247 | .mtl_fup_enable = sxgbe_mtl_fup_enable, | ||
| 248 | .mtl_fup_disable = sxgbe_mtl_fup_disable | ||
| 249 | }; | ||
| 250 | |||
| 251 | const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void) | ||
| 252 | { | ||
| 253 | return &mtl_ops; | ||
| 254 | } | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.h new file mode 100644 index 000000000000..7e4810c4137e --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mtl.h | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #ifndef __SXGBE_MTL_H__ | ||
| 13 | #define __SXGBE_MTL_H__ | ||
| 14 | |||
| 15 | #define SXGBE_MTL_OPMODE_ESTMASK 0x3 | ||
| 16 | #define SXGBE_MTL_OPMODE_RAAMASK 0x1 | ||
| 17 | #define SXGBE_MTL_FCMASK 0x7 | ||
| 18 | #define SXGBE_MTL_TX_FIFO_DIV 256 | ||
| 19 | #define SXGBE_MTL_RX_FIFO_DIV 256 | ||
| 20 | |||
| 21 | #define SXGBE_MTL_RXQ_OP_FEP BIT(4) | ||
| 22 | #define SXGBE_MTL_RXQ_OP_FUP BIT(3) | ||
| 23 | #define SXGBE_MTL_ENABLE_FC 0x80 | ||
| 24 | |||
| 25 | #define ETS_WRR 0xFFFFFF9F | ||
| 26 | #define ETS_RST 0xFFFFFF9F | ||
| 27 | #define ETS_WFQ 0x00000020 | ||
| 28 | #define ETS_DWRR 0x00000040 | ||
| 29 | #define RAA_SP 0xFFFFFFFB | ||
| 30 | #define RAA_WSP 0x00000004 | ||
| 31 | |||
| 32 | #define RX_QUEUE_DYNAMIC 0x80808080 | ||
| 33 | #define RX_FC_ACTIVE 8 | ||
| 34 | #define RX_FC_DEACTIVE 13 | ||
| 35 | |||
| 36 | enum ttc_control { | ||
| 37 | MTL_CONTROL_TTC_64 = 0x00000000, | ||
| 38 | MTL_CONTROL_TTC_96 = 0x00000020, | ||
| 39 | MTL_CONTROL_TTC_128 = 0x00000030, | ||
| 40 | MTL_CONTROL_TTC_192 = 0x00000040, | ||
| 41 | MTL_CONTROL_TTC_256 = 0x00000050, | ||
| 42 | MTL_CONTROL_TTC_384 = 0x00000060, | ||
| 43 | MTL_CONTROL_TTC_512 = 0x00000070, | ||
| 44 | }; | ||
| 45 | |||
| 46 | enum rtc_control { | ||
| 47 | MTL_CONTROL_RTC_64 = 0x00000000, | ||
| 48 | MTL_CONTROL_RTC_96 = 0x00000002, | ||
| 49 | MTL_CONTROL_RTC_128 = 0x00000003, | ||
| 50 | }; | ||
| 51 | |||
| 52 | enum flow_control_th { | ||
| 53 | MTL_FC_FULL_1K = 0x00000000, | ||
| 54 | MTL_FC_FULL_2K = 0x00000001, | ||
| 55 | MTL_FC_FULL_4K = 0x00000002, | ||
| 56 | MTL_FC_FULL_5K = 0x00000003, | ||
| 57 | MTL_FC_FULL_6K = 0x00000004, | ||
| 58 | MTL_FC_FULL_8K = 0x00000005, | ||
| 59 | MTL_FC_FULL_16K = 0x00000006, | ||
| 60 | MTL_FC_FULL_24K = 0x00000007, | ||
| 61 | }; | ||
| 62 | |||
| 63 | struct sxgbe_mtl_ops { | ||
| 64 | void (*mtl_init)(void __iomem *ioaddr, unsigned int etsalg, | ||
| 65 | unsigned int raa); | ||
| 66 | |||
| 67 | void (*mtl_set_txfifosize)(void __iomem *ioaddr, int queue_num, | ||
| 68 | int mtl_fifo); | ||
| 69 | |||
| 70 | void (*mtl_set_rxfifosize)(void __iomem *ioaddr, int queue_num, | ||
| 71 | int queue_fifo); | ||
| 72 | |||
| 73 | void (*mtl_enable_txqueue)(void __iomem *ioaddr, int queue_num); | ||
| 74 | |||
| 75 | void (*mtl_disable_txqueue)(void __iomem *ioaddr, int queue_num); | ||
| 76 | |||
| 77 | void (*set_tx_mtl_mode)(void __iomem *ioaddr, int queue_num, | ||
| 78 | int tx_mode); | ||
| 79 | |||
| 80 | void (*set_rx_mtl_mode)(void __iomem *ioaddr, int queue_num, | ||
| 81 | int rx_mode); | ||
| 82 | |||
| 83 | void (*mtl_dynamic_dma_rxqueue)(void __iomem *ioaddr); | ||
| 84 | |||
| 85 | void (*mtl_fc_active)(void __iomem *ioaddr, int queue_num, | ||
| 86 | int threshold); | ||
| 87 | |||
| 88 | void (*mtl_fc_deactive)(void __iomem *ioaddr, int queue_num, | ||
| 89 | int threshold); | ||
| 90 | |||
| 91 | void (*mtl_fc_enable)(void __iomem *ioaddr, int queue_num); | ||
| 92 | |||
| 93 | void (*mtl_fep_enable)(void __iomem *ioaddr, int queue_num); | ||
| 94 | |||
| 95 | void (*mtl_fep_disable)(void __iomem *ioaddr, int queue_num); | ||
| 96 | |||
| 97 | void (*mtl_fup_enable)(void __iomem *ioaddr, int queue_num); | ||
| 98 | |||
| 99 | void (*mtl_fup_disable)(void __iomem *ioaddr, int queue_num); | ||
| 100 | }; | ||
| 101 | |||
| 102 | const struct sxgbe_mtl_ops *sxgbe_get_mtl_ops(void); | ||
| 103 | |||
| 104 | #endif /* __SXGBE_MTL_H__ */ | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c new file mode 100644 index 000000000000..f5a9de710052 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c | |||
| @@ -0,0 +1,253 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 14 | |||
| 15 | #include <linux/etherdevice.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/of_irq.h> | ||
| 21 | #include <linux/of_net.h> | ||
| 22 | #include <linux/phy.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/sxgbe_platform.h> | ||
| 25 | |||
| 26 | #include "sxgbe_common.h" | ||
| 27 | #include "sxgbe_reg.h" | ||
| 28 | |||
| 29 | #ifdef CONFIG_OF | ||
| 30 | static int sxgbe_probe_config_dt(struct platform_device *pdev, | ||
| 31 | struct sxgbe_plat_data *plat, | ||
| 32 | const char **mac) | ||
| 33 | { | ||
| 34 | struct device_node *np = pdev->dev.of_node; | ||
| 35 | struct sxgbe_dma_cfg *dma_cfg; | ||
| 36 | |||
| 37 | if (!np) | ||
| 38 | return -ENODEV; | ||
| 39 | |||
| 40 | *mac = of_get_mac_address(np); | ||
| 41 | plat->interface = of_get_phy_mode(np); | ||
| 42 | |||
| 43 | plat->bus_id = of_alias_get_id(np, "ethernet"); | ||
| 44 | if (plat->bus_id < 0) | ||
| 45 | plat->bus_id = 0; | ||
| 46 | |||
| 47 | plat->mdio_bus_data = devm_kzalloc(&pdev->dev, | ||
| 48 | sizeof(*plat->mdio_bus_data), | ||
| 49 | GFP_KERNEL); | ||
| 50 | |||
| 51 | dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL); | ||
| 52 | if (!dma_cfg) | ||
| 53 | return -ENOMEM; | ||
| 54 | |||
| 55 | plat->dma_cfg = dma_cfg; | ||
| 56 | of_property_read_u32(np, "samsung,pbl", &dma_cfg->pbl); | ||
| 57 | if (of_property_read_u32(np, "samsung,burst-map", &dma_cfg->burst_map) == 0) | ||
| 58 | dma_cfg->fixed_burst = true; | ||
| 59 | |||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | #else | ||
| 63 | static int sxgbe_probe_config_dt(struct platform_device *pdev, | ||
| 64 | struct sxgbe_plat_data *plat, | ||
| 65 | const char **mac) | ||
| 66 | { | ||
| 67 | return -ENOSYS; | ||
| 68 | } | ||
| 69 | #endif /* CONFIG_OF */ | ||
| 70 | |||
| 71 | /** | ||
| 72 | * sxgbe_platform_probe | ||
| 73 | * @pdev: platform device pointer | ||
| 74 | * Description: platform_device probe function. It allocates | ||
| 75 | * the necessary resources and invokes the main to init | ||
| 76 | * the net device, register the mdio bus etc. | ||
| 77 | */ | ||
| 78 | static int sxgbe_platform_probe(struct platform_device *pdev) | ||
| 79 | { | ||
| 80 | int ret; | ||
| 81 | int i, chan; | ||
| 82 | struct resource *res; | ||
| 83 | struct device *dev = &pdev->dev; | ||
| 84 | void __iomem *addr; | ||
| 85 | struct sxgbe_priv_data *priv = NULL; | ||
| 86 | struct sxgbe_plat_data *plat_dat = NULL; | ||
| 87 | const char *mac = NULL; | ||
| 88 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
| 89 | struct device_node *node = dev->of_node; | ||
| 90 | |||
| 91 | /* Get memory resource */ | ||
| 92 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 93 | if (!res) | ||
| 94 | goto err_out; | ||
| 95 | |||
| 96 | addr = devm_ioremap_resource(dev, res); | ||
| 97 | if (IS_ERR(addr)) | ||
| 98 | return PTR_ERR(addr); | ||
| 99 | |||
| 100 | if (pdev->dev.of_node) { | ||
| 101 | plat_dat = devm_kzalloc(&pdev->dev, | ||
| 102 | sizeof(struct sxgbe_plat_data), | ||
| 103 | GFP_KERNEL); | ||
| 104 | if (!plat_dat) | ||
| 105 | return -ENOMEM; | ||
| 106 | |||
| 107 | ret = sxgbe_probe_config_dt(pdev, plat_dat, &mac); | ||
| 108 | if (ret) { | ||
| 109 | pr_err("%s: main dt probe failed\n", __func__); | ||
| 110 | return ret; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | /* Get MAC address if available (DT) */ | ||
| 115 | if (mac) | ||
| 116 | ether_addr_copy(priv->dev->dev_addr, mac); | ||
| 117 | |||
| 118 | priv = sxgbe_drv_probe(&(pdev->dev), plat_dat, addr); | ||
| 119 | if (!priv) { | ||
| 120 | pr_err("%s: main driver probe failed\n", __func__); | ||
| 121 | goto err_out; | ||
| 122 | } | ||
| 123 | |||
| 124 | /* Get the SXGBE common INT information */ | ||
| 125 | priv->irq = irq_of_parse_and_map(node, 0); | ||
| 126 | if (priv->irq <= 0) { | ||
| 127 | dev_err(dev, "sxgbe common irq parsing failed\n"); | ||
| 128 | goto err_drv_remove; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* Get the TX/RX IRQ numbers */ | ||
| 132 | for (i = 0, chan = 1; i < SXGBE_TX_QUEUES; i++) { | ||
| 133 | priv->txq[i]->irq_no = irq_of_parse_and_map(node, chan++); | ||
| 134 | if (priv->txq[i]->irq_no <= 0) { | ||
| 135 | dev_err(dev, "sxgbe tx irq parsing failed\n"); | ||
| 136 | goto err_tx_irq_unmap; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | for (i = 0; i < SXGBE_RX_QUEUES; i++) { | ||
| 141 | priv->rxq[i]->irq_no = irq_of_parse_and_map(node, chan++); | ||
| 142 | if (priv->rxq[i]->irq_no <= 0) { | ||
| 143 | dev_err(dev, "sxgbe rx irq parsing failed\n"); | ||
| 144 | goto err_rx_irq_unmap; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | platform_set_drvdata(pdev, priv->dev); | ||
| 149 | |||
| 150 | pr_debug("platform driver registration completed\n"); | ||
| 151 | |||
| 152 | return 0; | ||
| 153 | |||
| 154 | err_rx_irq_unmap: | ||
| 155 | while (--i) | ||
| 156 | irq_dispose_mapping(priv->rxq[i]->irq_no); | ||
| 157 | i = SXGBE_TX_QUEUES; | ||
| 158 | err_tx_irq_unmap: | ||
| 159 | while (--i) | ||
| 160 | irq_dispose_mapping(priv->txq[i]->irq_no); | ||
| 161 | irq_dispose_mapping(priv->irq); | ||
| 162 | err_drv_remove: | ||
| 163 | sxgbe_drv_remove(ndev); | ||
| 164 | err_out: | ||
| 165 | return -ENODEV; | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * sxgbe_platform_remove | ||
| 170 | * @pdev: platform device pointer | ||
| 171 | * Description: this function calls the main to free the net resources | ||
| 172 | * and calls the platforms hook and release the resources (e.g. mem). | ||
| 173 | */ | ||
| 174 | static int sxgbe_platform_remove(struct platform_device *pdev) | ||
| 175 | { | ||
| 176 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
| 177 | int ret = sxgbe_drv_remove(ndev); | ||
| 178 | |||
| 179 | return ret; | ||
| 180 | } | ||
| 181 | |||
| 182 | #ifdef CONFIG_PM | ||
| 183 | static int sxgbe_platform_suspend(struct device *dev) | ||
| 184 | { | ||
| 185 | struct net_device *ndev = dev_get_drvdata(dev); | ||
| 186 | |||
| 187 | return sxgbe_suspend(ndev); | ||
| 188 | } | ||
| 189 | |||
| 190 | static int sxgbe_platform_resume(struct device *dev) | ||
| 191 | { | ||
| 192 | struct net_device *ndev = dev_get_drvdata(dev); | ||
| 193 | |||
| 194 | return sxgbe_resume(ndev); | ||
| 195 | } | ||
| 196 | |||
| 197 | int sxgbe_platform_freeze(struct device *dev) | ||
| 198 | { | ||
| 199 | struct net_device *ndev = dev_get_drvdata(dev); | ||
| 200 | |||
| 201 | return sxgbe_freeze(ndev); | ||
| 202 | } | ||
| 203 | |||
| 204 | int sxgbe_platform_restore(struct device *dev) | ||
| 205 | { | ||
| 206 | struct net_device *ndev = dev_get_drvdata(dev); | ||
| 207 | |||
| 208 | return sxgbe_restore(ndev); | ||
| 209 | } | ||
| 210 | |||
| 211 | static const struct dev_pm_ops sxgbe_platform_pm_ops = { | ||
| 212 | .suspend = sxgbe_platform_suspend, | ||
| 213 | .resume = sxgbe_platform_resume, | ||
| 214 | .freeze = sxgbe_platform_freeze, | ||
| 215 | .thaw = sxgbe_platform_restore, | ||
| 216 | .restore = sxgbe_platform_restore, | ||
| 217 | }; | ||
| 218 | #else | ||
| 219 | static const struct dev_pm_ops sxgbe_platform_pm_ops; | ||
| 220 | #endif /* CONFIG_PM */ | ||
| 221 | |||
| 222 | static const struct of_device_id sxgbe_dt_ids[] = { | ||
| 223 | { .compatible = "samsung,sxgbe-v2.0a"}, | ||
| 224 | { /* sentinel */ } | ||
| 225 | }; | ||
| 226 | MODULE_DEVICE_TABLE(of, sxgbe_dt_ids); | ||
| 227 | |||
| 228 | struct platform_driver sxgbe_platform_driver = { | ||
| 229 | .probe = sxgbe_platform_probe, | ||
| 230 | .remove = sxgbe_platform_remove, | ||
| 231 | .driver = { | ||
| 232 | .name = SXGBE_RESOURCE_NAME, | ||
| 233 | .owner = THIS_MODULE, | ||
| 234 | .pm = &sxgbe_platform_pm_ops, | ||
| 235 | .of_match_table = of_match_ptr(sxgbe_dt_ids), | ||
| 236 | }, | ||
| 237 | }; | ||
| 238 | |||
| 239 | int sxgbe_register_platform(void) | ||
| 240 | { | ||
| 241 | int err; | ||
| 242 | |||
| 243 | err = platform_driver_register(&sxgbe_platform_driver); | ||
| 244 | if (err) | ||
| 245 | pr_err("failed to register the platform driver\n"); | ||
| 246 | |||
| 247 | return err; | ||
| 248 | } | ||
| 249 | |||
| 250 | void sxgbe_unregister_platform(void) | ||
| 251 | { | ||
| 252 | platform_driver_unregister(&sxgbe_platform_driver); | ||
| 253 | } | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h new file mode 100644 index 000000000000..d1cd9ac1b062 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_reg.h | |||
| @@ -0,0 +1,477 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #ifndef __SXGBE_REGMAP_H__ | ||
| 13 | #define __SXGBE_REGMAP_H__ | ||
| 14 | |||
| 15 | /* SXGBE MAC Registers */ | ||
| 16 | #define SXGBE_CORE_TX_CONFIG_REG 0x0000 | ||
| 17 | #define SXGBE_CORE_RX_CONFIG_REG 0x0004 | ||
| 18 | #define SXGBE_CORE_PKT_FILTER_REG 0x0008 | ||
| 19 | #define SXGBE_CORE_WATCHDOG_TIMEOUT_REG 0x000C | ||
| 20 | #define SXGBE_CORE_HASH_TABLE_REG0 0x0010 | ||
| 21 | #define SXGBE_CORE_HASH_TABLE_REG1 0x0014 | ||
| 22 | #define SXGBE_CORE_HASH_TABLE_REG2 0x0018 | ||
| 23 | #define SXGBE_CORE_HASH_TABLE_REG3 0x001C | ||
| 24 | #define SXGBE_CORE_HASH_TABLE_REG4 0x0020 | ||
| 25 | #define SXGBE_CORE_HASH_TABLE_REG5 0x0024 | ||
| 26 | #define SXGBE_CORE_HASH_TABLE_REG6 0x0028 | ||
| 27 | #define SXGBE_CORE_HASH_TABLE_REG7 0x002C | ||
| 28 | /* VLAN Specific Registers */ | ||
| 29 | #define SXGBE_CORE_VLAN_TAG_REG 0x0050 | ||
| 30 | #define SXGBE_CORE_VLAN_HASHTAB_REG 0x0058 | ||
| 31 | #define SXGBE_CORE_VLAN_INSCTL_REG 0x0060 | ||
| 32 | #define SXGBE_CORE_VLAN_INNERCTL_REG 0x0064 | ||
| 33 | #define SXGBE_CORE_RX_ETHTYPE_MATCH_REG 0x006C | ||
| 34 | |||
| 35 | /* Flow Contol Registers */ | ||
| 36 | #define SXGBE_CORE_TX_Q0_FLOWCTL_REG 0x0070 | ||
| 37 | #define SXGBE_CORE_TX_Q1_FLOWCTL_REG 0x0074 | ||
| 38 | #define SXGBE_CORE_TX_Q2_FLOWCTL_REG 0x0078 | ||
| 39 | #define SXGBE_CORE_TX_Q3_FLOWCTL_REG 0x007C | ||
| 40 | #define SXGBE_CORE_TX_Q4_FLOWCTL_REG 0x0080 | ||
| 41 | #define SXGBE_CORE_TX_Q5_FLOWCTL_REG 0x0084 | ||
| 42 | #define SXGBE_CORE_TX_Q6_FLOWCTL_REG 0x0088 | ||
| 43 | #define SXGBE_CORE_TX_Q7_FLOWCTL_REG 0x008C | ||
| 44 | #define SXGBE_CORE_RX_FLOWCTL_REG 0x0090 | ||
| 45 | #define SXGBE_CORE_RX_CTL0_REG 0x00A0 | ||
| 46 | #define SXGBE_CORE_RX_CTL1_REG 0x00A4 | ||
| 47 | #define SXGBE_CORE_RX_CTL2_REG 0x00A8 | ||
| 48 | #define SXGBE_CORE_RX_CTL3_REG 0x00AC | ||
| 49 | |||
| 50 | /* Interrupt Registers */ | ||
| 51 | #define SXGBE_CORE_INT_STATUS_REG 0x00B0 | ||
| 52 | #define SXGBE_CORE_INT_ENABLE_REG 0x00B4 | ||
| 53 | #define SXGBE_CORE_RXTX_ERR_STATUS_REG 0x00B8 | ||
| 54 | #define SXGBE_CORE_PMT_CTL_STATUS_REG 0x00C0 | ||
| 55 | #define SXGBE_CORE_RWK_PKT_FILTER_REG 0x00C4 | ||
| 56 | #define SXGBE_CORE_VERSION_REG 0x0110 | ||
| 57 | #define SXGBE_CORE_DEBUG_REG 0x0114 | ||
| 58 | #define SXGBE_CORE_HW_FEA_REG(index) (0x011C + index * 4) | ||
| 59 | |||
| 60 | /* SMA(MDIO) module registers */ | ||
| 61 | #define SXGBE_MDIO_SCMD_ADD_REG 0x0200 | ||
| 62 | #define SXGBE_MDIO_SCMD_DATA_REG 0x0204 | ||
| 63 | #define SXGBE_MDIO_CCMD_WADD_REG 0x0208 | ||
| 64 | #define SXGBE_MDIO_CCMD_WDATA_REG 0x020C | ||
| 65 | #define SXGBE_MDIO_CSCAN_PORT_REG 0x0210 | ||
| 66 | #define SXGBE_MDIO_INT_STATUS_REG 0x0214 | ||
| 67 | #define SXGBE_MDIO_INT_ENABLE_REG 0x0218 | ||
| 68 | #define SXGBE_MDIO_PORT_CONDCON_REG 0x021C | ||
| 69 | #define SXGBE_MDIO_CLAUSE22_PORT_REG 0x0220 | ||
| 70 | |||
| 71 | /* port specific, addr = 0-3 */ | ||
| 72 | #define SXGBE_MDIO_DEV_BASE_REG 0x0230 | ||
| 73 | #define SXGBE_MDIO_PORT_DEV_REG(addr) \ | ||
| 74 | (SXGBE_MDIO_DEV_BASE_REG + (0x10 * addr) + 0x0) | ||
| 75 | #define SXGBE_MDIO_PORT_LSTATUS_REG(addr) \ | ||
| 76 | (SXGBE_MDIO_DEV_BASE_REG + (0x10 * addr) + 0x4) | ||
| 77 | #define SXGBE_MDIO_PORT_ALIVE_REG(addr) \ | ||
| 78 | (SXGBE_MDIO_DEV_BASE_REG + (0x10 * addr) + 0x8) | ||
| 79 | |||
| 80 | #define SXGBE_CORE_GPIO_CTL_REG 0x0278 | ||
| 81 | #define SXGBE_CORE_GPIO_STATUS_REG 0x027C | ||
| 82 | |||
| 83 | /* Address registers for filtering */ | ||
| 84 | #define SXGBE_CORE_ADD_BASE_REG 0x0300 | ||
| 85 | |||
| 86 | /* addr = 0-31 */ | ||
| 87 | #define SXGBE_CORE_ADD_HIGHOFFSET(addr) \ | ||
| 88 | (SXGBE_CORE_ADD_BASE_REG + (0x8 * addr) + 0x0) | ||
| 89 | #define SXGBE_CORE_ADD_LOWOFFSET(addr) \ | ||
| 90 | (SXGBE_CORE_ADD_BASE_REG + (0x8 * addr) + 0x4) | ||
| 91 | |||
| 92 | /* SXGBE MMC registers */ | ||
| 93 | #define SXGBE_MMC_CTL_REG 0x0800 | ||
| 94 | #define SXGBE_MMC_RXINT_STATUS_REG 0x0804 | ||
| 95 | #define SXGBE_MMC_TXINT_STATUS_REG 0x0808 | ||
| 96 | #define SXGBE_MMC_RXINT_ENABLE_REG 0x080C | ||
| 97 | #define SXGBE_MMC_TXINT_ENABLE_REG 0x0810 | ||
| 98 | |||
| 99 | /* TX specific counters */ | ||
| 100 | #define SXGBE_MMC_TXOCTETHI_GBCNT_REG 0x0814 | ||
| 101 | #define SXGBE_MMC_TXOCTETLO_GBCNT_REG 0x0818 | ||
| 102 | #define SXGBE_MMC_TXFRAMELO_GBCNT_REG 0x081C | ||
| 103 | #define SXGBE_MMC_TXFRAMEHI_GBCNT_REG 0x0820 | ||
| 104 | #define SXGBE_MMC_TXBROADLO_GCNT_REG 0x0824 | ||
| 105 | #define SXGBE_MMC_TXBROADHI_GCNT_REG 0x0828 | ||
| 106 | #define SXGBE_MMC_TXMULTILO_GCNT_REG 0x082C | ||
| 107 | #define SXGBE_MMC_TXMULTIHI_GCNT_REG 0x0830 | ||
| 108 | #define SXGBE_MMC_TX64LO_GBCNT_REG 0x0834 | ||
| 109 | #define SXGBE_MMC_TX64HI_GBCNT_REG 0x0838 | ||
| 110 | #define SXGBE_MMC_TX65TO127LO_GBCNT_REG 0x083C | ||
| 111 | #define SXGBE_MMC_TX65TO127HI_GBCNT_REG 0x0840 | ||
| 112 | #define SXGBE_MMC_TX128TO255LO_GBCNT_REG 0x0844 | ||
| 113 | #define SXGBE_MMC_TX128TO255HI_GBCNT_REG 0x0848 | ||
| 114 | #define SXGBE_MMC_TX256TO511LO_GBCNT_REG 0x084C | ||
| 115 | #define SXGBE_MMC_TX256TO511HI_GBCNT_REG 0x0850 | ||
| 116 | #define SXGBE_MMC_TX512TO1023LO_GBCNT_REG 0x0854 | ||
| 117 | #define SXGBE_MMC_TX512TO1023HI_GBCNT_REG 0x0858 | ||
| 118 | #define SXGBE_MMC_TX1023TOMAXLO_GBCNT_REG 0x085C | ||
| 119 | #define SXGBE_MMC_TX1023TOMAXHI_GBCNT_REG 0x0860 | ||
| 120 | #define SXGBE_MMC_TXUNICASTLO_GBCNT_REG 0x0864 | ||
| 121 | #define SXGBE_MMC_TXUNICASTHI_GBCNT_REG 0x0868 | ||
| 122 | #define SXGBE_MMC_TXMULTILO_GBCNT_REG 0x086C | ||
| 123 | #define SXGBE_MMC_TXMULTIHI_GBCNT_REG 0x0870 | ||
| 124 | #define SXGBE_MMC_TXBROADLO_GBCNT_REG 0x0874 | ||
| 125 | #define SXGBE_MMC_TXBROADHI_GBCNT_REG 0x0878 | ||
| 126 | #define SXGBE_MMC_TXUFLWLO_GBCNT_REG 0x087C | ||
| 127 | #define SXGBE_MMC_TXUFLWHI_GBCNT_REG 0x0880 | ||
| 128 | #define SXGBE_MMC_TXOCTETLO_GCNT_REG 0x0884 | ||
| 129 | #define SXGBE_MMC_TXOCTETHI_GCNT_REG 0x0888 | ||
| 130 | #define SXGBE_MMC_TXFRAMELO_GCNT_REG 0x088C | ||
| 131 | #define SXGBE_MMC_TXFRAMEHI_GCNT_REG 0x0890 | ||
| 132 | #define SXGBE_MMC_TXPAUSELO_CNT_REG 0x0894 | ||
| 133 | #define SXGBE_MMC_TXPAUSEHI_CNT_REG 0x0898 | ||
| 134 | #define SXGBE_MMC_TXVLANLO_GCNT_REG 0x089C | ||
| 135 | #define SXGBE_MMC_TXVLANHI_GCNT_REG 0x08A0 | ||
| 136 | |||
| 137 | /* RX specific counters */ | ||
| 138 | #define SXGBE_MMC_RXFRAMELO_GBCNT_REG 0x0900 | ||
| 139 | #define SXGBE_MMC_RXFRAMEHI_GBCNT_REG 0x0904 | ||
| 140 | #define SXGBE_MMC_RXOCTETLO_GBCNT_REG 0x0908 | ||
| 141 | #define SXGBE_MMC_RXOCTETHI_GBCNT_REG 0x090C | ||
| 142 | #define SXGBE_MMC_RXOCTETLO_GCNT_REG 0x0910 | ||
| 143 | #define SXGBE_MMC_RXOCTETHI_GCNT_REG 0x0914 | ||
| 144 | #define SXGBE_MMC_RXBROADLO_GCNT_REG 0x0918 | ||
| 145 | #define SXGBE_MMC_RXBROADHI_GCNT_REG 0x091C | ||
| 146 | #define SXGBE_MMC_RXMULTILO_GCNT_REG 0x0920 | ||
| 147 | #define SXGBE_MMC_RXMULTIHI_GCNT_REG 0x0924 | ||
| 148 | #define SXGBE_MMC_RXCRCERRLO_REG 0x0928 | ||
| 149 | #define SXGBE_MMC_RXCRCERRHI_REG 0x092C | ||
| 150 | #define SXGBE_MMC_RXSHORT64BFRAME_ERR_REG 0x0930 | ||
| 151 | #define SXGBE_MMC_RXJABBERERR_REG 0x0934 | ||
| 152 | #define SXGBE_MMC_RXSHORT64BFRAME_COR_REG 0x0938 | ||
| 153 | #define SXGBE_MMC_RXOVERMAXFRAME_COR_REG 0x093C | ||
| 154 | #define SXGBE_MMC_RX64LO_GBCNT_REG 0x0940 | ||
| 155 | #define SXGBE_MMC_RX64HI_GBCNT_REG 0x0944 | ||
| 156 | #define SXGBE_MMC_RX65TO127LO_GBCNT_REG 0x0948 | ||
| 157 | #define SXGBE_MMC_RX65TO127HI_GBCNT_REG 0x094C | ||
| 158 | #define SXGBE_MMC_RX128TO255LO_GBCNT_REG 0x0950 | ||
| 159 | #define SXGBE_MMC_RX128TO255HI_GBCNT_REG 0x0954 | ||
| 160 | #define SXGBE_MMC_RX256TO511LO_GBCNT_REG 0x0958 | ||
| 161 | #define SXGBE_MMC_RX256TO511HI_GBCNT_REG 0x095C | ||
| 162 | #define SXGBE_MMC_RX512TO1023LO_GBCNT_REG 0x0960 | ||
| 163 | #define SXGBE_MMC_RX512TO1023HI_GBCNT_REG 0x0964 | ||
| 164 | #define SXGBE_MMC_RX1023TOMAXLO_GBCNT_REG 0x0968 | ||
| 165 | #define SXGBE_MMC_RX1023TOMAXHI_GBCNT_REG 0x096C | ||
| 166 | #define SXGBE_MMC_RXUNICASTLO_GCNT_REG 0x0970 | ||
| 167 | #define SXGBE_MMC_RXUNICASTHI_GCNT_REG 0x0974 | ||
| 168 | #define SXGBE_MMC_RXLENERRLO_REG 0x0978 | ||
| 169 | #define SXGBE_MMC_RXLENERRHI_REG 0x097C | ||
| 170 | #define SXGBE_MMC_RXOUTOFRANGETYPELO_REG 0x0980 | ||
| 171 | #define SXGBE_MMC_RXOUTOFRANGETYPEHI_REG 0x0984 | ||
| 172 | #define SXGBE_MMC_RXPAUSELO_CNT_REG 0x0988 | ||
| 173 | #define SXGBE_MMC_RXPAUSEHI_CNT_REG 0x098C | ||
| 174 | #define SXGBE_MMC_RXFIFOOVERFLOWLO_GBCNT_REG 0x0990 | ||
| 175 | #define SXGBE_MMC_RXFIFOOVERFLOWHI_GBCNT_REG 0x0994 | ||
| 176 | #define SXGBE_MMC_RXVLANLO_GBCNT_REG 0x0998 | ||
| 177 | #define SXGBE_MMC_RXVLANHI_GBCNT_REG 0x099C | ||
| 178 | #define SXGBE_MMC_RXWATCHDOG_ERR_REG 0x09A0 | ||
| 179 | |||
| 180 | /* L3/L4 function registers */ | ||
| 181 | #define SXGBE_CORE_L34_ADDCTL_REG 0x0C00 | ||
| 182 | #define SXGBE_CORE_L34_ADDCTL_REG 0x0C00 | ||
| 183 | #define SXGBE_CORE_L34_DATA_REG 0x0C04 | ||
| 184 | |||
| 185 | /* ARP registers */ | ||
| 186 | #define SXGBE_CORE_ARP_ADD_REG 0x0C10 | ||
| 187 | |||
| 188 | /* RSS registers */ | ||
| 189 | #define SXGBE_CORE_RSS_CTL_REG 0x0C80 | ||
| 190 | #define SXGBE_CORE_RSS_ADD_REG 0x0C88 | ||
| 191 | #define SXGBE_CORE_RSS_DATA_REG 0x0C8C | ||
| 192 | |||
| 193 | /* IEEE 1588 registers */ | ||
| 194 | #define SXGBE_CORE_TSTAMP_CTL_REG 0x0D00 | ||
| 195 | #define SXGBE_CORE_SUBSEC_INC_REG 0x0D04 | ||
| 196 | #define SXGBE_CORE_SYSTIME_SEC_REG 0x0D0C | ||
| 197 | #define SXGBE_CORE_SYSTIME_NSEC_REG 0x0D10 | ||
| 198 | #define SXGBE_CORE_SYSTIME_SECUP_REG 0x0D14 | ||
| 199 | #define SXGBE_CORE_TSTAMP_ADD_REG 0x0D18 | ||
| 200 | #define SXGBE_CORE_SYSTIME_HWORD_REG 0x0D1C | ||
| 201 | #define SXGBE_CORE_TSTAMP_STATUS_REG 0x0D20 | ||
| 202 | #define SXGBE_CORE_TXTIME_STATUSNSEC_REG 0x0D30 | ||
| 203 | #define SXGBE_CORE_TXTIME_STATUSSEC_REG 0x0D34 | ||
| 204 | |||
| 205 | /* Auxiliary registers */ | ||
| 206 | #define SXGBE_CORE_AUX_CTL_REG 0x0D40 | ||
| 207 | #define SXGBE_CORE_AUX_TSTAMP_NSEC_REG 0x0D48 | ||
| 208 | #define SXGBE_CORE_AUX_TSTAMP_SEC_REG 0x0D4C | ||
| 209 | #define SXGBE_CORE_AUX_TSTAMP_INGCOR_REG 0x0D50 | ||
| 210 | #define SXGBE_CORE_AUX_TSTAMP_ENGCOR_REG 0x0D54 | ||
| 211 | #define SXGBE_CORE_AUX_TSTAMP_INGCOR_NSEC_REG 0x0D58 | ||
| 212 | #define SXGBE_CORE_AUX_TSTAMP_INGCOR_SUBNSEC_REG 0x0D5C | ||
| 213 | #define SXGBE_CORE_AUX_TSTAMP_ENGCOR_NSEC_REG 0x0D60 | ||
| 214 | #define SXGBE_CORE_AUX_TSTAMP_ENGCOR_SUBNSEC_REG 0x0D64 | ||
| 215 | |||
| 216 | /* PPS registers */ | ||
| 217 | #define SXGBE_CORE_PPS_CTL_REG 0x0D70 | ||
| 218 | #define SXGBE_CORE_PPS_BASE 0x0D80 | ||
| 219 | |||
| 220 | /* addr = 0 - 3 */ | ||
| 221 | #define SXGBE_CORE_PPS_TTIME_SEC_REG(addr) \ | ||
| 222 | (SXGBE_CORE_PPS_BASE + (0x10 * addr) + 0x0) | ||
| 223 | #define SXGBE_CORE_PPS_TTIME_NSEC_REG(addr) \ | ||
| 224 | (SXGBE_CORE_PPS_BASE + (0x10 * addr) + 0x4) | ||
| 225 | #define SXGBE_CORE_PPS_INTERVAL_REG(addr) \ | ||
| 226 | (SXGBE_CORE_PPS_BASE + (0x10 * addr) + 0x8) | ||
| 227 | #define SXGBE_CORE_PPS_WIDTH_REG(addr) \ | ||
| 228 | (SXGBE_CORE_PPS_BASE + (0x10 * addr) + 0xC) | ||
| 229 | #define SXGBE_CORE_PTO_CTL_REG 0x0DC0 | ||
| 230 | #define SXGBE_CORE_SRCPORT_ITY0_REG 0x0DC4 | ||
| 231 | #define SXGBE_CORE_SRCPORT_ITY1_REG 0x0DC8 | ||
| 232 | #define SXGBE_CORE_SRCPORT_ITY2_REG 0x0DCC | ||
| 233 | #define SXGBE_CORE_LOGMSG_LEVEL_REG 0x0DD0 | ||
| 234 | |||
| 235 | /* SXGBE MTL Registers */ | ||
| 236 | #define SXGBE_MTL_BASE_REG 0x1000 | ||
| 237 | #define SXGBE_MTL_OP_MODE_REG (SXGBE_MTL_BASE_REG + 0x0000) | ||
| 238 | #define SXGBE_MTL_DEBUG_CTL_REG (SXGBE_MTL_BASE_REG + 0x0008) | ||
| 239 | #define SXGBE_MTL_DEBUG_STATUS_REG (SXGBE_MTL_BASE_REG + 0x000C) | ||
| 240 | #define SXGBE_MTL_FIFO_DEBUGDATA_REG (SXGBE_MTL_BASE_REG + 0x0010) | ||
| 241 | #define SXGBE_MTL_INT_STATUS_REG (SXGBE_MTL_BASE_REG + 0x0020) | ||
| 242 | #define SXGBE_MTL_RXQ_DMAMAP0_REG (SXGBE_MTL_BASE_REG + 0x0030) | ||
| 243 | #define SXGBE_MTL_RXQ_DMAMAP1_REG (SXGBE_MTL_BASE_REG + 0x0034) | ||
| 244 | #define SXGBE_MTL_RXQ_DMAMAP2_REG (SXGBE_MTL_BASE_REG + 0x0038) | ||
| 245 | #define SXGBE_MTL_TX_PRTYMAP0_REG (SXGBE_MTL_BASE_REG + 0x0040) | ||
| 246 | #define SXGBE_MTL_TX_PRTYMAP1_REG (SXGBE_MTL_BASE_REG + 0x0044) | ||
| 247 | |||
| 248 | /* TC/Queue registers, qnum=0-15 */ | ||
| 249 | #define SXGBE_MTL_TC_TXBASE_REG (SXGBE_MTL_BASE_REG + 0x0100) | ||
| 250 | #define SXGBE_MTL_TXQ_OPMODE_REG(qnum) \ | ||
| 251 | (SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x00) | ||
| 252 | #define SXGBE_MTL_SFMODE BIT(1) | ||
| 253 | #define SXGBE_MTL_FIFO_LSHIFT 16 | ||
| 254 | #define SXGBE_MTL_ENABLE_QUEUE 0x00000008 | ||
| 255 | #define SXGBE_MTL_TXQ_UNDERFLOW_REG(qnum) \ | ||
| 256 | (SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x04) | ||
| 257 | #define SXGBE_MTL_TXQ_DEBUG_REG(qnum) \ | ||
| 258 | (SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x08) | ||
| 259 | #define SXGBE_MTL_TXQ_ETSCTL_REG(qnum) \ | ||
| 260 | (SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x10) | ||
| 261 | #define SXGBE_MTL_TXQ_ETSSTATUS_REG(qnum) \ | ||
| 262 | (SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x14) | ||
| 263 | #define SXGBE_MTL_TXQ_QUANTWEIGHT_REG(qnum) \ | ||
| 264 | (SXGBE_MTL_TC_TXBASE_REG + (qnum * 0x80) + 0x18) | ||
| 265 | |||
| 266 | #define SXGBE_MTL_TC_RXBASE_REG 0x1140 | ||
| 267 | #define SXGBE_RX_MTL_SFMODE BIT(5) | ||
| 268 | #define SXGBE_MTL_RXQ_OPMODE_REG(qnum) \ | ||
| 269 | (SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x00) | ||
| 270 | #define SXGBE_MTL_RXQ_MISPKTOVERFLOW_REG(qnum) \ | ||
| 271 | (SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x04) | ||
| 272 | #define SXGBE_MTL_RXQ_DEBUG_REG(qnum) \ | ||
| 273 | (SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x08) | ||
| 274 | #define SXGBE_MTL_RXQ_CTL_REG(qnum) \ | ||
| 275 | (SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x0C) | ||
| 276 | #define SXGBE_MTL_RXQ_INTENABLE_REG(qnum) \ | ||
| 277 | (SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x30) | ||
| 278 | #define SXGBE_MTL_RXQ_INTSTATUS_REG(qnum) \ | ||
| 279 | (SXGBE_MTL_TC_RXBASE_REG + (qnum * 0x80) + 0x34) | ||
| 280 | |||
| 281 | /* SXGBE DMA Registers */ | ||
| 282 | #define SXGBE_DMA_BASE_REG 0x3000 | ||
| 283 | #define SXGBE_DMA_MODE_REG (SXGBE_DMA_BASE_REG + 0x0000) | ||
| 284 | #define SXGBE_DMA_SOFT_RESET BIT(0) | ||
| 285 | #define SXGBE_DMA_SYSBUS_MODE_REG (SXGBE_DMA_BASE_REG + 0x0004) | ||
| 286 | #define SXGBE_DMA_AXI_UNDEF_BURST BIT(0) | ||
| 287 | #define SXGBE_DMA_ENHACE_ADDR_MODE BIT(11) | ||
| 288 | #define SXGBE_DMA_INT_STATUS_REG (SXGBE_DMA_BASE_REG + 0x0008) | ||
| 289 | #define SXGBE_DMA_AXI_ARCACHECTL_REG (SXGBE_DMA_BASE_REG + 0x0010) | ||
| 290 | #define SXGBE_DMA_AXI_AWCACHECTL_REG (SXGBE_DMA_BASE_REG + 0x0018) | ||
| 291 | #define SXGBE_DMA_DEBUG_STATUS0_REG (SXGBE_DMA_BASE_REG + 0x0020) | ||
| 292 | #define SXGBE_DMA_DEBUG_STATUS1_REG (SXGBE_DMA_BASE_REG + 0x0024) | ||
| 293 | #define SXGBE_DMA_DEBUG_STATUS2_REG (SXGBE_DMA_BASE_REG + 0x0028) | ||
| 294 | #define SXGBE_DMA_DEBUG_STATUS3_REG (SXGBE_DMA_BASE_REG + 0x002C) | ||
| 295 | #define SXGBE_DMA_DEBUG_STATUS4_REG (SXGBE_DMA_BASE_REG + 0x0030) | ||
| 296 | #define SXGBE_DMA_DEBUG_STATUS5_REG (SXGBE_DMA_BASE_REG + 0x0034) | ||
| 297 | |||
| 298 | /* Channel Registers, cha_num = 0-15 */ | ||
| 299 | #define SXGBE_DMA_CHA_BASE_REG \ | ||
| 300 | (SXGBE_DMA_BASE_REG + 0x0100) | ||
| 301 | #define SXGBE_DMA_CHA_CTL_REG(cha_num) \ | ||
| 302 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x00) | ||
| 303 | #define SXGBE_DMA_PBL_X8MODE BIT(16) | ||
| 304 | #define SXGBE_DMA_CHA_TXCTL_TSE_ENABLE BIT(12) | ||
| 305 | #define SXGBE_DMA_CHA_TXCTL_REG(cha_num) \ | ||
| 306 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x04) | ||
| 307 | #define SXGBE_DMA_CHA_RXCTL_REG(cha_num) \ | ||
| 308 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x08) | ||
| 309 | #define SXGBE_DMA_CHA_TXDESC_HADD_REG(cha_num) \ | ||
| 310 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x10) | ||
| 311 | #define SXGBE_DMA_CHA_TXDESC_LADD_REG(cha_num) \ | ||
| 312 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x14) | ||
| 313 | #define SXGBE_DMA_CHA_RXDESC_HADD_REG(cha_num) \ | ||
| 314 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x18) | ||
| 315 | #define SXGBE_DMA_CHA_RXDESC_LADD_REG(cha_num) \ | ||
| 316 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x1C) | ||
| 317 | #define SXGBE_DMA_CHA_TXDESC_TAILPTR_REG(cha_num) \ | ||
| 318 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x24) | ||
| 319 | #define SXGBE_DMA_CHA_RXDESC_TAILPTR_REG(cha_num) \ | ||
| 320 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x2C) | ||
| 321 | #define SXGBE_DMA_CHA_TXDESC_RINGLEN_REG(cha_num) \ | ||
| 322 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x30) | ||
| 323 | #define SXGBE_DMA_CHA_RXDESC_RINGLEN_REG(cha_num) \ | ||
| 324 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x34) | ||
| 325 | #define SXGBE_DMA_CHA_INT_ENABLE_REG(cha_num) \ | ||
| 326 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x38) | ||
| 327 | #define SXGBE_DMA_CHA_INT_RXWATCHTMR_REG(cha_num) \ | ||
| 328 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x3C) | ||
| 329 | #define SXGBE_DMA_CHA_TXDESC_CURADDLO_REG(cha_num) \ | ||
| 330 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x44) | ||
| 331 | #define SXGBE_DMA_CHA_RXDESC_CURADDLO_REG(cha_num) \ | ||
| 332 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x4C) | ||
| 333 | #define SXGBE_DMA_CHA_CURTXBUF_ADDHI_REG(cha_num) \ | ||
| 334 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x50) | ||
| 335 | #define SXGBE_DMA_CHA_CURTXBUF_ADDLO_REG(cha_num) \ | ||
| 336 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x54) | ||
| 337 | #define SXGBE_DMA_CHA_CURRXBUF_ADDHI_REG(cha_num) \ | ||
| 338 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x58) | ||
| 339 | #define SXGBE_DMA_CHA_CURRXBUF_ADDLO_REG(cha_num) \ | ||
| 340 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x5C) | ||
| 341 | #define SXGBE_DMA_CHA_STATUS_REG(cha_num) \ | ||
| 342 | (SXGBE_DMA_CHA_BASE_REG + (cha_num * 0x80) + 0x60) | ||
| 343 | |||
| 344 | /* TX DMA control register specific */ | ||
| 345 | #define SXGBE_TX_START_DMA BIT(0) | ||
| 346 | |||
| 347 | /* sxgbe tx configuration register bitfields */ | ||
| 348 | #define SXGBE_SPEED_10G 0x0 | ||
| 349 | #define SXGBE_SPEED_2_5G 0x1 | ||
| 350 | #define SXGBE_SPEED_1G 0x2 | ||
| 351 | #define SXGBE_SPEED_LSHIFT 29 | ||
| 352 | |||
| 353 | #define SXGBE_TX_ENABLE BIT(0) | ||
| 354 | #define SXGBE_TX_DISDIC_ALGO BIT(1) | ||
| 355 | #define SXGBE_TX_JABBER_DISABLE BIT(16) | ||
| 356 | |||
| 357 | /* sxgbe rx configuration register bitfields */ | ||
| 358 | #define SXGBE_RX_ENABLE BIT(0) | ||
| 359 | #define SXGBE_RX_ACS_ENABLE BIT(1) | ||
| 360 | #define SXGBE_RX_WATCHDOG_DISABLE BIT(7) | ||
| 361 | #define SXGBE_RX_JUMBPKT_ENABLE BIT(8) | ||
| 362 | #define SXGBE_RX_CSUMOFFLOAD_ENABLE BIT(9) | ||
| 363 | #define SXGBE_RX_LOOPBACK_ENABLE BIT(10) | ||
| 364 | #define SXGBE_RX_ARPOFFLOAD_ENABLE BIT(31) | ||
| 365 | |||
| 366 | /* sxgbe vlan Tag Register bitfields */ | ||
| 367 | #define SXGBE_VLAN_SVLAN_ENABLE BIT(18) | ||
| 368 | #define SXGBE_VLAN_DOUBLEVLAN_ENABLE BIT(26) | ||
| 369 | #define SXGBE_VLAN_INNERVLAN_ENABLE BIT(27) | ||
| 370 | |||
| 371 | /* XMAC VLAN Tag Inclusion Register(0x0060) bitfields | ||
| 372 | * Below fields same for Inner VLAN Tag Inclusion | ||
| 373 | * Register(0x0064) register | ||
| 374 | */ | ||
| 375 | enum vlan_tag_ctl_tx { | ||
| 376 | VLAN_TAG_TX_NOP, | ||
| 377 | VLAN_TAG_TX_DEL, | ||
| 378 | VLAN_TAG_TX_INSERT, | ||
| 379 | VLAN_TAG_TX_REPLACE | ||
| 380 | }; | ||
| 381 | #define SXGBE_VLAN_PRTY_CTL BIT(18) | ||
| 382 | #define SXGBE_VLAN_CSVL_CTL BIT(19) | ||
| 383 | |||
| 384 | /* SXGBE TX Q Flow Control Register bitfields */ | ||
| 385 | #define SXGBE_TX_FLOW_CTL_FCB BIT(0) | ||
| 386 | #define SXGBE_TX_FLOW_CTL_TFB BIT(1) | ||
| 387 | |||
| 388 | /* SXGBE RX Q Flow Control Register bitfields */ | ||
| 389 | #define SXGBE_RX_FLOW_CTL_ENABLE BIT(0) | ||
| 390 | #define SXGBE_RX_UNICAST_DETECT BIT(1) | ||
| 391 | #define SXGBE_RX_PRTYFLOW_CTL_ENABLE BIT(8) | ||
| 392 | |||
| 393 | /* sxgbe rx Q control0 register bitfields */ | ||
| 394 | #define SXGBE_RX_Q_ENABLE 0x2 | ||
| 395 | |||
| 396 | /* SXGBE hardware features bitfield specific */ | ||
| 397 | /* Capability Register 0 */ | ||
| 398 | #define SXGBE_HW_FEAT_GMII(cap) ((cap & 0x00000002) >> 1) | ||
| 399 | #define SXGBE_HW_FEAT_VLAN_HASH_FILTER(cap) ((cap & 0x00000010) >> 4) | ||
| 400 | #define SXGBE_HW_FEAT_SMA(cap) ((cap & 0x00000020) >> 5) | ||
| 401 | #define SXGBE_HW_FEAT_PMT_TEMOTE_WOP(cap) ((cap & 0x00000040) >> 6) | ||
| 402 | #define SXGBE_HW_FEAT_PMT_MAGIC_PKT(cap) ((cap & 0x00000080) >> 7) | ||
| 403 | #define SXGBE_HW_FEAT_RMON(cap) ((cap & 0x00000100) >> 8) | ||
| 404 | #define SXGBE_HW_FEAT_ARP_OFFLOAD(cap) ((cap & 0x00000200) >> 9) | ||
| 405 | #define SXGBE_HW_FEAT_IEEE1500_2008(cap) ((cap & 0x00001000) >> 12) | ||
| 406 | #define SXGBE_HW_FEAT_EEE(cap) ((cap & 0x00002000) >> 13) | ||
| 407 | #define SXGBE_HW_FEAT_TX_CSUM_OFFLOAD(cap) ((cap & 0x00004000) >> 14) | ||
| 408 | #define SXGBE_HW_FEAT_RX_CSUM_OFFLOAD(cap) ((cap & 0x00010000) >> 16) | ||
| 409 | #define SXGBE_HW_FEAT_MACADDR_COUNT(cap) ((cap & 0x007C0000) >> 18) | ||
| 410 | #define SXGBE_HW_FEAT_TSTMAP_SRC(cap) ((cap & 0x06000000) >> 25) | ||
| 411 | #define SXGBE_HW_FEAT_SRCADDR_VLAN(cap) ((cap & 0x08000000) >> 27) | ||
| 412 | |||
| 413 | /* Capability Register 1 */ | ||
| 414 | #define SXGBE_HW_FEAT_RX_FIFO_SIZE(cap) ((cap & 0x0000001F)) | ||
| 415 | #define SXGBE_HW_FEAT_TX_FIFO_SIZE(cap) ((cap & 0x000007C0) >> 6) | ||
| 416 | #define SXGBE_HW_FEAT_IEEE1588_HWORD(cap) ((cap & 0x00002000) >> 13) | ||
| 417 | #define SXGBE_HW_FEAT_DCB(cap) ((cap & 0x00010000) >> 16) | ||
| 418 | #define SXGBE_HW_FEAT_SPLIT_HDR(cap) ((cap & 0x00020000) >> 17) | ||
| 419 | #define SXGBE_HW_FEAT_TSO(cap) ((cap & 0x00040000) >> 18) | ||
| 420 | #define SXGBE_HW_FEAT_DEBUG_MEM_IFACE(cap) ((cap & 0x00080000) >> 19) | ||
| 421 | #define SXGBE_HW_FEAT_RSS(cap) ((cap & 0x00100000) >> 20) | ||
| 422 | #define SXGBE_HW_FEAT_HASH_TABLE_SIZE(cap) ((cap & 0x03000000) >> 24) | ||
| 423 | #define SXGBE_HW_FEAT_L3L4_FILTER_NUM(cap) ((cap & 0x78000000) >> 27) | ||
| 424 | |||
| 425 | /* Capability Register 2 */ | ||
| 426 | #define SXGBE_HW_FEAT_RX_MTL_QUEUES(cap) ((cap & 0x0000000F)) | ||
| 427 | #define SXGBE_HW_FEAT_TX_MTL_QUEUES(cap) ((cap & 0x000003C0) >> 6) | ||
| 428 | #define SXGBE_HW_FEAT_RX_DMA_CHANNELS(cap) ((cap & 0x0000F000) >> 12) | ||
| 429 | #define SXGBE_HW_FEAT_TX_DMA_CHANNELS(cap) ((cap & 0x003C0000) >> 18) | ||
| 430 | #define SXGBE_HW_FEAT_PPS_OUTPUTS(cap) ((cap & 0x07000000) >> 24) | ||
| 431 | #define SXGBE_HW_FEAT_AUX_SNAPSHOTS(cap) ((cap & 0x70000000) >> 28) | ||
| 432 | |||
| 433 | /* DMAchannel interrupt enable specific */ | ||
| 434 | /* DMA Normal interrupt */ | ||
| 435 | #define SXGBE_DMA_INT_ENA_NIE BIT(16) /* Normal Summary */ | ||
| 436 | #define SXGBE_DMA_INT_ENA_TIE BIT(0) /* Transmit Interrupt */ | ||
| 437 | #define SXGBE_DMA_INT_ENA_TUE BIT(2) /* Transmit Buffer Unavailable */ | ||
| 438 | #define SXGBE_DMA_INT_ENA_RIE BIT(6) /* Receive Interrupt */ | ||
| 439 | |||
| 440 | #define SXGBE_DMA_INT_NORMAL \ | ||
| 441 | (SXGBE_DMA_INT_ENA_NIE | SXGBE_DMA_INT_ENA_RIE | \ | ||
| 442 | SXGBE_DMA_INT_ENA_TIE | SXGBE_DMA_INT_ENA_TUE) | ||
| 443 | |||
| 444 | /* DMA Abnormal interrupt */ | ||
| 445 | #define SXGBE_DMA_INT_ENA_AIE BIT(15) /* Abnormal Summary */ | ||
| 446 | #define SXGBE_DMA_INT_ENA_TSE BIT(1) /* Transmit Stopped */ | ||
| 447 | #define SXGBE_DMA_INT_ENA_RUE BIT(7) /* Receive Buffer Unavailable */ | ||
| 448 | #define SXGBE_DMA_INT_ENA_RSE BIT(8) /* Receive Stopped */ | ||
| 449 | #define SXGBE_DMA_INT_ENA_FBE BIT(12) /* Fatal Bus Error */ | ||
| 450 | #define SXGBE_DMA_INT_ENA_CDEE BIT(13) /* Context Descriptor Error */ | ||
| 451 | |||
| 452 | #define SXGBE_DMA_INT_ABNORMAL \ | ||
| 453 | (SXGBE_DMA_INT_ENA_AIE | SXGBE_DMA_INT_ENA_TSE | \ | ||
| 454 | SXGBE_DMA_INT_ENA_RUE | SXGBE_DMA_INT_ENA_RSE | \ | ||
| 455 | SXGBE_DMA_INT_ENA_FBE | SXGBE_DMA_INT_ENA_CDEE) | ||
| 456 | |||
| 457 | #define SXGBE_DMA_ENA_INT (SXGBE_DMA_INT_NORMAL | SXGBE_DMA_INT_ABNORMAL) | ||
| 458 | |||
| 459 | /* DMA channel interrupt status specific */ | ||
| 460 | #define SXGBE_DMA_INT_STATUS_REB2 BIT(21) | ||
| 461 | #define SXGBE_DMA_INT_STATUS_REB1 BIT(20) | ||
| 462 | #define SXGBE_DMA_INT_STATUS_REB0 BIT(19) | ||
| 463 | #define SXGBE_DMA_INT_STATUS_TEB2 BIT(18) | ||
| 464 | #define SXGBE_DMA_INT_STATUS_TEB1 BIT(17) | ||
| 465 | #define SXGBE_DMA_INT_STATUS_TEB0 BIT(16) | ||
| 466 | #define SXGBE_DMA_INT_STATUS_NIS BIT(15) | ||
| 467 | #define SXGBE_DMA_INT_STATUS_AIS BIT(14) | ||
| 468 | #define SXGBE_DMA_INT_STATUS_CTXTERR BIT(13) | ||
| 469 | #define SXGBE_DMA_INT_STATUS_FBE BIT(12) | ||
| 470 | #define SXGBE_DMA_INT_STATUS_RPS BIT(8) | ||
| 471 | #define SXGBE_DMA_INT_STATUS_RBU BIT(7) | ||
| 472 | #define SXGBE_DMA_INT_STATUS_RI BIT(6) | ||
| 473 | #define SXGBE_DMA_INT_STATUS_TBU BIT(2) | ||
| 474 | #define SXGBE_DMA_INT_STATUS_TPS BIT(1) | ||
| 475 | #define SXGBE_DMA_INT_STATUS_TI BIT(0) | ||
| 476 | |||
| 477 | #endif /* __SXGBE_REGMAP_H__ */ | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c new file mode 100644 index 000000000000..51c32194ba88 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Siva Reddy Kallam <siva.kallam@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #include <linux/bitops.h> | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/netdevice.h> | ||
| 15 | #include <linux/phy.h> | ||
| 16 | #include "sxgbe_common.h" | ||
| 17 | #include "sxgbe_xpcs.h" | ||
| 18 | |||
| 19 | static int sxgbe_xpcs_read(struct net_device *ndev, unsigned int reg) | ||
| 20 | { | ||
| 21 | u32 value; | ||
| 22 | struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||
| 23 | |||
| 24 | value = readl(priv->ioaddr + XPCS_OFFSET + reg); | ||
| 25 | |||
| 26 | return value; | ||
| 27 | } | ||
| 28 | |||
| 29 | static int sxgbe_xpcs_write(struct net_device *ndev, int reg, int data) | ||
| 30 | { | ||
| 31 | struct sxgbe_priv_data *priv = netdev_priv(ndev); | ||
| 32 | |||
| 33 | writel(data, priv->ioaddr + XPCS_OFFSET + reg); | ||
| 34 | |||
| 35 | return 0; | ||
| 36 | } | ||
| 37 | |||
| 38 | int sxgbe_xpcs_init(struct net_device *ndev) | ||
| 39 | { | ||
| 40 | u32 value; | ||
| 41 | |||
| 42 | value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||
| 43 | /* 10G XAUI mode */ | ||
| 44 | sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X); | ||
| 45 | sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE); | ||
| 46 | sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, value | BIT(13)); | ||
| 47 | sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11)); | ||
| 48 | |||
| 49 | do { | ||
| 50 | value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS); | ||
| 51 | } while ((value & XPCS_QSEQ_STATE_MPLLOFF) == XPCS_QSEQ_STATE_STABLE); | ||
| 52 | |||
| 53 | value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||
| 54 | sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11)); | ||
| 55 | |||
| 56 | do { | ||
| 57 | value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS); | ||
| 58 | } while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE); | ||
| 59 | |||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | int sxgbe_xpcs_init_1G(struct net_device *ndev) | ||
| 64 | { | ||
| 65 | int value; | ||
| 66 | |||
| 67 | /* 10GBASE-X PCS (1G) mode */ | ||
| 68 | sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X); | ||
| 69 | sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE); | ||
| 70 | value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||
| 71 | sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(13)); | ||
| 72 | |||
| 73 | value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL); | ||
| 74 | sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(6)); | ||
| 75 | sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value & ~BIT(13)); | ||
| 76 | value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||
| 77 | sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11)); | ||
| 78 | |||
| 79 | do { | ||
| 80 | value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS); | ||
| 81 | } while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE); | ||
| 82 | |||
| 83 | value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1); | ||
| 84 | sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11)); | ||
| 85 | |||
| 86 | /* Auto Negotiation cluase 37 enable */ | ||
| 87 | value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL); | ||
| 88 | sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(12)); | ||
| 89 | |||
| 90 | return 0; | ||
| 91 | } | ||
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h new file mode 100644 index 000000000000..6b26a50724d3 --- /dev/null +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | /* 10G controller driver for Samsung SoCs | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 Samsung Electronics Co., Ltd. | ||
| 4 | * http://www.samsung.com | ||
| 5 | * | ||
| 6 | * Author: Byungho An <bh74.an@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | */ | ||
| 12 | #ifndef __SXGBE_XPCS_H__ | ||
| 13 | #define __SXGBE_XPCS_H__ | ||
| 14 | |||
| 15 | /* XPCS Registers */ | ||
| 16 | #define XPCS_OFFSET 0x1A060000 | ||
| 17 | #define SR_PCS_MMD_CONTROL1 0x030000 | ||
| 18 | #define SR_PCS_CONTROL2 0x030007 | ||
| 19 | #define VR_PCS_MMD_XAUI_MODE_CONTROL 0x038004 | ||
| 20 | #define VR_PCS_MMD_DIGITAL_STATUS 0x038010 | ||
| 21 | #define SR_MII_MMD_CONTROL 0x1F0000 | ||
| 22 | #define SR_MII_MMD_AN_ADV 0x1F0004 | ||
| 23 | #define SR_MII_MMD_AN_LINK_PARTNER_BA 0x1F0005 | ||
| 24 | #define VR_MII_MMD_AN_CONTROL 0x1F8001 | ||
| 25 | #define VR_MII_MMD_AN_INT_STATUS 0x1F8002 | ||
| 26 | |||
| 27 | #define XPCS_QSEQ_STATE_STABLE 0x10 | ||
| 28 | #define XPCS_QSEQ_STATE_MPLLOFF 0x1c | ||
| 29 | #define XPCS_TYPE_SEL_R 0x00 | ||
| 30 | #define XPCS_TYPE_SEL_X 0x01 | ||
| 31 | #define XPCS_TYPE_SEL_W 0x02 | ||
| 32 | #define XPCS_XAUI_MODE 0x00 | ||
| 33 | #define XPCS_RXAUI_MODE 0x01 | ||
| 34 | |||
| 35 | int sxgbe_xpcs_init(struct net_device *ndev); | ||
| 36 | int sxgbe_xpcs_init_1G(struct net_device *ndev); | ||
| 37 | |||
| 38 | #endif /* __SXGBE_XPCS_H__ */ | ||
