mirror of https://gitee.com/openkylin/linux.git
Merge branch 'ravb-gbit-refactor'
Biju Das says: ==================== Add Factorisation code to support Gigabit Ethernet driver The DMAC and EMAC blocks of Gigabit Ethernet IP found on RZ/G2L SoC are similar to the R-Car Ethernet AVB IP. The Gigabit Ethernet IP consists of Ethernet controller (E-MAC), Internal TCP/IP Offload Engine (TOE) and Dedicated Direct memory access controller (DMAC). With a few changes in the driver we can support both IPs. This patch series aims to add factorisation code to support RZ/G2L SoC, hardware feature bits for gPTP feature, Multiple irq feature and optional reset support. Ref:- * https://lore.kernel.org/linux-renesas-soc/TYCPR01MB59334319695607A2683C1A5E86E59@TYCPR01MB5933.jpnprd01.prod.outlook.com/T/#t ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b87a542c5b
|
@ -956,10 +956,6 @@ enum RAVB_QUEUE {
|
|||
|
||||
#define RX_BUF_SZ (2048 - ETH_FCS_LEN + sizeof(__sum16))
|
||||
|
||||
/* TX descriptors per packet */
|
||||
#define NUM_TX_DESC_GEN2 2
|
||||
#define NUM_TX_DESC_GEN3 1
|
||||
|
||||
struct ravb_tstamp_skb {
|
||||
struct list_head list;
|
||||
struct sk_buff *skb;
|
||||
|
@ -983,17 +979,19 @@ struct ravb_ptp {
|
|||
struct ravb_ptp_perout perout[N_PER_OUT];
|
||||
};
|
||||
|
||||
enum ravb_chip_id {
|
||||
RCAR_GEN2,
|
||||
RCAR_GEN3,
|
||||
};
|
||||
|
||||
struct ravb_hw_info {
|
||||
void (*rx_ring_free)(struct net_device *ndev, int q);
|
||||
void (*rx_ring_format)(struct net_device *ndev, int q);
|
||||
void *(*alloc_rx_desc)(struct net_device *ndev, int q);
|
||||
bool (*receive)(struct net_device *ndev, int *quota, int q);
|
||||
void (*set_rate)(struct net_device *ndev);
|
||||
int (*set_rx_csum_feature)(struct net_device *ndev, netdev_features_t features);
|
||||
void (*dmac_init)(struct net_device *ndev);
|
||||
void (*emac_init)(struct net_device *ndev);
|
||||
const char (*gstrings_stats)[ETH_GSTRING_LEN];
|
||||
size_t gstrings_size;
|
||||
netdev_features_t net_hw_features;
|
||||
netdev_features_t net_features;
|
||||
enum ravb_chip_id chip_id;
|
||||
int stats_len;
|
||||
size_t max_rx_len;
|
||||
unsigned aligned_tx: 1;
|
||||
|
@ -1001,6 +999,9 @@ struct ravb_hw_info {
|
|||
/* hardware features */
|
||||
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 */
|
||||
};
|
||||
|
||||
struct ravb_private {
|
||||
|
@ -1044,7 +1045,6 @@ struct ravb_private {
|
|||
int msg_enable;
|
||||
int speed;
|
||||
int emac_irq;
|
||||
enum ravb_chip_id chip_id;
|
||||
int rx_irqs[NUM_RX_QUEUE];
|
||||
int tx_irqs[NUM_TX_QUEUE];
|
||||
|
||||
|
@ -1057,6 +1057,7 @@ struct ravb_private {
|
|||
unsigned int num_tx_desc; /* TX descriptors per packet */
|
||||
|
||||
const struct ravb_hw_info *info;
|
||||
struct reset_control *rstc;
|
||||
};
|
||||
|
||||
static inline u32 ravb_read(struct net_device *ndev, enum ravb_reg reg)
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
@ -216,31 +217,42 @@ static int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only)
|
|||
return free_num;
|
||||
}
|
||||
|
||||
static void ravb_rx_ring_free(struct net_device *ndev, int q)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
unsigned int ring_size;
|
||||
unsigned int i;
|
||||
|
||||
if (!priv->rx_ring[q])
|
||||
return;
|
||||
|
||||
for (i = 0; i < priv->num_rx_ring[q]; i++) {
|
||||
struct ravb_ex_rx_desc *desc = &priv->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),
|
||||
RX_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
ring_size = sizeof(struct ravb_ex_rx_desc) *
|
||||
(priv->num_rx_ring[q] + 1);
|
||||
dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
|
||||
priv->rx_desc_dma[q]);
|
||||
priv->rx_ring[q] = NULL;
|
||||
}
|
||||
|
||||
/* Free skb's and DMA buffers for Ethernet AVB */
|
||||
static void ravb_ring_free(struct net_device *ndev, int q)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
unsigned int num_tx_desc = priv->num_tx_desc;
|
||||
unsigned int ring_size;
|
||||
unsigned int i;
|
||||
|
||||
if (priv->rx_ring[q]) {
|
||||
for (i = 0; i < priv->num_rx_ring[q]; i++) {
|
||||
struct ravb_ex_rx_desc *desc = &priv->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),
|
||||
RX_BUF_SZ,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
ring_size = sizeof(struct ravb_ex_rx_desc) *
|
||||
(priv->num_rx_ring[q] + 1);
|
||||
dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
|
||||
priv->rx_desc_dma[q]);
|
||||
priv->rx_ring[q] = NULL;
|
||||
}
|
||||
info->rx_ring_free(ndev, q);
|
||||
|
||||
if (priv->tx_ring[q]) {
|
||||
ravb_tx_free(ndev, q, false);
|
||||
|
@ -271,25 +283,14 @@ static void ravb_ring_free(struct net_device *ndev, int q)
|
|||
priv->tx_skb[q] = NULL;
|
||||
}
|
||||
|
||||
/* Format skb and descriptor buffer for Ethernet AVB */
|
||||
static void ravb_ring_format(struct net_device *ndev, int q)
|
||||
static void ravb_rx_ring_format(struct net_device *ndev, int q)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
unsigned int num_tx_desc = priv->num_tx_desc;
|
||||
struct ravb_ex_rx_desc *rx_desc;
|
||||
struct ravb_tx_desc *tx_desc;
|
||||
struct ravb_desc *desc;
|
||||
unsigned int rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q];
|
||||
unsigned int tx_ring_size = sizeof(*tx_desc) * priv->num_tx_ring[q] *
|
||||
num_tx_desc;
|
||||
dma_addr_t dma_addr;
|
||||
unsigned int i;
|
||||
|
||||
priv->cur_rx[q] = 0;
|
||||
priv->cur_tx[q] = 0;
|
||||
priv->dirty_rx[q] = 0;
|
||||
priv->dirty_tx[q] = 0;
|
||||
|
||||
memset(priv->rx_ring[q], 0, rx_ring_size);
|
||||
/* Build RX ring buffer */
|
||||
for (i = 0; i < priv->num_rx_ring[q]; i++) {
|
||||
|
@ -310,6 +311,26 @@ static void ravb_ring_format(struct net_device *ndev, int q)
|
|||
rx_desc = &priv->rx_ring[q][i];
|
||||
rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]);
|
||||
rx_desc->die_dt = DT_LINKFIX; /* type */
|
||||
}
|
||||
|
||||
/* Format skb and descriptor buffer for Ethernet AVB */
|
||||
static void ravb_ring_format(struct net_device *ndev, int q)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
unsigned int num_tx_desc = priv->num_tx_desc;
|
||||
struct ravb_tx_desc *tx_desc;
|
||||
struct ravb_desc *desc;
|
||||
unsigned int tx_ring_size = sizeof(*tx_desc) * priv->num_tx_ring[q] *
|
||||
num_tx_desc;
|
||||
unsigned int i;
|
||||
|
||||
priv->cur_rx[q] = 0;
|
||||
priv->cur_tx[q] = 0;
|
||||
priv->dirty_rx[q] = 0;
|
||||
priv->dirty_tx[q] = 0;
|
||||
|
||||
info->rx_ring_format(ndev, q);
|
||||
|
||||
memset(priv->tx_ring[q], 0, tx_ring_size);
|
||||
/* Build TX ring buffer */
|
||||
|
@ -335,6 +356,19 @@ static void ravb_ring_format(struct net_device *ndev, int q)
|
|||
desc->dptr = cpu_to_le32((u32)priv->tx_desc_dma[q]);
|
||||
}
|
||||
|
||||
static void *ravb_alloc_rx_desc(struct net_device *ndev, int q)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
unsigned int ring_size;
|
||||
|
||||
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);
|
||||
return priv->rx_ring[q];
|
||||
}
|
||||
|
||||
/* Init skb and descriptor buffer for Ethernet AVB */
|
||||
static int ravb_ring_init(struct net_device *ndev, int q)
|
||||
{
|
||||
|
@ -370,11 +404,7 @@ 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])
|
||||
if (!info->alloc_rx_desc(ndev, q))
|
||||
goto error;
|
||||
|
||||
priv->dirty_rx[q] = 0;
|
||||
|
@ -396,8 +426,7 @@ static int ravb_ring_init(struct net_device *ndev, int q)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* E-MAC init function */
|
||||
static void ravb_emac_init(struct net_device *ndev)
|
||||
static void ravb_rcar_emac_init(struct net_device *ndev)
|
||||
{
|
||||
/* Receive frame limit set register */
|
||||
ravb_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN, RFLR);
|
||||
|
@ -423,10 +452,52 @@ static void ravb_emac_init(struct net_device *ndev)
|
|||
ravb_write(ndev, ECSIPR_ICDIP | ECSIPR_MPDIP | ECSIPR_LCHNGIP, ECSIPR);
|
||||
}
|
||||
|
||||
/* E-MAC init function */
|
||||
static void ravb_emac_init(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
|
||||
info->emac_init(ndev);
|
||||
}
|
||||
|
||||
static void ravb_rcar_dmac_init(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
|
||||
/* Set AVB RX */
|
||||
ravb_write(ndev,
|
||||
RCR_EFFS | RCR_ENCF | RCR_ETS0 | RCR_ESF | 0x18000000, RCR);
|
||||
|
||||
/* Set FIFO size */
|
||||
ravb_write(ndev, TGC_TQP_AVBMODE1 | 0x00112200, TGC);
|
||||
|
||||
/* Timestamp enable */
|
||||
ravb_write(ndev, TCCR_TFEN, TCCR);
|
||||
|
||||
/* Interrupt init: */
|
||||
if (info->multi_irqs) {
|
||||
/* Clear DIL.DPLx */
|
||||
ravb_write(ndev, 0, DIL);
|
||||
/* Set queue specific interrupt */
|
||||
ravb_write(ndev, CIE_CRIE | CIE_CTIE | CIE_CL0M, CIE);
|
||||
}
|
||||
/* Frame receive */
|
||||
ravb_write(ndev, RIC0_FRE0 | RIC0_FRE1, RIC0);
|
||||
/* Disable FIFO full warning */
|
||||
ravb_write(ndev, 0, RIC1);
|
||||
/* Receive FIFO full error, descriptor empty */
|
||||
ravb_write(ndev, RIC2_QFE0 | RIC2_QFE1 | RIC2_RFFE, RIC2);
|
||||
/* Frame transmitted, timestamp FIFO updated */
|
||||
ravb_write(ndev, TIC_FTE0 | TIC_FTE1 | TIC_TFUE, TIC);
|
||||
}
|
||||
|
||||
/* Device init function for Ethernet AVB */
|
||||
static int ravb_dmac_init(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
int error;
|
||||
|
||||
/* Set CONFIG mode */
|
||||
|
@ -447,31 +518,7 @@ static int ravb_dmac_init(struct net_device *ndev)
|
|||
ravb_ring_format(ndev, RAVB_BE);
|
||||
ravb_ring_format(ndev, RAVB_NC);
|
||||
|
||||
/* Set AVB RX */
|
||||
ravb_write(ndev,
|
||||
RCR_EFFS | RCR_ENCF | RCR_ETS0 | RCR_ESF | 0x18000000, RCR);
|
||||
|
||||
/* Set FIFO size */
|
||||
ravb_write(ndev, TGC_TQP_AVBMODE1 | 0x00112200, TGC);
|
||||
|
||||
/* Timestamp enable */
|
||||
ravb_write(ndev, TCCR_TFEN, TCCR);
|
||||
|
||||
/* Interrupt init: */
|
||||
if (priv->chip_id == RCAR_GEN3) {
|
||||
/* Clear DIL.DPLx */
|
||||
ravb_write(ndev, 0, DIL);
|
||||
/* Set queue specific interrupt */
|
||||
ravb_write(ndev, CIE_CRIE | CIE_CTIE | CIE_CL0M, CIE);
|
||||
}
|
||||
/* Frame receive */
|
||||
ravb_write(ndev, RIC0_FRE0 | RIC0_FRE1, RIC0);
|
||||
/* Disable FIFO full warning */
|
||||
ravb_write(ndev, 0, RIC1);
|
||||
/* Receive FIFO full error, descriptor empty */
|
||||
ravb_write(ndev, RIC2_QFE0 | RIC2_QFE1 | RIC2_RFFE, RIC2);
|
||||
/* Frame transmitted, timestamp FIFO updated */
|
||||
ravb_write(ndev, TIC_FTE0 | TIC_FTE1 | TIC_TFUE, TIC);
|
||||
info->dmac_init(ndev);
|
||||
|
||||
/* Setting the control will start the AVB-DMAC process. */
|
||||
ravb_modify(ndev, CCC, CCC_OPC, CCC_OPC_OPERATION);
|
||||
|
@ -532,8 +579,7 @@ static void ravb_rx_csum(struct sk_buff *skb)
|
|||
skb_trim(skb, skb->len - sizeof(__sum16));
|
||||
}
|
||||
|
||||
/* Packet receive function for Ethernet AVB */
|
||||
static bool ravb_rx(struct net_device *ndev, int *quota, int q)
|
||||
static bool ravb_rcar_rx(struct net_device *ndev, int *quota, int q)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
|
@ -647,6 +693,15 @@ static bool ravb_rx(struct net_device *ndev, int *quota, int q)
|
|||
return boguscnt <= 0;
|
||||
}
|
||||
|
||||
/* Packet receive function for Ethernet AVB */
|
||||
static bool ravb_rx(struct net_device *ndev, int *quota, int q)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
|
||||
return info->receive(ndev, quota, q);
|
||||
}
|
||||
|
||||
static void ravb_rcv_snd_disable(struct net_device *ndev)
|
||||
{
|
||||
/* Disable TX and RX */
|
||||
|
@ -758,6 +813,7 @@ static void ravb_error_interrupt(struct net_device *ndev)
|
|||
static bool ravb_queue_interrupt(struct net_device *ndev, int q)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
u32 ris0 = ravb_read(ndev, RIS0);
|
||||
u32 ric0 = ravb_read(ndev, RIC0);
|
||||
u32 tis = ravb_read(ndev, TIS);
|
||||
|
@ -766,7 +822,7 @@ static bool ravb_queue_interrupt(struct net_device *ndev, int q)
|
|||
if (((ris0 & ric0) & BIT(q)) || ((tis & tic) & BIT(q))) {
|
||||
if (napi_schedule_prep(&priv->napi[q])) {
|
||||
/* Mask RX and TX interrupts */
|
||||
if (priv->chip_id == RCAR_GEN2) {
|
||||
if (!info->multi_irqs) {
|
||||
ravb_write(ndev, ric0 & ~BIT(q), RIC0);
|
||||
ravb_write(ndev, tic & ~BIT(q), TIC);
|
||||
} else {
|
||||
|
@ -909,6 +965,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
|
|||
{
|
||||
struct net_device *ndev = napi->dev;
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
unsigned long flags;
|
||||
int q = napi - priv->napi;
|
||||
int mask = BIT(q);
|
||||
|
@ -932,7 +989,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
|
|||
|
||||
/* Re-enable RX/TX interrupts */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (priv->chip_id == RCAR_GEN2) {
|
||||
if (!info->multi_irqs) {
|
||||
ravb_modify(ndev, RIC0, mask, mask);
|
||||
ravb_modify(ndev, TIC, mask, mask);
|
||||
} else {
|
||||
|
@ -956,6 +1013,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
|
|||
static void ravb_adjust_link(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
struct phy_device *phydev = ndev->phydev;
|
||||
bool new_state = false;
|
||||
unsigned long flags;
|
||||
|
@ -970,7 +1028,7 @@ static void ravb_adjust_link(struct net_device *ndev)
|
|||
if (phydev->speed != priv->speed) {
|
||||
new_state = true;
|
||||
priv->speed = phydev->speed;
|
||||
ravb_set_rate(ndev);
|
||||
info->set_rate(ndev);
|
||||
}
|
||||
if (!priv->link) {
|
||||
ravb_modify(ndev, ECMR, ECMR_TXF, 0);
|
||||
|
@ -1202,6 +1260,7 @@ static int ravb_set_ringparam(struct net_device *ndev,
|
|||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
int error;
|
||||
|
||||
if (ring->tx_pending > BE_TX_RING_MAX ||
|
||||
|
@ -1215,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 (priv->chip_id == RCAR_GEN2)
|
||||
if (info->no_ptp_cfg_active)
|
||||
ravb_ptp_stop(ndev);
|
||||
/* Wait for DMA stopping */
|
||||
error = ravb_stop_dma(ndev);
|
||||
|
@ -1247,7 +1306,7 @@ static int ravb_set_ringparam(struct net_device *ndev,
|
|||
ravb_emac_init(ndev);
|
||||
|
||||
/* Initialise PTP Clock driver */
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (info->no_ptp_cfg_active)
|
||||
ravb_ptp_init(ndev, priv->pdev);
|
||||
|
||||
netif_device_attach(ndev);
|
||||
|
@ -1338,6 +1397,7 @@ static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler,
|
|||
static int ravb_open(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
struct platform_device *pdev = priv->pdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
int error;
|
||||
|
@ -1345,7 +1405,7 @@ static int ravb_open(struct net_device *ndev)
|
|||
napi_enable(&priv->napi[RAVB_BE]);
|
||||
napi_enable(&priv->napi[RAVB_NC]);
|
||||
|
||||
if (priv->chip_id == RCAR_GEN2) {
|
||||
if (!info->multi_irqs) {
|
||||
error = request_irq(ndev->irq, ravb_interrupt, IRQF_SHARED,
|
||||
ndev->name, ndev);
|
||||
if (error) {
|
||||
|
@ -1386,7 +1446,7 @@ static int ravb_open(struct net_device *ndev)
|
|||
ravb_emac_init(ndev);
|
||||
|
||||
/* Initialise PTP Clock driver */
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (info->no_ptp_cfg_active)
|
||||
ravb_ptp_init(ndev, priv->pdev);
|
||||
|
||||
netif_tx_start_all_queues(ndev);
|
||||
|
@ -1400,10 +1460,10 @@ static int ravb_open(struct net_device *ndev)
|
|||
|
||||
out_ptp_stop:
|
||||
/* Stop PTP Clock driver */
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (info->no_ptp_cfg_active)
|
||||
ravb_ptp_stop(ndev);
|
||||
out_free_irq_nc_tx:
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (!info->multi_irqs)
|
||||
goto out_free_irq;
|
||||
free_irq(priv->tx_irqs[RAVB_NC], ndev);
|
||||
out_free_irq_nc_rx:
|
||||
|
@ -1441,13 +1501,14 @@ static void ravb_tx_timeout_work(struct work_struct *work)
|
|||
{
|
||||
struct ravb_private *priv = container_of(work, struct ravb_private,
|
||||
work);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
struct net_device *ndev = priv->ndev;
|
||||
int error;
|
||||
|
||||
netif_tx_stop_all_queues(ndev);
|
||||
|
||||
/* Stop PTP Clock driver */
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (info->no_ptp_cfg_active)
|
||||
ravb_ptp_stop(ndev);
|
||||
|
||||
/* Wait for DMA stopping */
|
||||
|
@ -1482,7 +1543,7 @@ static void ravb_tx_timeout_work(struct work_struct *work)
|
|||
|
||||
out:
|
||||
/* Initialise PTP Clock driver */
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (info->no_ptp_cfg_active)
|
||||
ravb_ptp_init(ndev, priv->pdev);
|
||||
|
||||
netif_tx_start_all_queues(ndev);
|
||||
|
@ -1680,6 +1741,7 @@ static int ravb_close(struct net_device *ndev)
|
|||
{
|
||||
struct device_node *np = ndev->dev.parent->of_node;
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
struct ravb_tstamp_skb *ts_skb, *ts_skb2;
|
||||
|
||||
netif_tx_stop_all_queues(ndev);
|
||||
|
@ -1690,7 +1752,7 @@ static int ravb_close(struct net_device *ndev)
|
|||
ravb_write(ndev, 0, TIC);
|
||||
|
||||
/* Stop PTP Clock driver */
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (info->no_ptp_cfg_active)
|
||||
ravb_ptp_stop(ndev);
|
||||
|
||||
/* Set the config mode to stop the AVB-DMAC's processes */
|
||||
|
@ -1713,7 +1775,7 @@ static int ravb_close(struct net_device *ndev)
|
|||
of_phy_deregister_fixed_link(np);
|
||||
}
|
||||
|
||||
if (priv->chip_id != RCAR_GEN2) {
|
||||
if (info->multi_irqs) {
|
||||
free_irq(priv->tx_irqs[RAVB_NC], ndev);
|
||||
free_irq(priv->rx_irqs[RAVB_NC], ndev);
|
||||
free_irq(priv->tx_irqs[RAVB_BE], ndev);
|
||||
|
@ -1856,8 +1918,8 @@ static void ravb_set_rx_csum(struct net_device *ndev, bool enable)
|
|||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static int ravb_set_features(struct net_device *ndev,
|
||||
netdev_features_t features)
|
||||
static int ravb_set_features_rx_csum(struct net_device *ndev,
|
||||
netdev_features_t features)
|
||||
{
|
||||
netdev_features_t changed = ndev->features ^ features;
|
||||
|
||||
|
@ -1869,6 +1931,15 @@ static int ravb_set_features(struct net_device *ndev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ravb_set_features(struct net_device *ndev,
|
||||
netdev_features_t features)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
|
||||
return info->set_rx_csum_feature(ndev, features);
|
||||
}
|
||||
|
||||
static const struct net_device_ops ravb_netdev_ops = {
|
||||
.ndo_open = ravb_open,
|
||||
.ndo_stop = ravb_close,
|
||||
|
@ -1930,26 +2001,43 @@ static int ravb_mdio_release(struct ravb_private *priv)
|
|||
}
|
||||
|
||||
static const struct ravb_hw_info ravb_gen3_hw_info = {
|
||||
.rx_ring_free = ravb_rx_ring_free,
|
||||
.rx_ring_format = ravb_rx_ring_format,
|
||||
.alloc_rx_desc = ravb_alloc_rx_desc,
|
||||
.receive = ravb_rcar_rx,
|
||||
.set_rate = ravb_set_rate,
|
||||
.set_rx_csum_feature = ravb_set_features_rx_csum,
|
||||
.dmac_init = ravb_rcar_dmac_init,
|
||||
.emac_init = ravb_rcar_emac_init,
|
||||
.gstrings_stats = ravb_gstrings_stats,
|
||||
.gstrings_size = sizeof(ravb_gstrings_stats),
|
||||
.net_hw_features = NETIF_F_RXCSUM,
|
||||
.net_features = NETIF_F_RXCSUM,
|
||||
.chip_id = RCAR_GEN3,
|
||||
.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
|
||||
.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
|
||||
.internal_delay = 1,
|
||||
.tx_counters = 1,
|
||||
.multi_irqs = 1,
|
||||
.ptp_cfg_active = 1,
|
||||
};
|
||||
|
||||
static const struct ravb_hw_info ravb_gen2_hw_info = {
|
||||
.rx_ring_free = ravb_rx_ring_free,
|
||||
.rx_ring_format = ravb_rx_ring_format,
|
||||
.alloc_rx_desc = ravb_alloc_rx_desc,
|
||||
.receive = ravb_rcar_rx,
|
||||
.set_rate = ravb_set_rate,
|
||||
.set_rx_csum_feature = ravb_set_features_rx_csum,
|
||||
.dmac_init = ravb_rcar_dmac_init,
|
||||
.emac_init = ravb_rcar_emac_init,
|
||||
.gstrings_stats = ravb_gstrings_stats,
|
||||
.gstrings_size = sizeof(ravb_gstrings_stats),
|
||||
.net_hw_features = NETIF_F_RXCSUM,
|
||||
.net_features = NETIF_F_RXCSUM,
|
||||
.chip_id = RCAR_GEN2,
|
||||
.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
|
||||
.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
|
||||
.aligned_tx = 1,
|
||||
.no_ptp_cfg_active = 1,
|
||||
};
|
||||
|
||||
static const struct of_device_id ravb_match_table[] = {
|
||||
|
@ -1990,8 +2078,9 @@ static int ravb_set_gti(struct net_device *ndev)
|
|||
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 (priv->chip_id == RCAR_GEN2) {
|
||||
if (info->no_ptp_cfg_active) {
|
||||
ravb_modify(ndev, CCC, CCC_OPC, CCC_OPC_CONFIG);
|
||||
/* Set CSEL value */
|
||||
ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB);
|
||||
|
@ -2052,6 +2141,7 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const struct ravb_hw_info *info;
|
||||
struct reset_control *rstc;
|
||||
struct ravb_private *priv;
|
||||
struct net_device *ndev;
|
||||
int error, irq, q;
|
||||
|
@ -2064,6 +2154,11 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
|
||||
if (IS_ERR(rstc))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(rstc),
|
||||
"failed to get cpg reset\n");
|
||||
|
||||
ndev = alloc_etherdev_mqs(sizeof(struct ravb_private),
|
||||
NUM_TX_QUEUE, NUM_RX_QUEUE);
|
||||
if (!ndev)
|
||||
|
@ -2074,10 +2169,11 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
ndev->features = info->net_features;
|
||||
ndev->hw_features = info->net_hw_features;
|
||||
|
||||
reset_control_deassert(rstc);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
if (info->chip_id == RCAR_GEN3)
|
||||
if (info->multi_irqs)
|
||||
irq = platform_get_irq_byname(pdev, "ch22");
|
||||
else
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
|
@ -2091,6 +2187,7 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
|
||||
priv = netdev_priv(ndev);
|
||||
priv->info = info;
|
||||
priv->rstc = rstc;
|
||||
priv->ndev = ndev;
|
||||
priv->pdev = pdev;
|
||||
priv->num_tx_ring[RAVB_BE] = BE_TX_RING_SIZE;
|
||||
|
@ -2117,7 +2214,7 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
priv->avb_link_active_low =
|
||||
of_property_read_bool(np, "renesas,ether-link-active-low");
|
||||
|
||||
if (info->chip_id == RCAR_GEN3) {
|
||||
if (info->multi_irqs) {
|
||||
irq = platform_get_irq_byname(pdev, "ch24");
|
||||
if (irq < 0) {
|
||||
error = irq;
|
||||
|
@ -2142,8 +2239,6 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
priv->chip_id = info->chip_id;
|
||||
|
||||
priv->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
error = PTR_ERR(priv->clk);
|
||||
|
@ -2160,8 +2255,12 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
ndev->max_mtu = 2048 - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
|
||||
ndev->min_mtu = ETH_MIN_MTU;
|
||||
|
||||
priv->num_tx_desc = info->aligned_tx ?
|
||||
NUM_TX_DESC_GEN2 : NUM_TX_DESC_GEN3;
|
||||
/* FIXME: R-Car Gen2 has 4byte alignment restriction for tx buffer
|
||||
* Use two descriptor to handle such situation. First descriptor to
|
||||
* handle aligned data buffer and second descriptor to handle the
|
||||
* overflow data because of alignment.
|
||||
*/
|
||||
priv->num_tx_desc = info->aligned_tx ? 2 : 1;
|
||||
|
||||
/* Set function */
|
||||
ndev->netdev_ops = &ravb_netdev_ops;
|
||||
|
@ -2202,7 +2301,7 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
INIT_LIST_HEAD(&priv->ts_skb_list);
|
||||
|
||||
/* Initialise PTP Clock driver */
|
||||
if (info->chip_id != RCAR_GEN2)
|
||||
if (info->ptp_cfg_active)
|
||||
ravb_ptp_init(ndev, pdev);
|
||||
|
||||
/* Debug message level */
|
||||
|
@ -2250,7 +2349,7 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
priv->desc_bat_dma);
|
||||
|
||||
/* Stop PTP Clock driver */
|
||||
if (info->chip_id != RCAR_GEN2)
|
||||
if (info->ptp_cfg_active)
|
||||
ravb_ptp_stop(ndev);
|
||||
out_disable_refclk:
|
||||
clk_disable_unprepare(priv->refclk);
|
||||
|
@ -2259,6 +2358,7 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
|
||||
pm_runtime_put(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
reset_control_assert(rstc);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -2266,9 +2366,10 @@ static int ravb_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct net_device *ndev = platform_get_drvdata(pdev);
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
|
||||
/* Stop PTP Clock driver */
|
||||
if (priv->chip_id != RCAR_GEN2)
|
||||
if (info->ptp_cfg_active)
|
||||
ravb_ptp_stop(ndev);
|
||||
|
||||
clk_disable_unprepare(priv->refclk);
|
||||
|
@ -2283,6 +2384,7 @@ static int ravb_remove(struct platform_device *pdev)
|
|||
netif_napi_del(&priv->napi[RAVB_BE]);
|
||||
ravb_mdio_release(priv);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
reset_control_assert(priv->rstc);
|
||||
free_netdev(ndev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
|
|
|
@ -179,6 +179,7 @@ static int ravb_ptp_extts(struct ptp_clock_info *ptp,
|
|||
{
|
||||
struct ravb_private *priv = container_of(ptp, struct ravb_private,
|
||||
ptp.info);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
struct net_device *ndev = priv->ndev;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -197,7 +198,7 @@ static int ravb_ptp_extts(struct ptp_clock_info *ptp,
|
|||
priv->ptp.extts[req->index] = on;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (!info->multi_irqs)
|
||||
ravb_modify(ndev, GIC, GIC_PTCE, on ? GIC_PTCE : 0);
|
||||
else if (on)
|
||||
ravb_write(ndev, GIE_PTCS, GIE);
|
||||
|
@ -213,6 +214,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp,
|
|||
{
|
||||
struct ravb_private *priv = container_of(ptp, struct ravb_private,
|
||||
ptp.info);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
struct net_device *ndev = priv->ndev;
|
||||
struct ravb_ptp_perout *perout;
|
||||
unsigned long flags;
|
||||
|
@ -252,7 +254,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp,
|
|||
error = ravb_ptp_update_compare(priv, (u32)start_ns);
|
||||
if (!error) {
|
||||
/* Unmask interrupt */
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (!info->multi_irqs)
|
||||
ravb_modify(ndev, GIC, GIC_PTME, GIC_PTME);
|
||||
else
|
||||
ravb_write(ndev, GIE_PTMS0, GIE);
|
||||
|
@ -264,7 +266,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp,
|
|||
perout->period = 0;
|
||||
|
||||
/* Mask interrupt */
|
||||
if (priv->chip_id == RCAR_GEN2)
|
||||
if (!info->multi_irqs)
|
||||
ravb_modify(ndev, GIC, GIC_PTME, 0);
|
||||
else
|
||||
ravb_write(ndev, GID_PTMD0, GID);
|
||||
|
|
Loading…
Reference in New Issue