You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
net: emac: emac gigabit ethernet controller driver
Add support for the Qualcomm Technologies, Inc. EMAC gigabit Ethernet controller. This driver supports the following features: 1) Checksum offload. 2) Interrupt coalescing support. 3) SGMII phy. 4) phylib interface for external phy Based on original work by Niranjana Vishwanathapura <nvishwan@codeaurora.org> Gilad Avidov <gavidov@codeaurora.org> Signed-off-by: Timur Tabi <timur@codeaurora.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
04bed1434d
commit
b9b17debc6
111
Documentation/devicetree/bindings/net/qcom-emac.txt
Normal file
111
Documentation/devicetree/bindings/net/qcom-emac.txt
Normal file
@@ -0,0 +1,111 @@
|
||||
Qualcomm Technologies EMAC Gigabit Ethernet Controller
|
||||
|
||||
This network controller consists of two devices: a MAC and an SGMII
|
||||
internal PHY. Each device is represented by a device tree node. A phandle
|
||||
connects the MAC node to its corresponding internal phy node. Another
|
||||
phandle points to the external PHY node.
|
||||
|
||||
Required properties:
|
||||
|
||||
MAC node:
|
||||
- compatible : Should be "qcom,fsm9900-emac".
|
||||
- reg : Offset and length of the register regions for the device
|
||||
- interrupts : Interrupt number used by this controller
|
||||
- mac-address : The 6-byte MAC address. If present, it is the default
|
||||
MAC address.
|
||||
- internal-phy : phandle to the internal PHY node
|
||||
- phy-handle : phandle the the external PHY node
|
||||
|
||||
Internal PHY node:
|
||||
- compatible : Should be "qcom,fsm9900-emac-sgmii" or "qcom,qdf2432-emac-sgmii".
|
||||
- reg : Offset and length of the register region(s) for the device
|
||||
- interrupts : Interrupt number used by this controller
|
||||
|
||||
The external phy child node:
|
||||
- reg : The phy address
|
||||
|
||||
Example:
|
||||
|
||||
FSM9900:
|
||||
|
||||
soc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
emac0: ethernet@feb20000 {
|
||||
compatible = "qcom,fsm9900-emac";
|
||||
reg = <0xfeb20000 0x10000>,
|
||||
<0xfeb36000 0x1000>;
|
||||
interrupts = <76>;
|
||||
|
||||
clocks = <&gcc 0>, <&gcc 1>, <&gcc 3>, <&gcc 4>, <&gcc 5>,
|
||||
<&gcc 6>, <&gcc 7>;
|
||||
clock-names = "axi_clk", "cfg_ahb_clk", "high_speed_clk",
|
||||
"mdio_clk", "tx_clk", "rx_clk", "sys_clk";
|
||||
|
||||
internal-phy = <&emac_sgmii>;
|
||||
|
||||
phy-handle = <&phy0>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: ethernet-phy@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mdio_pins_a>;
|
||||
};
|
||||
|
||||
emac_sgmii: ethernet@feb38000 {
|
||||
compatible = "qcom,fsm9900-emac-sgmii";
|
||||
reg = <0xfeb38000 0x1000>;
|
||||
interrupts = <80>;
|
||||
};
|
||||
|
||||
tlmm: pinctrl@fd510000 {
|
||||
compatible = "qcom,fsm9900-pinctrl";
|
||||
|
||||
mdio_pins_a: mdio {
|
||||
state {
|
||||
pins = "gpio123", "gpio124";
|
||||
function = "mdio";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
QDF2432:
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
emac0: ethernet@38800000 {
|
||||
compatible = "qcom,fsm9900-emac";
|
||||
reg = <0x0 0x38800000 0x0 0x10000>,
|
||||
<0x0 0x38816000 0x0 0x1000>;
|
||||
interrupts = <0 256 4>;
|
||||
|
||||
clocks = <&gcc 0>, <&gcc 1>, <&gcc 3>, <&gcc 4>, <&gcc 5>,
|
||||
<&gcc 6>, <&gcc 7>;
|
||||
clock-names = "axi_clk", "cfg_ahb_clk", "high_speed_clk",
|
||||
"mdio_clk", "tx_clk", "rx_clk", "sys_clk";
|
||||
|
||||
internal-phy = <&emac_sgmii>;
|
||||
|
||||
phy-handle = <&phy0>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
phy0: ethernet-phy@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
emac_sgmii: ethernet@410400 {
|
||||
compatible = "qcom,qdf2432-emac-sgmii";
|
||||
reg = <0x0 0x00410400 0x0 0xc00>, /* Base address */
|
||||
<0x0 0x00410000 0x0 0x400>; /* Per-lane digital */
|
||||
interrupts = <0 254 1>;
|
||||
};
|
||||
@@ -9696,6 +9696,12 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
|
||||
S: Supported
|
||||
F: drivers/net/wireless/ath/ath10k/
|
||||
|
||||
QUALCOMM EMAC GIGABIT ETHERNET DRIVER
|
||||
M: Timur Tabi <timur@codeaurora.org>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/ethernet/qualcomm/emac/
|
||||
|
||||
QUALCOMM HEXAGON ARCHITECTURE
|
||||
M: Richard Kuo <rkuo@codeaurora.org>
|
||||
L: linux-hexagon@vger.kernel.org
|
||||
|
||||
@@ -24,4 +24,16 @@ config QCA7000
|
||||
To compile this driver as a module, choose M here. The module
|
||||
will be called qcaspi.
|
||||
|
||||
config QCOM_EMAC
|
||||
tristate "Qualcomm Technologies, Inc. EMAC Gigabit Ethernet support"
|
||||
select CRC32
|
||||
select PHYLIB
|
||||
---help---
|
||||
This driver supports the Qualcomm Technologies, Inc. Gigabit
|
||||
Ethernet Media Access Controller (EMAC). The controller
|
||||
supports IEEE 802.3-2002, half-duplex mode at 10/100 Mb/s,
|
||||
full-duplex mode at 10/100/1000Mb/s, Wake On LAN (WOL) for
|
||||
low power, Receive-Side Scaling (RSS), and IEEE 1588-2008
|
||||
Precision Clock Synchronization Protocol.
|
||||
|
||||
endif # NET_VENDOR_QUALCOMM
|
||||
|
||||
@@ -4,3 +4,5 @@
|
||||
|
||||
obj-$(CONFIG_QCA7000) += qcaspi.o
|
||||
qcaspi-objs := qca_spi.o qca_framing.o qca_7k.o qca_debug.o
|
||||
|
||||
obj-y += emac/
|
||||
|
||||
7
drivers/net/ethernet/qualcomm/emac/Makefile
Normal file
7
drivers/net/ethernet/qualcomm/emac/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Makefile for the Qualcomm Technologies, Inc. EMAC Gigabit Ethernet driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_QCOM_EMAC) += qcom-emac.o
|
||||
|
||||
qcom-emac-objs := emac.o emac-mac.o emac-phy.o emac-sgmii.o
|
||||
1528
drivers/net/ethernet/qualcomm/emac/emac-mac.c
Normal file
1528
drivers/net/ethernet/qualcomm/emac/emac-mac.c
Normal file
File diff suppressed because it is too large
Load Diff
248
drivers/net/ethernet/qualcomm/emac/emac-mac.h
Normal file
248
drivers/net/ethernet/qualcomm/emac/emac-mac.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/* EMAC DMA HW engine uses three rings:
|
||||
* Tx:
|
||||
* TPD: Transmit Packet Descriptor ring.
|
||||
* Rx:
|
||||
* RFD: Receive Free Descriptor ring.
|
||||
* Ring of descriptors with empty buffers to be filled by Rx HW.
|
||||
* RRD: Receive Return Descriptor ring.
|
||||
* Ring of descriptors with buffers filled with received data.
|
||||
*/
|
||||
|
||||
#ifndef _EMAC_HW_H_
|
||||
#define _EMAC_HW_H_
|
||||
|
||||
/* EMAC_CSR register offsets */
|
||||
#define EMAC_EMAC_WRAPPER_CSR1 0x000000
|
||||
#define EMAC_EMAC_WRAPPER_CSR2 0x000004
|
||||
#define EMAC_EMAC_WRAPPER_TX_TS_LO 0x000104
|
||||
#define EMAC_EMAC_WRAPPER_TX_TS_HI 0x000108
|
||||
#define EMAC_EMAC_WRAPPER_TX_TS_INX 0x00010c
|
||||
|
||||
/* DMA Order Settings */
|
||||
enum emac_dma_order {
|
||||
emac_dma_ord_in = 1,
|
||||
emac_dma_ord_enh = 2,
|
||||
emac_dma_ord_out = 4
|
||||
};
|
||||
|
||||
enum emac_dma_req_block {
|
||||
emac_dma_req_128 = 0,
|
||||
emac_dma_req_256 = 1,
|
||||
emac_dma_req_512 = 2,
|
||||
emac_dma_req_1024 = 3,
|
||||
emac_dma_req_2048 = 4,
|
||||
emac_dma_req_4096 = 5
|
||||
};
|
||||
|
||||
/* Returns the value of bits idx...idx+n_bits */
|
||||
#define BITS_GET(val, lo, hi) ((le32_to_cpu(val) & GENMASK((hi), (lo))) >> lo)
|
||||
#define BITS_SET(val, lo, hi, new_val) \
|
||||
val = cpu_to_le32((le32_to_cpu(val) & (~GENMASK((hi), (lo)))) | \
|
||||
(((new_val) << (lo)) & GENMASK((hi), (lo))))
|
||||
|
||||
/* RRD (Receive Return Descriptor) */
|
||||
struct emac_rrd {
|
||||
u32 word[6];
|
||||
|
||||
/* number of RFD */
|
||||
#define RRD_NOR(rrd) BITS_GET((rrd)->word[0], 16, 19)
|
||||
/* start consumer index of rfd-ring */
|
||||
#define RRD_SI(rrd) BITS_GET((rrd)->word[0], 20, 31)
|
||||
/* vlan-tag (CVID, CFI and PRI) */
|
||||
#define RRD_CVALN_TAG(rrd) BITS_GET((rrd)->word[2], 0, 15)
|
||||
/* length of the packet */
|
||||
#define RRD_PKT_SIZE(rrd) BITS_GET((rrd)->word[3], 0, 13)
|
||||
/* L4(TCP/UDP) checksum failed */
|
||||
#define RRD_L4F(rrd) BITS_GET((rrd)->word[3], 14, 14)
|
||||
/* vlan tagged */
|
||||
#define RRD_CVTAG(rrd) BITS_GET((rrd)->word[3], 16, 16)
|
||||
/* When set, indicates that the descriptor is updated by the IP core.
|
||||
* When cleared, indicates that the descriptor is invalid.
|
||||
*/
|
||||
#define RRD_UPDT(rrd) BITS_GET((rrd)->word[3], 31, 31)
|
||||
#define RRD_UPDT_SET(rrd, val) BITS_SET((rrd)->word[3], 31, 31, val)
|
||||
/* timestamp low */
|
||||
#define RRD_TS_LOW(rrd) BITS_GET((rrd)->word[4], 0, 29)
|
||||
/* timestamp high */
|
||||
#define RRD_TS_HI(rrd) le32_to_cpu((rrd)->word[5])
|
||||
};
|
||||
|
||||
/* TPD (Transmit Packet Descriptor) */
|
||||
struct emac_tpd {
|
||||
u32 word[4];
|
||||
|
||||
/* Number of bytes of the transmit packet. (include 4-byte CRC) */
|
||||
#define TPD_BUF_LEN_SET(tpd, val) BITS_SET((tpd)->word[0], 0, 15, val)
|
||||
/* Custom Checksum Offload: When set, ask IP core to offload custom checksum */
|
||||
#define TPD_CSX_SET(tpd, val) BITS_SET((tpd)->word[1], 8, 8, val)
|
||||
/* TCP Large Send Offload: When set, ask IP core to do offload TCP Large Send */
|
||||
#define TPD_LSO(tpd) BITS_GET((tpd)->word[1], 12, 12)
|
||||
#define TPD_LSO_SET(tpd, val) BITS_SET((tpd)->word[1], 12, 12, val)
|
||||
/* Large Send Offload Version: When set, indicates this is an LSOv2
|
||||
* (for both IPv4 and IPv6). When cleared, indicates this is an LSOv1
|
||||
* (only for IPv4).
|
||||
*/
|
||||
#define TPD_LSOV_SET(tpd, val) BITS_SET((tpd)->word[1], 13, 13, val)
|
||||
/* IPv4 packet: When set, indicates this is an IPv4 packet, this bit is only
|
||||
* for LSOV2 format.
|
||||
*/
|
||||
#define TPD_IPV4_SET(tpd, val) BITS_SET((tpd)->word[1], 16, 16, val)
|
||||
/* 0: Ethernet frame (DA+SA+TYPE+DATA+CRC)
|
||||
* 1: IEEE 802.3 frame (DA+SA+LEN+DSAP+SSAP+CTL+ORG+TYPE+DATA+CRC)
|
||||
*/
|
||||
#define TPD_TYP_SET(tpd, val) BITS_SET((tpd)->word[1], 17, 17, val)
|
||||
/* Low-32bit Buffer Address */
|
||||
#define TPD_BUFFER_ADDR_L_SET(tpd, val) ((tpd)->word[2] = cpu_to_le32(val))
|
||||
/* CVLAN Tag to be inserted if INS_VLAN_TAG is set, CVLAN TPID based on global
|
||||
* register configuration.
|
||||
*/
|
||||
#define TPD_CVLAN_TAG_SET(tpd, val) BITS_SET((tpd)->word[3], 0, 15, val)
|
||||
/* Insert CVlan Tag: When set, ask MAC to insert CVLAN TAG to outgoing packet
|
||||
*/
|
||||
#define TPD_INSTC_SET(tpd, val) BITS_SET((tpd)->word[3], 17, 17, val)
|
||||
/* High-14bit Buffer Address, So, the 64b-bit address is
|
||||
* {DESC_CTRL_11_TX_DATA_HIADDR[17:0],(register) BUFFER_ADDR_H, BUFFER_ADDR_L}
|
||||
*/
|
||||
#define TPD_BUFFER_ADDR_H_SET(tpd, val) BITS_SET((tpd)->word[3], 18, 30, val)
|
||||
/* Format D. Word offset from the 1st byte of this packet to start to calculate
|
||||
* the custom checksum.
|
||||
*/
|
||||
#define TPD_PAYLOAD_OFFSET_SET(tpd, val) BITS_SET((tpd)->word[1], 0, 7, val)
|
||||
/* Format D. Word offset from the 1st byte of this packet to fill the custom
|
||||
* checksum to
|
||||
*/
|
||||
#define TPD_CXSUM_OFFSET_SET(tpd, val) BITS_SET((tpd)->word[1], 18, 25, val)
|
||||
|
||||
/* Format C. TCP Header offset from the 1st byte of this packet. (byte unit) */
|
||||
#define TPD_TCPHDR_OFFSET_SET(tpd, val) BITS_SET((tpd)->word[1], 0, 7, val)
|
||||
/* Format C. MSS (Maximum Segment Size) got from the protocol layer. (byte unit)
|
||||
*/
|
||||
#define TPD_MSS_SET(tpd, val) BITS_SET((tpd)->word[1], 18, 30, val)
|
||||
/* packet length in ext tpd */
|
||||
#define TPD_PKT_LEN_SET(tpd, val) ((tpd)->word[2] = cpu_to_le32(val))
|
||||
};
|
||||
|
||||
/* emac_ring_header represents a single, contiguous block of DMA space
|
||||
* mapped for the three descriptor rings (tpd, rfd, rrd)
|
||||
*/
|
||||
struct emac_ring_header {
|
||||
void *v_addr; /* virtual address */
|
||||
dma_addr_t dma_addr; /* dma address */
|
||||
size_t size; /* length in bytes */
|
||||
size_t used;
|
||||
};
|
||||
|
||||
/* emac_buffer is wrapper around a pointer to a socket buffer
|
||||
* so a DMA handle can be stored along with the skb
|
||||
*/
|
||||
struct emac_buffer {
|
||||
struct sk_buff *skb; /* socket buffer */
|
||||
u16 length; /* rx buffer length */
|
||||
dma_addr_t dma_addr; /* dma address */
|
||||
};
|
||||
|
||||
/* receive free descriptor (rfd) ring */
|
||||
struct emac_rfd_ring {
|
||||
struct emac_buffer *rfbuff;
|
||||
u32 *v_addr; /* virtual address */
|
||||
dma_addr_t dma_addr; /* dma address */
|
||||
size_t size; /* length in bytes */
|
||||
unsigned int count; /* number of desc in the ring */
|
||||
unsigned int produce_idx;
|
||||
unsigned int process_idx;
|
||||
unsigned int consume_idx; /* unused */
|
||||
};
|
||||
|
||||
/* Receive Return Desciptor (RRD) ring */
|
||||
struct emac_rrd_ring {
|
||||
u32 *v_addr; /* virtual address */
|
||||
dma_addr_t dma_addr; /* physical address */
|
||||
size_t size; /* length in bytes */
|
||||
unsigned int count; /* number of desc in the ring */
|
||||
unsigned int produce_idx; /* unused */
|
||||
unsigned int consume_idx;
|
||||
};
|
||||
|
||||
/* Rx queue */
|
||||
struct emac_rx_queue {
|
||||
struct net_device *netdev; /* netdev ring belongs to */
|
||||
struct emac_rrd_ring rrd;
|
||||
struct emac_rfd_ring rfd;
|
||||
struct napi_struct napi;
|
||||
struct emac_irq *irq;
|
||||
|
||||
u32 intr;
|
||||
u32 produce_mask;
|
||||
u32 process_mask;
|
||||
u32 consume_mask;
|
||||
|
||||
u16 produce_reg;
|
||||
u16 process_reg;
|
||||
u16 consume_reg;
|
||||
|
||||
u8 produce_shift;
|
||||
u8 process_shft;
|
||||
u8 consume_shift;
|
||||
};
|
||||
|
||||
/* Transimit Packet Descriptor (tpd) ring */
|
||||
struct emac_tpd_ring {
|
||||
struct emac_buffer *tpbuff;
|
||||
u32 *v_addr; /* virtual address */
|
||||
dma_addr_t dma_addr; /* dma address */
|
||||
|
||||
size_t size; /* length in bytes */
|
||||
unsigned int count; /* number of desc in the ring */
|
||||
unsigned int produce_idx;
|
||||
unsigned int consume_idx;
|
||||
unsigned int last_produce_idx;
|
||||
};
|
||||
|
||||
/* Tx queue */
|
||||
struct emac_tx_queue {
|
||||
struct emac_tpd_ring tpd;
|
||||
|
||||
u32 produce_mask;
|
||||
u32 consume_mask;
|
||||
|
||||
u16 max_packets; /* max packets per interrupt */
|
||||
u16 produce_reg;
|
||||
u16 consume_reg;
|
||||
|
||||
u8 produce_shift;
|
||||
u8 consume_shift;
|
||||
};
|
||||
|
||||
struct emac_adapter;
|
||||
|
||||
int emac_mac_up(struct emac_adapter *adpt);
|
||||
void emac_mac_down(struct emac_adapter *adpt);
|
||||
void emac_mac_reset(struct emac_adapter *adpt);
|
||||
void emac_mac_start(struct emac_adapter *adpt);
|
||||
void emac_mac_stop(struct emac_adapter *adpt);
|
||||
void emac_mac_mode_config(struct emac_adapter *adpt);
|
||||
void emac_mac_rx_process(struct emac_adapter *adpt, struct emac_rx_queue *rx_q,
|
||||
int *num_pkts, int max_pkts);
|
||||
int emac_mac_tx_buf_send(struct emac_adapter *adpt, struct emac_tx_queue *tx_q,
|
||||
struct sk_buff *skb);
|
||||
void emac_mac_tx_process(struct emac_adapter *adpt, struct emac_tx_queue *tx_q);
|
||||
void emac_mac_rx_tx_ring_init_all(struct platform_device *pdev,
|
||||
struct emac_adapter *adpt);
|
||||
int emac_mac_rx_tx_rings_alloc_all(struct emac_adapter *adpt);
|
||||
void emac_mac_rx_tx_rings_free_all(struct emac_adapter *adpt);
|
||||
void emac_mac_multicast_addr_clear(struct emac_adapter *adpt);
|
||||
void emac_mac_multicast_addr_set(struct emac_adapter *adpt, u8 *addr);
|
||||
|
||||
#endif /*_EMAC_HW_H_*/
|
||||
204
drivers/net/ethernet/qualcomm/emac/emac-phy.c
Normal file
204
drivers/net/ethernet/qualcomm/emac/emac-phy.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/* Qualcomm Technologies, Inc. EMAC PHY Controller driver.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include "emac.h"
|
||||
#include "emac-mac.h"
|
||||
#include "emac-phy.h"
|
||||
#include "emac-sgmii.h"
|
||||
|
||||
/* EMAC base register offsets */
|
||||
#define EMAC_MDIO_CTRL 0x001414
|
||||
#define EMAC_PHY_STS 0x001418
|
||||
#define EMAC_MDIO_EX_CTRL 0x001440
|
||||
|
||||
/* EMAC_MDIO_CTRL */
|
||||
#define MDIO_MODE BIT(30)
|
||||
#define MDIO_PR BIT(29)
|
||||
#define MDIO_AP_EN BIT(28)
|
||||
#define MDIO_BUSY BIT(27)
|
||||
#define MDIO_CLK_SEL_BMSK 0x7000000
|
||||
#define MDIO_CLK_SEL_SHFT 24
|
||||
#define MDIO_START BIT(23)
|
||||
#define SUP_PREAMBLE BIT(22)
|
||||
#define MDIO_RD_NWR BIT(21)
|
||||
#define MDIO_REG_ADDR_BMSK 0x1f0000
|
||||
#define MDIO_REG_ADDR_SHFT 16
|
||||
#define MDIO_DATA_BMSK 0xffff
|
||||
#define MDIO_DATA_SHFT 0
|
||||
|
||||
/* EMAC_PHY_STS */
|
||||
#define PHY_ADDR_BMSK 0x1f0000
|
||||
#define PHY_ADDR_SHFT 16
|
||||
|
||||
#define MDIO_CLK_25_4 0
|
||||
#define MDIO_CLK_25_28 7
|
||||
|
||||
#define MDIO_WAIT_TIMES 1000
|
||||
|
||||
#define EMAC_LINK_SPEED_DEFAULT (\
|
||||
EMAC_LINK_SPEED_10_HALF |\
|
||||
EMAC_LINK_SPEED_10_FULL |\
|
||||
EMAC_LINK_SPEED_100_HALF |\
|
||||
EMAC_LINK_SPEED_100_FULL |\
|
||||
EMAC_LINK_SPEED_1GB_FULL)
|
||||
|
||||
/**
|
||||
* emac_phy_mdio_autopoll_disable() - disable mdio autopoll
|
||||
* @adpt: the emac adapter
|
||||
*
|
||||
* The autopoll feature takes over the MDIO bus. In order for
|
||||
* the PHY driver to be able to talk to the PHY over the MDIO
|
||||
* bus, we need to temporarily disable the autopoll feature.
|
||||
*/
|
||||
static int emac_phy_mdio_autopoll_disable(struct emac_adapter *adpt)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* disable autopoll */
|
||||
emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, MDIO_AP_EN, 0);
|
||||
|
||||
/* wait for any mdio polling to complete */
|
||||
if (!readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, val,
|
||||
!(val & MDIO_BUSY), 100, MDIO_WAIT_TIMES * 100))
|
||||
return 0;
|
||||
|
||||
/* failed to disable; ensure it is enabled before returning */
|
||||
emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN);
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
* emac_phy_mdio_autopoll_disable() - disable mdio autopoll
|
||||
* @adpt: the emac adapter
|
||||
*
|
||||
* The EMAC has the ability to poll the external PHY on the MDIO
|
||||
* bus for link state changes. This eliminates the need for the
|
||||
* driver to poll the phy. If if the link state does change,
|
||||
* the EMAC issues an interrupt on behalf of the PHY.
|
||||
*/
|
||||
static void emac_phy_mdio_autopoll_enable(struct emac_adapter *adpt)
|
||||
{
|
||||
emac_reg_update32(adpt->base + EMAC_MDIO_CTRL, 0, MDIO_AP_EN);
|
||||
}
|
||||
|
||||
static int emac_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
{
|
||||
struct emac_adapter *adpt = bus->priv;
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
ret = emac_phy_mdio_autopoll_disable(adpt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK,
|
||||
(addr << PHY_ADDR_SHFT));
|
||||
|
||||
reg = SUP_PREAMBLE |
|
||||
((MDIO_CLK_25_4 << MDIO_CLK_SEL_SHFT) & MDIO_CLK_SEL_BMSK) |
|
||||
((regnum << MDIO_REG_ADDR_SHFT) & MDIO_REG_ADDR_BMSK) |
|
||||
MDIO_START | MDIO_RD_NWR;
|
||||
|
||||
writel(reg, adpt->base + EMAC_MDIO_CTRL);
|
||||
|
||||
if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg,
|
||||
!(reg & (MDIO_START | MDIO_BUSY)),
|
||||
100, MDIO_WAIT_TIMES * 100))
|
||||
ret = -EIO;
|
||||
else
|
||||
ret = (reg >> MDIO_DATA_SHFT) & MDIO_DATA_BMSK;
|
||||
|
||||
emac_phy_mdio_autopoll_enable(adpt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int emac_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
|
||||
{
|
||||
struct emac_adapter *adpt = bus->priv;
|
||||
u32 reg;
|
||||
int ret;
|
||||
|
||||
ret = emac_phy_mdio_autopoll_disable(adpt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
emac_reg_update32(adpt->base + EMAC_PHY_STS, PHY_ADDR_BMSK,
|
||||
(addr << PHY_ADDR_SHFT));
|
||||
|
||||
reg = SUP_PREAMBLE |
|
||||
((MDIO_CLK_25_4 << MDIO_CLK_SEL_SHFT) & MDIO_CLK_SEL_BMSK) |
|
||||
((regnum << MDIO_REG_ADDR_SHFT) & MDIO_REG_ADDR_BMSK) |
|
||||
((val << MDIO_DATA_SHFT) & MDIO_DATA_BMSK) |
|
||||
MDIO_START;
|
||||
|
||||
writel(reg, adpt->base + EMAC_MDIO_CTRL);
|
||||
|
||||
if (readl_poll_timeout(adpt->base + EMAC_MDIO_CTRL, reg,
|
||||
!(reg & (MDIO_START | MDIO_BUSY)), 100,
|
||||
MDIO_WAIT_TIMES * 100))
|
||||
ret = -EIO;
|
||||
|
||||
emac_phy_mdio_autopoll_enable(adpt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Configure the MDIO bus and connect the external PHY */
|
||||
int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *phy_np;
|
||||
struct mii_bus *mii_bus;
|
||||
int ret;
|
||||
|
||||
/* Create the mii_bus object for talking to the MDIO bus */
|
||||
adpt->mii_bus = mii_bus = devm_mdiobus_alloc(&pdev->dev);
|
||||
if (!mii_bus)
|
||||
return -ENOMEM;
|
||||
|
||||
mii_bus->name = "emac-mdio";
|
||||
snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s", pdev->name);
|
||||
mii_bus->read = emac_mdio_read;
|
||||
mii_bus->write = emac_mdio_write;
|
||||
mii_bus->parent = &pdev->dev;
|
||||
mii_bus->priv = adpt;
|
||||
|
||||
ret = of_mdiobus_register(mii_bus, np);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "could not register mdio bus\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
phy_np = of_parse_phandle(np, "phy-handle", 0);
|
||||
adpt->phydev = of_phy_find_device(phy_np);
|
||||
if (!adpt->phydev) {
|
||||
dev_err(&pdev->dev, "could not find external phy\n");
|
||||
mdiobus_unregister(mii_bus);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (adpt->phydev->drv)
|
||||
phy_attached_print(adpt->phydev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
33
drivers/net/ethernet/qualcomm/emac/emac-phy.h
Normal file
33
drivers/net/ethernet/qualcomm/emac/emac-phy.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _EMAC_PHY_H_
|
||||
#define _EMAC_PHY_H_
|
||||
|
||||
typedef int (*emac_sgmii_initialize)(struct emac_adapter *adpt);
|
||||
|
||||
/** emac_phy - internal emac phy
|
||||
* @base base address
|
||||
* @digital per-lane digital block
|
||||
* @initialize initialization function
|
||||
*/
|
||||
struct emac_phy {
|
||||
void __iomem *base;
|
||||
void __iomem *digital;
|
||||
emac_sgmii_initialize initialize;
|
||||
};
|
||||
|
||||
struct emac_adapter;
|
||||
|
||||
int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt);
|
||||
|
||||
#endif /* _EMAC_PHY_H_ */
|
||||
721
drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
Normal file
721
drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
Normal file
File diff suppressed because it is too large
Load Diff
24
drivers/net/ethernet/qualcomm/emac/emac-sgmii.h
Normal file
24
drivers/net/ethernet/qualcomm/emac/emac-sgmii.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _EMAC_SGMII_H_
|
||||
#define _EMAC_SGMII_H_
|
||||
|
||||
struct emac_adapter;
|
||||
struct platform_device;
|
||||
|
||||
int emac_sgmii_init_v1(struct emac_adapter *adpt);
|
||||
int emac_sgmii_init_v2(struct emac_adapter *adpt);
|
||||
int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt);
|
||||
void emac_sgmii_reset(struct emac_adapter *adpt);
|
||||
|
||||
#endif
|
||||
743
drivers/net/ethernet/qualcomm/emac/emac.c
Normal file
743
drivers/net/ethernet/qualcomm/emac/emac.c
Normal file
File diff suppressed because it is too large
Load Diff
335
drivers/net/ethernet/qualcomm/emac/emac.h
Normal file
335
drivers/net/ethernet/qualcomm/emac/emac.h
Normal file
@@ -0,0 +1,335 @@
|
||||
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _EMAC_H_
|
||||
#define _EMAC_H_
|
||||
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "emac-mac.h"
|
||||
#include "emac-phy.h"
|
||||
|
||||
/* EMAC base register offsets */
|
||||
#define EMAC_DMA_MAS_CTRL 0x001400
|
||||
#define EMAC_IRQ_MOD_TIM_INIT 0x001408
|
||||
#define EMAC_BLK_IDLE_STS 0x00140c
|
||||
#define EMAC_PHY_LINK_DELAY 0x00141c
|
||||
#define EMAC_SYS_ALIV_CTRL 0x001434
|
||||
#define EMAC_MAC_IPGIFG_CTRL 0x001484
|
||||
#define EMAC_MAC_STA_ADDR0 0x001488
|
||||
#define EMAC_MAC_STA_ADDR1 0x00148c
|
||||
#define EMAC_HASH_TAB_REG0 0x001490
|
||||
#define EMAC_HASH_TAB_REG1 0x001494
|
||||
#define EMAC_MAC_HALF_DPLX_CTRL 0x001498
|
||||
#define EMAC_MAX_FRAM_LEN_CTRL 0x00149c
|
||||
#define EMAC_INT_STATUS 0x001600
|
||||
#define EMAC_INT_MASK 0x001604
|
||||
#define EMAC_RXMAC_STATC_REG0 0x001700
|
||||
#define EMAC_RXMAC_STATC_REG22 0x001758
|
||||
#define EMAC_TXMAC_STATC_REG0 0x001760
|
||||
#define EMAC_TXMAC_STATC_REG24 0x0017c0
|
||||
#define EMAC_CORE_HW_VERSION 0x001974
|
||||
#define EMAC_IDT_TABLE0 0x001b00
|
||||
#define EMAC_RXMAC_STATC_REG23 0x001bc8
|
||||
#define EMAC_RXMAC_STATC_REG24 0x001bcc
|
||||
#define EMAC_TXMAC_STATC_REG25 0x001bd0
|
||||
#define EMAC_INT1_MASK 0x001bf0
|
||||
#define EMAC_INT1_STATUS 0x001bf4
|
||||
#define EMAC_INT2_MASK 0x001bf8
|
||||
#define EMAC_INT2_STATUS 0x001bfc
|
||||
#define EMAC_INT3_MASK 0x001c00
|
||||
#define EMAC_INT3_STATUS 0x001c04
|
||||
|
||||
/* EMAC_DMA_MAS_CTRL */
|
||||
#define DEV_ID_NUM_BMSK 0x7f000000
|
||||
#define DEV_ID_NUM_SHFT 24
|
||||
#define DEV_REV_NUM_BMSK 0xff0000
|
||||
#define DEV_REV_NUM_SHFT 16
|
||||
#define INT_RD_CLR_EN 0x4000
|
||||
#define IRQ_MODERATOR2_EN 0x800
|
||||
#define IRQ_MODERATOR_EN 0x400
|
||||
#define LPW_CLK_SEL 0x80
|
||||
#define LPW_STATE 0x20
|
||||
#define LPW_MODE 0x10
|
||||
#define SOFT_RST 0x1
|
||||
|
||||
/* EMAC_IRQ_MOD_TIM_INIT */
|
||||
#define IRQ_MODERATOR2_INIT_BMSK 0xffff0000
|
||||
#define IRQ_MODERATOR2_INIT_SHFT 16
|
||||
#define IRQ_MODERATOR_INIT_BMSK 0xffff
|
||||
#define IRQ_MODERATOR_INIT_SHFT 0
|
||||
|
||||
/* EMAC_INT_STATUS */
|
||||
#define DIS_INT BIT(31)
|
||||
#define PTP_INT BIT(30)
|
||||
#define RFD4_UR_INT BIT(29)
|
||||
#define TX_PKT_INT3 BIT(26)
|
||||
#define TX_PKT_INT2 BIT(25)
|
||||
#define TX_PKT_INT1 BIT(24)
|
||||
#define RX_PKT_INT3 BIT(19)
|
||||
#define RX_PKT_INT2 BIT(18)
|
||||
#define RX_PKT_INT1 BIT(17)
|
||||
#define RX_PKT_INT0 BIT(16)
|
||||
#define TX_PKT_INT BIT(15)
|
||||
#define TXQ_TO_INT BIT(14)
|
||||
#define GPHY_WAKEUP_INT BIT(13)
|
||||
#define GPHY_LINK_DOWN_INT BIT(12)
|
||||
#define GPHY_LINK_UP_INT BIT(11)
|
||||
#define DMAW_TO_INT BIT(10)
|
||||
#define DMAR_TO_INT BIT(9)
|
||||
#define TXF_UR_INT BIT(8)
|
||||
#define RFD3_UR_INT BIT(7)
|
||||
#define RFD2_UR_INT BIT(6)
|
||||
#define RFD1_UR_INT BIT(5)
|
||||
#define RFD0_UR_INT BIT(4)
|
||||
#define RXF_OF_INT BIT(3)
|
||||
#define SW_MAN_INT BIT(2)
|
||||
|
||||
/* EMAC_MAILBOX_6 */
|
||||
#define RFD2_PROC_IDX_BMSK 0xfff0000
|
||||
#define RFD2_PROC_IDX_SHFT 16
|
||||
#define RFD2_PROD_IDX_BMSK 0xfff
|
||||
#define RFD2_PROD_IDX_SHFT 0
|
||||
|
||||
/* EMAC_CORE_HW_VERSION */
|
||||
#define MAJOR_BMSK 0xf0000000
|
||||
#define MAJOR_SHFT 28
|
||||
#define MINOR_BMSK 0xfff0000
|
||||
#define MINOR_SHFT 16
|
||||
#define STEP_BMSK 0xffff
|
||||
#define STEP_SHFT 0
|
||||
|
||||
/* EMAC_EMAC_WRAPPER_CSR1 */
|
||||
#define TX_INDX_FIFO_SYNC_RST BIT(23)
|
||||
#define TX_TS_FIFO_SYNC_RST BIT(22)
|
||||
#define RX_TS_FIFO2_SYNC_RST BIT(21)
|
||||
#define RX_TS_FIFO1_SYNC_RST BIT(20)
|
||||
#define TX_TS_ENABLE BIT(16)
|
||||
#define DIS_1588_CLKS BIT(11)
|
||||
#define FREQ_MODE BIT(9)
|
||||
#define ENABLE_RRD_TIMESTAMP BIT(3)
|
||||
|
||||
/* EMAC_EMAC_WRAPPER_CSR2 */
|
||||
#define HDRIVE_BMSK 0x3000
|
||||
#define HDRIVE_SHFT 12
|
||||
#define SLB_EN BIT(9)
|
||||
#define PLB_EN BIT(8)
|
||||
#define WOL_EN BIT(3)
|
||||
#define PHY_RESET BIT(0)
|
||||
|
||||
#define EMAC_DEV_ID 0x0040
|
||||
|
||||
/* SGMII v2 per lane registers */
|
||||
#define SGMII_LN_RSM_START 0x029C
|
||||
|
||||
/* SGMII v2 PHY common registers */
|
||||
#define SGMII_PHY_CMN_CTRL 0x0408
|
||||
#define SGMII_PHY_CMN_RESET_CTRL 0x0410
|
||||
|
||||
/* SGMII v2 PHY registers per lane */
|
||||
#define SGMII_PHY_LN_OFFSET 0x0400
|
||||
#define SGMII_PHY_LN_LANE_STATUS 0x00DC
|
||||
#define SGMII_PHY_LN_BIST_GEN0 0x008C
|
||||
#define SGMII_PHY_LN_BIST_GEN1 0x0090
|
||||
#define SGMII_PHY_LN_BIST_GEN2 0x0094
|
||||
#define SGMII_PHY_LN_BIST_GEN3 0x0098
|
||||
#define SGMII_PHY_LN_CDR_CTRL1 0x005C
|
||||
|
||||
enum emac_clk_id {
|
||||
EMAC_CLK_AXI,
|
||||
EMAC_CLK_CFG_AHB,
|
||||
EMAC_CLK_HIGH_SPEED,
|
||||
EMAC_CLK_MDIO,
|
||||
EMAC_CLK_TX,
|
||||
EMAC_CLK_RX,
|
||||
EMAC_CLK_SYS,
|
||||
EMAC_CLK_CNT
|
||||
};
|
||||
|
||||
#define EMAC_LINK_SPEED_UNKNOWN 0x0
|
||||
#define EMAC_LINK_SPEED_10_HALF BIT(0)
|
||||
#define EMAC_LINK_SPEED_10_FULL BIT(1)
|
||||
#define EMAC_LINK_SPEED_100_HALF BIT(2)
|
||||
#define EMAC_LINK_SPEED_100_FULL BIT(3)
|
||||
#define EMAC_LINK_SPEED_1GB_FULL BIT(5)
|
||||
|
||||
#define EMAC_MAX_SETUP_LNK_CYCLE 100
|
||||
|
||||
/* Wake On Lan */
|
||||
#define EMAC_WOL_PHY 0x00000001 /* PHY Status Change */
|
||||
#define EMAC_WOL_MAGIC 0x00000002 /* Magic Packet */
|
||||
|
||||
struct emac_stats {
|
||||
/* rx */
|
||||
u64 rx_ok; /* good packets */
|
||||
u64 rx_bcast; /* good broadcast packets */
|
||||
u64 rx_mcast; /* good multicast packets */
|
||||
u64 rx_pause; /* pause packet */
|
||||
u64 rx_ctrl; /* control packets other than pause frame. */
|
||||
u64 rx_fcs_err; /* packets with bad FCS. */
|
||||
u64 rx_len_err; /* packets with length mismatch */
|
||||
u64 rx_byte_cnt; /* good bytes count (without FCS) */
|
||||
u64 rx_runt; /* runt packets */
|
||||
u64 rx_frag; /* fragment count */
|
||||
u64 rx_sz_64; /* packets that are 64 bytes */
|
||||
u64 rx_sz_65_127; /* packets that are 65-127 bytes */
|
||||
u64 rx_sz_128_255; /* packets that are 128-255 bytes */
|
||||
u64 rx_sz_256_511; /* packets that are 256-511 bytes */
|
||||
u64 rx_sz_512_1023; /* packets that are 512-1023 bytes */
|
||||
u64 rx_sz_1024_1518; /* packets that are 1024-1518 bytes */
|
||||
u64 rx_sz_1519_max; /* packets that are 1519-MTU bytes*/
|
||||
u64 rx_sz_ov; /* packets that are >MTU bytes (truncated) */
|
||||
u64 rx_rxf_ov; /* packets dropped due to RX FIFO overflow */
|
||||
u64 rx_align_err; /* alignment errors */
|
||||
u64 rx_bcast_byte_cnt; /* broadcast packets byte count (without FCS) */
|
||||
u64 rx_mcast_byte_cnt; /* multicast packets byte count (without FCS) */
|
||||
u64 rx_err_addr; /* packets dropped due to address filtering */
|
||||
u64 rx_crc_align; /* CRC align errors */
|
||||
u64 rx_jabbers; /* jabbers */
|
||||
|
||||
/* tx */
|
||||
u64 tx_ok; /* good packets */
|
||||
u64 tx_bcast; /* good broadcast packets */
|
||||
u64 tx_mcast; /* good multicast packets */
|
||||
u64 tx_pause; /* pause packets */
|
||||
u64 tx_exc_defer; /* packets with excessive deferral */
|
||||
u64 tx_ctrl; /* control packets other than pause frame */
|
||||
u64 tx_defer; /* packets that are deferred. */
|
||||
u64 tx_byte_cnt; /* good bytes count (without FCS) */
|
||||
u64 tx_sz_64; /* packets that are 64 bytes */
|
||||
u64 tx_sz_65_127; /* packets that are 65-127 bytes */
|
||||
u64 tx_sz_128_255; /* packets that are 128-255 bytes */
|
||||
u64 tx_sz_256_511; /* packets that are 256-511 bytes */
|
||||
u64 tx_sz_512_1023; /* packets that are 512-1023 bytes */
|
||||
u64 tx_sz_1024_1518; /* packets that are 1024-1518 bytes */
|
||||
u64 tx_sz_1519_max; /* packets that are 1519-MTU bytes */
|
||||
u64 tx_1_col; /* packets single prior collision */
|
||||
u64 tx_2_col; /* packets with multiple prior collisions */
|
||||
u64 tx_late_col; /* packets with late collisions */
|
||||
u64 tx_abort_col; /* packets aborted due to excess collisions */
|
||||
u64 tx_underrun; /* packets aborted due to FIFO underrun */
|
||||
u64 tx_rd_eop; /* count of reads beyond EOP */
|
||||
u64 tx_len_err; /* packets with length mismatch */
|
||||
u64 tx_trunc; /* packets truncated due to size >MTU */
|
||||
u64 tx_bcast_byte; /* broadcast packets byte count (without FCS) */
|
||||
u64 tx_mcast_byte; /* multicast packets byte count (without FCS) */
|
||||
u64 tx_col; /* collisions */
|
||||
|
||||
spinlock_t lock; /* prevent multiple simultaneous readers */
|
||||
};
|
||||
|
||||
/* RSS hstype Definitions */
|
||||
#define EMAC_RSS_HSTYP_IPV4_EN 0x00000001
|
||||
#define EMAC_RSS_HSTYP_TCP4_EN 0x00000002
|
||||
#define EMAC_RSS_HSTYP_IPV6_EN 0x00000004
|
||||
#define EMAC_RSS_HSTYP_TCP6_EN 0x00000008
|
||||
#define EMAC_RSS_HSTYP_ALL_EN (\
|
||||
EMAC_RSS_HSTYP_IPV4_EN |\
|
||||
EMAC_RSS_HSTYP_TCP4_EN |\
|
||||
EMAC_RSS_HSTYP_IPV6_EN |\
|
||||
EMAC_RSS_HSTYP_TCP6_EN)
|
||||
|
||||
#define EMAC_VLAN_TO_TAG(_vlan, _tag) \
|
||||
(_tag = ((((_vlan) >> 8) & 0xFF) | (((_vlan) & 0xFF) << 8)))
|
||||
|
||||
#define EMAC_TAG_TO_VLAN(_tag, _vlan) \
|
||||
(_vlan = ((((_tag) >> 8) & 0xFF) | (((_tag) & 0xFF) << 8)))
|
||||
|
||||
#define EMAC_DEF_RX_BUF_SIZE 1536
|
||||
#define EMAC_MAX_JUMBO_PKT_SIZE (9 * 1024)
|
||||
#define EMAC_MAX_TX_OFFLOAD_THRESH (9 * 1024)
|
||||
|
||||
#define EMAC_MAX_ETH_FRAME_SIZE EMAC_MAX_JUMBO_PKT_SIZE
|
||||
#define EMAC_MIN_ETH_FRAME_SIZE 68
|
||||
|
||||
#define EMAC_DEF_TX_QUEUES 1
|
||||
#define EMAC_DEF_RX_QUEUES 1
|
||||
|
||||
#define EMAC_MIN_TX_DESCS 128
|
||||
#define EMAC_MIN_RX_DESCS 128
|
||||
|
||||
#define EMAC_MAX_TX_DESCS 16383
|
||||
#define EMAC_MAX_RX_DESCS 2047
|
||||
|
||||
#define EMAC_DEF_TX_DESCS 512
|
||||
#define EMAC_DEF_RX_DESCS 256
|
||||
|
||||
#define EMAC_DEF_RX_IRQ_MOD 250
|
||||
#define EMAC_DEF_TX_IRQ_MOD 250
|
||||
|
||||
#define EMAC_WATCHDOG_TIME (5 * HZ)
|
||||
|
||||
/* by default check link every 4 seconds */
|
||||
#define EMAC_TRY_LINK_TIMEOUT (4 * HZ)
|
||||
|
||||
/* emac_irq per-device (per-adapter) irq properties.
|
||||
* @irq: irq number.
|
||||
* @mask mask to use over status register.
|
||||
*/
|
||||
struct emac_irq {
|
||||
unsigned int irq;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
/* The device's main data structure */
|
||||
struct emac_adapter {
|
||||
struct net_device *netdev;
|
||||
struct mii_bus *mii_bus;
|
||||
struct phy_device *phydev;
|
||||
|
||||
void __iomem *base;
|
||||
void __iomem *csr;
|
||||
|
||||
struct emac_phy phy;
|
||||
struct emac_stats stats;
|
||||
|
||||
struct emac_irq irq;
|
||||
struct clk *clk[EMAC_CLK_CNT];
|
||||
|
||||
/* All Descriptor memory */
|
||||
struct emac_ring_header ring_header;
|
||||
struct emac_tx_queue tx_q;
|
||||
struct emac_rx_queue rx_q;
|
||||
unsigned int tx_desc_cnt;
|
||||
unsigned int rx_desc_cnt;
|
||||
unsigned int rrd_size; /* in quad words */
|
||||
unsigned int rfd_size; /* in quad words */
|
||||
unsigned int tpd_size; /* in quad words */
|
||||
|
||||
unsigned int rxbuf_size;
|
||||
|
||||
/* Ring parameter */
|
||||
u8 tpd_burst;
|
||||
u8 rfd_burst;
|
||||
unsigned int dmaw_dly_cnt;
|
||||
unsigned int dmar_dly_cnt;
|
||||
enum emac_dma_req_block dmar_block;
|
||||
enum emac_dma_req_block dmaw_block;
|
||||
enum emac_dma_order dma_order;
|
||||
|
||||
u32 irq_mod;
|
||||
u32 preamble;
|
||||
|
||||
struct work_struct work_thread;
|
||||
|
||||
u16 msg_enable;
|
||||
|
||||
struct mutex reset_lock;
|
||||
};
|
||||
|
||||
int emac_reinit_locked(struct emac_adapter *adpt);
|
||||
void emac_reg_update32(void __iomem *addr, u32 mask, u32 val);
|
||||
irqreturn_t emac_isr(int irq, void *data);
|
||||
|
||||
#endif /* _EMAC_H_ */
|
||||
Reference in New Issue
Block a user