Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0db64ce authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'stmmac'



Giuseppe CAVALLARO says:

====================
These patches enhance the driver adding the PTP support and the initial code
for RGMII/SGMII/TBI/RTBI modes.
Also this patches review the driver removing some Koption for selecting between
chain and ring modes. REally useful to validate the driver also at build time.
Before adding PTP, the extended descriptor support has been added because it
is mandatory to save HW timestamp in new dedicated descriptors. Also in this
case no Koption added.

Concerning the PTP, I have hacked/reviewed and tested many
part of these patches also verifying the back compatibility on
several HW and chips.

Concerning the SGMII/RGMII we have already discussed about the support
in the net.dev Mailing list with Byungho where these patchs were partially
analysed.
So I have only ported them against the latest net-next (and on
top of PTP). I have added some missing things: e.g. some parts of the
ethtool for ANE. As we clarified with Byungho, we will add further
enhancements on top of these patches if needed.

I have also built all against ARM/SH/X68 platforms and no issues on
ST-Boxes.

Thx goes to Rayagond that wrote and tested the PTP and to Byungho for SGMII.

V2: This Version 2 has the fixes discussed in the ML, for example:
    o completely remove the Koption... all the decisions are made at probe time
    o review the PTP patches and better organize them just in two patches
    o added all the fixes provided by Richard on PTP and CLK driver.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ad999eee 94fbbbf8
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -326,6 +326,35 @@ To enter in Tx LPI mode the driver needs to have a software timer
that enable and disable the LPI mode when there is nothing to be
transmitted.

7) TODO:
7) Extended descriptors
The extended descriptors give us information about the receive Ethernet payload
when it is carrying PTP packets or TCP/UDP/ICMP over IP.
These are not available on GMAC Synopsys chips older than the 3.50.
At probe time the driver will decide if these can be actually used.
This support also is mandatory for PTPv2 because the extra descriptors 6 and 7
are used for saving the hardware timestamps.

8) Precision Time Protocol (PTP)
The driver supports the IEEE 1588-2002, Precision Time Protocol (PTP),
which enables precise synchronization of clocks in measurement and
control systems implemented with technologies such as network
communication.

In addition to the basic timestamp features mentioned in IEEE 1588-2002
Timestamps, new GMAC cores support the advanced timestamp features.
IEEE 1588-2008 that can be enabled when configure the Kernel.

9) SGMII/RGMII supports
New GMAC devices provide own way to manage RGMII/SGMII.
This information is available at run-time by looking at the
HW capability register. This means that the stmmac can manage
auto-negotiation and link status w/o using the PHYLIB stuff
In fact, the HW provides a subset of extended registers to
restart the ANE, verify Full/Half duplex mode and Speed.
Also thanks to these registers it is possible to look at the
Auto-negotiated Link Parter Ability.

10) TODO:
 o XGMAC is not supported.
 o Add the PTP - precision time protocol
 o Complete the TBI & RTBI support.
 o extened VLAN support for 3.70a SYNP GMAC.
+1 −18
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ config STMMAC_ETH
	select MII
	select PHYLIB
	select CRC32
	select PTP_1588_CLOCK
	---help---
	  This is the driver for the Ethernet IPs are built around a
	  Synopsys IP Core and only tested on the STMicroelectronics
@@ -54,22 +55,4 @@ config STMMAC_DA
	  By default, the DMA arbitration scheme is based on Round-robin
	  (rx:tx priority is 1:1).

choice
	prompt "Select the DMA TX/RX descriptor operating modes"
	depends on STMMAC_ETH
	---help---
	  This driver supports DMA descriptor to operate both in dual buffer
	  (RING) and linked-list(CHAINED) mode. In RING mode each descriptor
	  points to two data buffer pointers whereas in CHAINED mode they
	  points to only one data buffer pointer.

config STMMAC_RING
	bool "Enable Descriptor Ring Mode"

config STMMAC_CHAINED
	bool "Enable Descriptor Chained Mode"

endchoice


endif
+3 −5
Original line number Diff line number Diff line
obj-$(CONFIG_STMMAC_ETH) += stmmac.o
stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
stmmac-$(CONFIG_STMMAC_PCI) += stmmac_pci.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o	\
	      dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o	\
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
	      chain_mode.o dwmac_lib.o dwmac1000_core.o  dwmac1000_dma.o \
	      dwmac100_core.o dwmac100_dma.o enh_desc.o  norm_desc.o \
	      mmc_core.o $(stmmac-y)
	      mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o $(stmmac-y)
+57 −33
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@

#include "stmmac.h"

unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
{
	struct stmmac_priv *priv = (struct stmmac_priv *) p;
	unsigned int txsize = priv->dma_tx_size;
@@ -47,7 +47,8 @@ unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)

	desc->des2 = dma_map_single(priv->device, skb->data,
				    bmax, DMA_TO_DEVICE);
	priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum);
	priv->tx_skbuff_dma[entry] = desc->des2;
	priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);

	while (len != 0) {
		entry = (++priv->cur_tx) % txsize;
@@ -57,8 +58,9 @@ unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
			desc->des2 = dma_map_single(priv->device,
						    (skb->data + bmax * i),
						    bmax, DMA_TO_DEVICE);
			priv->hw->desc->prepare_tx_desc(desc, 0, bmax,
							csum);
			priv->tx_skbuff_dma[entry] = desc->des2;
			priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
							STMMAC_CHAIN_MODE);
			priv->hw->desc->set_tx_owner(desc);
			priv->tx_skbuff[entry] = NULL;
			len -= bmax;
@@ -67,8 +69,9 @@ unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
			desc->des2 = dma_map_single(priv->device,
						    (skb->data + bmax * i), len,
						    DMA_TO_DEVICE);
			priv->hw->desc->prepare_tx_desc(desc, 0, len,
							csum);
			priv->tx_skbuff_dma[entry] = desc->des2;
			priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
							STMMAC_CHAIN_MODE);
			priv->hw->desc->set_tx_owner(desc);
			priv->tx_skbuff[entry] = NULL;
			len = 0;
@@ -89,29 +92,27 @@ static unsigned int stmmac_is_jumbo_frm(int len, int enh_desc)
	return ret;
}

static void stmmac_refill_desc3(int bfsize, struct dma_desc *p)
{
}

static void stmmac_init_desc3(int des3_as_data_buf, struct dma_desc *p)
{
}

static void stmmac_clean_desc3(struct dma_desc *p)
{
}

static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
				  unsigned int size)
