Inter-revision diff: patch 2

Comparing v1 (message) to rfc (message)

--- v1
+++ vrfc
@@ -1,156 +1,1276 @@
-Rename the variable "no_ptp_cfg_active" with "gptp" and
-"ptp_cfg_active" with "ccc_gac" to match the HW features.
+Add Gigabit Ethernet driver support.
 
-There is no functional change.
+The Gigabit Etherner IP consists of Ethernet controller (E-MAC),
+Internal TCP/IP Offload Engine (TOE) and Dedicated Direct memory
+access controller (DMAC).
 
 Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
-Suggested-by: Sergey Shtylyov <s.shtylyov@omp.ru>
-Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
 ---
-RFc->v1:
- * Renamed the variable "no_ptp_cfg_active" with "gptp" and
-   "ptp_cfg_active" with "ccc_gac
----
- drivers/net/ethernet/renesas/ravb.h      |  4 ++--
- drivers/net/ethernet/renesas/ravb_main.c | 26 ++++++++++++------------
- 2 files changed, 15 insertions(+), 15 deletions(-)
+ drivers/net/ethernet/renesas/ravb.h      |  92 ++-
+ drivers/net/ethernet/renesas/ravb_main.c | 683 ++++++++++++++++++++---
+ 2 files changed, 682 insertions(+), 93 deletions(-)
 
 diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
-index 7363abae6e59..a33fbcb4aac3 100644
+index 80e62ca2e3d3..4e65683fb458 100644
 --- a/drivers/net/ethernet/renesas/ravb.h
 +++ b/drivers/net/ethernet/renesas/ravb.h