static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,
				  unsigned int size, unsigned int extend_desc)
{
	/*
	 * In chained mode the des3 points to the next element in the ring.
	 * The latest element has to point to the head.
	 */
	int i;
	struct dma_desc *p = des;
	dma_addr_t dma_phy = phy_addr;

	if (extend_desc) {
		struct dma_extended_desc *p = (struct dma_extended_desc *) des;
		for (i = 0; i < (size - 1); i++) {
			dma_phy += sizeof(struct dma_extended_desc);
			p->basic.des3 = (unsigned int)dma_phy;
			p++;
		}
		p->basic.des3 = (unsigned int)phy_addr;

	} else {
		struct dma_desc *p = (struct dma_desc *) des;
		for (i = 0; i < (size - 1); i++) {
			dma_phy += sizeof(struct dma_desc);
			p->des3 = (unsigned int)dma_phy;
@@ -119,19 +120,42 @@ static void stmmac_init_dma_chain(struct dma_desc *des, dma_addr_t phy_addr,
		}
		p->des3 = (unsigned int)phy_addr;
	}
}

static int stmmac_set_16kib_bfsize(int mtu)
static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
{
	/* Not supported */
	return 0;
	struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;

	if (priv->hwts_rx_en && !priv->extend_desc)
		/* NOTE: Device will overwrite des3 with timestamp value if
		 * 1588-2002 time stamping is enabled, hence reinitialize it
		 * to keep explicit chaining in the descriptor.
		 */
		p->des3 = (unsigned int)(priv->dma_rx_phy +
					 (((priv->dirty_rx) + 1) %
					 priv->dma_rx_size) *
					 sizeof(struct dma_desc));
}

static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
{
	struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;

	if (priv->hw->desc->get_tx_ls(p) && !priv->extend_desc)
		/* NOTE: Device will overwrite des3 with timestamp value if
		 * 1588-2002 time stamping is enabled, hence reinitialize it
		 * to keep explicit chaining in the descriptor.
		 */
		p->des3 = (unsigned int)(priv->dma_tx_phy +
					 (((priv->dirty_tx + 1) %
					 priv->dma_tx_size) *
					 sizeof(struct dma_desc)));
}

const struct stmmac_ring_mode_ops ring_mode_ops = {
const struct stmmac_chain_mode_ops chain_mode_ops = {
	.init = stmmac_init_dma_chain,
	.is_jumbo_frm = stmmac_is_jumbo_frm,
	.jumbo_frm = stmmac_jumbo_frm,
	.refill_desc3 = stmmac_refill_desc3,
	.init_desc3 = stmmac_init_desc3,
	.init_dma_chain = stmmac_init_dma_chain,
	.clean_desc3 = stmmac_clean_desc3,
	.set_16kib_bfsize = stmmac_set_16kib_bfsize,
};
+101 −21
Original line number Diff line number Diff line
@@ -117,6 +117,36 @@ struct stmmac_extra_stats {
	unsigned long irq_rx_path_in_lpi_mode_n;
	unsigned long irq_rx_path_exit_lpi_mode_n;
	unsigned long phy_eee_wakeup_error_n;
	/* Extended RDES status */
	unsigned long ip_hdr_err;
	unsigned long ip_payload_err;
	unsigned long ip_csum_bypassed;
	unsigned long ipv4_pkt_rcvd;
	unsigned long ipv6_pkt_rcvd;
	unsigned long rx_msg_type_ext_no_ptp;
	unsigned long rx_msg_type_sync;
	unsigned long rx_msg_type_follow_up;
	unsigned long rx_msg_type_delay_req;
	unsigned long rx_msg_type_delay_resp;
	unsigned long rx_msg_type_pdelay_req;
	unsigned long rx_msg_type_pdelay_resp;
	unsigned long rx_msg_type_pdelay_follow_up;
	unsigned long ptp_frame_type;
	unsigned long ptp_ver;
	unsigned long timestamp_dropped;
	unsigned long av_pkt_rcvd;
	unsigned long av_tagged_pkt_rcvd;
	unsigned long vlan_tag_priority_val;
	unsigned long l3_filter_match;
	unsigned long l4_filter_match;
	unsigned long l3_l4_filter_no_match;
	/* PCS */
	unsigned long irq_pcs_ane_n;
	unsigned long irq_pcs_link_n;
	unsigned long irq_rgmii_n;
	unsigned long pcs_link;
	unsigned long pcs_duplex;
	unsigned long pcs_speed;
};

/* CSR Frequency Access Defines*/
@@ -138,6 +168,12 @@ struct stmmac_extra_stats {
#define FLOW_TX		2
#define FLOW_AUTO	(FLOW_TX | FLOW_RX)

/* PCS defines */
#define STMMAC_PCS_RGMII	(1 << 0)
#define STMMAC_PCS_SGMII	(1 << 1)
#define STMMAC_PCS_TBI		(1 << 2)
#define STMMAC_PCS_RTBI		(1 << 3)

#define SF_DMA_MODE 1 /* DMA STORE-AND-FORWARD Operation Mode */

/* DAM HW feature register fields */
@@ -194,17 +230,25 @@ enum dma_irq_status {
	handle_tx = 0x8,
};

enum core_specific_irq_mask {
	core_mmc_tx_irq = 1,
	core_mmc_rx_irq = 2,
	core_mmc_rx_csum_offload_irq = 4,
	core_irq_receive_pmt_irq = 8,
	core_irq_tx_path_in_lpi_mode = 16,
	core_irq_tx_path_exit_lpi_mode = 32,
	core_irq_rx_path_in_lpi_mode = 64,
	core_irq_rx_path_exit_lpi_mode = 128,
#define	CORE_IRQ_TX_PATH_IN_LPI_MODE	(1 << 1)
#define	CORE_IRQ_TX_PATH_EXIT_LPI_MODE	(1 << 2)
#define	CORE_IRQ_RX_PATH_IN_LPI_MODE	(1 << 3)
#define	CORE_IRQ_RX_PATH_EXIT_LPI_MODE	(1 << 4)

#define	CORE_PCS_ANE_COMPLETE		(1 << 5)
#define	CORE_PCS_LINK_STATUS		(1 << 6)
#define	CORE_RGMII_IRQ			(1 << 7)

struct rgmii_adv {
	unsigned int pause;
	unsigned int duplex;
	unsigned int lp_pause;
	unsigned int lp_duplex;
};

#define STMMAC_PCS_PAUSE	1
#define STMMAC_PCS_ASYM_PAUSE	2

/* DMA HW capabilities */
struct dma_features {
	unsigned int mbps_10_100;
@@ -255,23 +299,26 @@ struct dma_features {
#define STMMAC_DEFAULT_LIT_LS_TIMER	0x3E8
#define STMMAC_DEFAULT_TWT_LS_TIMER	0x0

#define STMMAC_CHAIN_MODE	0x1
#define STMMAC_RING_MODE	0x2

struct stmmac_desc_ops {
	/* DMA RX descriptor ring initialization */
	void (*init_rx_desc) (struct dma_desc *p, unsigned int ring_size,
			      int disable_rx_ic);
	void (*init_rx_desc) (struct dma_desc *p, int disable_rx_ic, int mode,
			      int end);
	/* DMA TX descriptor ring initialization */
	void (*init_tx_desc) (struct dma_desc *p, unsigned int ring_size);
	void (*init_tx_desc) (struct dma_desc *p, int mode, int end);

	/* Invoked by the xmit function to prepare the tx descriptor */
	void (*prepare_tx_desc) (struct dma_desc *p, int is_fs, int len,
				 int csum_flag);
				 int csum_flag, int mode);
	/* Set/get the owner of the descriptor */
	void (*set_tx_owner) (struct dma_desc *p);
	int (*get_tx_owner) (struct dma_desc *p);
	/* Invoked by the xmit function to close the tx descriptor */
	void (*close_tx_desc) (struct dma_desc *p);
	/* Clean the tx descriptor as soon as the tx irq is received */
	void (*release_tx_desc) (struct dma_desc *p);
	void (*release_tx_desc) (struct dma_desc *p, int mode);
	/* Clear interrupt on tx frame completion. When this bit is
	 * set an interrupt happens as soon as the frame is transmitted */
	void (*clear_tx_ic) (struct dma_desc *p);
@@ -290,12 +337,22 @@ struct stmmac_desc_ops {
	/* Return the reception status looking at the RDES1 */
	int (*rx_status) (void *data, struct stmmac_extra_stats *x,
			  struct dma_desc *p);
	void (*rx_extended_status) (void *data, struct stmmac_extra_stats *x,
				    struct dma_extended_desc *p);
	/* Set tx timestamp enable bit */
	void (*enable_tx_timestamp) (struct dma_desc *p);
	/* get tx timestamp status */
	int (*get_tx_timestamp_status) (struct dma_desc *p);
	/* get timestamp value */
	u64 (*get_timestamp) (void *desc, u32 ats);
	/* get rx timestamp status */
	int (*get_rx_timestamp_status) (void *desc, u32 ats);
};

struct stmmac_dma_ops {
	/* DMA core initialization */
	int (*init) (void __iomem *ioaddr, int pbl, int fb, int mb,
		     int burst_len, u32 dma_tx, u32 dma_rx);
		     int burst_len, u32 dma_tx, u32 dma_rx, int atds);
	/* Dump DMA registers */
	void (*dump_regs) (void __iomem *ioaddr);
	/* Set tx/rx threshold in the csr6 register
@@ -327,7 +384,8 @@ struct stmmac_ops {
	/* Dump MAC registers */
	void (*dump_regs) (void __iomem *ioaddr);
	/* Handle extra events on specific interrupts hw dependent */
	int (*host_irq_status) (void __iomem *ioaddr);
	int (*host_irq_status) (void __iomem *ioaddr,
				struct stmmac_extra_stats *x);
	/* Multicast filter setting */
	void (*set_filter) (struct net_device *dev, int id);
	/* Flow control setting */
@@ -344,6 +402,18 @@ struct stmmac_ops {
	void (*reset_eee_mode) (void __iomem *ioaddr);
	void (*set_eee_timer) (void __iomem *ioaddr, int ls, int tw);
	void (*set_eee_pls) (void __iomem *ioaddr, int link);
	void (*ctrl_ane) (void __iomem *ioaddr, bool restart);
	void (*get_adv) (void __iomem *ioaddr, struct rgmii_adv *adv);
};

struct stmmac_hwtimestamp {
	void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
	void (*config_sub_second_increment) (void __iomem *ioaddr);
	int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
	int (*config_addend)(void __iomem *ioaddr, u32 addend);
	int (*adjust_systime)(void __iomem *ioaddr, u32 sec, u32 nsec,
			      int add_sub);
	u64 (*get_systime)(void __iomem *ioaddr);
};

struct mac_link {
@@ -360,19 +430,28 @@ struct mii_regs {
struct stmmac_ring_mode_ops {
	unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
	unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
	void (*refill_desc3) (int bfsize, struct dma_desc *p);
	void (*init_desc3) (int des3_as_data_buf, struct dma_desc *p);
	void (*init_dma_chain) (struct dma_desc *des, dma_addr_t phy_addr,
				unsigned int size);
	void (*clean_desc3) (struct dma_desc *p);
	void (*refill_desc3) (void *priv, struct dma_desc *p);
	void (*init_desc3) (struct dma_desc *p);
	void (*clean_desc3) (void *priv, struct dma_desc *p);
	int (*set_16kib_bfsize) (int mtu);
};

struct stmmac_chain_mode_ops {
	void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
		      unsigned int extend_desc);
	unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
	unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
	void (*refill_desc3) (void *priv, struct dma_desc *p);
	void (*clean_desc3) (void *priv, struct dma_desc *p);
};

struct mac_device_info {
	const struct stmmac_ops		*mac;
	const struct stmmac_desc_ops	*desc;
	const struct stmmac_dma_ops	*dma;
	const struct stmmac_ring_mode_ops	*ring;
	const struct stmmac_chain_mode_ops	*chain;
	const struct stmmac_hwtimestamp *ptp;
	struct mii_regs mii;	/* MII register Addresses */
	struct mac_link link;
	unsigned int synopsys_uid;
@@ -390,5 +469,6 @@ extern void stmmac_set_mac(void __iomem *ioaddr, bool enable);

extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
extern const struct stmmac_ring_mode_ops ring_mode_ops;
extern const struct stmmac_chain_mode_ops chain_mode_ops;

#endif /* __COMMON_H__ */
Loading