-@@ -1000,8 +1000,8 @@ struct ravb_hw_info {
- 	unsigned internal_delay:1;	/* AVB-DMAC has internal delays */
- 	unsigned tx_counters:1;		/* E-MAC has TX counters */
- 	unsigned multi_irqs:1;		/* AVB-DMAC and E-MAC has multiple irqs */
--	unsigned no_ptp_cfg_active:1;	/* AVB-DMAC does not support gPTP active in config mode */
--	unsigned ptp_cfg_active:1;	/* AVB-DMAC has gPTP support active in config mode */
-+	unsigned gptp:1;		/* AVB-DMAC has gPTP support */
-+	unsigned ccc_gac:1;		/* AVB-DMAC has gPTP support active in config mode */
+@@ -81,6 +81,7 @@ enum ravb_reg {
+ 	RQC3	= 0x00A0,
+ 	RQC4	= 0x00A4,
+ 	RPC	= 0x00B0,
++	RTC	= 0x00B4,	/* RZ/G2L only */
+ 	UFCW	= 0x00BC,
+ 	UFCS	= 0x00C0,
+ 	UFCV0	= 0x00C4,
+@@ -156,6 +157,7 @@ enum ravb_reg {
+ 	TIS	= 0x037C,
+ 	ISS	= 0x0380,
+ 	CIE	= 0x0384,	/* R-Car Gen3 only */
++	RIC3	= 0x0388,	/* RZ/G2L only */
+ 	GCCR	= 0x0390,
+ 	GMTT	= 0x0394,
+ 	GPTC	= 0x0398,
+@@ -181,25 +183,39 @@ enum ravb_reg {
+ 
+ 	/* E-MAC registers */
+ 	ECMR	= 0x0500,
++	CXR20	= 0x0500,	/* Documented for RZ/G2L only */
+ 	RFLR	= 0x0508,
++	CXR2A	= 0x0508,	/* Documented for RZ/G2L only */
+ 	ECSR	= 0x0510,
+ 	ECSIPR	= 0x0518,
+ 	PIR	= 0x0520,
+ 	PSR	= 0x0528,
+ 	PIPR	= 0x052c,
++	CXR31	= 0x0530,	/* Documented for RZ/G2L only */
++	CXR35	= 0x0540,	/* Documented for RZ/G2L only */
+ 	MPR	= 0x0558,
+ 	PFTCR	= 0x055c,
+ 	PFRCR	= 0x0560,
+ 	GECMR	= 0x05b0,
+ 	MAHR	= 0x05c0,
+ 	MALR	= 0x05c8,
+-	TROCR	= 0x0700,	/* R-Car Gen3 only */
++	TROCR	= 0x0700,	/* R-Car Gen3 and RZ/G2L only */
++	CDCR	= 0x0708,	/* Documented for RZ/G2L only */
++	LCCR	= 0x0710,	/* Documented for RZ/G2L only */
+ 	CEFCR	= 0x0740,
+ 	FRECR	= 0x0748,
+ 	TSFRCR	= 0x0750,
+ 	TLFRCR	= 0x0758,
+ 	RFCR	= 0x0760,
++	CERCR	= 0x0768,	/* Documented for RZ/G2L only */
++	CEECR	= 0x0770,	/* Documented for RZ/G2L only */
+ 	MAFCR	= 0x0778,
++	LPTXMOD2 = 0x07B4,	/* Documented for RZ/G2L only */
++	LPTXGTH1 = 0x07C0,	/* Documented for RZ/G2L only */
++	LPTXMTH1 = 0x07D0,	/* Documented for RZ/G2L only */
++	CSR0     = 0x0800,	/* Documented for RZ/G2L only */
++	CSR1     = 0x0804,	/* Documented for RZ/G2L only */
++	CSR2     = 0x0808,	/* Documented for RZ/G2L only */
  };
  
+ 
+@@ -216,6 +232,7 @@ enum CCC_BIT {
+ 	CCC_CSEL_HPB	= 0x00010000,
+ 	CCC_CSEL_ETH_TX	= 0x00020000,
+ 	CCC_CSEL_GMII_REF = 0x00030000,
++	CCC_BOC		= 0x00100000,	/* Documented for RZ/G2L only */
+ 	CCC_LBME	= 0x01000000,
+ };
+ 
+@@ -804,16 +821,21 @@ enum TID_BIT {
+ enum ECMR_BIT {
+ 	ECMR_PRM	= 0x00000001,
+ 	ECMR_DM		= 0x00000002,
++	CXR20_LPM	= 0x00000010,	/* Documented for RZ/G2L only */
+ 	ECMR_TE		= 0x00000020,
+ 	ECMR_RE		= 0x00000040,
+ 	ECMR_MPDE	= 0x00000200,
++	CXR20_CER	= 0x00001000,	/* Documented for RZ/G2L only */
+ 	ECMR_TXF	= 0x00010000,	/* Documented for R-Car Gen3 only */
+ 	ECMR_RXF	= 0x00020000,
+ 	ECMR_PFR	= 0x00040000,
+ 	ECMR_ZPF	= 0x00080000,	/* Documented for R-Car Gen3 only */
+ 	ECMR_RZPF	= 0x00100000,
+ 	ECMR_DPAD	= 0x00200000,
++	CXR20_CXSER	= 0x00400000,	/* Documented for RZ/G2L only */
+ 	ECMR_RCSC	= 0x00800000,
++	CXR20_TCPT	= 0x01000000,	/* Documented for RZ/G2L only */
++	CXR20_RCPT	= 0x02000000,	/* Documented for RZ/G2L only */
+ 	ECMR_TRCCM	= 0x04000000,
+ };
+ 
+@@ -823,6 +845,7 @@ enum ECSR_BIT {
+ 	ECSR_MPD	= 0x00000002,
+ 	ECSR_LCHNG	= 0x00000004,
+ 	ECSR_PHYI	= 0x00000008,
++	ECSR_RFRI	= 0x00000010,	/* Documented for RZ/G2L only */
+ };
+ 
+ /* ECSIPR */
+@@ -862,6 +885,14 @@ enum GECMR_BIT {
+ 	GECMR_SPEED_1000 = 0x00000001,
+ };
+ 
++/* GECMR */
++enum RGETH_GECMR_BIT {
++	RGETH_GECMR_SPEED	= 0x00000030,
++	RGETH_GECMR_SPEED_10	= 0x00000000,
++	RGETH_GECMR_SPEED_100	= 0x00000010,
++	RGETH_GECMR_SPEED_1000	= 0x00000020,
++};
++
+ /* The Ethernet AVB descriptor definitions. */
+ struct ravb_desc {
+ 	__le16 ds;	/* Descriptor size */
+@@ -949,6 +980,54 @@ enum RAVB_QUEUE {
+ 	RAVB_NC,	/* Network Control Queue */
+ };
+ 
++enum CXR31_BIT {
++	CXR31_SEL_LINK0	= 0x00000001,
++	CXR31_SEL_LINK1	= 0x00000008,
++};
++
++enum CXR35_BIT {
++	CXR35_SEL_MODIN	= 0x00000100,
++};
++
++enum CSR0_BIT {
++	CSR0_CCM	= 0x00000001,
++	CSR0_TPE	= 0x00000010,
++	CSR0_RPE	= 0x00000020,
++	CSR0_TBP	= 0x00000100,
++	CSR0_RBP	= 0x00000200,
++	CSR0_FIFOCAP	= 0x00003000,
++};
++
++enum CSR1_BIT {
++	CSR1_TIP4	= 0x00000001,
++	CSR1_TTCP4	= 0x00000010,
++	CSR1_TUDP4	= 0x00000020,
++	CSR1_TICMP4	= 0x00000040,
++	CSR1_TTCP6	= 0x00100000,
++	CSR1_TUDP6	= 0x00200000,
++	CSR1_TICMP6	= 0x00400000,
++	CSR1_THOP	= 0x01000000,
++	CSR1_TROUT	= 0x02000000,
++	CSR1_TAHD	= 0x04000000,
++	CSR1_TDHD	= 0x08000000,
++	CSR1_ALL	= 0x0F700071,
++};
++
++enum CSR2_BIT {
++	CSR2_RIP4	= 0x00000001,
++	CSR2_RTCP4	= 0x00000010,
++	CSR2_RUDP4	= 0x00000020,
++	CSR2_RICMP4	= 0x00000040,
++	CSR2_RTCP6	= 0x00100000,
++	CSR2_RUDP6	= 0x00200000,
++	CSR2_RICMP6	= 0x00400000,
++	CSR2_RHOP	= 0x01000000,
++	CSR2_RROUT	= 0x02000000,
++	CSR2_RAHD	= 0x04000000,
++	CSR2_RDHD	= 0x08000000,
++	CSR2_ALL	= 0x0F700071,
++};
++
+ #define DBAT_ENTRY_NUM	22
+ #define RX_QUEUE_OFFSET	4
+ #define NUM_RX_QUEUE	2
+@@ -956,8 +1035,11 @@ enum RAVB_QUEUE {
+ 
+ #define RX_BUF_SZ	(2048 - ETH_FCS_LEN + sizeof(__sum16))
+ 
++#define RGETH_RCV_BUFF_MAX 8192
++#define RGETH_RCV_DESCRIPTOR_DATA_SIZE 4080
++
+ /* TX descriptors per packet */
+-#define NUM_TX_DESC_GEN2	2
++#define NUM_TX_DESC_GEN2	2	/* RCar Gen2 or RZ/G2L */
+ #define NUM_TX_DESC_GEN3	1
+ 
+ struct ravb_tstamp_skb {
+@@ -986,6 +1068,7 @@ struct ravb_ptp {
+ enum ravb_chip_id {
+ 	RCAR_GEN2,
+ 	RCAR_GEN3,
++	RZ_G2L,
+ };
+ 
  struct ravb_private {
+@@ -1040,6 +1123,11 @@ struct ravb_private {
+ 	unsigned txcidm:1;		/* TX Clock Internal Delay Mode */
+ 	unsigned rgmii_override:1;	/* Deprecated rgmii-*id behavior */
+ 	int num_tx_desc;		/* TX descriptors per packet */
++
++	int duplex;
++	struct ravb_rx_desc *rgeth_rx_ring[NUM_RX_QUEUE];
++	struct sk_buff *rxtop_skb;
++	struct reset_control *rstc;
+ };
+ 
+ static inline u32 ravb_read(struct net_device *ndev, enum ravb_reg reg)
 diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
-index 8f2358caef34..dc7654abfe55 100644
+index 7e6feda59f4a..e28a63de553d 100644
 --- a/drivers/net/ethernet/renesas/ravb_main.c
 +++ b/drivers/net/ethernet/renesas/ravb_main.c
-@@ -1274,7 +1274,7 @@ static int ravb_set_ringparam(struct net_device *ndev,
- 	if (netif_running(ndev)) {
- 		netif_device_detach(ndev);
- 		/* Stop PTP Clock driver */
--		if (info->no_ptp_cfg_active)
-+		if (info->gptp)
- 			ravb_ptp_stop(ndev);
- 		/* Wait for DMA stopping */
- 		error = ravb_stop_dma(ndev);
-@@ -1306,7 +1306,7 @@ static int ravb_set_ringparam(struct net_device *ndev,
- 		ravb_emac_init(ndev);
- 
- 		/* Initialise PTP Clock driver */
--		if (info->no_ptp_cfg_active)
-+		if (info->gptp)
- 			ravb_ptp_init(ndev, priv->pdev);
- 
- 		netif_device_attach(ndev);
-@@ -1446,7 +1446,7 @@ static int ravb_open(struct net_device *ndev)
- 	ravb_emac_init(ndev);
- 
- 	/* Initialise PTP Clock driver */
--	if (info->no_ptp_cfg_active)
-+	if (info->gptp)
- 		ravb_ptp_init(ndev, priv->pdev);
- 
- 	netif_tx_start_all_queues(ndev);
-@@ -1460,7 +1460,7 @@ static int ravb_open(struct net_device *ndev)
- 
- out_ptp_stop:
- 	/* Stop PTP Clock driver */
--	if (info->no_ptp_cfg_active)
-+	if (info->gptp)
- 		ravb_ptp_stop(ndev);
- out_free_irq_nc_tx:
- 	if (!info->multi_irqs)
-@@ -1508,7 +1508,7 @@ static void ravb_tx_timeout_work(struct work_struct *work)
- 	netif_tx_stop_all_queues(ndev);
- 
- 	/* Stop PTP Clock driver */
--	if (info->no_ptp_cfg_active)
-+	if (info->gptp)
- 		ravb_ptp_stop(ndev);
- 
- 	/* Wait for DMA stopping */
-@@ -1543,7 +1543,7 @@ static void ravb_tx_timeout_work(struct work_struct *work)
- 
- out:
- 	/* Initialise PTP Clock driver */
--	if (info->no_ptp_cfg_active)
-+	if (info->gptp)
- 		ravb_ptp_init(ndev, priv->pdev);
- 
- 	netif_tx_start_all_queues(ndev);
-@@ -1752,7 +1752,7 @@ static int ravb_close(struct net_device *ndev)
- 	ravb_write(ndev, 0, TIC);
- 
- 	/* Stop PTP Clock driver */
--	if (info->no_ptp_cfg_active)
-+	if (info->gptp)
- 		ravb_ptp_stop(ndev);
- 
- 	/* Set the config mode to stop the AVB-DMAC's processes */
-@@ -2018,7 +2018,7 @@ static const struct ravb_hw_info ravb_gen3_hw_info = {
- 	.internal_delay = 1,
- 	.tx_counters = 1,
- 	.multi_irqs = 1,
--	.ptp_cfg_active = 1,
-+	.ccc_gac = 1,
+@@ -29,6 +29,7 @@
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+ #include <linux/sys_soc.h>
++#include <linux/reset.h>
+ 
+ #include <asm/div64.h>
+ 
+@@ -82,6 +83,23 @@ static int ravb_config(struct net_device *ndev)
+ 	return error;
+ }
+ 
++static void rgeth_set_rate(struct net_device *ndev)
++{
++	struct ravb_private *priv = netdev_priv(ndev);
++
++	switch (priv->speed) {
++	case 10:                /* 10BASE */
++		ravb_write(ndev, RGETH_GECMR_SPEED_10, GECMR);
++		break;
++	case 100:               /* 100BASE */
++		ravb_write(ndev, RGETH_GECMR_SPEED_100, GECMR);
++		break;
++	case 1000:              /* 1000BASE */
++		ravb_write(ndev, RGETH_GECMR_SPEED_1000, GECMR);
++		break;
++	}
++}
++
+ static void ravb_set_rate(struct net_device *ndev)
+ {
+ 	struct ravb_private *priv = netdev_priv(ndev);
+@@ -217,6 +235,29 @@ static int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only)
+ }
+ 
+ /* Free skb's and DMA buffers for Ethernet AVB */
++static void rgeth_ring_free_ex(struct net_device *ndev, int q)
++{
++	struct ravb_private *priv = netdev_priv(ndev);
++	int ring_size;
++	int i;
++
++	for (i = 0; i < priv->num_rx_ring[q]; i++) {
++		struct ravb_rx_desc *desc = &priv->rgeth_rx_ring[q][i];
++
++		if (!dma_mapping_error(ndev->dev.parent,
++				       le32_to_cpu(desc->dptr)))
++			dma_unmap_single(ndev->dev.parent,
++					 le32_to_cpu(desc->dptr),
++					 RGETH_RCV_BUFF_MAX,
++					 DMA_FROM_DEVICE);
++	}
++	ring_size = sizeof(struct ravb_rx_desc) *
++		    (priv->num_rx_ring[q] + 1);
++	dma_free_coherent(ndev->dev.parent, ring_size, priv->rgeth_rx_ring[q],
++			  priv->rx_desc_dma[q]);
++	priv->rgeth_rx_ring[q] = NULL;
++}
++
+ static void ravb_ring_free_ex(struct net_device *ndev, int q)
+ {
+ 	struct ravb_private *priv = netdev_priv(ndev);
+@@ -247,8 +288,12 @@ static void ravb_ring_free(struct net_device *ndev, int q)
+ 	int ring_size;
+ 	int i;
+ 
+-	if (priv->rx_ring[q]) {
+-		ravb_ring_free_ex(ndev, q);
++	if (priv->chip_id == RZ_G2L) {
++		if (priv->rgeth_rx_ring[q])
++			rgeth_ring_free_ex(ndev, q);
++	} else {
++		if (priv->rx_ring[q])
++			ravb_ring_free_ex(ndev, q);
+ 	}
+ 
+ 	if (priv->tx_ring[q]) {
+@@ -281,6 +326,36 @@ static void ravb_ring_free(struct net_device *ndev, int q)
+ }
+ 
+ /* Format skb and descriptor buffer for Ethernet AVB */
++static void rgeth_ring_format_ex(struct net_device *ndev, int q)
++{
++	struct ravb_private *priv = netdev_priv(ndev);
++	struct ravb_rx_desc *rx_desc;
++	int rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q];
++	dma_addr_t dma_addr;
++	int i;
++
++	memset(priv->rgeth_rx_ring[q], 0, rx_ring_size);
++	/* Build RX ring buffer */
++	for (i = 0; i < priv->num_rx_ring[q]; i++) {
++		/* RX descriptor */
++		rx_desc = &priv->rgeth_rx_ring[q][i];
++		rx_desc->ds_cc = cpu_to_le16(RGETH_RCV_DESCRIPTOR_DATA_SIZE);
++		dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data,
++					  RGETH_RCV_BUFF_MAX,
++					  DMA_FROM_DEVICE);
++		/* We just set the data size to 0 for a failed mapping which
++		 * should prevent DMA from happening...
++		 */
++		if (dma_mapping_error(ndev->dev.parent, dma_addr))
++			rx_desc->ds_cc = cpu_to_le16(0);
++		rx_desc->dptr = cpu_to_le32(dma_addr);
++		rx_desc->die_dt = DT_FEMPTY;
++	}
++	rx_desc = &priv->rgeth_rx_ring[q][i];
++	rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]);
++	rx_desc->die_dt = DT_LINKFIX; /* type */
++}
++
+ static void ravb_ring_format_ex(struct net_device *ndev, int q)
+ {
+ 	struct ravb_private *priv = netdev_priv(ndev);
+@@ -326,7 +401,10 @@ static void ravb_ring_format(struct net_device *ndev, int q)
+ 	priv->dirty_tx[q] = 0;
+ 
+ 	/* Build RX ring buffer */
+-	ravb_ring_format_ex(ndev, q);
++	if (priv->chip_id == RZ_G2L)
++		rgeth_ring_format_ex(ndev, q);
++	else
++		ravb_ring_format_ex(ndev, q);
+ 
+ 	memset(priv->tx_ring[q], 0, tx_ring_size);
+ 	/* Build TX ring buffer */
+@@ -356,7 +434,7 @@ static void ravb_ring_format(struct net_device *ndev, int q)
+ static int ravb_ring_init(struct net_device *ndev, int q)
+ {
+ 	struct ravb_private *priv = netdev_priv(ndev);
+-	size_t skb_sz = RX_BUF_SZ;
++	size_t skb_sz = (priv->chip_id == RZ_G2L) ? RGETH_RCV_BUFF_MAX : RX_BUF_SZ;
+ 	int num_tx_desc = priv->num_tx_desc;
+ 	struct sk_buff *skb;
+ 	int ring_size;
+@@ -387,12 +465,23 @@ static int ravb_ring_init(struct net_device *ndev, int q)
+ 	}
+ 
+ 	/* Allocate all RX descriptors. */
+-	ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1);
+-	priv->rx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size,
+-					      &priv->rx_desc_dma[q],
+-					      GFP_KERNEL);
+-	if (!priv->rx_ring[q])
+-		goto error;
++	if (priv->chip_id == RZ_G2L) {
++		ring_size = sizeof(struct ravb_rx_desc) * (priv->num_rx_ring[q] + 1);
++
++		priv->rgeth_rx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size,
++							    &priv->rx_desc_dma[q],
++							    GFP_KERNEL);
++		if (!priv->rgeth_rx_ring[q])
++			goto error;
++	} else {
++		ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1);
++
++		priv->rx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size,
++						      &priv->rx_desc_dma[q],
++						      GFP_KERNEL);
++		if (!priv->rx_ring[q])
++			goto error;
++	}
+ 
+ 	priv->dirty_rx[q] = 0;
+ 
+@@ -414,6 +503,45 @@ static int ravb_ring_init(struct net_device *ndev, int q)
+ }
+ 
+ /* E-MAC init function */
++static void rgeth_emac_init_ex(struct net_device *ndev)
++{
++	struct ravb_private *priv = netdev_priv(ndev);
++
++	/* Receive frame limit set register */
++	ravb_write(ndev, RGETH_RCV_BUFF_MAX + ETH_FCS_LEN, RFLR);
++
++	/* PAUSE prohibition */
++	ravb_write(ndev, ECMR_ZPF | (priv->duplex ? ECMR_DM : 0) |
++			 ECMR_TE | ECMR_RE | CXR20_RCPT |
++			 ECMR_TXF | ECMR_RXF | ECMR_PRM, ECMR);
++
++	rgeth_set_rate(ndev);
++
++	/* Set MAC address */
++	ravb_write(ndev,
++		   (ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
++		   (ndev->dev_addr[2] << 8)  | (ndev->dev_addr[3]), MAHR);
++	ravb_write(ndev,
++		   (ndev->dev_addr[4] << 8)  | (ndev->dev_addr[5]), MALR);
++
++	/* E-MAC status register clear */
++	ravb_write(ndev, ECSR_ICD | ECSR_LCHNG | ECSR_RFRI, ECSR);
++	ravb_write(ndev, CSR0_TPE | CSR0_RPE, CSR0);
++
++	/* E-MAC interrupt enable register */
++	ravb_write(ndev, ECSIPR_ICDIP, ECSIPR);
++
++	ravb_write(ndev, ravb_read(ndev, CXR31)
++			 & ~CXR31_SEL_LINK1, CXR31);
++	if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) {
++		ravb_write(ndev, ravb_read(ndev, CXR31)
++			 | CXR31_SEL_LINK0, CXR31);
++	} else {
++		ravb_write(ndev, ravb_read(ndev, CXR31)
++			 & ~CXR31_SEL_LINK0, CXR31);
++	}
++}
++
+ static void ravb_emac_init_ex(struct net_device *ndev)
+ {
+ 	/* Receive frame limit set register */
+@@ -442,10 +570,41 @@ static void ravb_emac_init_ex(struct net_device *ndev)
+ 
+ static void ravb_emac_init(struct net_device *ndev)
+ {
+-	ravb_emac_init_ex(ndev);
++	struct ravb_private *priv = netdev_priv(ndev);
++
++	if (priv->chip_id == RZ_G2L)
++		rgeth_emac_init_ex(ndev);
++	else
++		ravb_emac_init_ex(ndev);
++
+ }
+ 
+ /* Device init function for Ethernet AVB */
++static void rgeth_dmac_init_ex(struct net_device *ndev)
++{
++	/* Set AVB RX */
++	ravb_write(ndev, 0x60000000, RCR);
++
++	/* Set Max Frame Length (RTC) */
++	ravb_write(ndev, 0x7ffc0000 | RGETH_RCV_BUFF_MAX, RTC);
++
++	/* Set FIFO size */
++	ravb_write(ndev, 0x00222200, TGC);
++
++	ravb_write(ndev, 0, TCCR);
++
++	/* Frame receive */
++	ravb_write(ndev, RIC0_FRE0, RIC0);
++	/* Disable FIFO full warning */
++	ravb_write(ndev, 0x0, RIC1);
++	/* Receive FIFO full error, descriptor empty */
++	ravb_write(ndev, RIC2_QFE0 | RIC2_RFFE, RIC2);
++
++	ravb_write(ndev, 0x0, RIC3);
++
++	ravb_write(ndev, TIC_FTE0, TIC);
++}
++
+ static void ravb_dmac_init_ex(struct net_device *ndev)
+ {
+ 	struct ravb_private *priv = netdev_priv(ndev);
+@@ -479,6 +638,7 @@ static void ravb_dmac_init_ex(struct net_device *ndev)
+ 
+ static int ravb_dmac_init(struct net_device *ndev)
+ {
++	struct ravb_private *priv = netdev_priv(ndev);
+ 	int error;
+ 
+ 	/* Set CONFIG mode */
+@@ -499,7 +659,10 @@ static int ravb_dmac_init(struct net_device *ndev)
+ 	ravb_ring_format(ndev, RAVB_BE);
+ 	ravb_ring_format(ndev, RAVB_NC);
+ 
+-	ravb_dmac_init_ex(ndev);
++	if (priv->chip_id == RZ_G2L)
++		rgeth_dmac_init_ex(ndev);
++	else
++		ravb_dmac_init_ex(ndev);
+ 
+ 	/* Setting the control will start the AVB-DMAC process. */
+ 	ravb_modify(ndev, CCC, CCC_OPC, CCC_OPC_OPERATION);
+@@ -545,6 +708,23 @@ static void ravb_get_tx_tstamp(struct net_device *ndev)
+ 	}
+ }
+ 
++static void rgeth_rx_csum(struct sk_buff *skb)
++{
++	u8 *hw_csum;
++
++	/* The hardware checksum is contained in sizeof(__sum16) (2) bytes
++	 * appended to packet data
++	 */
++	if (unlikely(skb->len < sizeof(__sum16)))
++		return;
++	hw_csum = skb_tail_pointer(skb) - sizeof(__sum16);
++
++	if (*hw_csum == 0)
++		skb->ip_summed = CHECKSUM_UNNECESSARY;
++	else
++		skb->ip_summed = CHECKSUM_NONE;
++}
++
+ static void ravb_rx_csum(struct sk_buff *skb)
+ {
+ 	u8 *hw_csum;
+@@ -561,6 +741,143 @@ static void ravb_rx_csum(struct sk_buff *skb)
+ }
+ 
+ /* Packet receive function for Ethernet AVB */
++struct sk_buff *rgeth_get_skb(struct net_device *ndev,  int q, int entry,
++			      struct ravb_rx_desc *desc)
++{
++	struct ravb_private *priv = netdev_priv(ndev);
++	struct sk_buff *skb;
++
++	skb = priv->rx_skb[q][entry];
++	priv->rx_skb[q][entry] = NULL;
++	dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
++			 ALIGN(RGETH_RCV_BUFF_MAX, 16), DMA_FROM_DEVICE);
++
++	return skb;
++}
++
++static bool rgeth_rx_ex(struct net_device *ndev, int *quota, int q)
++{
++	struct ravb_private *priv = netdev_priv(ndev);
++	int entry = priv->cur_rx[q] % priv->num_rx_ring[q];
++	int boguscnt = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
++	struct net_device_stats *stats = &priv->stats[q];
++	struct ravb_rx_desc *desc;
++	struct sk_buff *skb;
++	dma_addr_t dma_addr;
++	u8  desc_status;
++	u8  die_dt;
++	u16 pkt_len;
++	int limit;
++
++	boguscnt = min(boguscnt, *quota);
++	limit = boguscnt;
++	desc = &priv->rgeth_rx_ring[q][entry];
++	while (desc->die_dt != DT_FEMPTY) {
++		/* Descriptor type must be checked before all other reads */
++		dma_rmb();
++		desc_status = desc->msc;
++		pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS;
++
++		if (--boguscnt < 0)
++			break;
++
++		/* We use 0-byte descriptors to mark the DMA mapping errors */
++		if (!pkt_len)
++			continue;
++
++		if (desc_status & MSC_MC)
++			stats->multicast++;
++
++		if (desc_status & (MSC_CRC | MSC_RFE | MSC_RTSF | MSC_RTLF | MSC_CEEF)) {
++			stats->rx_errors++;
++			if (desc_status & MSC_CRC)
++				stats->rx_crc_errors++;
++			if (desc_status & MSC_RFE)
++				stats->rx_frame_errors++;
++			if (desc_status & (MSC_RTLF | MSC_RTSF))
++				stats->rx_length_errors++;
++			if (desc_status & MSC_CEEF)
++				stats->rx_missed_errors++;
++		} else {
++			die_dt = desc->die_dt & 0xF0;
++			if (die_dt == DT_FSINGLE) {
++				skb = rgeth_get_skb(ndev, q, entry, desc);
++				skb_put(skb, pkt_len);
++				skb->protocol = eth_type_trans(skb, ndev);
++				if (ndev->features & NETIF_F_RXCSUM)
++					rgeth_rx_csum(skb);
++				napi_gro_receive(&priv->napi[q], skb);
++				stats->rx_packets++;
++				stats->rx_bytes += pkt_len;
++			} else if (die_dt == DT_FSTART) {
++				priv->rxtop_skb = rgeth_get_skb(ndev, q, entry, desc);
++				skb_put(priv->rxtop_skb, pkt_len);
++			} else if (die_dt == DT_FMID) {
++				skb = rgeth_get_skb(ndev, q, entry, desc);
++				skb_copy_to_linear_data_offset(priv->rxtop_skb,
++							       priv->rxtop_skb->len,
++							       skb->data,
++							       pkt_len);
++				skb_put(priv->rxtop_skb, pkt_len);
++				dev_kfree_skb(skb);
++			} else if (die_dt == DT_FEND) {
++				skb = rgeth_get_skb(ndev, q, entry, desc);
++				skb_copy_to_linear_data_offset(priv->rxtop_skb,
++							       priv->rxtop_skb->len,
++							       skb->data,
++							       pkt_len);
++				skb_put(priv->rxtop_skb, pkt_len);
++				dev_kfree_skb(skb);
++				priv->rxtop_skb->protocol =
++					eth_type_trans(priv->rxtop_skb, ndev);
++				if (ndev->features & NETIF_F_RXCSUM)
++					rgeth_rx_csum(skb);
++				napi_gro_receive(&priv->napi[q],
++						 priv->rxtop_skb);
++				stats->rx_packets++;
++				stats->rx_bytes += priv->rxtop_skb->len;
++			}
++		}
++
++		entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q];
++		desc = &priv->rgeth_rx_ring[q][entry];
++	}
++
++	/* Refill the RX ring buffers. */
++	for (; priv->cur_rx[q] - priv->dirty_rx[q] > 0; priv->dirty_rx[q]++) {
++		entry = priv->dirty_rx[q] % priv->num_rx_ring[q];
++		desc = &priv->rgeth_rx_ring[q][entry];
++		desc->ds_cc = cpu_to_le16(RGETH_RCV_DESCRIPTOR_DATA_SIZE);
++
++		if (!priv->rx_skb[q][entry]) {
++			skb = netdev_alloc_skb(ndev,
++					       RGETH_RCV_BUFF_MAX + RAVB_ALIGN - 1);
++			if (!skb)
++				break;  /* Better luck next round. */
++			ravb_set_buffer_align(skb);
++			dma_addr = dma_map_single(ndev->dev.parent,
++						  skb->data,
++						  le16_to_cpu(RGETH_RCV_BUFF_MAX),
++						  DMA_FROM_DEVICE);
++			skb_checksum_none_assert(skb);
++			/* We just set the data size to 0 for a failed mapping
++			 * which should prevent DMA  from happening...
++			 */
++			if (dma_mapping_error(ndev->dev.parent, dma_addr))
++				desc->ds_cc = cpu_to_le16(0);
++			desc->dptr = cpu_to_le32(dma_addr);
++			priv->rx_skb[q][entry] = skb;
++		}
++		/* Descriptor type must be set after all the above writes */
++		dma_wmb();
++		desc->die_dt = DT_FEMPTY;
++	}
++
++	*quota -= limit - (++boguscnt);
++
++	return boguscnt <= 0;
++}
++
+ static bool ravb_rx_ex(struct net_device *ndev, int *quota, int q)
+ {
+ 	struct ravb_private *priv = netdev_priv(ndev);
+@@ -678,7 +995,10 @@ static bool ravb_rx_ex(struct net_device *ndev, int *quota, int q)
+ 
+ static bool ravb_rx(struct net_device *ndev, int *quota, int q)
+ {
+-	return ravb_rx_ex(ndev, quota, q);
++	struct ravb_private *priv = netdev_priv(ndev);
++
++	return (priv->chip_id == RZ_G2L) ?
++		rgeth_rx_ex(ndev, quota, q) : ravb_rx_ex(ndev, quota, q);
+ }
+ 
+ static void ravb_rcv_snd_disable(struct net_device *ndev)
+@@ -696,11 +1016,15 @@ static void ravb_rcv_snd_enable(struct net_device *ndev)
+ /* function for waiting dma process finished */
+ static int ravb_stop_dma(struct net_device *ndev)
+ {
++	struct ravb_private *priv = netdev_priv(ndev);
+ 	int error;
+ 
+ 	/* Wait for stopping the hardware TX process */
+-	error = ravb_wait(ndev, TCCR,
+-			  TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 0);
++	if (priv->chip_id == RZ_G2L)
++		error = ravb_wait(ndev, TCCR, TCCR_TSRQ0, 0);
++	else
++		error = ravb_wait(ndev, TCCR,
++				  TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 0);
+ 	if (error)
+ 		return error;
+ 
+@@ -730,7 +1054,7 @@ static void ravb_emac_interrupt_unlocked(struct net_device *ndev)
+ 	ecsr = ravb_read(ndev, ECSR);
+ 	ravb_write(ndev, ecsr, ECSR);	/* clear interrupt */
+ 
+-	if (ecsr & ECSR_MPD)
++	if (priv->chip_id != RZ_G2L && (ecsr & ECSR_MPD))
+ 		pm_wakeup_event(&priv->pdev->dev, 0);
+ 	if (ecsr & ECSR_ICD)
+ 		ndev->stats.tx_carrier_errors++;
+@@ -823,11 +1147,13 @@ static bool ravb_queue_interrupt(struct net_device *ndev, int q)
+ 
+ static bool ravb_timestamp_interrupt(struct net_device *ndev)
+ {
++	struct ravb_private *priv = netdev_priv(ndev);
+ 	u32 tis = ravb_read(ndev, TIS);
+ 
+ 	if (tis & TIS_TFUF) {
+ 		ravb_write(ndev, ~(TIS_TFUF | TIS_RESERVED), TIS);
+-		ravb_get_tx_tstamp(ndev);
++		if (priv->chip_id != RZ_G2L)
++			ravb_get_tx_tstamp(ndev);
+ 		return true;
+ 	}
+ 	return false;
+@@ -872,7 +1198,7 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id)
+ 	}
+ 
+ 	/* gPTP interrupt status summary */
+-	if (iss & ISS_CGIS) {
++	if (priv->chip_id != RZ_G2L && (iss & ISS_CGIS)) {
+ 		ravb_ptp_interrupt(ndev);
+ 		result = IRQ_HANDLED;
+ 	}
+@@ -947,12 +1273,20 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ 	int q = napi - priv->napi;
+ 	int mask = BIT(q);
+ 	int quota = budget;
++	int entry;
++	struct ravb_rx_desc *desc;
+ 
++	if (priv->chip_id == RZ_G2L) {
++		entry = priv->cur_rx[q] % priv->num_rx_ring[q];
++		desc = &priv->rgeth_rx_ring[q][entry];
++	}
+ 	/* Processing RX Descriptor Ring */
+ 	/* Clear RX interrupt */
+ 	ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
+-	if (ravb_rx(ndev, &quota, q))
+-		goto out;
++	if (priv->chip_id != RZ_G2L || desc->die_dt != DT_FEMPTY) {
++		if (ravb_rx(ndev, &quota, q))
++			goto out;
++	}
+ 
+ 	/* Processing TX Descriptor Ring */
+ 	spin_lock_irqsave(&priv->lock, flags);
+@@ -986,6 +1320,18 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ 	return budget - quota;
+ }
+ 
++static void rgeth_set_duplex(struct net_device *ndev)
++{
++	struct ravb_private *priv = netdev_priv(ndev);
++	u32 ecmr = ravb_read(ndev, ECMR);
++
++	if (priv->duplex)       /* Full */
++		ecmr |=  ECMR_DM;
++	else                    /* Half */
++		ecmr &= ~ECMR_DM;
++	ravb_write(ndev, ecmr, ECMR);
++}
++
+ /* PHY state control function */
+ static void ravb_adjust_link(struct net_device *ndev)
+ {
+@@ -1001,10 +1347,19 @@ static void ravb_adjust_link(struct net_device *ndev)
+ 		ravb_rcv_snd_disable(ndev);
+ 
+ 	if (phydev->link) {
++		if (priv->chip_id == RZ_G2L && phydev->duplex != priv->duplex) {
++			new_state = true;
++			priv->duplex = phydev->duplex;
++			rgeth_set_duplex(ndev);
++		}
++
+ 		if (phydev->speed != priv->speed) {
+ 			new_state = true;
+ 			priv->speed = phydev->speed;
+-			ravb_set_rate(ndev);
++			if (priv->chip_id == RZ_G2L)
++				rgeth_set_rate(ndev);
++			else
++				ravb_set_rate(ndev);
+ 		}
+ 		if (!priv->link) {
+ 			ravb_modify(ndev, ECMR, ECMR_TXF, 0);
+@@ -1015,6 +1370,8 @@ static void ravb_adjust_link(struct net_device *ndev)
+ 		new_state = true;
+ 		priv->link = 0;
+ 		priv->speed = 0;
++		if (priv->chip_id == RZ_G2L)
++			priv->duplex = -1;
+ 	}
+ 
+ 	/* Enable TX and RX right over here, if E-MAC change is ignored */
+@@ -1044,6 +1401,7 @@ static int ravb_phy_init(struct net_device *ndev)
+ 
+ 	priv->link = 0;
+ 	priv->speed = 0;
++	priv->duplex = -1;
+ 
+ 	/* Try connecting to PHY */
+ 	pn = of_parse_phandle(np, "phy-handle", 0);
+@@ -1082,15 +1440,23 @@ static int ravb_phy_init(struct net_device *ndev)
+ 		netdev_info(ndev, "limited PHY to 100Mbit/s\n");
+ 	}
+ 
+-	/* 10BASE, Pause and Asym Pause is not supported */
+-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
+-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
+-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT);
+-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
++	if (priv->chip_id == RZ_G2L) {
++		if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID)
++			ravb_write(ndev, ravb_read(ndev, CXR35) | CXR35_SEL_MODIN, CXR35);
++		else if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII)
++			ravb_write(ndev, 0x3E80000, CXR35);
++	} else {
+ 
+-	/* Half Duplex is not supported */
+-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+-	phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
++		/* 10BASE, Pause and Asym Pause is not supported */
++		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
++		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
++		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT);
++		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
++
++		/* Half Duplex is not supported */
++		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
++		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
++	}
+ 
+ 	phy_attached_info(phydev);
+ 
+@@ -1133,6 +1499,24 @@ static void ravb_set_msglevel(struct net_device *ndev, u32 value)
+ 	priv->msg_enable = value;
+ }
+ 
++static const char rgeth_gstrings_stats[][ETH_GSTRING_LEN] = {
++	"rx_queue_0_current",
++	"tx_queue_0_current",
++	"rx_queue_0_dirty",
++	"tx_queue_0_dirty",
++	"rx_queue_0_packets",
++	"tx_queue_0_packets",
++	"rx_queue_0_bytes",
++	"tx_queue_0_bytes",
++	"rx_queue_0_mcast_packets",
++	"rx_queue_0_errors",
++	"rx_queue_0_crc_errors",
++	"rx_queue_0_frame_errors",
++	"rx_queue_0_length_errors",
++	"rx_queue_0_csum_offload_errors",
++	"rx_queue_0_over_errors",
++};
++
+ static const char ravb_gstrings_stats[][ETH_GSTRING_LEN] = {
+ 	"rx_queue_0_current",
+ 	"tx_queue_0_current",
+@@ -1168,12 +1552,15 @@ static const char ravb_gstrings_stats[][ETH_GSTRING_LEN] = {
  };
  
- static const struct ravb_hw_info ravb_gen2_hw_info = {
-@@ -2037,7 +2037,7 @@ static const struct ravb_hw_info ravb_gen2_hw_info = {
- 	.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
- 	.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
- 	.aligned_tx = 1,
--	.no_ptp_cfg_active = 1,
-+	.gptp = 1,
+ #define RAVB_STATS_LEN	ARRAY_SIZE(ravb_gstrings_stats)
++#define RGETH_STATS_LEN	ARRAY_SIZE(rgeth_gstrings_stats)
+ 
+ static int ravb_get_sset_count(struct net_device *netdev, int sset)
+ {
++	struct ravb_private *priv = netdev_priv(netdev);
++
+ 	switch (sset) {
+ 	case ETH_SS_STATS:
+-		return RAVB_STATS_LEN;
++		return (priv->chip_id == RZ_G2L) ? RGETH_STATS_LEN : RAVB_STATS_LEN;
+ 	default:
+ 		return -EOPNOTSUPP;
+ 	}
+@@ -1183,7 +1570,7 @@ static void ravb_get_ethtool_stats(struct net_device *ndev,
+ 				   struct ethtool_stats *estats, u64 *data)
+ {
+ 	struct ravb_private *priv = netdev_priv(ndev);
+-	int num_queue = NUM_RX_QUEUE;
++	int num_queue = (priv->chip_id == RZ_G2L) ? 1 : NUM_RX_QUEUE;
+ 	int i = 0;
+ 	int q;
+ 
+@@ -1211,9 +1598,14 @@ static void ravb_get_ethtool_stats(struct net_device *ndev,
+ 
+ static void ravb_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+ {
++	struct ravb_private *priv = netdev_priv(ndev);
++
+ 	switch (stringset) {
+ 	case ETH_SS_STATS:
+-		memcpy(data, ravb_gstrings_stats, sizeof(ravb_gstrings_stats));
++		if (priv->chip_id == RZ_G2L)
++			memcpy(data, rgeth_gstrings_stats, sizeof(rgeth_gstrings_stats));
++		else
++			memcpy(data, ravb_gstrings_stats, sizeof(ravb_gstrings_stats));
+ 		break;
+ 	}
+ }
+@@ -1304,7 +1696,8 @@ static int ravb_get_ts_info(struct net_device *ndev,
+ 		(1 << HWTSTAMP_FILTER_NONE) |
+ 		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ 		(1 << HWTSTAMP_FILTER_ALL);
+-	info->phc_index = ptp_clock_index(priv->ptp.clock);
++	if (priv->chip_id != RZ_G2L)
++		info->phc_index = ptp_clock_index(priv->ptp.clock);
+ 
+ 	return 0;
+ }
+@@ -1348,6 +1741,21 @@ static const struct ethtool_ops ravb_ethtool_ops = {
+ 	.set_wol		= ravb_set_wol,
  };
  
- static const struct of_device_id ravb_match_table[] = {
-@@ -2080,7 +2080,7 @@ static void ravb_set_config_mode(struct net_device *ndev)
- 	struct ravb_private *priv = netdev_priv(ndev);
- 	const struct ravb_hw_info *info = priv->info;
- 
--	if (info->no_ptp_cfg_active) {
-+	if (info->gptp) {
++static const struct ethtool_ops rgeth_ethtool_ops = {
++	.nway_reset		= phy_ethtool_nway_reset,
++	.get_msglevel		= ravb_get_msglevel,
++	.set_msglevel		= ravb_set_msglevel,
++	.get_link		= ethtool_op_get_link,
++	.get_strings		= ravb_get_strings,
++	.get_ethtool_stats	= ravb_get_ethtool_stats,
++	.get_sset_count		= ravb_get_sset_count,
++	.get_ringparam		= ravb_get_ringparam,
++	.set_ringparam		= ravb_set_ringparam,
++	.get_ts_info		= ravb_get_ts_info,
++	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
++	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
++};
++
+ static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler,
+ 				struct net_device *ndev, struct device *dev,
+ 				const char *ch)
+@@ -1599,28 +2007,30 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+ 	desc->dptr = cpu_to_le32(dma_addr);
+ 
+ 	/* TX timestamp required */
+-	if (q == RAVB_NC) {
+-		ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC);
+-		if (!ts_skb) {
+-			if (num_tx_desc > 1) {
+-				desc--;
+-				dma_unmap_single(ndev->dev.parent, dma_addr,
+-						 len, DMA_TO_DEVICE);
++	if (priv->chip_id != RZ_G2L) {
++		if (q == RAVB_NC) {
++			ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC);
++			if (!ts_skb) {
++				if (num_tx_desc > 1) {
++					desc--;
++					dma_unmap_single(ndev->dev.parent, dma_addr,
++							 len, DMA_TO_DEVICE);
++				}
++				goto unmap;
+ 			}
+-			goto unmap;
++			ts_skb->skb = skb_get(skb);
++			ts_skb->tag = priv->ts_skb_tag++;
++			priv->ts_skb_tag &= 0x3ff;
++			list_add_tail(&ts_skb->list, &priv->ts_skb_list);
++
++			/* TAG and timestamp required flag */
++			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
++			desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR;
++			desc->ds_tagl |= cpu_to_le16(ts_skb->tag << 12);
+ 		}
+-		ts_skb->skb = skb_get(skb);
+-		ts_skb->tag = priv->ts_skb_tag++;
+-		priv->ts_skb_tag &= 0x3ff;
+-		list_add_tail(&ts_skb->list, &priv->ts_skb_list);
+ 
+-		/* TAG and timestamp required flag */
+-		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+-		desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR;
+-		desc->ds_tagl |= cpu_to_le16(ts_skb->tag << 12);
++		skb_tx_timestamp(skb);
+ 	}
+-
+-	skb_tx_timestamp(skb);
+ 	/* Descriptor type must be set after all the above writes */
+ 	dma_wmb();
+ 	if (num_tx_desc > 1) {
+@@ -1669,6 +2079,20 @@ static struct net_device_stats *ravb_get_stats(struct net_device *ndev)
+ 	stats0 = &priv->stats[RAVB_BE];
+ 	stats1 = &priv->stats[RAVB_NC];
+ 
++	if (priv->chip_id == RZ_G2L) {
++		nstats->tx_dropped += ravb_read(ndev, TROCR);
++		ravb_write(ndev, 0, TROCR);	/* (write clear) */
++		nstats->collisions += ravb_read(ndev, CDCR);
++		ravb_write(ndev, 0, CDCR);	/* (write clear) */
++		nstats->tx_carrier_errors += ravb_read(ndev, LCCR);
++		ravb_write(ndev, 0, LCCR);	/* (write clear) */
++
++		nstats->tx_carrier_errors += ravb_read(ndev, CERCR);
++		ravb_write(ndev, 0, CERCR);	/* (write clear) */
++		nstats->tx_carrier_errors += ravb_read(ndev, CEECR);
++		ravb_write(ndev, 0, CEECR);	/* (write clear) */
++	}
++
+ 	if (priv->chip_id == RCAR_GEN3) {
+ 		nstats->tx_dropped += ravb_read(ndev, TROCR);
+ 		ravb_write(ndev, 0, TROCR);	/* (write clear) */
+@@ -1729,10 +2153,12 @@ static int ravb_close(struct net_device *ndev)
+ 			   "device will be stopped after h/w processes are done.\n");
+ 
+ 	/* Clear the timestamp list */
+-	list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
+-		list_del(&ts_skb->list);
+-		kfree_skb(ts_skb->skb);
+-		kfree(ts_skb);
++	if (priv->chip_id != RZ_G2L) {
++		list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
++			list_del(&ts_skb->list);
++			kfree_skb(ts_skb->skb);
++			kfree(ts_skb);
++		}
+ 	}
+ 
+ 	/* PHY disconnect */
+@@ -1899,6 +2325,44 @@ static int ravb_set_features(struct net_device *ndev,
+ 	return 0;
+ }
+ 
++static int rgeth_set_features(struct net_device *ndev,
++			      netdev_features_t features)
++{
++	int error;
++	unsigned int reg = 0;
++	netdev_features_t changed = features ^ ndev->features;
++
++	reg = ravb_read(ndev, CSR0);
++
++	ravb_write(ndev, ravb_read(ndev, CSR0) & ~(CSR0_RPE | CSR0_TPE), CSR0);
++	error = ravb_wait(ndev, CSR0, CSR0_RPE | CSR0_TPE, 0);
++	if (error) {
++		ravb_write(ndev, reg, CSR0);
++		return error;
++	}
++
++	if (changed & NETIF_F_RXCSUM) {
++		if (features & NETIF_F_RXCSUM)
++			ravb_write(ndev, CSR2_ALL, CSR2);
++		else
++			ravb_write(ndev, 0, CSR2);
++	}
++
++	if (changed & NETIF_F_HW_CSUM) {
++		if (features & NETIF_F_HW_CSUM) {
++			ravb_write(ndev, CSR1_ALL, CSR1);
++			ndev->features |= NETIF_F_CSUM_MASK;
++		} else {
++			ravb_write(ndev, 0, CSR1);
++		}
++	}
++	ravb_write(ndev, reg, CSR0);
++
++	ndev->features = features;
++
++	return 0;
++}
++
+ static const struct net_device_ops ravb_netdev_ops = {
+ 	.ndo_open		= ravb_open,
+ 	.ndo_stop		= ravb_close,
+@@ -1914,6 +2378,20 @@ static const struct net_device_ops ravb_netdev_ops = {
+ 	.ndo_set_features	= ravb_set_features,
+ };
+ 
++static const struct net_device_ops rgeth_netdev_ops = {
++	.ndo_open               = ravb_open,
++	.ndo_stop               = ravb_close,
++	.ndo_start_xmit         = ravb_start_xmit,
++	.ndo_select_queue       = ravb_select_queue,
++	.ndo_get_stats          = ravb_get_stats,
++	.ndo_set_rx_mode        = ravb_set_rx_mode,
++	.ndo_tx_timeout         = ravb_tx_timeout,
++	.ndo_do_ioctl           = ravb_do_ioctl,
++	.ndo_validate_addr      = eth_validate_addr,
++	.ndo_set_mac_address    = eth_mac_addr,
++	.ndo_set_features       = rgeth_set_features,
++};
++
+ /* MDIO bus init function */
+ static int ravb_mdio_init(struct ravb_private *priv)
+ {
+@@ -1930,7 +2408,10 @@ static int ravb_mdio_init(struct ravb_private *priv)
+ 		return -ENOMEM;
+ 
+ 	/* Hook up MII support for ethtool */
+-	priv->mii_bus->name = "ravb_mii";
++	if (priv->chip_id == RZ_G2L)
++		priv->mii_bus->name = "rgeth_mii";
++	else
++		priv->mii_bus->name = "ravb_mii";
+ 	priv->mii_bus->parent = dev;
+ 	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
+ 		 pdev->name, pdev->id);
+@@ -1965,6 +2446,7 @@ static const struct of_device_id ravb_match_table[] = {
+ 	{ .compatible = "renesas,etheravb-rcar-gen2", .data = (void *)RCAR_GEN2 },
+ 	{ .compatible = "renesas,etheravb-r8a7795", .data = (void *)RCAR_GEN3 },
+ 	{ .compatible = "renesas,etheravb-rcar-gen3", .data = (void *)RCAR_GEN3 },
++	{ .compatible = "renesas,rzg2l-gether", .data = (void *)RZ_G2L },
+ 	{ }
+ };
+ MODULE_DEVICE_TABLE(of, ravb_match_table);
+@@ -2001,7 +2483,8 @@ static void ravb_set_config_mode(struct net_device *ndev)
+ 	if (priv->chip_id != RCAR_GEN3) {
  		ravb_modify(ndev, CCC, CCC_OPC, CCC_OPC_CONFIG);
  		/* Set CSEL value */
- 		ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB);
-@@ -2301,7 +2301,7 @@ static int ravb_probe(struct platform_device *pdev)
- 	INIT_LIST_HEAD(&priv->ts_skb_list);
- 
- 	/* Initialise PTP Clock driver */
--	if (info->ptp_cfg_active)
-+	if (info->ccc_gac)
- 		ravb_ptp_init(ndev, pdev);
- 
- 	/* Debug message level */
-@@ -2349,7 +2349,7 @@ static int ravb_probe(struct platform_device *pdev)
- 			  priv->desc_bat_dma);
- 
- 	/* Stop PTP Clock driver */
--	if (info->ptp_cfg_active)
-+	if (info->ccc_gac)
- 		ravb_ptp_stop(ndev);
- out_disable_refclk:
- 	clk_disable_unprepare(priv->refclk);
-@@ -2369,7 +2369,7 @@ static int ravb_remove(struct platform_device *pdev)
- 	const struct ravb_hw_info *info = priv->info;
- 
- 	/* Stop PTP Clock driver */
--	if (info->ptp_cfg_active)
-+	if (info->ccc_gac)
- 		ravb_ptp_stop(ndev);
- 
- 	clk_disable_unprepare(priv->refclk);
+-		ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB);
++		if (priv->chip_id == RCAR_GEN2)
++			ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB);
+ 	} else {
+ 		ravb_modify(ndev, CCC, CCC_OPC, CCC_OPC_CONFIG |
+ 			    CCC_GAC | CCC_CSEL_HPB);
+@@ -2082,20 +2565,11 @@ static int ravb_probe(struct platform_device *pdev)
+ 		return -EINVAL;
+ 	}
+ 
+-	/* Get base address */
+-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-	if (!res) {
+-		dev_err(&pdev->dev, "invalid resource\n");
+-		return -EINVAL;
+-	}
+-
+ 	ndev = alloc_etherdev_mqs(sizeof(struct ravb_private),
+ 				  NUM_TX_QUEUE, NUM_RX_QUEUE);
+ 	if (!ndev)
+ 		return -ENOMEM;
+ 
+-	/* The Ether-specific entries in the device structure. */
+-	ndev->base_addr = res->start;
+ 
+ 	chip_id = (enum ravb_chip_id)of_device_get_match_data(&pdev->dev);
+ 
+@@ -2104,11 +2578,19 @@ static int ravb_probe(struct platform_device *pdev)
+ 	priv = netdev_priv(ndev);
+ 	priv->chip_id = chip_id;
+ 
+-	ndev->features = NETIF_F_RXCSUM;
+-	ndev->hw_features = NETIF_F_RXCSUM;
+-
+-	pm_runtime_enable(&pdev->dev);
+-	pm_runtime_get_sync(&pdev->dev);
++	if (chip_id == RZ_G2L) {
++		ndev->hw_features |= (NETIF_F_HW_CSUM | NETIF_F_RXCSUM);
++		priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
++		if (IS_ERR(priv->rstc)) {
++			dev_err(&pdev->dev, "failed to get cpg reset\n");
++			free_netdev(ndev);
++			return PTR_ERR(priv->rstc);
++		}
++		reset_control_deassert(priv->rstc);
++	} else {
++		ndev->features = NETIF_F_RXCSUM;
++		ndev->hw_features = NETIF_F_RXCSUM;
++	}
+ 
+ 	if (chip_id == RCAR_GEN3)
+ 		irq = platform_get_irq_byname(pdev, "ch22");
+@@ -2120,18 +2602,24 @@ static int ravb_probe(struct platform_device *pdev)
+ 	}
+ 	ndev->irq = irq;
+ 
++	pm_runtime_enable(&pdev->dev);
++	pm_runtime_get_sync(&pdev->dev);
++
+ 	priv->ndev = ndev;
+ 	priv->pdev = pdev;
+ 	priv->num_tx_ring[RAVB_BE] = BE_TX_RING_SIZE;
+ 	priv->num_rx_ring[RAVB_BE] = BE_RX_RING_SIZE;
+ 	priv->num_tx_ring[RAVB_NC] = NC_TX_RING_SIZE;
+ 	priv->num_rx_ring[RAVB_NC] = NC_RX_RING_SIZE;
+-	priv->addr = devm_ioremap_resource(&pdev->dev, res);
++	priv->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ 	if (IS_ERR(priv->addr)) {
+ 		error = PTR_ERR(priv->addr);
+ 		goto out_release;
+ 	}
+ 
++	/* The Ether-specific entries in the device structure. */
++	ndev->base_addr = res->start;
++
+ 	spin_lock_init(&priv->lock);
+ 	INIT_WORK(&priv->work, ravb_tx_timeout_work);
+ 
+@@ -2168,6 +2656,8 @@ static int ravb_probe(struct platform_device *pdev)
+ 		}
+ 	}
+ 
++	priv->chip_id = chip_id;
++
+ 	priv->clk = devm_clk_get(&pdev->dev, NULL);
+ 	if (IS_ERR(priv->clk)) {
+ 		error = PTR_ERR(priv->clk);
+@@ -2181,30 +2671,39 @@ static int ravb_probe(struct platform_device *pdev)
+ 	}
+ 	clk_prepare_enable(priv->refclk);
+ 
+-	ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
+-	ndev->min_mtu = ETH_MIN_MTU;
++	if (chip_id != RZ_G2L) {
++		ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
++		ndev->min_mtu = ETH_MIN_MTU;
++	}
+ 
+ 	priv->num_tx_desc = chip_id == RCAR_GEN3 ?
+ 		NUM_TX_DESC_GEN3 : NUM_TX_DESC_GEN2;
+ 
+ 	/* Set function */
+-	ndev->netdev_ops = &ravb_netdev_ops;
+-	ndev->ethtool_ops = &ravb_ethtool_ops;
++	if  (chip_id == RZ_G2L) {
++		ndev->netdev_ops = &rgeth_netdev_ops;
++		ndev->ethtool_ops = &rgeth_ethtool_ops;
++	} else {
++		ndev->netdev_ops = &ravb_netdev_ops;
++		ndev->ethtool_ops = &ravb_ethtool_ops;
++	}
+ 
+ 	/* Set AVB config mode */
+ 	ravb_set_config_mode(ndev);
+ 
+-	/* Set GTI value */
+-	error = ravb_set_gti(ndev);
+-	if (error)
+-		goto out_disable_refclk;
++	if (priv->chip_id != RZ_G2L) {
++		/* Set GTI value */
++		error = ravb_set_gti(ndev);
++		if (error)
++			goto out_disable_refclk;
+ 
+-	/* Request GTI loading */
+-	ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
++		/* Request GTI loading */
++		ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
+ 
+-	if (priv->chip_id == RCAR_GEN3) {
+-		ravb_parse_delay_mode(np, ndev);
+-		ravb_set_delay_mode(ndev);
++		if (priv->chip_id == RCAR_GEN3) {
++			ravb_parse_delay_mode(np, ndev);
++			ravb_set_delay_mode(ndev);
++		}
+ 	}
+ 
+ 	/* Allocate descriptor base address table */
+@@ -2389,13 +2888,15 @@ static int __maybe_unused ravb_resume(struct device *dev)
+ 	/* Set AVB config mode */
+ 	ravb_set_config_mode(ndev);
+ 
+-	/* Set GTI value */
+-	ret = ravb_set_gti(ndev);
+-	if (ret)
+-		return ret;
++	if (priv->chip_id != RZ_G2L) {
++		/* Set GTI value */
++		ret = ravb_set_gti(ndev);
++		if (ret)
++			return ret;
+ 
+-	/* Request GTI loading */
+-	ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
++		/* Request GTI loading */
++		ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
++	}
+ 
+ 	if (priv->chip_id == RCAR_GEN3)
+ 		ravb_set_delay_mode(ndev);
 -- 
 2.17.1
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help