162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Renesas Ethernet AVB device driver 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2014-2019 Renesas Electronics Corporation 562306a36Sopenharmony_ci * Copyright (C) 2015 Renesas Solutions Corp. 662306a36Sopenharmony_ci * Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Based on the SuperH Ethernet driver 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/cache.h> 1262306a36Sopenharmony_ci#include <linux/clk.h> 1362306a36Sopenharmony_ci#include <linux/delay.h> 1462306a36Sopenharmony_ci#include <linux/dma-mapping.h> 1562306a36Sopenharmony_ci#include <linux/err.h> 1662306a36Sopenharmony_ci#include <linux/etherdevice.h> 1762306a36Sopenharmony_ci#include <linux/ethtool.h> 1862306a36Sopenharmony_ci#include <linux/if_vlan.h> 1962306a36Sopenharmony_ci#include <linux/kernel.h> 2062306a36Sopenharmony_ci#include <linux/list.h> 2162306a36Sopenharmony_ci#include <linux/module.h> 2262306a36Sopenharmony_ci#include <linux/net_tstamp.h> 2362306a36Sopenharmony_ci#include <linux/of.h> 2462306a36Sopenharmony_ci#include <linux/of_mdio.h> 2562306a36Sopenharmony_ci#include <linux/of_net.h> 2662306a36Sopenharmony_ci#include <linux/platform_device.h> 2762306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2862306a36Sopenharmony_ci#include <linux/slab.h> 2962306a36Sopenharmony_ci#include <linux/spinlock.h> 3062306a36Sopenharmony_ci#include <linux/reset.h> 3162306a36Sopenharmony_ci#include <linux/math64.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include "ravb.h" 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define RAVB_DEF_MSG_ENABLE \ 3662306a36Sopenharmony_ci (NETIF_MSG_LINK | \ 3762306a36Sopenharmony_ci NETIF_MSG_TIMER | \ 3862306a36Sopenharmony_ci NETIF_MSG_RX_ERR | \ 3962306a36Sopenharmony_ci NETIF_MSG_TX_ERR) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic const char *ravb_rx_irqs[NUM_RX_QUEUE] = { 4262306a36Sopenharmony_ci "ch0", /* RAVB_BE */ 4362306a36Sopenharmony_ci "ch1", /* RAVB_NC */ 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic const char *ravb_tx_irqs[NUM_TX_QUEUE] = { 4762306a36Sopenharmony_ci "ch18", /* RAVB_BE */ 4862306a36Sopenharmony_ci "ch19", /* RAVB_NC */ 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_civoid ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear, 5262306a36Sopenharmony_ci u32 set) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci ravb_write(ndev, (ravb_read(ndev, reg) & ~clear) | set, reg); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciint ravb_wait(struct net_device *ndev, enum ravb_reg reg, u32 mask, u32 value) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci int i; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci for (i = 0; i < 10000; i++) { 6262306a36Sopenharmony_ci if ((ravb_read(ndev, reg) & mask) == value) 6362306a36Sopenharmony_ci return 0; 6462306a36Sopenharmony_ci udelay(10); 6562306a36Sopenharmony_ci } 6662306a36Sopenharmony_ci return -ETIMEDOUT; 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic int ravb_set_opmode(struct net_device *ndev, u32 opmode) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci u32 csr_ops = 1U << (opmode & CCC_OPC); 7262306a36Sopenharmony_ci u32 ccc_mask = CCC_OPC; 7362306a36Sopenharmony_ci int error; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci /* If gPTP active in config mode is supported it needs to be configured 7662306a36Sopenharmony_ci * along with CSEL and operating mode in the same access. This is a 7762306a36Sopenharmony_ci * hardware limitation. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci if (opmode & CCC_GAC) 8062306a36Sopenharmony_ci ccc_mask |= CCC_GAC | CCC_CSEL; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* Set operating mode */ 8362306a36Sopenharmony_ci ravb_modify(ndev, CCC, ccc_mask, opmode); 8462306a36Sopenharmony_ci /* Check if the operating mode is changed to the requested one */ 8562306a36Sopenharmony_ci error = ravb_wait(ndev, CSR, CSR_OPS, csr_ops); 8662306a36Sopenharmony_ci if (error) { 8762306a36Sopenharmony_ci netdev_err(ndev, "failed to switch device to requested mode (%u)\n", 8862306a36Sopenharmony_ci opmode & CCC_OPC); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci return error; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic void ravb_set_rate_gbeth(struct net_device *ndev) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci switch (priv->speed) { 9962306a36Sopenharmony_ci case 10: /* 10BASE */ 10062306a36Sopenharmony_ci ravb_write(ndev, GBETH_GECMR_SPEED_10, GECMR); 10162306a36Sopenharmony_ci break; 10262306a36Sopenharmony_ci case 100: /* 100BASE */ 10362306a36Sopenharmony_ci ravb_write(ndev, GBETH_GECMR_SPEED_100, GECMR); 10462306a36Sopenharmony_ci break; 10562306a36Sopenharmony_ci case 1000: /* 1000BASE */ 10662306a36Sopenharmony_ci ravb_write(ndev, GBETH_GECMR_SPEED_1000, GECMR); 10762306a36Sopenharmony_ci break; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic void ravb_set_rate_rcar(struct net_device *ndev) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci switch (priv->speed) { 11662306a36Sopenharmony_ci case 100: /* 100BASE */ 11762306a36Sopenharmony_ci ravb_write(ndev, GECMR_SPEED_100, GECMR); 11862306a36Sopenharmony_ci break; 11962306a36Sopenharmony_ci case 1000: /* 1000BASE */ 12062306a36Sopenharmony_ci ravb_write(ndev, GECMR_SPEED_1000, GECMR); 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic void ravb_set_buffer_align(struct sk_buff *skb) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci u32 reserve = (unsigned long)skb->data & (RAVB_ALIGN - 1); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci if (reserve) 13062306a36Sopenharmony_ci skb_reserve(skb, RAVB_ALIGN - reserve); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* Get MAC address from the MAC address registers 13462306a36Sopenharmony_ci * 13562306a36Sopenharmony_ci * Ethernet AVB device doesn't have ROM for MAC address. 13662306a36Sopenharmony_ci * This function gets the MAC address that was used by a bootloader. 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_cistatic void ravb_read_mac_address(struct device_node *np, 13962306a36Sopenharmony_ci struct net_device *ndev) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci int ret; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci ret = of_get_ethdev_address(np, ndev); 14462306a36Sopenharmony_ci if (ret) { 14562306a36Sopenharmony_ci u32 mahr = ravb_read(ndev, MAHR); 14662306a36Sopenharmony_ci u32 malr = ravb_read(ndev, MALR); 14762306a36Sopenharmony_ci u8 addr[ETH_ALEN]; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci addr[0] = (mahr >> 24) & 0xFF; 15062306a36Sopenharmony_ci addr[1] = (mahr >> 16) & 0xFF; 15162306a36Sopenharmony_ci addr[2] = (mahr >> 8) & 0xFF; 15262306a36Sopenharmony_ci addr[3] = (mahr >> 0) & 0xFF; 15362306a36Sopenharmony_ci addr[4] = (malr >> 8) & 0xFF; 15462306a36Sopenharmony_ci addr[5] = (malr >> 0) & 0xFF; 15562306a36Sopenharmony_ci eth_hw_addr_set(ndev, addr); 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic void ravb_mdio_ctrl(struct mdiobb_ctrl *ctrl, u32 mask, int set) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci struct ravb_private *priv = container_of(ctrl, struct ravb_private, 16262306a36Sopenharmony_ci mdiobb); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci ravb_modify(priv->ndev, PIR, mask, set ? mask : 0); 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci/* MDC pin control */ 16862306a36Sopenharmony_cistatic void ravb_set_mdc(struct mdiobb_ctrl *ctrl, int level) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci ravb_mdio_ctrl(ctrl, PIR_MDC, level); 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci/* Data I/O pin control */ 17462306a36Sopenharmony_cistatic void ravb_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci ravb_mdio_ctrl(ctrl, PIR_MMD, output); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/* Set data bit */ 18062306a36Sopenharmony_cistatic void ravb_set_mdio_data(struct mdiobb_ctrl *ctrl, int value) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci ravb_mdio_ctrl(ctrl, PIR_MDO, value); 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* Get data bit */ 18662306a36Sopenharmony_cistatic int ravb_get_mdio_data(struct mdiobb_ctrl *ctrl) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci struct ravb_private *priv = container_of(ctrl, struct ravb_private, 18962306a36Sopenharmony_ci mdiobb); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return (ravb_read(priv->ndev, PIR) & PIR_MDI) != 0; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci/* MDIO bus control struct */ 19562306a36Sopenharmony_cistatic const struct mdiobb_ops bb_ops = { 19662306a36Sopenharmony_ci .owner = THIS_MODULE, 19762306a36Sopenharmony_ci .set_mdc = ravb_set_mdc, 19862306a36Sopenharmony_ci .set_mdio_dir = ravb_set_mdio_dir, 19962306a36Sopenharmony_ci .set_mdio_data = ravb_set_mdio_data, 20062306a36Sopenharmony_ci .get_mdio_data = ravb_get_mdio_data, 20162306a36Sopenharmony_ci}; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci/* Free TX skb function for AVB-IP */ 20462306a36Sopenharmony_cistatic int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 20762306a36Sopenharmony_ci struct net_device_stats *stats = &priv->stats[q]; 20862306a36Sopenharmony_ci unsigned int num_tx_desc = priv->num_tx_desc; 20962306a36Sopenharmony_ci struct ravb_tx_desc *desc; 21062306a36Sopenharmony_ci unsigned int entry; 21162306a36Sopenharmony_ci int free_num = 0; 21262306a36Sopenharmony_ci u32 size; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) { 21562306a36Sopenharmony_ci bool txed; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] * 21862306a36Sopenharmony_ci num_tx_desc); 21962306a36Sopenharmony_ci desc = &priv->tx_ring[q][entry]; 22062306a36Sopenharmony_ci txed = desc->die_dt == DT_FEMPTY; 22162306a36Sopenharmony_ci if (free_txed_only && !txed) 22262306a36Sopenharmony_ci break; 22362306a36Sopenharmony_ci /* Descriptor type must be checked before all other reads */ 22462306a36Sopenharmony_ci dma_rmb(); 22562306a36Sopenharmony_ci size = le16_to_cpu(desc->ds_tagl) & TX_DS; 22662306a36Sopenharmony_ci /* Free the original skb. */ 22762306a36Sopenharmony_ci if (priv->tx_skb[q][entry / num_tx_desc]) { 22862306a36Sopenharmony_ci dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), 22962306a36Sopenharmony_ci size, DMA_TO_DEVICE); 23062306a36Sopenharmony_ci /* Last packet descriptor? */ 23162306a36Sopenharmony_ci if (entry % num_tx_desc == num_tx_desc - 1) { 23262306a36Sopenharmony_ci entry /= num_tx_desc; 23362306a36Sopenharmony_ci dev_kfree_skb_any(priv->tx_skb[q][entry]); 23462306a36Sopenharmony_ci priv->tx_skb[q][entry] = NULL; 23562306a36Sopenharmony_ci if (txed) 23662306a36Sopenharmony_ci stats->tx_packets++; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci free_num++; 23962306a36Sopenharmony_ci } 24062306a36Sopenharmony_ci if (txed) 24162306a36Sopenharmony_ci stats->tx_bytes += size; 24262306a36Sopenharmony_ci desc->die_dt = DT_EEMPTY; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci return free_num; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic void ravb_rx_ring_free_gbeth(struct net_device *ndev, int q) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 25062306a36Sopenharmony_ci unsigned int ring_size; 25162306a36Sopenharmony_ci unsigned int i; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci if (!priv->gbeth_rx_ring) 25462306a36Sopenharmony_ci return; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci for (i = 0; i < priv->num_rx_ring[q]; i++) { 25762306a36Sopenharmony_ci struct ravb_rx_desc *desc = &priv->gbeth_rx_ring[i]; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (!dma_mapping_error(ndev->dev.parent, 26062306a36Sopenharmony_ci le32_to_cpu(desc->dptr))) 26162306a36Sopenharmony_ci dma_unmap_single(ndev->dev.parent, 26262306a36Sopenharmony_ci le32_to_cpu(desc->dptr), 26362306a36Sopenharmony_ci GBETH_RX_BUFF_MAX, 26462306a36Sopenharmony_ci DMA_FROM_DEVICE); 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci ring_size = sizeof(struct ravb_rx_desc) * (priv->num_rx_ring[q] + 1); 26762306a36Sopenharmony_ci dma_free_coherent(ndev->dev.parent, ring_size, priv->gbeth_rx_ring, 26862306a36Sopenharmony_ci priv->rx_desc_dma[q]); 26962306a36Sopenharmony_ci priv->gbeth_rx_ring = NULL; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic void ravb_rx_ring_free_rcar(struct net_device *ndev, int q) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 27562306a36Sopenharmony_ci unsigned int ring_size; 27662306a36Sopenharmony_ci unsigned int i; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (!priv->rx_ring[q]) 27962306a36Sopenharmony_ci return; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci for (i = 0; i < priv->num_rx_ring[q]; i++) { 28262306a36Sopenharmony_ci struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i]; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (!dma_mapping_error(ndev->dev.parent, 28562306a36Sopenharmony_ci le32_to_cpu(desc->dptr))) 28662306a36Sopenharmony_ci dma_unmap_single(ndev->dev.parent, 28762306a36Sopenharmony_ci le32_to_cpu(desc->dptr), 28862306a36Sopenharmony_ci RX_BUF_SZ, 28962306a36Sopenharmony_ci DMA_FROM_DEVICE); 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci ring_size = sizeof(struct ravb_ex_rx_desc) * 29262306a36Sopenharmony_ci (priv->num_rx_ring[q] + 1); 29362306a36Sopenharmony_ci dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q], 29462306a36Sopenharmony_ci priv->rx_desc_dma[q]); 29562306a36Sopenharmony_ci priv->rx_ring[q] = NULL; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci/* Free skb's and DMA buffers for Ethernet AVB */ 29962306a36Sopenharmony_cistatic void ravb_ring_free(struct net_device *ndev, int q) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 30262306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 30362306a36Sopenharmony_ci unsigned int num_tx_desc = priv->num_tx_desc; 30462306a36Sopenharmony_ci unsigned int ring_size; 30562306a36Sopenharmony_ci unsigned int i; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci info->rx_ring_free(ndev, q); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (priv->tx_ring[q]) { 31062306a36Sopenharmony_ci ravb_tx_free(ndev, q, false); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci ring_size = sizeof(struct ravb_tx_desc) * 31362306a36Sopenharmony_ci (priv->num_tx_ring[q] * num_tx_desc + 1); 31462306a36Sopenharmony_ci dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q], 31562306a36Sopenharmony_ci priv->tx_desc_dma[q]); 31662306a36Sopenharmony_ci priv->tx_ring[q] = NULL; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci /* Free RX skb ringbuffer */ 32062306a36Sopenharmony_ci if (priv->rx_skb[q]) { 32162306a36Sopenharmony_ci for (i = 0; i < priv->num_rx_ring[q]; i++) 32262306a36Sopenharmony_ci dev_kfree_skb(priv->rx_skb[q][i]); 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci kfree(priv->rx_skb[q]); 32562306a36Sopenharmony_ci priv->rx_skb[q] = NULL; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci /* Free aligned TX buffers */ 32862306a36Sopenharmony_ci kfree(priv->tx_align[q]); 32962306a36Sopenharmony_ci priv->tx_align[q] = NULL; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci /* Free TX skb ringbuffer. 33262306a36Sopenharmony_ci * SKBs are freed by ravb_tx_free() call above. 33362306a36Sopenharmony_ci */ 33462306a36Sopenharmony_ci kfree(priv->tx_skb[q]); 33562306a36Sopenharmony_ci priv->tx_skb[q] = NULL; 33662306a36Sopenharmony_ci} 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic void ravb_rx_ring_format_gbeth(struct net_device *ndev, int q) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 34162306a36Sopenharmony_ci struct ravb_rx_desc *rx_desc; 34262306a36Sopenharmony_ci unsigned int rx_ring_size; 34362306a36Sopenharmony_ci dma_addr_t dma_addr; 34462306a36Sopenharmony_ci unsigned int i; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q]; 34762306a36Sopenharmony_ci memset(priv->gbeth_rx_ring, 0, rx_ring_size); 34862306a36Sopenharmony_ci /* Build RX ring buffer */ 34962306a36Sopenharmony_ci for (i = 0; i < priv->num_rx_ring[q]; i++) { 35062306a36Sopenharmony_ci /* RX descriptor */ 35162306a36Sopenharmony_ci rx_desc = &priv->gbeth_rx_ring[i]; 35262306a36Sopenharmony_ci rx_desc->ds_cc = cpu_to_le16(GBETH_RX_DESC_DATA_SIZE); 35362306a36Sopenharmony_ci dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data, 35462306a36Sopenharmony_ci GBETH_RX_BUFF_MAX, 35562306a36Sopenharmony_ci DMA_FROM_DEVICE); 35662306a36Sopenharmony_ci /* We just set the data size to 0 for a failed mapping which 35762306a36Sopenharmony_ci * should prevent DMA from happening... 35862306a36Sopenharmony_ci */ 35962306a36Sopenharmony_ci if (dma_mapping_error(ndev->dev.parent, dma_addr)) 36062306a36Sopenharmony_ci rx_desc->ds_cc = cpu_to_le16(0); 36162306a36Sopenharmony_ci rx_desc->dptr = cpu_to_le32(dma_addr); 36262306a36Sopenharmony_ci rx_desc->die_dt = DT_FEMPTY; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci rx_desc = &priv->gbeth_rx_ring[i]; 36562306a36Sopenharmony_ci rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]); 36662306a36Sopenharmony_ci rx_desc->die_dt = DT_LINKFIX; /* type */ 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic void ravb_rx_ring_format_rcar(struct net_device *ndev, int q) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 37262306a36Sopenharmony_ci struct ravb_ex_rx_desc *rx_desc; 37362306a36Sopenharmony_ci unsigned int rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q]; 37462306a36Sopenharmony_ci dma_addr_t dma_addr; 37562306a36Sopenharmony_ci unsigned int i; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci memset(priv->rx_ring[q], 0, rx_ring_size); 37862306a36Sopenharmony_ci /* Build RX ring buffer */ 37962306a36Sopenharmony_ci for (i = 0; i < priv->num_rx_ring[q]; i++) { 38062306a36Sopenharmony_ci /* RX descriptor */ 38162306a36Sopenharmony_ci rx_desc = &priv->rx_ring[q][i]; 38262306a36Sopenharmony_ci rx_desc->ds_cc = cpu_to_le16(RX_BUF_SZ); 38362306a36Sopenharmony_ci dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data, 38462306a36Sopenharmony_ci RX_BUF_SZ, 38562306a36Sopenharmony_ci DMA_FROM_DEVICE); 38662306a36Sopenharmony_ci /* We just set the data size to 0 for a failed mapping which 38762306a36Sopenharmony_ci * should prevent DMA from happening... 38862306a36Sopenharmony_ci */ 38962306a36Sopenharmony_ci if (dma_mapping_error(ndev->dev.parent, dma_addr)) 39062306a36Sopenharmony_ci rx_desc->ds_cc = cpu_to_le16(0); 39162306a36Sopenharmony_ci rx_desc->dptr = cpu_to_le32(dma_addr); 39262306a36Sopenharmony_ci rx_desc->die_dt = DT_FEMPTY; 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci rx_desc = &priv->rx_ring[q][i]; 39562306a36Sopenharmony_ci rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]); 39662306a36Sopenharmony_ci rx_desc->die_dt = DT_LINKFIX; /* type */ 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci/* Format skb and descriptor buffer for Ethernet AVB */ 40062306a36Sopenharmony_cistatic void ravb_ring_format(struct net_device *ndev, int q) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 40362306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 40462306a36Sopenharmony_ci unsigned int num_tx_desc = priv->num_tx_desc; 40562306a36Sopenharmony_ci struct ravb_tx_desc *tx_desc; 40662306a36Sopenharmony_ci struct ravb_desc *desc; 40762306a36Sopenharmony_ci unsigned int tx_ring_size = sizeof(*tx_desc) * priv->num_tx_ring[q] * 40862306a36Sopenharmony_ci num_tx_desc; 40962306a36Sopenharmony_ci unsigned int i; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci priv->cur_rx[q] = 0; 41262306a36Sopenharmony_ci priv->cur_tx[q] = 0; 41362306a36Sopenharmony_ci priv->dirty_rx[q] = 0; 41462306a36Sopenharmony_ci priv->dirty_tx[q] = 0; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci info->rx_ring_format(ndev, q); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci memset(priv->tx_ring[q], 0, tx_ring_size); 41962306a36Sopenharmony_ci /* Build TX ring buffer */ 42062306a36Sopenharmony_ci for (i = 0, tx_desc = priv->tx_ring[q]; i < priv->num_tx_ring[q]; 42162306a36Sopenharmony_ci i++, tx_desc++) { 42262306a36Sopenharmony_ci tx_desc->die_dt = DT_EEMPTY; 42362306a36Sopenharmony_ci if (num_tx_desc > 1) { 42462306a36Sopenharmony_ci tx_desc++; 42562306a36Sopenharmony_ci tx_desc->die_dt = DT_EEMPTY; 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci tx_desc->dptr = cpu_to_le32((u32)priv->tx_desc_dma[q]); 42962306a36Sopenharmony_ci tx_desc->die_dt = DT_LINKFIX; /* type */ 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci /* RX descriptor base address for best effort */ 43262306a36Sopenharmony_ci desc = &priv->desc_bat[RX_QUEUE_OFFSET + q]; 43362306a36Sopenharmony_ci desc->die_dt = DT_LINKFIX; /* type */ 43462306a36Sopenharmony_ci desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci /* TX descriptor base address for best effort */ 43762306a36Sopenharmony_ci desc = &priv->desc_bat[q]; 43862306a36Sopenharmony_ci desc->die_dt = DT_LINKFIX; /* type */ 43962306a36Sopenharmony_ci desc->dptr = cpu_to_le32((u32)priv->tx_desc_dma[q]); 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic void *ravb_alloc_rx_desc_gbeth(struct net_device *ndev, int q) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 44562306a36Sopenharmony_ci unsigned int ring_size; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci ring_size = sizeof(struct ravb_rx_desc) * (priv->num_rx_ring[q] + 1); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci priv->gbeth_rx_ring = dma_alloc_coherent(ndev->dev.parent, ring_size, 45062306a36Sopenharmony_ci &priv->rx_desc_dma[q], 45162306a36Sopenharmony_ci GFP_KERNEL); 45262306a36Sopenharmony_ci return priv->gbeth_rx_ring; 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_cistatic void *ravb_alloc_rx_desc_rcar(struct net_device *ndev, int q) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 45862306a36Sopenharmony_ci unsigned int ring_size; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1); 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci priv->rx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size, 46362306a36Sopenharmony_ci &priv->rx_desc_dma[q], 46462306a36Sopenharmony_ci GFP_KERNEL); 46562306a36Sopenharmony_ci return priv->rx_ring[q]; 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci/* Init skb and descriptor buffer for Ethernet AVB */ 46962306a36Sopenharmony_cistatic int ravb_ring_init(struct net_device *ndev, int q) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 47262306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 47362306a36Sopenharmony_ci unsigned int num_tx_desc = priv->num_tx_desc; 47462306a36Sopenharmony_ci unsigned int ring_size; 47562306a36Sopenharmony_ci struct sk_buff *skb; 47662306a36Sopenharmony_ci unsigned int i; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci /* Allocate RX and TX skb rings */ 47962306a36Sopenharmony_ci priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q], 48062306a36Sopenharmony_ci sizeof(*priv->rx_skb[q]), GFP_KERNEL); 48162306a36Sopenharmony_ci priv->tx_skb[q] = kcalloc(priv->num_tx_ring[q], 48262306a36Sopenharmony_ci sizeof(*priv->tx_skb[q]), GFP_KERNEL); 48362306a36Sopenharmony_ci if (!priv->rx_skb[q] || !priv->tx_skb[q]) 48462306a36Sopenharmony_ci goto error; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci for (i = 0; i < priv->num_rx_ring[q]; i++) { 48762306a36Sopenharmony_ci skb = __netdev_alloc_skb(ndev, info->max_rx_len, GFP_KERNEL); 48862306a36Sopenharmony_ci if (!skb) 48962306a36Sopenharmony_ci goto error; 49062306a36Sopenharmony_ci ravb_set_buffer_align(skb); 49162306a36Sopenharmony_ci priv->rx_skb[q][i] = skb; 49262306a36Sopenharmony_ci } 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci if (num_tx_desc > 1) { 49562306a36Sopenharmony_ci /* Allocate rings for the aligned buffers */ 49662306a36Sopenharmony_ci priv->tx_align[q] = kmalloc(DPTR_ALIGN * priv->num_tx_ring[q] + 49762306a36Sopenharmony_ci DPTR_ALIGN - 1, GFP_KERNEL); 49862306a36Sopenharmony_ci if (!priv->tx_align[q]) 49962306a36Sopenharmony_ci goto error; 50062306a36Sopenharmony_ci } 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* Allocate all RX descriptors. */ 50362306a36Sopenharmony_ci if (!info->alloc_rx_desc(ndev, q)) 50462306a36Sopenharmony_ci goto error; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci priv->dirty_rx[q] = 0; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* Allocate all TX descriptors. */ 50962306a36Sopenharmony_ci ring_size = sizeof(struct ravb_tx_desc) * 51062306a36Sopenharmony_ci (priv->num_tx_ring[q] * num_tx_desc + 1); 51162306a36Sopenharmony_ci priv->tx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size, 51262306a36Sopenharmony_ci &priv->tx_desc_dma[q], 51362306a36Sopenharmony_ci GFP_KERNEL); 51462306a36Sopenharmony_ci if (!priv->tx_ring[q]) 51562306a36Sopenharmony_ci goto error; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci return 0; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_cierror: 52062306a36Sopenharmony_ci ravb_ring_free(ndev, q); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci return -ENOMEM; 52362306a36Sopenharmony_ci} 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_cistatic void ravb_emac_init_gbeth(struct net_device *ndev) 52662306a36Sopenharmony_ci{ 52762306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci if (priv->phy_interface == PHY_INTERFACE_MODE_MII) { 53062306a36Sopenharmony_ci ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_MII, CXR35); 53162306a36Sopenharmony_ci ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, 0); 53262306a36Sopenharmony_ci } else { 53362306a36Sopenharmony_ci ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_RGMII, CXR35); 53462306a36Sopenharmony_ci ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, 53562306a36Sopenharmony_ci CXR31_SEL_LINK0); 53662306a36Sopenharmony_ci } 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci /* Receive frame limit set register */ 53962306a36Sopenharmony_ci ravb_write(ndev, GBETH_RX_BUFF_MAX + ETH_FCS_LEN, RFLR); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci /* EMAC Mode: PAUSE prohibition; Duplex; TX; RX; CRC Pass Through */ 54262306a36Sopenharmony_ci ravb_write(ndev, ECMR_ZPF | ((priv->duplex > 0) ? ECMR_DM : 0) | 54362306a36Sopenharmony_ci ECMR_TE | ECMR_RE | ECMR_RCPT | 54462306a36Sopenharmony_ci ECMR_TXF | ECMR_RXF, ECMR); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci ravb_set_rate_gbeth(ndev); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci /* Set MAC address */ 54962306a36Sopenharmony_ci ravb_write(ndev, 55062306a36Sopenharmony_ci (ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) | 55162306a36Sopenharmony_ci (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR); 55262306a36Sopenharmony_ci ravb_write(ndev, (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci /* E-MAC status register clear */ 55562306a36Sopenharmony_ci ravb_write(ndev, ECSR_ICD | ECSR_LCHNG | ECSR_PFRI, ECSR); 55662306a36Sopenharmony_ci ravb_write(ndev, CSR0_TPE | CSR0_RPE, CSR0); 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci /* E-MAC interrupt enable register */ 55962306a36Sopenharmony_ci ravb_write(ndev, ECSIPR_ICDIP, ECSIPR); 56062306a36Sopenharmony_ci} 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic void ravb_emac_init_rcar(struct net_device *ndev) 56362306a36Sopenharmony_ci{ 56462306a36Sopenharmony_ci /* Receive frame limit set register */ 56562306a36Sopenharmony_ci ravb_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN, RFLR); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci /* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */ 56862306a36Sopenharmony_ci ravb_write(ndev, ECMR_ZPF | ECMR_DM | 56962306a36Sopenharmony_ci (ndev->features & NETIF_F_RXCSUM ? ECMR_RCSC : 0) | 57062306a36Sopenharmony_ci ECMR_TE | ECMR_RE, ECMR); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci ravb_set_rate_rcar(ndev); 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci /* Set MAC address */ 57562306a36Sopenharmony_ci ravb_write(ndev, 57662306a36Sopenharmony_ci (ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) | 57762306a36Sopenharmony_ci (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR); 57862306a36Sopenharmony_ci ravb_write(ndev, 57962306a36Sopenharmony_ci (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci /* E-MAC status register clear */ 58262306a36Sopenharmony_ci ravb_write(ndev, ECSR_ICD | ECSR_MPD, ECSR); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci /* E-MAC interrupt enable register */ 58562306a36Sopenharmony_ci ravb_write(ndev, ECSIPR_ICDIP | ECSIPR_MPDIP | ECSIPR_LCHNGIP, ECSIPR); 58662306a36Sopenharmony_ci} 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci/* E-MAC init function */ 58962306a36Sopenharmony_cistatic void ravb_emac_init(struct net_device *ndev) 59062306a36Sopenharmony_ci{ 59162306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 59262306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci info->emac_init(ndev); 59562306a36Sopenharmony_ci} 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cistatic int ravb_dmac_init_gbeth(struct net_device *ndev) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci int error; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci error = ravb_ring_init(ndev, RAVB_BE); 60262306a36Sopenharmony_ci if (error) 60362306a36Sopenharmony_ci return error; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci /* Descriptor format */ 60662306a36Sopenharmony_ci ravb_ring_format(ndev, RAVB_BE); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci /* Set DMAC RX */ 60962306a36Sopenharmony_ci ravb_write(ndev, 0x60000000, RCR); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci /* Set Max Frame Length (RTC) */ 61262306a36Sopenharmony_ci ravb_write(ndev, 0x7ffc0000 | GBETH_RX_BUFF_MAX, RTC); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci /* Set FIFO size */ 61562306a36Sopenharmony_ci ravb_write(ndev, 0x00222200, TGC); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci ravb_write(ndev, 0, TCCR); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci /* Frame receive */ 62062306a36Sopenharmony_ci ravb_write(ndev, RIC0_FRE0, RIC0); 62162306a36Sopenharmony_ci /* Disable FIFO full warning */ 62262306a36Sopenharmony_ci ravb_write(ndev, 0x0, RIC1); 62362306a36Sopenharmony_ci /* Receive FIFO full error, descriptor empty */ 62462306a36Sopenharmony_ci ravb_write(ndev, RIC2_QFE0 | RIC2_RFFE, RIC2); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci ravb_write(ndev, TIC_FTE0, TIC); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci return 0; 62962306a36Sopenharmony_ci} 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_cistatic int ravb_dmac_init_rcar(struct net_device *ndev) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 63462306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 63562306a36Sopenharmony_ci int error; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci error = ravb_ring_init(ndev, RAVB_BE); 63862306a36Sopenharmony_ci if (error) 63962306a36Sopenharmony_ci return error; 64062306a36Sopenharmony_ci error = ravb_ring_init(ndev, RAVB_NC); 64162306a36Sopenharmony_ci if (error) { 64262306a36Sopenharmony_ci ravb_ring_free(ndev, RAVB_BE); 64362306a36Sopenharmony_ci return error; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci /* Descriptor format */ 64762306a36Sopenharmony_ci ravb_ring_format(ndev, RAVB_BE); 64862306a36Sopenharmony_ci ravb_ring_format(ndev, RAVB_NC); 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci /* Set AVB RX */ 65162306a36Sopenharmony_ci ravb_write(ndev, 65262306a36Sopenharmony_ci RCR_EFFS | RCR_ENCF | RCR_ETS0 | RCR_ESF | 0x18000000, RCR); 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci /* Set FIFO size */ 65562306a36Sopenharmony_ci ravb_write(ndev, TGC_TQP_AVBMODE1 | 0x00112200, TGC); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* Timestamp enable */ 65862306a36Sopenharmony_ci ravb_write(ndev, TCCR_TFEN, TCCR); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* Interrupt init: */ 66162306a36Sopenharmony_ci if (info->multi_irqs) { 66262306a36Sopenharmony_ci /* Clear DIL.DPLx */ 66362306a36Sopenharmony_ci ravb_write(ndev, 0, DIL); 66462306a36Sopenharmony_ci /* Set queue specific interrupt */ 66562306a36Sopenharmony_ci ravb_write(ndev, CIE_CRIE | CIE_CTIE | CIE_CL0M, CIE); 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci /* Frame receive */ 66862306a36Sopenharmony_ci ravb_write(ndev, RIC0_FRE0 | RIC0_FRE1, RIC0); 66962306a36Sopenharmony_ci /* Disable FIFO full warning */ 67062306a36Sopenharmony_ci ravb_write(ndev, 0, RIC1); 67162306a36Sopenharmony_ci /* Receive FIFO full error, descriptor empty */ 67262306a36Sopenharmony_ci ravb_write(ndev, RIC2_QFE0 | RIC2_QFE1 | RIC2_RFFE, RIC2); 67362306a36Sopenharmony_ci /* Frame transmitted, timestamp FIFO updated */ 67462306a36Sopenharmony_ci ravb_write(ndev, TIC_FTE0 | TIC_FTE1 | TIC_TFUE, TIC); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci return 0; 67762306a36Sopenharmony_ci} 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci/* Device init function for Ethernet AVB */ 68062306a36Sopenharmony_cistatic int ravb_dmac_init(struct net_device *ndev) 68162306a36Sopenharmony_ci{ 68262306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 68362306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 68462306a36Sopenharmony_ci int error; 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci /* Set CONFIG mode */ 68762306a36Sopenharmony_ci error = ravb_set_opmode(ndev, CCC_OPC_CONFIG); 68862306a36Sopenharmony_ci if (error) 68962306a36Sopenharmony_ci return error; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci error = info->dmac_init(ndev); 69262306a36Sopenharmony_ci if (error) 69362306a36Sopenharmony_ci return error; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci /* Setting the control will start the AVB-DMAC process. */ 69662306a36Sopenharmony_ci return ravb_set_opmode(ndev, CCC_OPC_OPERATION); 69762306a36Sopenharmony_ci} 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_cistatic void ravb_get_tx_tstamp(struct net_device *ndev) 70062306a36Sopenharmony_ci{ 70162306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 70262306a36Sopenharmony_ci struct ravb_tstamp_skb *ts_skb, *ts_skb2; 70362306a36Sopenharmony_ci struct skb_shared_hwtstamps shhwtstamps; 70462306a36Sopenharmony_ci struct sk_buff *skb; 70562306a36Sopenharmony_ci struct timespec64 ts; 70662306a36Sopenharmony_ci u16 tag, tfa_tag; 70762306a36Sopenharmony_ci int count; 70862306a36Sopenharmony_ci u32 tfa2; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci count = (ravb_read(ndev, TSR) & TSR_TFFL) >> 8; 71162306a36Sopenharmony_ci while (count--) { 71262306a36Sopenharmony_ci tfa2 = ravb_read(ndev, TFA2); 71362306a36Sopenharmony_ci tfa_tag = (tfa2 & TFA2_TST) >> 16; 71462306a36Sopenharmony_ci ts.tv_nsec = (u64)ravb_read(ndev, TFA0); 71562306a36Sopenharmony_ci ts.tv_sec = ((u64)(tfa2 & TFA2_TSV) << 32) | 71662306a36Sopenharmony_ci ravb_read(ndev, TFA1); 71762306a36Sopenharmony_ci memset(&shhwtstamps, 0, sizeof(shhwtstamps)); 71862306a36Sopenharmony_ci shhwtstamps.hwtstamp = timespec64_to_ktime(ts); 71962306a36Sopenharmony_ci list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, 72062306a36Sopenharmony_ci list) { 72162306a36Sopenharmony_ci skb = ts_skb->skb; 72262306a36Sopenharmony_ci tag = ts_skb->tag; 72362306a36Sopenharmony_ci list_del(&ts_skb->list); 72462306a36Sopenharmony_ci kfree(ts_skb); 72562306a36Sopenharmony_ci if (tag == tfa_tag) { 72662306a36Sopenharmony_ci skb_tstamp_tx(skb, &shhwtstamps); 72762306a36Sopenharmony_ci dev_consume_skb_any(skb); 72862306a36Sopenharmony_ci break; 72962306a36Sopenharmony_ci } else { 73062306a36Sopenharmony_ci dev_kfree_skb_any(skb); 73162306a36Sopenharmony_ci } 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR); 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci} 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_cistatic void ravb_rx_csum(struct sk_buff *skb) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci u8 *hw_csum; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci /* The hardware checksum is contained in sizeof(__sum16) (2) bytes 74262306a36Sopenharmony_ci * appended to packet data 74362306a36Sopenharmony_ci */ 74462306a36Sopenharmony_ci if (unlikely(skb->len < sizeof(__sum16))) 74562306a36Sopenharmony_ci return; 74662306a36Sopenharmony_ci hw_csum = skb_tail_pointer(skb) - sizeof(__sum16); 74762306a36Sopenharmony_ci skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum)); 74862306a36Sopenharmony_ci skb->ip_summed = CHECKSUM_COMPLETE; 74962306a36Sopenharmony_ci skb_trim(skb, skb->len - sizeof(__sum16)); 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic struct sk_buff *ravb_get_skb_gbeth(struct net_device *ndev, int entry, 75362306a36Sopenharmony_ci struct ravb_rx_desc *desc) 75462306a36Sopenharmony_ci{ 75562306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 75662306a36Sopenharmony_ci struct sk_buff *skb; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci skb = priv->rx_skb[RAVB_BE][entry]; 75962306a36Sopenharmony_ci priv->rx_skb[RAVB_BE][entry] = NULL; 76062306a36Sopenharmony_ci dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), 76162306a36Sopenharmony_ci ALIGN(GBETH_RX_BUFF_MAX, 16), DMA_FROM_DEVICE); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci return skb; 76462306a36Sopenharmony_ci} 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci/* Packet receive function for Gigabit Ethernet */ 76762306a36Sopenharmony_cistatic bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q) 76862306a36Sopenharmony_ci{ 76962306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 77062306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 77162306a36Sopenharmony_ci struct net_device_stats *stats; 77262306a36Sopenharmony_ci struct ravb_rx_desc *desc; 77362306a36Sopenharmony_ci struct sk_buff *skb; 77462306a36Sopenharmony_ci dma_addr_t dma_addr; 77562306a36Sopenharmony_ci u8 desc_status; 77662306a36Sopenharmony_ci int boguscnt; 77762306a36Sopenharmony_ci u16 pkt_len; 77862306a36Sopenharmony_ci u8 die_dt; 77962306a36Sopenharmony_ci int entry; 78062306a36Sopenharmony_ci int limit; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci entry = priv->cur_rx[q] % priv->num_rx_ring[q]; 78362306a36Sopenharmony_ci boguscnt = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q]; 78462306a36Sopenharmony_ci stats = &priv->stats[q]; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_ci boguscnt = min(boguscnt, *quota); 78762306a36Sopenharmony_ci limit = boguscnt; 78862306a36Sopenharmony_ci desc = &priv->gbeth_rx_ring[entry]; 78962306a36Sopenharmony_ci while (desc->die_dt != DT_FEMPTY) { 79062306a36Sopenharmony_ci /* Descriptor type must be checked before all other reads */ 79162306a36Sopenharmony_ci dma_rmb(); 79262306a36Sopenharmony_ci desc_status = desc->msc; 79362306a36Sopenharmony_ci pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci if (--boguscnt < 0) 79662306a36Sopenharmony_ci break; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci /* We use 0-byte descriptors to mark the DMA mapping errors */ 79962306a36Sopenharmony_ci if (!pkt_len) 80062306a36Sopenharmony_ci continue; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci if (desc_status & MSC_MC) 80362306a36Sopenharmony_ci stats->multicast++; 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci if (desc_status & (MSC_CRC | MSC_RFE | MSC_RTSF | MSC_RTLF | MSC_CEEF)) { 80662306a36Sopenharmony_ci stats->rx_errors++; 80762306a36Sopenharmony_ci if (desc_status & MSC_CRC) 80862306a36Sopenharmony_ci stats->rx_crc_errors++; 80962306a36Sopenharmony_ci if (desc_status & MSC_RFE) 81062306a36Sopenharmony_ci stats->rx_frame_errors++; 81162306a36Sopenharmony_ci if (desc_status & (MSC_RTLF | MSC_RTSF)) 81262306a36Sopenharmony_ci stats->rx_length_errors++; 81362306a36Sopenharmony_ci if (desc_status & MSC_CEEF) 81462306a36Sopenharmony_ci stats->rx_missed_errors++; 81562306a36Sopenharmony_ci } else { 81662306a36Sopenharmony_ci die_dt = desc->die_dt & 0xF0; 81762306a36Sopenharmony_ci switch (die_dt) { 81862306a36Sopenharmony_ci case DT_FSINGLE: 81962306a36Sopenharmony_ci skb = ravb_get_skb_gbeth(ndev, entry, desc); 82062306a36Sopenharmony_ci skb_put(skb, pkt_len); 82162306a36Sopenharmony_ci skb->protocol = eth_type_trans(skb, ndev); 82262306a36Sopenharmony_ci napi_gro_receive(&priv->napi[q], skb); 82362306a36Sopenharmony_ci stats->rx_packets++; 82462306a36Sopenharmony_ci stats->rx_bytes += pkt_len; 82562306a36Sopenharmony_ci break; 82662306a36Sopenharmony_ci case DT_FSTART: 82762306a36Sopenharmony_ci priv->rx_1st_skb = ravb_get_skb_gbeth(ndev, entry, desc); 82862306a36Sopenharmony_ci skb_put(priv->rx_1st_skb, pkt_len); 82962306a36Sopenharmony_ci break; 83062306a36Sopenharmony_ci case DT_FMID: 83162306a36Sopenharmony_ci skb = ravb_get_skb_gbeth(ndev, entry, desc); 83262306a36Sopenharmony_ci skb_copy_to_linear_data_offset(priv->rx_1st_skb, 83362306a36Sopenharmony_ci priv->rx_1st_skb->len, 83462306a36Sopenharmony_ci skb->data, 83562306a36Sopenharmony_ci pkt_len); 83662306a36Sopenharmony_ci skb_put(priv->rx_1st_skb, pkt_len); 83762306a36Sopenharmony_ci dev_kfree_skb(skb); 83862306a36Sopenharmony_ci break; 83962306a36Sopenharmony_ci case DT_FEND: 84062306a36Sopenharmony_ci skb = ravb_get_skb_gbeth(ndev, entry, desc); 84162306a36Sopenharmony_ci skb_copy_to_linear_data_offset(priv->rx_1st_skb, 84262306a36Sopenharmony_ci priv->rx_1st_skb->len, 84362306a36Sopenharmony_ci skb->data, 84462306a36Sopenharmony_ci pkt_len); 84562306a36Sopenharmony_ci skb_put(priv->rx_1st_skb, pkt_len); 84662306a36Sopenharmony_ci dev_kfree_skb(skb); 84762306a36Sopenharmony_ci priv->rx_1st_skb->protocol = 84862306a36Sopenharmony_ci eth_type_trans(priv->rx_1st_skb, ndev); 84962306a36Sopenharmony_ci napi_gro_receive(&priv->napi[q], 85062306a36Sopenharmony_ci priv->rx_1st_skb); 85162306a36Sopenharmony_ci stats->rx_packets++; 85262306a36Sopenharmony_ci stats->rx_bytes += pkt_len; 85362306a36Sopenharmony_ci break; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q]; 85862306a36Sopenharmony_ci desc = &priv->gbeth_rx_ring[entry]; 85962306a36Sopenharmony_ci } 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* Refill the RX ring buffers. */ 86262306a36Sopenharmony_ci for (; priv->cur_rx[q] - priv->dirty_rx[q] > 0; priv->dirty_rx[q]++) { 86362306a36Sopenharmony_ci entry = priv->dirty_rx[q] % priv->num_rx_ring[q]; 86462306a36Sopenharmony_ci desc = &priv->gbeth_rx_ring[entry]; 86562306a36Sopenharmony_ci desc->ds_cc = cpu_to_le16(GBETH_RX_DESC_DATA_SIZE); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci if (!priv->rx_skb[q][entry]) { 86862306a36Sopenharmony_ci skb = netdev_alloc_skb(ndev, info->max_rx_len); 86962306a36Sopenharmony_ci if (!skb) 87062306a36Sopenharmony_ci break; 87162306a36Sopenharmony_ci ravb_set_buffer_align(skb); 87262306a36Sopenharmony_ci dma_addr = dma_map_single(ndev->dev.parent, 87362306a36Sopenharmony_ci skb->data, 87462306a36Sopenharmony_ci GBETH_RX_BUFF_MAX, 87562306a36Sopenharmony_ci DMA_FROM_DEVICE); 87662306a36Sopenharmony_ci skb_checksum_none_assert(skb); 87762306a36Sopenharmony_ci /* We just set the data size to 0 for a failed mapping 87862306a36Sopenharmony_ci * which should prevent DMA from happening... 87962306a36Sopenharmony_ci */ 88062306a36Sopenharmony_ci if (dma_mapping_error(ndev->dev.parent, dma_addr)) 88162306a36Sopenharmony_ci desc->ds_cc = cpu_to_le16(0); 88262306a36Sopenharmony_ci desc->dptr = cpu_to_le32(dma_addr); 88362306a36Sopenharmony_ci priv->rx_skb[q][entry] = skb; 88462306a36Sopenharmony_ci } 88562306a36Sopenharmony_ci /* Descriptor type must be set after all the above writes */ 88662306a36Sopenharmony_ci dma_wmb(); 88762306a36Sopenharmony_ci desc->die_dt = DT_FEMPTY; 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci *quota -= limit - (++boguscnt); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci return boguscnt <= 0; 89362306a36Sopenharmony_ci} 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci/* Packet receive function for Ethernet AVB */ 89662306a36Sopenharmony_cistatic bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q) 89762306a36Sopenharmony_ci{ 89862306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 89962306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 90062306a36Sopenharmony_ci int entry = priv->cur_rx[q] % priv->num_rx_ring[q]; 90162306a36Sopenharmony_ci int boguscnt = (priv->dirty_rx[q] + priv->num_rx_ring[q]) - 90262306a36Sopenharmony_ci priv->cur_rx[q]; 90362306a36Sopenharmony_ci struct net_device_stats *stats = &priv->stats[q]; 90462306a36Sopenharmony_ci struct ravb_ex_rx_desc *desc; 90562306a36Sopenharmony_ci struct sk_buff *skb; 90662306a36Sopenharmony_ci dma_addr_t dma_addr; 90762306a36Sopenharmony_ci struct timespec64 ts; 90862306a36Sopenharmony_ci u8 desc_status; 90962306a36Sopenharmony_ci u16 pkt_len; 91062306a36Sopenharmony_ci int limit; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci boguscnt = min(boguscnt, *quota); 91362306a36Sopenharmony_ci limit = boguscnt; 91462306a36Sopenharmony_ci desc = &priv->rx_ring[q][entry]; 91562306a36Sopenharmony_ci while (desc->die_dt != DT_FEMPTY) { 91662306a36Sopenharmony_ci /* Descriptor type must be checked before all other reads */ 91762306a36Sopenharmony_ci dma_rmb(); 91862306a36Sopenharmony_ci desc_status = desc->msc; 91962306a36Sopenharmony_ci pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci if (--boguscnt < 0) 92262306a36Sopenharmony_ci break; 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci /* We use 0-byte descriptors to mark the DMA mapping errors */ 92562306a36Sopenharmony_ci if (!pkt_len) 92662306a36Sopenharmony_ci continue; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (desc_status & MSC_MC) 92962306a36Sopenharmony_ci stats->multicast++; 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci if (desc_status & (MSC_CRC | MSC_RFE | MSC_RTSF | MSC_RTLF | 93262306a36Sopenharmony_ci MSC_CEEF)) { 93362306a36Sopenharmony_ci stats->rx_errors++; 93462306a36Sopenharmony_ci if (desc_status & MSC_CRC) 93562306a36Sopenharmony_ci stats->rx_crc_errors++; 93662306a36Sopenharmony_ci if (desc_status & MSC_RFE) 93762306a36Sopenharmony_ci stats->rx_frame_errors++; 93862306a36Sopenharmony_ci if (desc_status & (MSC_RTLF | MSC_RTSF)) 93962306a36Sopenharmony_ci stats->rx_length_errors++; 94062306a36Sopenharmony_ci if (desc_status & MSC_CEEF) 94162306a36Sopenharmony_ci stats->rx_missed_errors++; 94262306a36Sopenharmony_ci } else { 94362306a36Sopenharmony_ci u32 get_ts = priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE; 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci skb = priv->rx_skb[q][entry]; 94662306a36Sopenharmony_ci priv->rx_skb[q][entry] = NULL; 94762306a36Sopenharmony_ci dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), 94862306a36Sopenharmony_ci RX_BUF_SZ, 94962306a36Sopenharmony_ci DMA_FROM_DEVICE); 95062306a36Sopenharmony_ci get_ts &= (q == RAVB_NC) ? 95162306a36Sopenharmony_ci RAVB_RXTSTAMP_TYPE_V2_L2_EVENT : 95262306a36Sopenharmony_ci ~RAVB_RXTSTAMP_TYPE_V2_L2_EVENT; 95362306a36Sopenharmony_ci if (get_ts) { 95462306a36Sopenharmony_ci struct skb_shared_hwtstamps *shhwtstamps; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci shhwtstamps = skb_hwtstamps(skb); 95762306a36Sopenharmony_ci memset(shhwtstamps, 0, sizeof(*shhwtstamps)); 95862306a36Sopenharmony_ci ts.tv_sec = ((u64) le16_to_cpu(desc->ts_sh) << 95962306a36Sopenharmony_ci 32) | le32_to_cpu(desc->ts_sl); 96062306a36Sopenharmony_ci ts.tv_nsec = le32_to_cpu(desc->ts_n); 96162306a36Sopenharmony_ci shhwtstamps->hwtstamp = timespec64_to_ktime(ts); 96262306a36Sopenharmony_ci } 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci skb_put(skb, pkt_len); 96562306a36Sopenharmony_ci skb->protocol = eth_type_trans(skb, ndev); 96662306a36Sopenharmony_ci if (ndev->features & NETIF_F_RXCSUM) 96762306a36Sopenharmony_ci ravb_rx_csum(skb); 96862306a36Sopenharmony_ci napi_gro_receive(&priv->napi[q], skb); 96962306a36Sopenharmony_ci stats->rx_packets++; 97062306a36Sopenharmony_ci stats->rx_bytes += pkt_len; 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q]; 97462306a36Sopenharmony_ci desc = &priv->rx_ring[q][entry]; 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci /* Refill the RX ring buffers. */ 97862306a36Sopenharmony_ci for (; priv->cur_rx[q] - priv->dirty_rx[q] > 0; priv->dirty_rx[q]++) { 97962306a36Sopenharmony_ci entry = priv->dirty_rx[q] % priv->num_rx_ring[q]; 98062306a36Sopenharmony_ci desc = &priv->rx_ring[q][entry]; 98162306a36Sopenharmony_ci desc->ds_cc = cpu_to_le16(RX_BUF_SZ); 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci if (!priv->rx_skb[q][entry]) { 98462306a36Sopenharmony_ci skb = netdev_alloc_skb(ndev, info->max_rx_len); 98562306a36Sopenharmony_ci if (!skb) 98662306a36Sopenharmony_ci break; /* Better luck next round. */ 98762306a36Sopenharmony_ci ravb_set_buffer_align(skb); 98862306a36Sopenharmony_ci dma_addr = dma_map_single(ndev->dev.parent, skb->data, 98962306a36Sopenharmony_ci le16_to_cpu(desc->ds_cc), 99062306a36Sopenharmony_ci DMA_FROM_DEVICE); 99162306a36Sopenharmony_ci skb_checksum_none_assert(skb); 99262306a36Sopenharmony_ci /* We just set the data size to 0 for a failed mapping 99362306a36Sopenharmony_ci * which should prevent DMA from happening... 99462306a36Sopenharmony_ci */ 99562306a36Sopenharmony_ci if (dma_mapping_error(ndev->dev.parent, dma_addr)) 99662306a36Sopenharmony_ci desc->ds_cc = cpu_to_le16(0); 99762306a36Sopenharmony_ci desc->dptr = cpu_to_le32(dma_addr); 99862306a36Sopenharmony_ci priv->rx_skb[q][entry] = skb; 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci /* Descriptor type must be set after all the above writes */ 100162306a36Sopenharmony_ci dma_wmb(); 100262306a36Sopenharmony_ci desc->die_dt = DT_FEMPTY; 100362306a36Sopenharmony_ci } 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci *quota -= limit - (++boguscnt); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci return boguscnt <= 0; 100862306a36Sopenharmony_ci} 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci/* Packet receive function for Ethernet AVB */ 101162306a36Sopenharmony_cistatic bool ravb_rx(struct net_device *ndev, int *quota, int q) 101262306a36Sopenharmony_ci{ 101362306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 101462306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci return info->receive(ndev, quota, q); 101762306a36Sopenharmony_ci} 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_cistatic void ravb_rcv_snd_disable(struct net_device *ndev) 102062306a36Sopenharmony_ci{ 102162306a36Sopenharmony_ci /* Disable TX and RX */ 102262306a36Sopenharmony_ci ravb_modify(ndev, ECMR, ECMR_RE | ECMR_TE, 0); 102362306a36Sopenharmony_ci} 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_cistatic void ravb_rcv_snd_enable(struct net_device *ndev) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci /* Enable TX and RX */ 102862306a36Sopenharmony_ci ravb_modify(ndev, ECMR, ECMR_RE | ECMR_TE, ECMR_RE | ECMR_TE); 102962306a36Sopenharmony_ci} 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci/* function for waiting dma process finished */ 103262306a36Sopenharmony_cistatic int ravb_stop_dma(struct net_device *ndev) 103362306a36Sopenharmony_ci{ 103462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 103562306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 103662306a36Sopenharmony_ci int error; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci /* Wait for stopping the hardware TX process */ 103962306a36Sopenharmony_ci error = ravb_wait(ndev, TCCR, info->tccr_mask, 0); 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci if (error) 104262306a36Sopenharmony_ci return error; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci error = ravb_wait(ndev, CSR, CSR_TPO0 | CSR_TPO1 | CSR_TPO2 | CSR_TPO3, 104562306a36Sopenharmony_ci 0); 104662306a36Sopenharmony_ci if (error) 104762306a36Sopenharmony_ci return error; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci /* Stop the E-MAC's RX/TX processes. */ 105062306a36Sopenharmony_ci ravb_rcv_snd_disable(ndev); 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci /* Wait for stopping the RX DMA process */ 105362306a36Sopenharmony_ci error = ravb_wait(ndev, CSR, CSR_RPO, 0); 105462306a36Sopenharmony_ci if (error) 105562306a36Sopenharmony_ci return error; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci /* Stop AVB-DMAC process */ 105862306a36Sopenharmony_ci return ravb_set_opmode(ndev, CCC_OPC_CONFIG); 105962306a36Sopenharmony_ci} 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci/* E-MAC interrupt handler */ 106262306a36Sopenharmony_cistatic void ravb_emac_interrupt_unlocked(struct net_device *ndev) 106362306a36Sopenharmony_ci{ 106462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 106562306a36Sopenharmony_ci u32 ecsr, psr; 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci ecsr = ravb_read(ndev, ECSR); 106862306a36Sopenharmony_ci ravb_write(ndev, ecsr, ECSR); /* clear interrupt */ 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_ci if (ecsr & ECSR_MPD) 107162306a36Sopenharmony_ci pm_wakeup_event(&priv->pdev->dev, 0); 107262306a36Sopenharmony_ci if (ecsr & ECSR_ICD) 107362306a36Sopenharmony_ci ndev->stats.tx_carrier_errors++; 107462306a36Sopenharmony_ci if (ecsr & ECSR_LCHNG) { 107562306a36Sopenharmony_ci /* Link changed */ 107662306a36Sopenharmony_ci if (priv->no_avb_link) 107762306a36Sopenharmony_ci return; 107862306a36Sopenharmony_ci psr = ravb_read(ndev, PSR); 107962306a36Sopenharmony_ci if (priv->avb_link_active_low) 108062306a36Sopenharmony_ci psr ^= PSR_LMON; 108162306a36Sopenharmony_ci if (!(psr & PSR_LMON)) { 108262306a36Sopenharmony_ci /* DIsable RX and TX */ 108362306a36Sopenharmony_ci ravb_rcv_snd_disable(ndev); 108462306a36Sopenharmony_ci } else { 108562306a36Sopenharmony_ci /* Enable RX and TX */ 108662306a36Sopenharmony_ci ravb_rcv_snd_enable(ndev); 108762306a36Sopenharmony_ci } 108862306a36Sopenharmony_ci } 108962306a36Sopenharmony_ci} 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_cistatic irqreturn_t ravb_emac_interrupt(int irq, void *dev_id) 109262306a36Sopenharmony_ci{ 109362306a36Sopenharmony_ci struct net_device *ndev = dev_id; 109462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci spin_lock(&priv->lock); 109762306a36Sopenharmony_ci ravb_emac_interrupt_unlocked(ndev); 109862306a36Sopenharmony_ci spin_unlock(&priv->lock); 109962306a36Sopenharmony_ci return IRQ_HANDLED; 110062306a36Sopenharmony_ci} 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci/* Error interrupt handler */ 110362306a36Sopenharmony_cistatic void ravb_error_interrupt(struct net_device *ndev) 110462306a36Sopenharmony_ci{ 110562306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 110662306a36Sopenharmony_ci u32 eis, ris2; 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci eis = ravb_read(ndev, EIS); 110962306a36Sopenharmony_ci ravb_write(ndev, ~(EIS_QFS | EIS_RESERVED), EIS); 111062306a36Sopenharmony_ci if (eis & EIS_QFS) { 111162306a36Sopenharmony_ci ris2 = ravb_read(ndev, RIS2); 111262306a36Sopenharmony_ci ravb_write(ndev, ~(RIS2_QFF0 | RIS2_QFF1 | RIS2_RFFF | RIS2_RESERVED), 111362306a36Sopenharmony_ci RIS2); 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci /* Receive Descriptor Empty int */ 111662306a36Sopenharmony_ci if (ris2 & RIS2_QFF0) 111762306a36Sopenharmony_ci priv->stats[RAVB_BE].rx_over_errors++; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci /* Receive Descriptor Empty int */ 112062306a36Sopenharmony_ci if (ris2 & RIS2_QFF1) 112162306a36Sopenharmony_ci priv->stats[RAVB_NC].rx_over_errors++; 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci /* Receive FIFO Overflow int */ 112462306a36Sopenharmony_ci if (ris2 & RIS2_RFFF) 112562306a36Sopenharmony_ci priv->rx_fifo_errors++; 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci} 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_cistatic bool ravb_queue_interrupt(struct net_device *ndev, int q) 113062306a36Sopenharmony_ci{ 113162306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 113262306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 113362306a36Sopenharmony_ci u32 ris0 = ravb_read(ndev, RIS0); 113462306a36Sopenharmony_ci u32 ric0 = ravb_read(ndev, RIC0); 113562306a36Sopenharmony_ci u32 tis = ravb_read(ndev, TIS); 113662306a36Sopenharmony_ci u32 tic = ravb_read(ndev, TIC); 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci if (((ris0 & ric0) & BIT(q)) || ((tis & tic) & BIT(q))) { 113962306a36Sopenharmony_ci if (napi_schedule_prep(&priv->napi[q])) { 114062306a36Sopenharmony_ci /* Mask RX and TX interrupts */ 114162306a36Sopenharmony_ci if (!info->irq_en_dis) { 114262306a36Sopenharmony_ci ravb_write(ndev, ric0 & ~BIT(q), RIC0); 114362306a36Sopenharmony_ci ravb_write(ndev, tic & ~BIT(q), TIC); 114462306a36Sopenharmony_ci } else { 114562306a36Sopenharmony_ci ravb_write(ndev, BIT(q), RID0); 114662306a36Sopenharmony_ci ravb_write(ndev, BIT(q), TID); 114762306a36Sopenharmony_ci } 114862306a36Sopenharmony_ci __napi_schedule(&priv->napi[q]); 114962306a36Sopenharmony_ci } else { 115062306a36Sopenharmony_ci netdev_warn(ndev, 115162306a36Sopenharmony_ci "ignoring interrupt, rx status 0x%08x, rx mask 0x%08x,\n", 115262306a36Sopenharmony_ci ris0, ric0); 115362306a36Sopenharmony_ci netdev_warn(ndev, 115462306a36Sopenharmony_ci " tx status 0x%08x, tx mask 0x%08x.\n", 115562306a36Sopenharmony_ci tis, tic); 115662306a36Sopenharmony_ci } 115762306a36Sopenharmony_ci return true; 115862306a36Sopenharmony_ci } 115962306a36Sopenharmony_ci return false; 116062306a36Sopenharmony_ci} 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_cistatic bool ravb_timestamp_interrupt(struct net_device *ndev) 116362306a36Sopenharmony_ci{ 116462306a36Sopenharmony_ci u32 tis = ravb_read(ndev, TIS); 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci if (tis & TIS_TFUF) { 116762306a36Sopenharmony_ci ravb_write(ndev, ~(TIS_TFUF | TIS_RESERVED), TIS); 116862306a36Sopenharmony_ci ravb_get_tx_tstamp(ndev); 116962306a36Sopenharmony_ci return true; 117062306a36Sopenharmony_ci } 117162306a36Sopenharmony_ci return false; 117262306a36Sopenharmony_ci} 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_cistatic irqreturn_t ravb_interrupt(int irq, void *dev_id) 117562306a36Sopenharmony_ci{ 117662306a36Sopenharmony_ci struct net_device *ndev = dev_id; 117762306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 117862306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 117962306a36Sopenharmony_ci irqreturn_t result = IRQ_NONE; 118062306a36Sopenharmony_ci u32 iss; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci spin_lock(&priv->lock); 118362306a36Sopenharmony_ci /* Get interrupt status */ 118462306a36Sopenharmony_ci iss = ravb_read(ndev, ISS); 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci /* Received and transmitted interrupts */ 118762306a36Sopenharmony_ci if (iss & (ISS_FRS | ISS_FTS | ISS_TFUS)) { 118862306a36Sopenharmony_ci int q; 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci /* Timestamp updated */ 119162306a36Sopenharmony_ci if (ravb_timestamp_interrupt(ndev)) 119262306a36Sopenharmony_ci result = IRQ_HANDLED; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci /* Network control and best effort queue RX/TX */ 119562306a36Sopenharmony_ci if (info->nc_queues) { 119662306a36Sopenharmony_ci for (q = RAVB_NC; q >= RAVB_BE; q--) { 119762306a36Sopenharmony_ci if (ravb_queue_interrupt(ndev, q)) 119862306a36Sopenharmony_ci result = IRQ_HANDLED; 119962306a36Sopenharmony_ci } 120062306a36Sopenharmony_ci } else { 120162306a36Sopenharmony_ci if (ravb_queue_interrupt(ndev, RAVB_BE)) 120262306a36Sopenharmony_ci result = IRQ_HANDLED; 120362306a36Sopenharmony_ci } 120462306a36Sopenharmony_ci } 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci /* E-MAC status summary */ 120762306a36Sopenharmony_ci if (iss & ISS_MS) { 120862306a36Sopenharmony_ci ravb_emac_interrupt_unlocked(ndev); 120962306a36Sopenharmony_ci result = IRQ_HANDLED; 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci /* Error status summary */ 121362306a36Sopenharmony_ci if (iss & ISS_ES) { 121462306a36Sopenharmony_ci ravb_error_interrupt(ndev); 121562306a36Sopenharmony_ci result = IRQ_HANDLED; 121662306a36Sopenharmony_ci } 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci /* gPTP interrupt status summary */ 121962306a36Sopenharmony_ci if (iss & ISS_CGIS) { 122062306a36Sopenharmony_ci ravb_ptp_interrupt(ndev); 122162306a36Sopenharmony_ci result = IRQ_HANDLED; 122262306a36Sopenharmony_ci } 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci spin_unlock(&priv->lock); 122562306a36Sopenharmony_ci return result; 122662306a36Sopenharmony_ci} 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci/* Timestamp/Error/gPTP interrupt handler */ 122962306a36Sopenharmony_cistatic irqreturn_t ravb_multi_interrupt(int irq, void *dev_id) 123062306a36Sopenharmony_ci{ 123162306a36Sopenharmony_ci struct net_device *ndev = dev_id; 123262306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 123362306a36Sopenharmony_ci irqreturn_t result = IRQ_NONE; 123462306a36Sopenharmony_ci u32 iss; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci spin_lock(&priv->lock); 123762306a36Sopenharmony_ci /* Get interrupt status */ 123862306a36Sopenharmony_ci iss = ravb_read(ndev, ISS); 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci /* Timestamp updated */ 124162306a36Sopenharmony_ci if ((iss & ISS_TFUS) && ravb_timestamp_interrupt(ndev)) 124262306a36Sopenharmony_ci result = IRQ_HANDLED; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci /* Error status summary */ 124562306a36Sopenharmony_ci if (iss & ISS_ES) { 124662306a36Sopenharmony_ci ravb_error_interrupt(ndev); 124762306a36Sopenharmony_ci result = IRQ_HANDLED; 124862306a36Sopenharmony_ci } 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci /* gPTP interrupt status summary */ 125162306a36Sopenharmony_ci if (iss & ISS_CGIS) { 125262306a36Sopenharmony_ci ravb_ptp_interrupt(ndev); 125362306a36Sopenharmony_ci result = IRQ_HANDLED; 125462306a36Sopenharmony_ci } 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci spin_unlock(&priv->lock); 125762306a36Sopenharmony_ci return result; 125862306a36Sopenharmony_ci} 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_cistatic irqreturn_t ravb_dma_interrupt(int irq, void *dev_id, int q) 126162306a36Sopenharmony_ci{ 126262306a36Sopenharmony_ci struct net_device *ndev = dev_id; 126362306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 126462306a36Sopenharmony_ci irqreturn_t result = IRQ_NONE; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci spin_lock(&priv->lock); 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci /* Network control/Best effort queue RX/TX */ 126962306a36Sopenharmony_ci if (ravb_queue_interrupt(ndev, q)) 127062306a36Sopenharmony_ci result = IRQ_HANDLED; 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci spin_unlock(&priv->lock); 127362306a36Sopenharmony_ci return result; 127462306a36Sopenharmony_ci} 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_cistatic irqreturn_t ravb_be_interrupt(int irq, void *dev_id) 127762306a36Sopenharmony_ci{ 127862306a36Sopenharmony_ci return ravb_dma_interrupt(irq, dev_id, RAVB_BE); 127962306a36Sopenharmony_ci} 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_cistatic irqreturn_t ravb_nc_interrupt(int irq, void *dev_id) 128262306a36Sopenharmony_ci{ 128362306a36Sopenharmony_ci return ravb_dma_interrupt(irq, dev_id, RAVB_NC); 128462306a36Sopenharmony_ci} 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_cistatic int ravb_poll(struct napi_struct *napi, int budget) 128762306a36Sopenharmony_ci{ 128862306a36Sopenharmony_ci struct net_device *ndev = napi->dev; 128962306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 129062306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 129162306a36Sopenharmony_ci bool gptp = info->gptp || info->ccc_gac; 129262306a36Sopenharmony_ci struct ravb_rx_desc *desc; 129362306a36Sopenharmony_ci unsigned long flags; 129462306a36Sopenharmony_ci int q = napi - priv->napi; 129562306a36Sopenharmony_ci int mask = BIT(q); 129662306a36Sopenharmony_ci int quota = budget; 129762306a36Sopenharmony_ci unsigned int entry; 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci if (!gptp) { 130062306a36Sopenharmony_ci entry = priv->cur_rx[q] % priv->num_rx_ring[q]; 130162306a36Sopenharmony_ci desc = &priv->gbeth_rx_ring[entry]; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci /* Processing RX Descriptor Ring */ 130462306a36Sopenharmony_ci /* Clear RX interrupt */ 130562306a36Sopenharmony_ci ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0); 130662306a36Sopenharmony_ci if (gptp || desc->die_dt != DT_FEMPTY) { 130762306a36Sopenharmony_ci if (ravb_rx(ndev, "a, q)) 130862306a36Sopenharmony_ci goto out; 130962306a36Sopenharmony_ci } 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci /* Processing TX Descriptor Ring */ 131262306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 131362306a36Sopenharmony_ci /* Clear TX interrupt */ 131462306a36Sopenharmony_ci ravb_write(ndev, ~(mask | TIS_RESERVED), TIS); 131562306a36Sopenharmony_ci ravb_tx_free(ndev, q, true); 131662306a36Sopenharmony_ci netif_wake_subqueue(ndev, q); 131762306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci napi_complete(napi); 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci /* Re-enable RX/TX interrupts */ 132262306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 132362306a36Sopenharmony_ci if (!info->irq_en_dis) { 132462306a36Sopenharmony_ci ravb_modify(ndev, RIC0, mask, mask); 132562306a36Sopenharmony_ci ravb_modify(ndev, TIC, mask, mask); 132662306a36Sopenharmony_ci } else { 132762306a36Sopenharmony_ci ravb_write(ndev, mask, RIE0); 132862306a36Sopenharmony_ci ravb_write(ndev, mask, TIE); 132962306a36Sopenharmony_ci } 133062306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci /* Receive error message handling */ 133362306a36Sopenharmony_ci priv->rx_over_errors = priv->stats[RAVB_BE].rx_over_errors; 133462306a36Sopenharmony_ci if (info->nc_queues) 133562306a36Sopenharmony_ci priv->rx_over_errors += priv->stats[RAVB_NC].rx_over_errors; 133662306a36Sopenharmony_ci if (priv->rx_over_errors != ndev->stats.rx_over_errors) 133762306a36Sopenharmony_ci ndev->stats.rx_over_errors = priv->rx_over_errors; 133862306a36Sopenharmony_ci if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors) 133962306a36Sopenharmony_ci ndev->stats.rx_fifo_errors = priv->rx_fifo_errors; 134062306a36Sopenharmony_ciout: 134162306a36Sopenharmony_ci return budget - quota; 134262306a36Sopenharmony_ci} 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_cistatic void ravb_set_duplex_gbeth(struct net_device *ndev) 134562306a36Sopenharmony_ci{ 134662306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci ravb_modify(ndev, ECMR, ECMR_DM, priv->duplex > 0 ? ECMR_DM : 0); 134962306a36Sopenharmony_ci} 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci/* PHY state control function */ 135262306a36Sopenharmony_cistatic void ravb_adjust_link(struct net_device *ndev) 135362306a36Sopenharmony_ci{ 135462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 135562306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 135662306a36Sopenharmony_ci struct phy_device *phydev = ndev->phydev; 135762306a36Sopenharmony_ci bool new_state = false; 135862306a36Sopenharmony_ci unsigned long flags; 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci /* Disable TX and RX right over here, if E-MAC change is ignored */ 136362306a36Sopenharmony_ci if (priv->no_avb_link) 136462306a36Sopenharmony_ci ravb_rcv_snd_disable(ndev); 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci if (phydev->link) { 136762306a36Sopenharmony_ci if (info->half_duplex && phydev->duplex != priv->duplex) { 136862306a36Sopenharmony_ci new_state = true; 136962306a36Sopenharmony_ci priv->duplex = phydev->duplex; 137062306a36Sopenharmony_ci ravb_set_duplex_gbeth(ndev); 137162306a36Sopenharmony_ci } 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci if (phydev->speed != priv->speed) { 137462306a36Sopenharmony_ci new_state = true; 137562306a36Sopenharmony_ci priv->speed = phydev->speed; 137662306a36Sopenharmony_ci info->set_rate(ndev); 137762306a36Sopenharmony_ci } 137862306a36Sopenharmony_ci if (!priv->link) { 137962306a36Sopenharmony_ci ravb_modify(ndev, ECMR, ECMR_TXF, 0); 138062306a36Sopenharmony_ci new_state = true; 138162306a36Sopenharmony_ci priv->link = phydev->link; 138262306a36Sopenharmony_ci } 138362306a36Sopenharmony_ci } else if (priv->link) { 138462306a36Sopenharmony_ci new_state = true; 138562306a36Sopenharmony_ci priv->link = 0; 138662306a36Sopenharmony_ci priv->speed = 0; 138762306a36Sopenharmony_ci if (info->half_duplex) 138862306a36Sopenharmony_ci priv->duplex = -1; 138962306a36Sopenharmony_ci } 139062306a36Sopenharmony_ci 139162306a36Sopenharmony_ci /* Enable TX and RX right over here, if E-MAC change is ignored */ 139262306a36Sopenharmony_ci if (priv->no_avb_link && phydev->link) 139362306a36Sopenharmony_ci ravb_rcv_snd_enable(ndev); 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci if (new_state && netif_msg_link(priv)) 139862306a36Sopenharmony_ci phy_print_status(phydev); 139962306a36Sopenharmony_ci} 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci/* PHY init function */ 140262306a36Sopenharmony_cistatic int ravb_phy_init(struct net_device *ndev) 140362306a36Sopenharmony_ci{ 140462306a36Sopenharmony_ci struct device_node *np = ndev->dev.parent->of_node; 140562306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 140662306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 140762306a36Sopenharmony_ci struct phy_device *phydev; 140862306a36Sopenharmony_ci struct device_node *pn; 140962306a36Sopenharmony_ci phy_interface_t iface; 141062306a36Sopenharmony_ci int err; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci priv->link = 0; 141362306a36Sopenharmony_ci priv->speed = 0; 141462306a36Sopenharmony_ci priv->duplex = -1; 141562306a36Sopenharmony_ci 141662306a36Sopenharmony_ci /* Try connecting to PHY */ 141762306a36Sopenharmony_ci pn = of_parse_phandle(np, "phy-handle", 0); 141862306a36Sopenharmony_ci if (!pn) { 141962306a36Sopenharmony_ci /* In the case of a fixed PHY, the DT node associated 142062306a36Sopenharmony_ci * to the PHY is the Ethernet MAC DT node. 142162306a36Sopenharmony_ci */ 142262306a36Sopenharmony_ci if (of_phy_is_fixed_link(np)) { 142362306a36Sopenharmony_ci err = of_phy_register_fixed_link(np); 142462306a36Sopenharmony_ci if (err) 142562306a36Sopenharmony_ci return err; 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci pn = of_node_get(np); 142862306a36Sopenharmony_ci } 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci iface = priv->rgmii_override ? PHY_INTERFACE_MODE_RGMII 143162306a36Sopenharmony_ci : priv->phy_interface; 143262306a36Sopenharmony_ci phydev = of_phy_connect(ndev, pn, ravb_adjust_link, 0, iface); 143362306a36Sopenharmony_ci of_node_put(pn); 143462306a36Sopenharmony_ci if (!phydev) { 143562306a36Sopenharmony_ci netdev_err(ndev, "failed to connect PHY\n"); 143662306a36Sopenharmony_ci err = -ENOENT; 143762306a36Sopenharmony_ci goto err_deregister_fixed_link; 143862306a36Sopenharmony_ci } 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci if (!info->half_duplex) { 144162306a36Sopenharmony_ci /* 10BASE, Pause and Asym Pause is not supported */ 144262306a36Sopenharmony_ci phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); 144362306a36Sopenharmony_ci phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT); 144462306a36Sopenharmony_ci phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT); 144562306a36Sopenharmony_ci phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT); 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci /* Half Duplex is not supported */ 144862306a36Sopenharmony_ci phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); 144962306a36Sopenharmony_ci phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); 145062306a36Sopenharmony_ci } 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci phy_attached_info(phydev); 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci return 0; 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_cierr_deregister_fixed_link: 145762306a36Sopenharmony_ci if (of_phy_is_fixed_link(np)) 145862306a36Sopenharmony_ci of_phy_deregister_fixed_link(np); 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci return err; 146162306a36Sopenharmony_ci} 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci/* PHY control start function */ 146462306a36Sopenharmony_cistatic int ravb_phy_start(struct net_device *ndev) 146562306a36Sopenharmony_ci{ 146662306a36Sopenharmony_ci int error; 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci error = ravb_phy_init(ndev); 146962306a36Sopenharmony_ci if (error) 147062306a36Sopenharmony_ci return error; 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci phy_start(ndev->phydev); 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci return 0; 147562306a36Sopenharmony_ci} 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_cistatic u32 ravb_get_msglevel(struct net_device *ndev) 147862306a36Sopenharmony_ci{ 147962306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci return priv->msg_enable; 148262306a36Sopenharmony_ci} 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_cistatic void ravb_set_msglevel(struct net_device *ndev, u32 value) 148562306a36Sopenharmony_ci{ 148662306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci priv->msg_enable = value; 148962306a36Sopenharmony_ci} 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_cistatic const char ravb_gstrings_stats_gbeth[][ETH_GSTRING_LEN] = { 149262306a36Sopenharmony_ci "rx_queue_0_current", 149362306a36Sopenharmony_ci "tx_queue_0_current", 149462306a36Sopenharmony_ci "rx_queue_0_dirty", 149562306a36Sopenharmony_ci "tx_queue_0_dirty", 149662306a36Sopenharmony_ci "rx_queue_0_packets", 149762306a36Sopenharmony_ci "tx_queue_0_packets", 149862306a36Sopenharmony_ci "rx_queue_0_bytes", 149962306a36Sopenharmony_ci "tx_queue_0_bytes", 150062306a36Sopenharmony_ci "rx_queue_0_mcast_packets", 150162306a36Sopenharmony_ci "rx_queue_0_errors", 150262306a36Sopenharmony_ci "rx_queue_0_crc_errors", 150362306a36Sopenharmony_ci "rx_queue_0_frame_errors", 150462306a36Sopenharmony_ci "rx_queue_0_length_errors", 150562306a36Sopenharmony_ci "rx_queue_0_csum_offload_errors", 150662306a36Sopenharmony_ci "rx_queue_0_over_errors", 150762306a36Sopenharmony_ci}; 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_cistatic const char ravb_gstrings_stats[][ETH_GSTRING_LEN] = { 151062306a36Sopenharmony_ci "rx_queue_0_current", 151162306a36Sopenharmony_ci "tx_queue_0_current", 151262306a36Sopenharmony_ci "rx_queue_0_dirty", 151362306a36Sopenharmony_ci "tx_queue_0_dirty", 151462306a36Sopenharmony_ci "rx_queue_0_packets", 151562306a36Sopenharmony_ci "tx_queue_0_packets", 151662306a36Sopenharmony_ci "rx_queue_0_bytes", 151762306a36Sopenharmony_ci "tx_queue_0_bytes", 151862306a36Sopenharmony_ci "rx_queue_0_mcast_packets", 151962306a36Sopenharmony_ci "rx_queue_0_errors", 152062306a36Sopenharmony_ci "rx_queue_0_crc_errors", 152162306a36Sopenharmony_ci "rx_queue_0_frame_errors", 152262306a36Sopenharmony_ci "rx_queue_0_length_errors", 152362306a36Sopenharmony_ci "rx_queue_0_missed_errors", 152462306a36Sopenharmony_ci "rx_queue_0_over_errors", 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci "rx_queue_1_current", 152762306a36Sopenharmony_ci "tx_queue_1_current", 152862306a36Sopenharmony_ci "rx_queue_1_dirty", 152962306a36Sopenharmony_ci "tx_queue_1_dirty", 153062306a36Sopenharmony_ci "rx_queue_1_packets", 153162306a36Sopenharmony_ci "tx_queue_1_packets", 153262306a36Sopenharmony_ci "rx_queue_1_bytes", 153362306a36Sopenharmony_ci "tx_queue_1_bytes", 153462306a36Sopenharmony_ci "rx_queue_1_mcast_packets", 153562306a36Sopenharmony_ci "rx_queue_1_errors", 153662306a36Sopenharmony_ci "rx_queue_1_crc_errors", 153762306a36Sopenharmony_ci "rx_queue_1_frame_errors", 153862306a36Sopenharmony_ci "rx_queue_1_length_errors", 153962306a36Sopenharmony_ci "rx_queue_1_missed_errors", 154062306a36Sopenharmony_ci "rx_queue_1_over_errors", 154162306a36Sopenharmony_ci}; 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_cistatic int ravb_get_sset_count(struct net_device *netdev, int sset) 154462306a36Sopenharmony_ci{ 154562306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(netdev); 154662306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci switch (sset) { 154962306a36Sopenharmony_ci case ETH_SS_STATS: 155062306a36Sopenharmony_ci return info->stats_len; 155162306a36Sopenharmony_ci default: 155262306a36Sopenharmony_ci return -EOPNOTSUPP; 155362306a36Sopenharmony_ci } 155462306a36Sopenharmony_ci} 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_cistatic void ravb_get_ethtool_stats(struct net_device *ndev, 155762306a36Sopenharmony_ci struct ethtool_stats *estats, u64 *data) 155862306a36Sopenharmony_ci{ 155962306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 156062306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 156162306a36Sopenharmony_ci int num_rx_q; 156262306a36Sopenharmony_ci int i = 0; 156362306a36Sopenharmony_ci int q; 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci num_rx_q = info->nc_queues ? NUM_RX_QUEUE : 1; 156662306a36Sopenharmony_ci /* Device-specific stats */ 156762306a36Sopenharmony_ci for (q = RAVB_BE; q < num_rx_q; q++) { 156862306a36Sopenharmony_ci struct net_device_stats *stats = &priv->stats[q]; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci data[i++] = priv->cur_rx[q]; 157162306a36Sopenharmony_ci data[i++] = priv->cur_tx[q]; 157262306a36Sopenharmony_ci data[i++] = priv->dirty_rx[q]; 157362306a36Sopenharmony_ci data[i++] = priv->dirty_tx[q]; 157462306a36Sopenharmony_ci data[i++] = stats->rx_packets; 157562306a36Sopenharmony_ci data[i++] = stats->tx_packets; 157662306a36Sopenharmony_ci data[i++] = stats->rx_bytes; 157762306a36Sopenharmony_ci data[i++] = stats->tx_bytes; 157862306a36Sopenharmony_ci data[i++] = stats->multicast; 157962306a36Sopenharmony_ci data[i++] = stats->rx_errors; 158062306a36Sopenharmony_ci data[i++] = stats->rx_crc_errors; 158162306a36Sopenharmony_ci data[i++] = stats->rx_frame_errors; 158262306a36Sopenharmony_ci data[i++] = stats->rx_length_errors; 158362306a36Sopenharmony_ci data[i++] = stats->rx_missed_errors; 158462306a36Sopenharmony_ci data[i++] = stats->rx_over_errors; 158562306a36Sopenharmony_ci } 158662306a36Sopenharmony_ci} 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_cistatic void ravb_get_strings(struct net_device *ndev, u32 stringset, u8 *data) 158962306a36Sopenharmony_ci{ 159062306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 159162306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci switch (stringset) { 159462306a36Sopenharmony_ci case ETH_SS_STATS: 159562306a36Sopenharmony_ci memcpy(data, info->gstrings_stats, info->gstrings_size); 159662306a36Sopenharmony_ci break; 159762306a36Sopenharmony_ci } 159862306a36Sopenharmony_ci} 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_cistatic void ravb_get_ringparam(struct net_device *ndev, 160162306a36Sopenharmony_ci struct ethtool_ringparam *ring, 160262306a36Sopenharmony_ci struct kernel_ethtool_ringparam *kernel_ring, 160362306a36Sopenharmony_ci struct netlink_ext_ack *extack) 160462306a36Sopenharmony_ci{ 160562306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_ci ring->rx_max_pending = BE_RX_RING_MAX; 160862306a36Sopenharmony_ci ring->tx_max_pending = BE_TX_RING_MAX; 160962306a36Sopenharmony_ci ring->rx_pending = priv->num_rx_ring[RAVB_BE]; 161062306a36Sopenharmony_ci ring->tx_pending = priv->num_tx_ring[RAVB_BE]; 161162306a36Sopenharmony_ci} 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_cistatic int ravb_set_ringparam(struct net_device *ndev, 161462306a36Sopenharmony_ci struct ethtool_ringparam *ring, 161562306a36Sopenharmony_ci struct kernel_ethtool_ringparam *kernel_ring, 161662306a36Sopenharmony_ci struct netlink_ext_ack *extack) 161762306a36Sopenharmony_ci{ 161862306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 161962306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 162062306a36Sopenharmony_ci int error; 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci if (ring->tx_pending > BE_TX_RING_MAX || 162362306a36Sopenharmony_ci ring->rx_pending > BE_RX_RING_MAX || 162462306a36Sopenharmony_ci ring->tx_pending < BE_TX_RING_MIN || 162562306a36Sopenharmony_ci ring->rx_pending < BE_RX_RING_MIN) 162662306a36Sopenharmony_ci return -EINVAL; 162762306a36Sopenharmony_ci if (ring->rx_mini_pending || ring->rx_jumbo_pending) 162862306a36Sopenharmony_ci return -EINVAL; 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci if (netif_running(ndev)) { 163162306a36Sopenharmony_ci netif_device_detach(ndev); 163262306a36Sopenharmony_ci /* Stop PTP Clock driver */ 163362306a36Sopenharmony_ci if (info->gptp) 163462306a36Sopenharmony_ci ravb_ptp_stop(ndev); 163562306a36Sopenharmony_ci /* Wait for DMA stopping */ 163662306a36Sopenharmony_ci error = ravb_stop_dma(ndev); 163762306a36Sopenharmony_ci if (error) { 163862306a36Sopenharmony_ci netdev_err(ndev, 163962306a36Sopenharmony_ci "cannot set ringparam! Any AVB processes are still running?\n"); 164062306a36Sopenharmony_ci return error; 164162306a36Sopenharmony_ci } 164262306a36Sopenharmony_ci synchronize_irq(ndev->irq); 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci /* Free all the skb's in the RX queue and the DMA buffers. */ 164562306a36Sopenharmony_ci ravb_ring_free(ndev, RAVB_BE); 164662306a36Sopenharmony_ci if (info->nc_queues) 164762306a36Sopenharmony_ci ravb_ring_free(ndev, RAVB_NC); 164862306a36Sopenharmony_ci } 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci /* Set new parameters */ 165162306a36Sopenharmony_ci priv->num_rx_ring[RAVB_BE] = ring->rx_pending; 165262306a36Sopenharmony_ci priv->num_tx_ring[RAVB_BE] = ring->tx_pending; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci if (netif_running(ndev)) { 165562306a36Sopenharmony_ci error = ravb_dmac_init(ndev); 165662306a36Sopenharmony_ci if (error) { 165762306a36Sopenharmony_ci netdev_err(ndev, 165862306a36Sopenharmony_ci "%s: ravb_dmac_init() failed, error %d\n", 165962306a36Sopenharmony_ci __func__, error); 166062306a36Sopenharmony_ci return error; 166162306a36Sopenharmony_ci } 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci ravb_emac_init(ndev); 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_ci /* Initialise PTP Clock driver */ 166662306a36Sopenharmony_ci if (info->gptp) 166762306a36Sopenharmony_ci ravb_ptp_init(ndev, priv->pdev); 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci netif_device_attach(ndev); 167062306a36Sopenharmony_ci } 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci return 0; 167362306a36Sopenharmony_ci} 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_cistatic int ravb_get_ts_info(struct net_device *ndev, 167662306a36Sopenharmony_ci struct ethtool_ts_info *info) 167762306a36Sopenharmony_ci{ 167862306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 167962306a36Sopenharmony_ci const struct ravb_hw_info *hw_info = priv->info; 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci info->so_timestamping = 168262306a36Sopenharmony_ci SOF_TIMESTAMPING_TX_SOFTWARE | 168362306a36Sopenharmony_ci SOF_TIMESTAMPING_RX_SOFTWARE | 168462306a36Sopenharmony_ci SOF_TIMESTAMPING_SOFTWARE | 168562306a36Sopenharmony_ci SOF_TIMESTAMPING_TX_HARDWARE | 168662306a36Sopenharmony_ci SOF_TIMESTAMPING_RX_HARDWARE | 168762306a36Sopenharmony_ci SOF_TIMESTAMPING_RAW_HARDWARE; 168862306a36Sopenharmony_ci info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); 168962306a36Sopenharmony_ci info->rx_filters = 169062306a36Sopenharmony_ci (1 << HWTSTAMP_FILTER_NONE) | 169162306a36Sopenharmony_ci (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) | 169262306a36Sopenharmony_ci (1 << HWTSTAMP_FILTER_ALL); 169362306a36Sopenharmony_ci if (hw_info->gptp || hw_info->ccc_gac) 169462306a36Sopenharmony_ci info->phc_index = ptp_clock_index(priv->ptp.clock); 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci return 0; 169762306a36Sopenharmony_ci} 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_cistatic void ravb_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 170062306a36Sopenharmony_ci{ 170162306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci wol->supported = WAKE_MAGIC; 170462306a36Sopenharmony_ci wol->wolopts = priv->wol_enabled ? WAKE_MAGIC : 0; 170562306a36Sopenharmony_ci} 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_cistatic int ravb_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) 170862306a36Sopenharmony_ci{ 170962306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 171062306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci if (!info->magic_pkt || (wol->wolopts & ~WAKE_MAGIC)) 171362306a36Sopenharmony_ci return -EOPNOTSUPP; 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci priv->wol_enabled = !!(wol->wolopts & WAKE_MAGIC); 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci device_set_wakeup_enable(&priv->pdev->dev, priv->wol_enabled); 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci return 0; 172062306a36Sopenharmony_ci} 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_cistatic const struct ethtool_ops ravb_ethtool_ops = { 172362306a36Sopenharmony_ci .nway_reset = phy_ethtool_nway_reset, 172462306a36Sopenharmony_ci .get_msglevel = ravb_get_msglevel, 172562306a36Sopenharmony_ci .set_msglevel = ravb_set_msglevel, 172662306a36Sopenharmony_ci .get_link = ethtool_op_get_link, 172762306a36Sopenharmony_ci .get_strings = ravb_get_strings, 172862306a36Sopenharmony_ci .get_ethtool_stats = ravb_get_ethtool_stats, 172962306a36Sopenharmony_ci .get_sset_count = ravb_get_sset_count, 173062306a36Sopenharmony_ci .get_ringparam = ravb_get_ringparam, 173162306a36Sopenharmony_ci .set_ringparam = ravb_set_ringparam, 173262306a36Sopenharmony_ci .get_ts_info = ravb_get_ts_info, 173362306a36Sopenharmony_ci .get_link_ksettings = phy_ethtool_get_link_ksettings, 173462306a36Sopenharmony_ci .set_link_ksettings = phy_ethtool_set_link_ksettings, 173562306a36Sopenharmony_ci .get_wol = ravb_get_wol, 173662306a36Sopenharmony_ci .set_wol = ravb_set_wol, 173762306a36Sopenharmony_ci}; 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_cistatic inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler, 174062306a36Sopenharmony_ci struct net_device *ndev, struct device *dev, 174162306a36Sopenharmony_ci const char *ch) 174262306a36Sopenharmony_ci{ 174362306a36Sopenharmony_ci char *name; 174462306a36Sopenharmony_ci int error; 174562306a36Sopenharmony_ci 174662306a36Sopenharmony_ci name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch); 174762306a36Sopenharmony_ci if (!name) 174862306a36Sopenharmony_ci return -ENOMEM; 174962306a36Sopenharmony_ci error = request_irq(irq, handler, 0, name, ndev); 175062306a36Sopenharmony_ci if (error) 175162306a36Sopenharmony_ci netdev_err(ndev, "cannot request IRQ %s\n", name); 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci return error; 175462306a36Sopenharmony_ci} 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci/* Network device open function for Ethernet AVB */ 175762306a36Sopenharmony_cistatic int ravb_open(struct net_device *ndev) 175862306a36Sopenharmony_ci{ 175962306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 176062306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 176162306a36Sopenharmony_ci struct platform_device *pdev = priv->pdev; 176262306a36Sopenharmony_ci struct device *dev = &pdev->dev; 176362306a36Sopenharmony_ci int error; 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci napi_enable(&priv->napi[RAVB_BE]); 176662306a36Sopenharmony_ci if (info->nc_queues) 176762306a36Sopenharmony_ci napi_enable(&priv->napi[RAVB_NC]); 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci if (!info->multi_irqs) { 177062306a36Sopenharmony_ci error = request_irq(ndev->irq, ravb_interrupt, IRQF_SHARED, 177162306a36Sopenharmony_ci ndev->name, ndev); 177262306a36Sopenharmony_ci if (error) { 177362306a36Sopenharmony_ci netdev_err(ndev, "cannot request IRQ\n"); 177462306a36Sopenharmony_ci goto out_napi_off; 177562306a36Sopenharmony_ci } 177662306a36Sopenharmony_ci } else { 177762306a36Sopenharmony_ci error = ravb_hook_irq(ndev->irq, ravb_multi_interrupt, ndev, 177862306a36Sopenharmony_ci dev, "ch22:multi"); 177962306a36Sopenharmony_ci if (error) 178062306a36Sopenharmony_ci goto out_napi_off; 178162306a36Sopenharmony_ci error = ravb_hook_irq(priv->emac_irq, ravb_emac_interrupt, ndev, 178262306a36Sopenharmony_ci dev, "ch24:emac"); 178362306a36Sopenharmony_ci if (error) 178462306a36Sopenharmony_ci goto out_free_irq; 178562306a36Sopenharmony_ci error = ravb_hook_irq(priv->rx_irqs[RAVB_BE], ravb_be_interrupt, 178662306a36Sopenharmony_ci ndev, dev, "ch0:rx_be"); 178762306a36Sopenharmony_ci if (error) 178862306a36Sopenharmony_ci goto out_free_irq_emac; 178962306a36Sopenharmony_ci error = ravb_hook_irq(priv->tx_irqs[RAVB_BE], ravb_be_interrupt, 179062306a36Sopenharmony_ci ndev, dev, "ch18:tx_be"); 179162306a36Sopenharmony_ci if (error) 179262306a36Sopenharmony_ci goto out_free_irq_be_rx; 179362306a36Sopenharmony_ci error = ravb_hook_irq(priv->rx_irqs[RAVB_NC], ravb_nc_interrupt, 179462306a36Sopenharmony_ci ndev, dev, "ch1:rx_nc"); 179562306a36Sopenharmony_ci if (error) 179662306a36Sopenharmony_ci goto out_free_irq_be_tx; 179762306a36Sopenharmony_ci error = ravb_hook_irq(priv->tx_irqs[RAVB_NC], ravb_nc_interrupt, 179862306a36Sopenharmony_ci ndev, dev, "ch19:tx_nc"); 179962306a36Sopenharmony_ci if (error) 180062306a36Sopenharmony_ci goto out_free_irq_nc_rx; 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci if (info->err_mgmt_irqs) { 180362306a36Sopenharmony_ci error = ravb_hook_irq(priv->erra_irq, ravb_multi_interrupt, 180462306a36Sopenharmony_ci ndev, dev, "err_a"); 180562306a36Sopenharmony_ci if (error) 180662306a36Sopenharmony_ci goto out_free_irq_nc_tx; 180762306a36Sopenharmony_ci error = ravb_hook_irq(priv->mgmta_irq, ravb_multi_interrupt, 180862306a36Sopenharmony_ci ndev, dev, "mgmt_a"); 180962306a36Sopenharmony_ci if (error) 181062306a36Sopenharmony_ci goto out_free_irq_erra; 181162306a36Sopenharmony_ci } 181262306a36Sopenharmony_ci } 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci /* Device init */ 181562306a36Sopenharmony_ci error = ravb_dmac_init(ndev); 181662306a36Sopenharmony_ci if (error) 181762306a36Sopenharmony_ci goto out_free_irq_mgmta; 181862306a36Sopenharmony_ci ravb_emac_init(ndev); 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci /* Initialise PTP Clock driver */ 182162306a36Sopenharmony_ci if (info->gptp) 182262306a36Sopenharmony_ci ravb_ptp_init(ndev, priv->pdev); 182362306a36Sopenharmony_ci 182462306a36Sopenharmony_ci /* PHY control start */ 182562306a36Sopenharmony_ci error = ravb_phy_start(ndev); 182662306a36Sopenharmony_ci if (error) 182762306a36Sopenharmony_ci goto out_ptp_stop; 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci netif_tx_start_all_queues(ndev); 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci return 0; 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ciout_ptp_stop: 183462306a36Sopenharmony_ci /* Stop PTP Clock driver */ 183562306a36Sopenharmony_ci if (info->gptp) 183662306a36Sopenharmony_ci ravb_ptp_stop(ndev); 183762306a36Sopenharmony_ci ravb_stop_dma(ndev); 183862306a36Sopenharmony_ciout_free_irq_mgmta: 183962306a36Sopenharmony_ci if (!info->multi_irqs) 184062306a36Sopenharmony_ci goto out_free_irq; 184162306a36Sopenharmony_ci if (info->err_mgmt_irqs) 184262306a36Sopenharmony_ci free_irq(priv->mgmta_irq, ndev); 184362306a36Sopenharmony_ciout_free_irq_erra: 184462306a36Sopenharmony_ci if (info->err_mgmt_irqs) 184562306a36Sopenharmony_ci free_irq(priv->erra_irq, ndev); 184662306a36Sopenharmony_ciout_free_irq_nc_tx: 184762306a36Sopenharmony_ci free_irq(priv->tx_irqs[RAVB_NC], ndev); 184862306a36Sopenharmony_ciout_free_irq_nc_rx: 184962306a36Sopenharmony_ci free_irq(priv->rx_irqs[RAVB_NC], ndev); 185062306a36Sopenharmony_ciout_free_irq_be_tx: 185162306a36Sopenharmony_ci free_irq(priv->tx_irqs[RAVB_BE], ndev); 185262306a36Sopenharmony_ciout_free_irq_be_rx: 185362306a36Sopenharmony_ci free_irq(priv->rx_irqs[RAVB_BE], ndev); 185462306a36Sopenharmony_ciout_free_irq_emac: 185562306a36Sopenharmony_ci free_irq(priv->emac_irq, ndev); 185662306a36Sopenharmony_ciout_free_irq: 185762306a36Sopenharmony_ci free_irq(ndev->irq, ndev); 185862306a36Sopenharmony_ciout_napi_off: 185962306a36Sopenharmony_ci if (info->nc_queues) 186062306a36Sopenharmony_ci napi_disable(&priv->napi[RAVB_NC]); 186162306a36Sopenharmony_ci napi_disable(&priv->napi[RAVB_BE]); 186262306a36Sopenharmony_ci return error; 186362306a36Sopenharmony_ci} 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci/* Timeout function for Ethernet AVB */ 186662306a36Sopenharmony_cistatic void ravb_tx_timeout(struct net_device *ndev, unsigned int txqueue) 186762306a36Sopenharmony_ci{ 186862306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_ci netif_err(priv, tx_err, ndev, 187162306a36Sopenharmony_ci "transmit timed out, status %08x, resetting...\n", 187262306a36Sopenharmony_ci ravb_read(ndev, ISS)); 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci /* tx_errors count up */ 187562306a36Sopenharmony_ci ndev->stats.tx_errors++; 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_ci schedule_work(&priv->work); 187862306a36Sopenharmony_ci} 187962306a36Sopenharmony_ci 188062306a36Sopenharmony_cistatic void ravb_tx_timeout_work(struct work_struct *work) 188162306a36Sopenharmony_ci{ 188262306a36Sopenharmony_ci struct ravb_private *priv = container_of(work, struct ravb_private, 188362306a36Sopenharmony_ci work); 188462306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 188562306a36Sopenharmony_ci struct net_device *ndev = priv->ndev; 188662306a36Sopenharmony_ci int error; 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci if (!rtnl_trylock()) { 188962306a36Sopenharmony_ci usleep_range(1000, 2000); 189062306a36Sopenharmony_ci schedule_work(&priv->work); 189162306a36Sopenharmony_ci return; 189262306a36Sopenharmony_ci } 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci netif_tx_stop_all_queues(ndev); 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci /* Stop PTP Clock driver */ 189762306a36Sopenharmony_ci if (info->gptp) 189862306a36Sopenharmony_ci ravb_ptp_stop(ndev); 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci /* Wait for DMA stopping */ 190162306a36Sopenharmony_ci if (ravb_stop_dma(ndev)) { 190262306a36Sopenharmony_ci /* If ravb_stop_dma() fails, the hardware is still operating 190362306a36Sopenharmony_ci * for TX and/or RX. So, this should not call the following 190462306a36Sopenharmony_ci * functions because ravb_dmac_init() is possible to fail too. 190562306a36Sopenharmony_ci * Also, this should not retry ravb_stop_dma() again and again 190662306a36Sopenharmony_ci * here because it's possible to wait forever. So, this just 190762306a36Sopenharmony_ci * re-enables the TX and RX and skip the following 190862306a36Sopenharmony_ci * re-initialization procedure. 190962306a36Sopenharmony_ci */ 191062306a36Sopenharmony_ci ravb_rcv_snd_enable(ndev); 191162306a36Sopenharmony_ci goto out; 191262306a36Sopenharmony_ci } 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci ravb_ring_free(ndev, RAVB_BE); 191562306a36Sopenharmony_ci if (info->nc_queues) 191662306a36Sopenharmony_ci ravb_ring_free(ndev, RAVB_NC); 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_ci /* Device init */ 191962306a36Sopenharmony_ci error = ravb_dmac_init(ndev); 192062306a36Sopenharmony_ci if (error) { 192162306a36Sopenharmony_ci /* If ravb_dmac_init() fails, descriptors are freed. So, this 192262306a36Sopenharmony_ci * should return here to avoid re-enabling the TX and RX in 192362306a36Sopenharmony_ci * ravb_emac_init(). 192462306a36Sopenharmony_ci */ 192562306a36Sopenharmony_ci netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n", 192662306a36Sopenharmony_ci __func__, error); 192762306a36Sopenharmony_ci goto out_unlock; 192862306a36Sopenharmony_ci } 192962306a36Sopenharmony_ci ravb_emac_init(ndev); 193062306a36Sopenharmony_ci 193162306a36Sopenharmony_ciout: 193262306a36Sopenharmony_ci /* Initialise PTP Clock driver */ 193362306a36Sopenharmony_ci if (info->gptp) 193462306a36Sopenharmony_ci ravb_ptp_init(ndev, priv->pdev); 193562306a36Sopenharmony_ci 193662306a36Sopenharmony_ci netif_tx_start_all_queues(ndev); 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ciout_unlock: 193962306a36Sopenharmony_ci rtnl_unlock(); 194062306a36Sopenharmony_ci} 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci/* Packet transmit function for Ethernet AVB */ 194362306a36Sopenharmony_cistatic netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) 194462306a36Sopenharmony_ci{ 194562306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 194662306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 194762306a36Sopenharmony_ci unsigned int num_tx_desc = priv->num_tx_desc; 194862306a36Sopenharmony_ci u16 q = skb_get_queue_mapping(skb); 194962306a36Sopenharmony_ci struct ravb_tstamp_skb *ts_skb; 195062306a36Sopenharmony_ci struct ravb_tx_desc *desc; 195162306a36Sopenharmony_ci unsigned long flags; 195262306a36Sopenharmony_ci dma_addr_t dma_addr; 195362306a36Sopenharmony_ci void *buffer; 195462306a36Sopenharmony_ci u32 entry; 195562306a36Sopenharmony_ci u32 len; 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 195862306a36Sopenharmony_ci if (priv->cur_tx[q] - priv->dirty_tx[q] > (priv->num_tx_ring[q] - 1) * 195962306a36Sopenharmony_ci num_tx_desc) { 196062306a36Sopenharmony_ci netif_err(priv, tx_queued, ndev, 196162306a36Sopenharmony_ci "still transmitting with the full ring!\n"); 196262306a36Sopenharmony_ci netif_stop_subqueue(ndev, q); 196362306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 196462306a36Sopenharmony_ci return NETDEV_TX_BUSY; 196562306a36Sopenharmony_ci } 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci if (skb_put_padto(skb, ETH_ZLEN)) 196862306a36Sopenharmony_ci goto exit; 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci entry = priv->cur_tx[q] % (priv->num_tx_ring[q] * num_tx_desc); 197162306a36Sopenharmony_ci priv->tx_skb[q][entry / num_tx_desc] = skb; 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ci if (num_tx_desc > 1) { 197462306a36Sopenharmony_ci buffer = PTR_ALIGN(priv->tx_align[q], DPTR_ALIGN) + 197562306a36Sopenharmony_ci entry / num_tx_desc * DPTR_ALIGN; 197662306a36Sopenharmony_ci len = PTR_ALIGN(skb->data, DPTR_ALIGN) - skb->data; 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci /* Zero length DMA descriptors are problematic as they seem 197962306a36Sopenharmony_ci * to terminate DMA transfers. Avoid them by simply using a 198062306a36Sopenharmony_ci * length of DPTR_ALIGN (4) when skb data is aligned to 198162306a36Sopenharmony_ci * DPTR_ALIGN. 198262306a36Sopenharmony_ci * 198362306a36Sopenharmony_ci * As skb is guaranteed to have at least ETH_ZLEN (60) 198462306a36Sopenharmony_ci * bytes of data by the call to skb_put_padto() above this 198562306a36Sopenharmony_ci * is safe with respect to both the length of the first DMA 198662306a36Sopenharmony_ci * descriptor (len) overflowing the available data and the 198762306a36Sopenharmony_ci * length of the second DMA descriptor (skb->len - len) 198862306a36Sopenharmony_ci * being negative. 198962306a36Sopenharmony_ci */ 199062306a36Sopenharmony_ci if (len == 0) 199162306a36Sopenharmony_ci len = DPTR_ALIGN; 199262306a36Sopenharmony_ci 199362306a36Sopenharmony_ci memcpy(buffer, skb->data, len); 199462306a36Sopenharmony_ci dma_addr = dma_map_single(ndev->dev.parent, buffer, len, 199562306a36Sopenharmony_ci DMA_TO_DEVICE); 199662306a36Sopenharmony_ci if (dma_mapping_error(ndev->dev.parent, dma_addr)) 199762306a36Sopenharmony_ci goto drop; 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci desc = &priv->tx_ring[q][entry]; 200062306a36Sopenharmony_ci desc->ds_tagl = cpu_to_le16(len); 200162306a36Sopenharmony_ci desc->dptr = cpu_to_le32(dma_addr); 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci buffer = skb->data + len; 200462306a36Sopenharmony_ci len = skb->len - len; 200562306a36Sopenharmony_ci dma_addr = dma_map_single(ndev->dev.parent, buffer, len, 200662306a36Sopenharmony_ci DMA_TO_DEVICE); 200762306a36Sopenharmony_ci if (dma_mapping_error(ndev->dev.parent, dma_addr)) 200862306a36Sopenharmony_ci goto unmap; 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci desc++; 201162306a36Sopenharmony_ci } else { 201262306a36Sopenharmony_ci desc = &priv->tx_ring[q][entry]; 201362306a36Sopenharmony_ci len = skb->len; 201462306a36Sopenharmony_ci dma_addr = dma_map_single(ndev->dev.parent, skb->data, skb->len, 201562306a36Sopenharmony_ci DMA_TO_DEVICE); 201662306a36Sopenharmony_ci if (dma_mapping_error(ndev->dev.parent, dma_addr)) 201762306a36Sopenharmony_ci goto drop; 201862306a36Sopenharmony_ci } 201962306a36Sopenharmony_ci desc->ds_tagl = cpu_to_le16(len); 202062306a36Sopenharmony_ci desc->dptr = cpu_to_le32(dma_addr); 202162306a36Sopenharmony_ci 202262306a36Sopenharmony_ci /* TX timestamp required */ 202362306a36Sopenharmony_ci if (info->gptp || info->ccc_gac) { 202462306a36Sopenharmony_ci if (q == RAVB_NC) { 202562306a36Sopenharmony_ci ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC); 202662306a36Sopenharmony_ci if (!ts_skb) { 202762306a36Sopenharmony_ci if (num_tx_desc > 1) { 202862306a36Sopenharmony_ci desc--; 202962306a36Sopenharmony_ci dma_unmap_single(ndev->dev.parent, dma_addr, 203062306a36Sopenharmony_ci len, DMA_TO_DEVICE); 203162306a36Sopenharmony_ci } 203262306a36Sopenharmony_ci goto unmap; 203362306a36Sopenharmony_ci } 203462306a36Sopenharmony_ci ts_skb->skb = skb_get(skb); 203562306a36Sopenharmony_ci ts_skb->tag = priv->ts_skb_tag++; 203662306a36Sopenharmony_ci priv->ts_skb_tag &= 0x3ff; 203762306a36Sopenharmony_ci list_add_tail(&ts_skb->list, &priv->ts_skb_list); 203862306a36Sopenharmony_ci 203962306a36Sopenharmony_ci /* TAG and timestamp required flag */ 204062306a36Sopenharmony_ci skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 204162306a36Sopenharmony_ci desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR; 204262306a36Sopenharmony_ci desc->ds_tagl |= cpu_to_le16(ts_skb->tag << 12); 204362306a36Sopenharmony_ci } 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci skb_tx_timestamp(skb); 204662306a36Sopenharmony_ci } 204762306a36Sopenharmony_ci /* Descriptor type must be set after all the above writes */ 204862306a36Sopenharmony_ci dma_wmb(); 204962306a36Sopenharmony_ci if (num_tx_desc > 1) { 205062306a36Sopenharmony_ci desc->die_dt = DT_FEND; 205162306a36Sopenharmony_ci desc--; 205262306a36Sopenharmony_ci desc->die_dt = DT_FSTART; 205362306a36Sopenharmony_ci } else { 205462306a36Sopenharmony_ci desc->die_dt = DT_FSINGLE; 205562306a36Sopenharmony_ci } 205662306a36Sopenharmony_ci ravb_modify(ndev, TCCR, TCCR_TSRQ0 << q, TCCR_TSRQ0 << q); 205762306a36Sopenharmony_ci 205862306a36Sopenharmony_ci priv->cur_tx[q] += num_tx_desc; 205962306a36Sopenharmony_ci if (priv->cur_tx[q] - priv->dirty_tx[q] > 206062306a36Sopenharmony_ci (priv->num_tx_ring[q] - 1) * num_tx_desc && 206162306a36Sopenharmony_ci !ravb_tx_free(ndev, q, true)) 206262306a36Sopenharmony_ci netif_stop_subqueue(ndev, q); 206362306a36Sopenharmony_ci 206462306a36Sopenharmony_ciexit: 206562306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 206662306a36Sopenharmony_ci return NETDEV_TX_OK; 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ciunmap: 206962306a36Sopenharmony_ci dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr), 207062306a36Sopenharmony_ci le16_to_cpu(desc->ds_tagl), DMA_TO_DEVICE); 207162306a36Sopenharmony_cidrop: 207262306a36Sopenharmony_ci dev_kfree_skb_any(skb); 207362306a36Sopenharmony_ci priv->tx_skb[q][entry / num_tx_desc] = NULL; 207462306a36Sopenharmony_ci goto exit; 207562306a36Sopenharmony_ci} 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_cistatic u16 ravb_select_queue(struct net_device *ndev, struct sk_buff *skb, 207862306a36Sopenharmony_ci struct net_device *sb_dev) 207962306a36Sopenharmony_ci{ 208062306a36Sopenharmony_ci /* If skb needs TX timestamp, it is handled in network control queue */ 208162306a36Sopenharmony_ci return (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ? RAVB_NC : 208262306a36Sopenharmony_ci RAVB_BE; 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci} 208562306a36Sopenharmony_ci 208662306a36Sopenharmony_cistatic struct net_device_stats *ravb_get_stats(struct net_device *ndev) 208762306a36Sopenharmony_ci{ 208862306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 208962306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 209062306a36Sopenharmony_ci struct net_device_stats *nstats, *stats0, *stats1; 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci nstats = &ndev->stats; 209362306a36Sopenharmony_ci stats0 = &priv->stats[RAVB_BE]; 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci if (info->tx_counters) { 209662306a36Sopenharmony_ci nstats->tx_dropped += ravb_read(ndev, TROCR); 209762306a36Sopenharmony_ci ravb_write(ndev, 0, TROCR); /* (write clear) */ 209862306a36Sopenharmony_ci } 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci if (info->carrier_counters) { 210162306a36Sopenharmony_ci nstats->collisions += ravb_read(ndev, CXR41); 210262306a36Sopenharmony_ci ravb_write(ndev, 0, CXR41); /* (write clear) */ 210362306a36Sopenharmony_ci nstats->tx_carrier_errors += ravb_read(ndev, CXR42); 210462306a36Sopenharmony_ci ravb_write(ndev, 0, CXR42); /* (write clear) */ 210562306a36Sopenharmony_ci } 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_ci nstats->rx_packets = stats0->rx_packets; 210862306a36Sopenharmony_ci nstats->tx_packets = stats0->tx_packets; 210962306a36Sopenharmony_ci nstats->rx_bytes = stats0->rx_bytes; 211062306a36Sopenharmony_ci nstats->tx_bytes = stats0->tx_bytes; 211162306a36Sopenharmony_ci nstats->multicast = stats0->multicast; 211262306a36Sopenharmony_ci nstats->rx_errors = stats0->rx_errors; 211362306a36Sopenharmony_ci nstats->rx_crc_errors = stats0->rx_crc_errors; 211462306a36Sopenharmony_ci nstats->rx_frame_errors = stats0->rx_frame_errors; 211562306a36Sopenharmony_ci nstats->rx_length_errors = stats0->rx_length_errors; 211662306a36Sopenharmony_ci nstats->rx_missed_errors = stats0->rx_missed_errors; 211762306a36Sopenharmony_ci nstats->rx_over_errors = stats0->rx_over_errors; 211862306a36Sopenharmony_ci if (info->nc_queues) { 211962306a36Sopenharmony_ci stats1 = &priv->stats[RAVB_NC]; 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_ci nstats->rx_packets += stats1->rx_packets; 212262306a36Sopenharmony_ci nstats->tx_packets += stats1->tx_packets; 212362306a36Sopenharmony_ci nstats->rx_bytes += stats1->rx_bytes; 212462306a36Sopenharmony_ci nstats->tx_bytes += stats1->tx_bytes; 212562306a36Sopenharmony_ci nstats->multicast += stats1->multicast; 212662306a36Sopenharmony_ci nstats->rx_errors += stats1->rx_errors; 212762306a36Sopenharmony_ci nstats->rx_crc_errors += stats1->rx_crc_errors; 212862306a36Sopenharmony_ci nstats->rx_frame_errors += stats1->rx_frame_errors; 212962306a36Sopenharmony_ci nstats->rx_length_errors += stats1->rx_length_errors; 213062306a36Sopenharmony_ci nstats->rx_missed_errors += stats1->rx_missed_errors; 213162306a36Sopenharmony_ci nstats->rx_over_errors += stats1->rx_over_errors; 213262306a36Sopenharmony_ci } 213362306a36Sopenharmony_ci 213462306a36Sopenharmony_ci return nstats; 213562306a36Sopenharmony_ci} 213662306a36Sopenharmony_ci 213762306a36Sopenharmony_ci/* Update promiscuous bit */ 213862306a36Sopenharmony_cistatic void ravb_set_rx_mode(struct net_device *ndev) 213962306a36Sopenharmony_ci{ 214062306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 214162306a36Sopenharmony_ci unsigned long flags; 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 214462306a36Sopenharmony_ci ravb_modify(ndev, ECMR, ECMR_PRM, 214562306a36Sopenharmony_ci ndev->flags & IFF_PROMISC ? ECMR_PRM : 0); 214662306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 214762306a36Sopenharmony_ci} 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci/* Device close function for Ethernet AVB */ 215062306a36Sopenharmony_cistatic int ravb_close(struct net_device *ndev) 215162306a36Sopenharmony_ci{ 215262306a36Sopenharmony_ci struct device_node *np = ndev->dev.parent->of_node; 215362306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 215462306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 215562306a36Sopenharmony_ci struct ravb_tstamp_skb *ts_skb, *ts_skb2; 215662306a36Sopenharmony_ci 215762306a36Sopenharmony_ci netif_tx_stop_all_queues(ndev); 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci /* Disable interrupts by clearing the interrupt masks. */ 216062306a36Sopenharmony_ci ravb_write(ndev, 0, RIC0); 216162306a36Sopenharmony_ci ravb_write(ndev, 0, RIC2); 216262306a36Sopenharmony_ci ravb_write(ndev, 0, TIC); 216362306a36Sopenharmony_ci 216462306a36Sopenharmony_ci /* Stop PTP Clock driver */ 216562306a36Sopenharmony_ci if (info->gptp) 216662306a36Sopenharmony_ci ravb_ptp_stop(ndev); 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci /* Set the config mode to stop the AVB-DMAC's processes */ 216962306a36Sopenharmony_ci if (ravb_stop_dma(ndev) < 0) 217062306a36Sopenharmony_ci netdev_err(ndev, 217162306a36Sopenharmony_ci "device will be stopped after h/w processes are done.\n"); 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_ci /* Clear the timestamp list */ 217462306a36Sopenharmony_ci if (info->gptp || info->ccc_gac) { 217562306a36Sopenharmony_ci list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) { 217662306a36Sopenharmony_ci list_del(&ts_skb->list); 217762306a36Sopenharmony_ci kfree_skb(ts_skb->skb); 217862306a36Sopenharmony_ci kfree(ts_skb); 217962306a36Sopenharmony_ci } 218062306a36Sopenharmony_ci } 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_ci /* PHY disconnect */ 218362306a36Sopenharmony_ci if (ndev->phydev) { 218462306a36Sopenharmony_ci phy_stop(ndev->phydev); 218562306a36Sopenharmony_ci phy_disconnect(ndev->phydev); 218662306a36Sopenharmony_ci if (of_phy_is_fixed_link(np)) 218762306a36Sopenharmony_ci of_phy_deregister_fixed_link(np); 218862306a36Sopenharmony_ci } 218962306a36Sopenharmony_ci 219062306a36Sopenharmony_ci cancel_work_sync(&priv->work); 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci if (info->multi_irqs) { 219362306a36Sopenharmony_ci free_irq(priv->tx_irqs[RAVB_NC], ndev); 219462306a36Sopenharmony_ci free_irq(priv->rx_irqs[RAVB_NC], ndev); 219562306a36Sopenharmony_ci free_irq(priv->tx_irqs[RAVB_BE], ndev); 219662306a36Sopenharmony_ci free_irq(priv->rx_irqs[RAVB_BE], ndev); 219762306a36Sopenharmony_ci free_irq(priv->emac_irq, ndev); 219862306a36Sopenharmony_ci if (info->err_mgmt_irqs) { 219962306a36Sopenharmony_ci free_irq(priv->erra_irq, ndev); 220062306a36Sopenharmony_ci free_irq(priv->mgmta_irq, ndev); 220162306a36Sopenharmony_ci } 220262306a36Sopenharmony_ci } 220362306a36Sopenharmony_ci free_irq(ndev->irq, ndev); 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci if (info->nc_queues) 220662306a36Sopenharmony_ci napi_disable(&priv->napi[RAVB_NC]); 220762306a36Sopenharmony_ci napi_disable(&priv->napi[RAVB_BE]); 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci /* Free all the skb's in the RX queue and the DMA buffers. */ 221062306a36Sopenharmony_ci ravb_ring_free(ndev, RAVB_BE); 221162306a36Sopenharmony_ci if (info->nc_queues) 221262306a36Sopenharmony_ci ravb_ring_free(ndev, RAVB_NC); 221362306a36Sopenharmony_ci 221462306a36Sopenharmony_ci return 0; 221562306a36Sopenharmony_ci} 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_cistatic int ravb_hwtstamp_get(struct net_device *ndev, struct ifreq *req) 221862306a36Sopenharmony_ci{ 221962306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 222062306a36Sopenharmony_ci struct hwtstamp_config config; 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci config.flags = 0; 222362306a36Sopenharmony_ci config.tx_type = priv->tstamp_tx_ctrl ? HWTSTAMP_TX_ON : 222462306a36Sopenharmony_ci HWTSTAMP_TX_OFF; 222562306a36Sopenharmony_ci switch (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE) { 222662306a36Sopenharmony_ci case RAVB_RXTSTAMP_TYPE_V2_L2_EVENT: 222762306a36Sopenharmony_ci config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; 222862306a36Sopenharmony_ci break; 222962306a36Sopenharmony_ci case RAVB_RXTSTAMP_TYPE_ALL: 223062306a36Sopenharmony_ci config.rx_filter = HWTSTAMP_FILTER_ALL; 223162306a36Sopenharmony_ci break; 223262306a36Sopenharmony_ci default: 223362306a36Sopenharmony_ci config.rx_filter = HWTSTAMP_FILTER_NONE; 223462306a36Sopenharmony_ci } 223562306a36Sopenharmony_ci 223662306a36Sopenharmony_ci return copy_to_user(req->ifr_data, &config, sizeof(config)) ? 223762306a36Sopenharmony_ci -EFAULT : 0; 223862306a36Sopenharmony_ci} 223962306a36Sopenharmony_ci 224062306a36Sopenharmony_ci/* Control hardware time stamping */ 224162306a36Sopenharmony_cistatic int ravb_hwtstamp_set(struct net_device *ndev, struct ifreq *req) 224262306a36Sopenharmony_ci{ 224362306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 224462306a36Sopenharmony_ci struct hwtstamp_config config; 224562306a36Sopenharmony_ci u32 tstamp_rx_ctrl = RAVB_RXTSTAMP_ENABLED; 224662306a36Sopenharmony_ci u32 tstamp_tx_ctrl; 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci if (copy_from_user(&config, req->ifr_data, sizeof(config))) 224962306a36Sopenharmony_ci return -EFAULT; 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_ci switch (config.tx_type) { 225262306a36Sopenharmony_ci case HWTSTAMP_TX_OFF: 225362306a36Sopenharmony_ci tstamp_tx_ctrl = 0; 225462306a36Sopenharmony_ci break; 225562306a36Sopenharmony_ci case HWTSTAMP_TX_ON: 225662306a36Sopenharmony_ci tstamp_tx_ctrl = RAVB_TXTSTAMP_ENABLED; 225762306a36Sopenharmony_ci break; 225862306a36Sopenharmony_ci default: 225962306a36Sopenharmony_ci return -ERANGE; 226062306a36Sopenharmony_ci } 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci switch (config.rx_filter) { 226362306a36Sopenharmony_ci case HWTSTAMP_FILTER_NONE: 226462306a36Sopenharmony_ci tstamp_rx_ctrl = 0; 226562306a36Sopenharmony_ci break; 226662306a36Sopenharmony_ci case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 226762306a36Sopenharmony_ci tstamp_rx_ctrl |= RAVB_RXTSTAMP_TYPE_V2_L2_EVENT; 226862306a36Sopenharmony_ci break; 226962306a36Sopenharmony_ci default: 227062306a36Sopenharmony_ci config.rx_filter = HWTSTAMP_FILTER_ALL; 227162306a36Sopenharmony_ci tstamp_rx_ctrl |= RAVB_RXTSTAMP_TYPE_ALL; 227262306a36Sopenharmony_ci } 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci priv->tstamp_tx_ctrl = tstamp_tx_ctrl; 227562306a36Sopenharmony_ci priv->tstamp_rx_ctrl = tstamp_rx_ctrl; 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_ci return copy_to_user(req->ifr_data, &config, sizeof(config)) ? 227862306a36Sopenharmony_ci -EFAULT : 0; 227962306a36Sopenharmony_ci} 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_ci/* ioctl to device function */ 228262306a36Sopenharmony_cistatic int ravb_do_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) 228362306a36Sopenharmony_ci{ 228462306a36Sopenharmony_ci struct phy_device *phydev = ndev->phydev; 228562306a36Sopenharmony_ci 228662306a36Sopenharmony_ci if (!netif_running(ndev)) 228762306a36Sopenharmony_ci return -EINVAL; 228862306a36Sopenharmony_ci 228962306a36Sopenharmony_ci if (!phydev) 229062306a36Sopenharmony_ci return -ENODEV; 229162306a36Sopenharmony_ci 229262306a36Sopenharmony_ci switch (cmd) { 229362306a36Sopenharmony_ci case SIOCGHWTSTAMP: 229462306a36Sopenharmony_ci return ravb_hwtstamp_get(ndev, req); 229562306a36Sopenharmony_ci case SIOCSHWTSTAMP: 229662306a36Sopenharmony_ci return ravb_hwtstamp_set(ndev, req); 229762306a36Sopenharmony_ci } 229862306a36Sopenharmony_ci 229962306a36Sopenharmony_ci return phy_mii_ioctl(phydev, req, cmd); 230062306a36Sopenharmony_ci} 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_cistatic int ravb_change_mtu(struct net_device *ndev, int new_mtu) 230362306a36Sopenharmony_ci{ 230462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 230562306a36Sopenharmony_ci 230662306a36Sopenharmony_ci ndev->mtu = new_mtu; 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_ci if (netif_running(ndev)) { 230962306a36Sopenharmony_ci synchronize_irq(priv->emac_irq); 231062306a36Sopenharmony_ci ravb_emac_init(ndev); 231162306a36Sopenharmony_ci } 231262306a36Sopenharmony_ci 231362306a36Sopenharmony_ci netdev_update_features(ndev); 231462306a36Sopenharmony_ci 231562306a36Sopenharmony_ci return 0; 231662306a36Sopenharmony_ci} 231762306a36Sopenharmony_ci 231862306a36Sopenharmony_cistatic void ravb_set_rx_csum(struct net_device *ndev, bool enable) 231962306a36Sopenharmony_ci{ 232062306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 232162306a36Sopenharmony_ci unsigned long flags; 232262306a36Sopenharmony_ci 232362306a36Sopenharmony_ci spin_lock_irqsave(&priv->lock, flags); 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_ci /* Disable TX and RX */ 232662306a36Sopenharmony_ci ravb_rcv_snd_disable(ndev); 232762306a36Sopenharmony_ci 232862306a36Sopenharmony_ci /* Modify RX Checksum setting */ 232962306a36Sopenharmony_ci ravb_modify(ndev, ECMR, ECMR_RCSC, enable ? ECMR_RCSC : 0); 233062306a36Sopenharmony_ci 233162306a36Sopenharmony_ci /* Enable TX and RX */ 233262306a36Sopenharmony_ci ravb_rcv_snd_enable(ndev); 233362306a36Sopenharmony_ci 233462306a36Sopenharmony_ci spin_unlock_irqrestore(&priv->lock, flags); 233562306a36Sopenharmony_ci} 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_cistatic int ravb_set_features_gbeth(struct net_device *ndev, 233862306a36Sopenharmony_ci netdev_features_t features) 233962306a36Sopenharmony_ci{ 234062306a36Sopenharmony_ci /* Place holder */ 234162306a36Sopenharmony_ci return 0; 234262306a36Sopenharmony_ci} 234362306a36Sopenharmony_ci 234462306a36Sopenharmony_cistatic int ravb_set_features_rcar(struct net_device *ndev, 234562306a36Sopenharmony_ci netdev_features_t features) 234662306a36Sopenharmony_ci{ 234762306a36Sopenharmony_ci netdev_features_t changed = ndev->features ^ features; 234862306a36Sopenharmony_ci 234962306a36Sopenharmony_ci if (changed & NETIF_F_RXCSUM) 235062306a36Sopenharmony_ci ravb_set_rx_csum(ndev, features & NETIF_F_RXCSUM); 235162306a36Sopenharmony_ci 235262306a36Sopenharmony_ci ndev->features = features; 235362306a36Sopenharmony_ci 235462306a36Sopenharmony_ci return 0; 235562306a36Sopenharmony_ci} 235662306a36Sopenharmony_ci 235762306a36Sopenharmony_cistatic int ravb_set_features(struct net_device *ndev, 235862306a36Sopenharmony_ci netdev_features_t features) 235962306a36Sopenharmony_ci{ 236062306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 236162306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_ci return info->set_feature(ndev, features); 236462306a36Sopenharmony_ci} 236562306a36Sopenharmony_ci 236662306a36Sopenharmony_cistatic const struct net_device_ops ravb_netdev_ops = { 236762306a36Sopenharmony_ci .ndo_open = ravb_open, 236862306a36Sopenharmony_ci .ndo_stop = ravb_close, 236962306a36Sopenharmony_ci .ndo_start_xmit = ravb_start_xmit, 237062306a36Sopenharmony_ci .ndo_select_queue = ravb_select_queue, 237162306a36Sopenharmony_ci .ndo_get_stats = ravb_get_stats, 237262306a36Sopenharmony_ci .ndo_set_rx_mode = ravb_set_rx_mode, 237362306a36Sopenharmony_ci .ndo_tx_timeout = ravb_tx_timeout, 237462306a36Sopenharmony_ci .ndo_eth_ioctl = ravb_do_ioctl, 237562306a36Sopenharmony_ci .ndo_change_mtu = ravb_change_mtu, 237662306a36Sopenharmony_ci .ndo_validate_addr = eth_validate_addr, 237762306a36Sopenharmony_ci .ndo_set_mac_address = eth_mac_addr, 237862306a36Sopenharmony_ci .ndo_set_features = ravb_set_features, 237962306a36Sopenharmony_ci}; 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_ci/* MDIO bus init function */ 238262306a36Sopenharmony_cistatic int ravb_mdio_init(struct ravb_private *priv) 238362306a36Sopenharmony_ci{ 238462306a36Sopenharmony_ci struct platform_device *pdev = priv->pdev; 238562306a36Sopenharmony_ci struct device *dev = &pdev->dev; 238662306a36Sopenharmony_ci struct phy_device *phydev; 238762306a36Sopenharmony_ci struct device_node *pn; 238862306a36Sopenharmony_ci int error; 238962306a36Sopenharmony_ci 239062306a36Sopenharmony_ci /* Bitbang init */ 239162306a36Sopenharmony_ci priv->mdiobb.ops = &bb_ops; 239262306a36Sopenharmony_ci 239362306a36Sopenharmony_ci /* MII controller setting */ 239462306a36Sopenharmony_ci priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb); 239562306a36Sopenharmony_ci if (!priv->mii_bus) 239662306a36Sopenharmony_ci return -ENOMEM; 239762306a36Sopenharmony_ci 239862306a36Sopenharmony_ci /* Hook up MII support for ethtool */ 239962306a36Sopenharmony_ci priv->mii_bus->name = "ravb_mii"; 240062306a36Sopenharmony_ci priv->mii_bus->parent = dev; 240162306a36Sopenharmony_ci snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", 240262306a36Sopenharmony_ci pdev->name, pdev->id); 240362306a36Sopenharmony_ci 240462306a36Sopenharmony_ci /* Register MDIO bus */ 240562306a36Sopenharmony_ci error = of_mdiobus_register(priv->mii_bus, dev->of_node); 240662306a36Sopenharmony_ci if (error) 240762306a36Sopenharmony_ci goto out_free_bus; 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci pn = of_parse_phandle(dev->of_node, "phy-handle", 0); 241062306a36Sopenharmony_ci phydev = of_phy_find_device(pn); 241162306a36Sopenharmony_ci if (phydev) { 241262306a36Sopenharmony_ci phydev->mac_managed_pm = true; 241362306a36Sopenharmony_ci put_device(&phydev->mdio.dev); 241462306a36Sopenharmony_ci } 241562306a36Sopenharmony_ci of_node_put(pn); 241662306a36Sopenharmony_ci 241762306a36Sopenharmony_ci return 0; 241862306a36Sopenharmony_ci 241962306a36Sopenharmony_ciout_free_bus: 242062306a36Sopenharmony_ci free_mdio_bitbang(priv->mii_bus); 242162306a36Sopenharmony_ci return error; 242262306a36Sopenharmony_ci} 242362306a36Sopenharmony_ci 242462306a36Sopenharmony_ci/* MDIO bus release function */ 242562306a36Sopenharmony_cistatic int ravb_mdio_release(struct ravb_private *priv) 242662306a36Sopenharmony_ci{ 242762306a36Sopenharmony_ci /* Unregister mdio bus */ 242862306a36Sopenharmony_ci mdiobus_unregister(priv->mii_bus); 242962306a36Sopenharmony_ci 243062306a36Sopenharmony_ci /* Free bitbang info */ 243162306a36Sopenharmony_ci free_mdio_bitbang(priv->mii_bus); 243262306a36Sopenharmony_ci 243362306a36Sopenharmony_ci return 0; 243462306a36Sopenharmony_ci} 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_cistatic const struct ravb_hw_info ravb_gen3_hw_info = { 243762306a36Sopenharmony_ci .rx_ring_free = ravb_rx_ring_free_rcar, 243862306a36Sopenharmony_ci .rx_ring_format = ravb_rx_ring_format_rcar, 243962306a36Sopenharmony_ci .alloc_rx_desc = ravb_alloc_rx_desc_rcar, 244062306a36Sopenharmony_ci .receive = ravb_rx_rcar, 244162306a36Sopenharmony_ci .set_rate = ravb_set_rate_rcar, 244262306a36Sopenharmony_ci .set_feature = ravb_set_features_rcar, 244362306a36Sopenharmony_ci .dmac_init = ravb_dmac_init_rcar, 244462306a36Sopenharmony_ci .emac_init = ravb_emac_init_rcar, 244562306a36Sopenharmony_ci .gstrings_stats = ravb_gstrings_stats, 244662306a36Sopenharmony_ci .gstrings_size = sizeof(ravb_gstrings_stats), 244762306a36Sopenharmony_ci .net_hw_features = NETIF_F_RXCSUM, 244862306a36Sopenharmony_ci .net_features = NETIF_F_RXCSUM, 244962306a36Sopenharmony_ci .stats_len = ARRAY_SIZE(ravb_gstrings_stats), 245062306a36Sopenharmony_ci .max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1, 245162306a36Sopenharmony_ci .tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 245262306a36Sopenharmony_ci .rx_max_buf_size = SZ_2K, 245362306a36Sopenharmony_ci .internal_delay = 1, 245462306a36Sopenharmony_ci .tx_counters = 1, 245562306a36Sopenharmony_ci .multi_irqs = 1, 245662306a36Sopenharmony_ci .irq_en_dis = 1, 245762306a36Sopenharmony_ci .ccc_gac = 1, 245862306a36Sopenharmony_ci .nc_queues = 1, 245962306a36Sopenharmony_ci .magic_pkt = 1, 246062306a36Sopenharmony_ci}; 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_cistatic const struct ravb_hw_info ravb_gen2_hw_info = { 246362306a36Sopenharmony_ci .rx_ring_free = ravb_rx_ring_free_rcar, 246462306a36Sopenharmony_ci .rx_ring_format = ravb_rx_ring_format_rcar, 246562306a36Sopenharmony_ci .alloc_rx_desc = ravb_alloc_rx_desc_rcar, 246662306a36Sopenharmony_ci .receive = ravb_rx_rcar, 246762306a36Sopenharmony_ci .set_rate = ravb_set_rate_rcar, 246862306a36Sopenharmony_ci .set_feature = ravb_set_features_rcar, 246962306a36Sopenharmony_ci .dmac_init = ravb_dmac_init_rcar, 247062306a36Sopenharmony_ci .emac_init = ravb_emac_init_rcar, 247162306a36Sopenharmony_ci .gstrings_stats = ravb_gstrings_stats, 247262306a36Sopenharmony_ci .gstrings_size = sizeof(ravb_gstrings_stats), 247362306a36Sopenharmony_ci .net_hw_features = NETIF_F_RXCSUM, 247462306a36Sopenharmony_ci .net_features = NETIF_F_RXCSUM, 247562306a36Sopenharmony_ci .stats_len = ARRAY_SIZE(ravb_gstrings_stats), 247662306a36Sopenharmony_ci .max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1, 247762306a36Sopenharmony_ci .tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 247862306a36Sopenharmony_ci .rx_max_buf_size = SZ_2K, 247962306a36Sopenharmony_ci .aligned_tx = 1, 248062306a36Sopenharmony_ci .gptp = 1, 248162306a36Sopenharmony_ci .nc_queues = 1, 248262306a36Sopenharmony_ci .magic_pkt = 1, 248362306a36Sopenharmony_ci}; 248462306a36Sopenharmony_ci 248562306a36Sopenharmony_cistatic const struct ravb_hw_info ravb_rzv2m_hw_info = { 248662306a36Sopenharmony_ci .rx_ring_free = ravb_rx_ring_free_rcar, 248762306a36Sopenharmony_ci .rx_ring_format = ravb_rx_ring_format_rcar, 248862306a36Sopenharmony_ci .alloc_rx_desc = ravb_alloc_rx_desc_rcar, 248962306a36Sopenharmony_ci .receive = ravb_rx_rcar, 249062306a36Sopenharmony_ci .set_rate = ravb_set_rate_rcar, 249162306a36Sopenharmony_ci .set_feature = ravb_set_features_rcar, 249262306a36Sopenharmony_ci .dmac_init = ravb_dmac_init_rcar, 249362306a36Sopenharmony_ci .emac_init = ravb_emac_init_rcar, 249462306a36Sopenharmony_ci .gstrings_stats = ravb_gstrings_stats, 249562306a36Sopenharmony_ci .gstrings_size = sizeof(ravb_gstrings_stats), 249662306a36Sopenharmony_ci .net_hw_features = NETIF_F_RXCSUM, 249762306a36Sopenharmony_ci .net_features = NETIF_F_RXCSUM, 249862306a36Sopenharmony_ci .stats_len = ARRAY_SIZE(ravb_gstrings_stats), 249962306a36Sopenharmony_ci .max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1, 250062306a36Sopenharmony_ci .tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3, 250162306a36Sopenharmony_ci .rx_max_buf_size = SZ_2K, 250262306a36Sopenharmony_ci .multi_irqs = 1, 250362306a36Sopenharmony_ci .err_mgmt_irqs = 1, 250462306a36Sopenharmony_ci .gptp = 1, 250562306a36Sopenharmony_ci .gptp_ref_clk = 1, 250662306a36Sopenharmony_ci .nc_queues = 1, 250762306a36Sopenharmony_ci .magic_pkt = 1, 250862306a36Sopenharmony_ci}; 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_cistatic const struct ravb_hw_info gbeth_hw_info = { 251162306a36Sopenharmony_ci .rx_ring_free = ravb_rx_ring_free_gbeth, 251262306a36Sopenharmony_ci .rx_ring_format = ravb_rx_ring_format_gbeth, 251362306a36Sopenharmony_ci .alloc_rx_desc = ravb_alloc_rx_desc_gbeth, 251462306a36Sopenharmony_ci .receive = ravb_rx_gbeth, 251562306a36Sopenharmony_ci .set_rate = ravb_set_rate_gbeth, 251662306a36Sopenharmony_ci .set_feature = ravb_set_features_gbeth, 251762306a36Sopenharmony_ci .dmac_init = ravb_dmac_init_gbeth, 251862306a36Sopenharmony_ci .emac_init = ravb_emac_init_gbeth, 251962306a36Sopenharmony_ci .gstrings_stats = ravb_gstrings_stats_gbeth, 252062306a36Sopenharmony_ci .gstrings_size = sizeof(ravb_gstrings_stats_gbeth), 252162306a36Sopenharmony_ci .stats_len = ARRAY_SIZE(ravb_gstrings_stats_gbeth), 252262306a36Sopenharmony_ci .max_rx_len = ALIGN(GBETH_RX_BUFF_MAX, RAVB_ALIGN), 252362306a36Sopenharmony_ci .tccr_mask = TCCR_TSRQ0, 252462306a36Sopenharmony_ci .rx_max_buf_size = SZ_8K, 252562306a36Sopenharmony_ci .aligned_tx = 1, 252662306a36Sopenharmony_ci .tx_counters = 1, 252762306a36Sopenharmony_ci .carrier_counters = 1, 252862306a36Sopenharmony_ci .half_duplex = 1, 252962306a36Sopenharmony_ci}; 253062306a36Sopenharmony_ci 253162306a36Sopenharmony_cistatic const struct of_device_id ravb_match_table[] = { 253262306a36Sopenharmony_ci { .compatible = "renesas,etheravb-r8a7790", .data = &ravb_gen2_hw_info }, 253362306a36Sopenharmony_ci { .compatible = "renesas,etheravb-r8a7794", .data = &ravb_gen2_hw_info }, 253462306a36Sopenharmony_ci { .compatible = "renesas,etheravb-rcar-gen2", .data = &ravb_gen2_hw_info }, 253562306a36Sopenharmony_ci { .compatible = "renesas,etheravb-r8a7795", .data = &ravb_gen3_hw_info }, 253662306a36Sopenharmony_ci { .compatible = "renesas,etheravb-rcar-gen3", .data = &ravb_gen3_hw_info }, 253762306a36Sopenharmony_ci { .compatible = "renesas,etheravb-rcar-gen4", .data = &ravb_gen3_hw_info }, 253862306a36Sopenharmony_ci { .compatible = "renesas,etheravb-rzv2m", .data = &ravb_rzv2m_hw_info }, 253962306a36Sopenharmony_ci { .compatible = "renesas,rzg2l-gbeth", .data = &gbeth_hw_info }, 254062306a36Sopenharmony_ci { } 254162306a36Sopenharmony_ci}; 254262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ravb_match_table); 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_cistatic int ravb_set_gti(struct net_device *ndev) 254562306a36Sopenharmony_ci{ 254662306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 254762306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 254862306a36Sopenharmony_ci struct device *dev = ndev->dev.parent; 254962306a36Sopenharmony_ci unsigned long rate; 255062306a36Sopenharmony_ci uint64_t inc; 255162306a36Sopenharmony_ci 255262306a36Sopenharmony_ci if (info->gptp_ref_clk) 255362306a36Sopenharmony_ci rate = clk_get_rate(priv->gptp_clk); 255462306a36Sopenharmony_ci else 255562306a36Sopenharmony_ci rate = clk_get_rate(priv->clk); 255662306a36Sopenharmony_ci if (!rate) 255762306a36Sopenharmony_ci return -EINVAL; 255862306a36Sopenharmony_ci 255962306a36Sopenharmony_ci inc = div64_ul(1000000000ULL << 20, rate); 256062306a36Sopenharmony_ci 256162306a36Sopenharmony_ci if (inc < GTI_TIV_MIN || inc > GTI_TIV_MAX) { 256262306a36Sopenharmony_ci dev_err(dev, "gti.tiv increment 0x%llx is outside the range 0x%x - 0x%x\n", 256362306a36Sopenharmony_ci inc, GTI_TIV_MIN, GTI_TIV_MAX); 256462306a36Sopenharmony_ci return -EINVAL; 256562306a36Sopenharmony_ci } 256662306a36Sopenharmony_ci 256762306a36Sopenharmony_ci ravb_write(ndev, inc, GTI); 256862306a36Sopenharmony_ci 256962306a36Sopenharmony_ci return 0; 257062306a36Sopenharmony_ci} 257162306a36Sopenharmony_ci 257262306a36Sopenharmony_cistatic int ravb_set_config_mode(struct net_device *ndev) 257362306a36Sopenharmony_ci{ 257462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 257562306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 257662306a36Sopenharmony_ci int error; 257762306a36Sopenharmony_ci 257862306a36Sopenharmony_ci if (info->gptp) { 257962306a36Sopenharmony_ci error = ravb_set_opmode(ndev, CCC_OPC_CONFIG); 258062306a36Sopenharmony_ci if (error) 258162306a36Sopenharmony_ci return error; 258262306a36Sopenharmony_ci /* Set CSEL value */ 258362306a36Sopenharmony_ci ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB); 258462306a36Sopenharmony_ci } else if (info->ccc_gac) { 258562306a36Sopenharmony_ci error = ravb_set_opmode(ndev, CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB); 258662306a36Sopenharmony_ci } else { 258762306a36Sopenharmony_ci error = ravb_set_opmode(ndev, CCC_OPC_CONFIG); 258862306a36Sopenharmony_ci } 258962306a36Sopenharmony_ci 259062306a36Sopenharmony_ci return error; 259162306a36Sopenharmony_ci} 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci/* Set tx and rx clock internal delay modes */ 259462306a36Sopenharmony_cistatic void ravb_parse_delay_mode(struct device_node *np, struct net_device *ndev) 259562306a36Sopenharmony_ci{ 259662306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 259762306a36Sopenharmony_ci bool explicit_delay = false; 259862306a36Sopenharmony_ci u32 delay; 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci if (!of_property_read_u32(np, "rx-internal-delay-ps", &delay)) { 260162306a36Sopenharmony_ci /* Valid values are 0 and 1800, according to DT bindings */ 260262306a36Sopenharmony_ci priv->rxcidm = !!delay; 260362306a36Sopenharmony_ci explicit_delay = true; 260462306a36Sopenharmony_ci } 260562306a36Sopenharmony_ci if (!of_property_read_u32(np, "tx-internal-delay-ps", &delay)) { 260662306a36Sopenharmony_ci /* Valid values are 0 and 2000, according to DT bindings */ 260762306a36Sopenharmony_ci priv->txcidm = !!delay; 260862306a36Sopenharmony_ci explicit_delay = true; 260962306a36Sopenharmony_ci } 261062306a36Sopenharmony_ci 261162306a36Sopenharmony_ci if (explicit_delay) 261262306a36Sopenharmony_ci return; 261362306a36Sopenharmony_ci 261462306a36Sopenharmony_ci /* Fall back to legacy rgmii-*id behavior */ 261562306a36Sopenharmony_ci if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || 261662306a36Sopenharmony_ci priv->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) { 261762306a36Sopenharmony_ci priv->rxcidm = 1; 261862306a36Sopenharmony_ci priv->rgmii_override = 1; 261962306a36Sopenharmony_ci } 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID || 262262306a36Sopenharmony_ci priv->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) { 262362306a36Sopenharmony_ci priv->txcidm = 1; 262462306a36Sopenharmony_ci priv->rgmii_override = 1; 262562306a36Sopenharmony_ci } 262662306a36Sopenharmony_ci} 262762306a36Sopenharmony_ci 262862306a36Sopenharmony_cistatic void ravb_set_delay_mode(struct net_device *ndev) 262962306a36Sopenharmony_ci{ 263062306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 263162306a36Sopenharmony_ci u32 set = 0; 263262306a36Sopenharmony_ci 263362306a36Sopenharmony_ci if (priv->rxcidm) 263462306a36Sopenharmony_ci set |= APSR_RDM; 263562306a36Sopenharmony_ci if (priv->txcidm) 263662306a36Sopenharmony_ci set |= APSR_TDM; 263762306a36Sopenharmony_ci ravb_modify(ndev, APSR, APSR_RDM | APSR_TDM, set); 263862306a36Sopenharmony_ci} 263962306a36Sopenharmony_ci 264062306a36Sopenharmony_cistatic int ravb_probe(struct platform_device *pdev) 264162306a36Sopenharmony_ci{ 264262306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 264362306a36Sopenharmony_ci const struct ravb_hw_info *info; 264462306a36Sopenharmony_ci struct reset_control *rstc; 264562306a36Sopenharmony_ci struct ravb_private *priv; 264662306a36Sopenharmony_ci struct net_device *ndev; 264762306a36Sopenharmony_ci int error, irq, q; 264862306a36Sopenharmony_ci struct resource *res; 264962306a36Sopenharmony_ci int i; 265062306a36Sopenharmony_ci 265162306a36Sopenharmony_ci if (!np) { 265262306a36Sopenharmony_ci dev_err(&pdev->dev, 265362306a36Sopenharmony_ci "this driver is required to be instantiated from device tree\n"); 265462306a36Sopenharmony_ci return -EINVAL; 265562306a36Sopenharmony_ci } 265662306a36Sopenharmony_ci 265762306a36Sopenharmony_ci rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); 265862306a36Sopenharmony_ci if (IS_ERR(rstc)) 265962306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(rstc), 266062306a36Sopenharmony_ci "failed to get cpg reset\n"); 266162306a36Sopenharmony_ci 266262306a36Sopenharmony_ci ndev = alloc_etherdev_mqs(sizeof(struct ravb_private), 266362306a36Sopenharmony_ci NUM_TX_QUEUE, NUM_RX_QUEUE); 266462306a36Sopenharmony_ci if (!ndev) 266562306a36Sopenharmony_ci return -ENOMEM; 266662306a36Sopenharmony_ci 266762306a36Sopenharmony_ci info = of_device_get_match_data(&pdev->dev); 266862306a36Sopenharmony_ci 266962306a36Sopenharmony_ci ndev->features = info->net_features; 267062306a36Sopenharmony_ci ndev->hw_features = info->net_hw_features; 267162306a36Sopenharmony_ci 267262306a36Sopenharmony_ci error = reset_control_deassert(rstc); 267362306a36Sopenharmony_ci if (error) 267462306a36Sopenharmony_ci goto out_free_netdev; 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci pm_runtime_enable(&pdev->dev); 267762306a36Sopenharmony_ci error = pm_runtime_resume_and_get(&pdev->dev); 267862306a36Sopenharmony_ci if (error < 0) 267962306a36Sopenharmony_ci goto out_rpm_disable; 268062306a36Sopenharmony_ci 268162306a36Sopenharmony_ci if (info->multi_irqs) { 268262306a36Sopenharmony_ci if (info->err_mgmt_irqs) 268362306a36Sopenharmony_ci irq = platform_get_irq_byname(pdev, "dia"); 268462306a36Sopenharmony_ci else 268562306a36Sopenharmony_ci irq = platform_get_irq_byname(pdev, "ch22"); 268662306a36Sopenharmony_ci } else { 268762306a36Sopenharmony_ci irq = platform_get_irq(pdev, 0); 268862306a36Sopenharmony_ci } 268962306a36Sopenharmony_ci if (irq < 0) { 269062306a36Sopenharmony_ci error = irq; 269162306a36Sopenharmony_ci goto out_release; 269262306a36Sopenharmony_ci } 269362306a36Sopenharmony_ci ndev->irq = irq; 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_ci SET_NETDEV_DEV(ndev, &pdev->dev); 269662306a36Sopenharmony_ci 269762306a36Sopenharmony_ci priv = netdev_priv(ndev); 269862306a36Sopenharmony_ci priv->info = info; 269962306a36Sopenharmony_ci priv->rstc = rstc; 270062306a36Sopenharmony_ci priv->ndev = ndev; 270162306a36Sopenharmony_ci priv->pdev = pdev; 270262306a36Sopenharmony_ci priv->num_tx_ring[RAVB_BE] = BE_TX_RING_SIZE; 270362306a36Sopenharmony_ci priv->num_rx_ring[RAVB_BE] = BE_RX_RING_SIZE; 270462306a36Sopenharmony_ci if (info->nc_queues) { 270562306a36Sopenharmony_ci priv->num_tx_ring[RAVB_NC] = NC_TX_RING_SIZE; 270662306a36Sopenharmony_ci priv->num_rx_ring[RAVB_NC] = NC_RX_RING_SIZE; 270762306a36Sopenharmony_ci } 270862306a36Sopenharmony_ci 270962306a36Sopenharmony_ci priv->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 271062306a36Sopenharmony_ci if (IS_ERR(priv->addr)) { 271162306a36Sopenharmony_ci error = PTR_ERR(priv->addr); 271262306a36Sopenharmony_ci goto out_release; 271362306a36Sopenharmony_ci } 271462306a36Sopenharmony_ci 271562306a36Sopenharmony_ci /* The Ether-specific entries in the device structure. */ 271662306a36Sopenharmony_ci ndev->base_addr = res->start; 271762306a36Sopenharmony_ci 271862306a36Sopenharmony_ci spin_lock_init(&priv->lock); 271962306a36Sopenharmony_ci INIT_WORK(&priv->work, ravb_tx_timeout_work); 272062306a36Sopenharmony_ci 272162306a36Sopenharmony_ci error = of_get_phy_mode(np, &priv->phy_interface); 272262306a36Sopenharmony_ci if (error && error != -ENODEV) 272362306a36Sopenharmony_ci goto out_release; 272462306a36Sopenharmony_ci 272562306a36Sopenharmony_ci priv->no_avb_link = of_property_read_bool(np, "renesas,no-ether-link"); 272662306a36Sopenharmony_ci priv->avb_link_active_low = 272762306a36Sopenharmony_ci of_property_read_bool(np, "renesas,ether-link-active-low"); 272862306a36Sopenharmony_ci 272962306a36Sopenharmony_ci if (info->multi_irqs) { 273062306a36Sopenharmony_ci if (info->err_mgmt_irqs) 273162306a36Sopenharmony_ci irq = platform_get_irq_byname(pdev, "line3"); 273262306a36Sopenharmony_ci else 273362306a36Sopenharmony_ci irq = platform_get_irq_byname(pdev, "ch24"); 273462306a36Sopenharmony_ci if (irq < 0) { 273562306a36Sopenharmony_ci error = irq; 273662306a36Sopenharmony_ci goto out_release; 273762306a36Sopenharmony_ci } 273862306a36Sopenharmony_ci priv->emac_irq = irq; 273962306a36Sopenharmony_ci for (i = 0; i < NUM_RX_QUEUE; i++) { 274062306a36Sopenharmony_ci irq = platform_get_irq_byname(pdev, ravb_rx_irqs[i]); 274162306a36Sopenharmony_ci if (irq < 0) { 274262306a36Sopenharmony_ci error = irq; 274362306a36Sopenharmony_ci goto out_release; 274462306a36Sopenharmony_ci } 274562306a36Sopenharmony_ci priv->rx_irqs[i] = irq; 274662306a36Sopenharmony_ci } 274762306a36Sopenharmony_ci for (i = 0; i < NUM_TX_QUEUE; i++) { 274862306a36Sopenharmony_ci irq = platform_get_irq_byname(pdev, ravb_tx_irqs[i]); 274962306a36Sopenharmony_ci if (irq < 0) { 275062306a36Sopenharmony_ci error = irq; 275162306a36Sopenharmony_ci goto out_release; 275262306a36Sopenharmony_ci } 275362306a36Sopenharmony_ci priv->tx_irqs[i] = irq; 275462306a36Sopenharmony_ci } 275562306a36Sopenharmony_ci 275662306a36Sopenharmony_ci if (info->err_mgmt_irqs) { 275762306a36Sopenharmony_ci irq = platform_get_irq_byname(pdev, "err_a"); 275862306a36Sopenharmony_ci if (irq < 0) { 275962306a36Sopenharmony_ci error = irq; 276062306a36Sopenharmony_ci goto out_release; 276162306a36Sopenharmony_ci } 276262306a36Sopenharmony_ci priv->erra_irq = irq; 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci irq = platform_get_irq_byname(pdev, "mgmt_a"); 276562306a36Sopenharmony_ci if (irq < 0) { 276662306a36Sopenharmony_ci error = irq; 276762306a36Sopenharmony_ci goto out_release; 276862306a36Sopenharmony_ci } 276962306a36Sopenharmony_ci priv->mgmta_irq = irq; 277062306a36Sopenharmony_ci } 277162306a36Sopenharmony_ci } 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_ci priv->clk = devm_clk_get(&pdev->dev, NULL); 277462306a36Sopenharmony_ci if (IS_ERR(priv->clk)) { 277562306a36Sopenharmony_ci error = PTR_ERR(priv->clk); 277662306a36Sopenharmony_ci goto out_release; 277762306a36Sopenharmony_ci } 277862306a36Sopenharmony_ci 277962306a36Sopenharmony_ci priv->refclk = devm_clk_get_optional(&pdev->dev, "refclk"); 278062306a36Sopenharmony_ci if (IS_ERR(priv->refclk)) { 278162306a36Sopenharmony_ci error = PTR_ERR(priv->refclk); 278262306a36Sopenharmony_ci goto out_release; 278362306a36Sopenharmony_ci } 278462306a36Sopenharmony_ci clk_prepare_enable(priv->refclk); 278562306a36Sopenharmony_ci 278662306a36Sopenharmony_ci if (info->gptp_ref_clk) { 278762306a36Sopenharmony_ci priv->gptp_clk = devm_clk_get(&pdev->dev, "gptp"); 278862306a36Sopenharmony_ci if (IS_ERR(priv->gptp_clk)) { 278962306a36Sopenharmony_ci error = PTR_ERR(priv->gptp_clk); 279062306a36Sopenharmony_ci goto out_disable_refclk; 279162306a36Sopenharmony_ci } 279262306a36Sopenharmony_ci clk_prepare_enable(priv->gptp_clk); 279362306a36Sopenharmony_ci } 279462306a36Sopenharmony_ci 279562306a36Sopenharmony_ci ndev->max_mtu = info->rx_max_buf_size - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN); 279662306a36Sopenharmony_ci ndev->min_mtu = ETH_MIN_MTU; 279762306a36Sopenharmony_ci 279862306a36Sopenharmony_ci /* FIXME: R-Car Gen2 has 4byte alignment restriction for tx buffer 279962306a36Sopenharmony_ci * Use two descriptor to handle such situation. First descriptor to 280062306a36Sopenharmony_ci * handle aligned data buffer and second descriptor to handle the 280162306a36Sopenharmony_ci * overflow data because of alignment. 280262306a36Sopenharmony_ci */ 280362306a36Sopenharmony_ci priv->num_tx_desc = info->aligned_tx ? 2 : 1; 280462306a36Sopenharmony_ci 280562306a36Sopenharmony_ci /* Set function */ 280662306a36Sopenharmony_ci ndev->netdev_ops = &ravb_netdev_ops; 280762306a36Sopenharmony_ci ndev->ethtool_ops = &ravb_ethtool_ops; 280862306a36Sopenharmony_ci 280962306a36Sopenharmony_ci /* Set AVB config mode */ 281062306a36Sopenharmony_ci error = ravb_set_config_mode(ndev); 281162306a36Sopenharmony_ci if (error) 281262306a36Sopenharmony_ci goto out_disable_gptp_clk; 281362306a36Sopenharmony_ci 281462306a36Sopenharmony_ci if (info->gptp || info->ccc_gac) { 281562306a36Sopenharmony_ci /* Set GTI value */ 281662306a36Sopenharmony_ci error = ravb_set_gti(ndev); 281762306a36Sopenharmony_ci if (error) 281862306a36Sopenharmony_ci goto out_disable_gptp_clk; 281962306a36Sopenharmony_ci 282062306a36Sopenharmony_ci /* Request GTI loading */ 282162306a36Sopenharmony_ci ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI); 282262306a36Sopenharmony_ci } 282362306a36Sopenharmony_ci 282462306a36Sopenharmony_ci if (info->internal_delay) { 282562306a36Sopenharmony_ci ravb_parse_delay_mode(np, ndev); 282662306a36Sopenharmony_ci ravb_set_delay_mode(ndev); 282762306a36Sopenharmony_ci } 282862306a36Sopenharmony_ci 282962306a36Sopenharmony_ci /* Allocate descriptor base address table */ 283062306a36Sopenharmony_ci priv->desc_bat_size = sizeof(struct ravb_desc) * DBAT_ENTRY_NUM; 283162306a36Sopenharmony_ci priv->desc_bat = dma_alloc_coherent(ndev->dev.parent, priv->desc_bat_size, 283262306a36Sopenharmony_ci &priv->desc_bat_dma, GFP_KERNEL); 283362306a36Sopenharmony_ci if (!priv->desc_bat) { 283462306a36Sopenharmony_ci dev_err(&pdev->dev, 283562306a36Sopenharmony_ci "Cannot allocate desc base address table (size %d bytes)\n", 283662306a36Sopenharmony_ci priv->desc_bat_size); 283762306a36Sopenharmony_ci error = -ENOMEM; 283862306a36Sopenharmony_ci goto out_disable_gptp_clk; 283962306a36Sopenharmony_ci } 284062306a36Sopenharmony_ci for (q = RAVB_BE; q < DBAT_ENTRY_NUM; q++) 284162306a36Sopenharmony_ci priv->desc_bat[q].die_dt = DT_EOS; 284262306a36Sopenharmony_ci ravb_write(ndev, priv->desc_bat_dma, DBAT); 284362306a36Sopenharmony_ci 284462306a36Sopenharmony_ci /* Initialise HW timestamp list */ 284562306a36Sopenharmony_ci INIT_LIST_HEAD(&priv->ts_skb_list); 284662306a36Sopenharmony_ci 284762306a36Sopenharmony_ci /* Initialise PTP Clock driver */ 284862306a36Sopenharmony_ci if (info->ccc_gac) 284962306a36Sopenharmony_ci ravb_ptp_init(ndev, pdev); 285062306a36Sopenharmony_ci 285162306a36Sopenharmony_ci /* Debug message level */ 285262306a36Sopenharmony_ci priv->msg_enable = RAVB_DEF_MSG_ENABLE; 285362306a36Sopenharmony_ci 285462306a36Sopenharmony_ci /* Read and set MAC address */ 285562306a36Sopenharmony_ci ravb_read_mac_address(np, ndev); 285662306a36Sopenharmony_ci if (!is_valid_ether_addr(ndev->dev_addr)) { 285762306a36Sopenharmony_ci dev_warn(&pdev->dev, 285862306a36Sopenharmony_ci "no valid MAC address supplied, using a random one\n"); 285962306a36Sopenharmony_ci eth_hw_addr_random(ndev); 286062306a36Sopenharmony_ci } 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci /* MDIO bus init */ 286362306a36Sopenharmony_ci error = ravb_mdio_init(priv); 286462306a36Sopenharmony_ci if (error) { 286562306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to initialize MDIO\n"); 286662306a36Sopenharmony_ci goto out_dma_free; 286762306a36Sopenharmony_ci } 286862306a36Sopenharmony_ci 286962306a36Sopenharmony_ci netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll); 287062306a36Sopenharmony_ci if (info->nc_queues) 287162306a36Sopenharmony_ci netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll); 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci /* Network device register */ 287462306a36Sopenharmony_ci error = register_netdev(ndev); 287562306a36Sopenharmony_ci if (error) 287662306a36Sopenharmony_ci goto out_napi_del; 287762306a36Sopenharmony_ci 287862306a36Sopenharmony_ci device_set_wakeup_capable(&pdev->dev, 1); 287962306a36Sopenharmony_ci 288062306a36Sopenharmony_ci /* Print device information */ 288162306a36Sopenharmony_ci netdev_info(ndev, "Base address at %#x, %pM, IRQ %d.\n", 288262306a36Sopenharmony_ci (u32)ndev->base_addr, ndev->dev_addr, ndev->irq); 288362306a36Sopenharmony_ci 288462306a36Sopenharmony_ci platform_set_drvdata(pdev, ndev); 288562306a36Sopenharmony_ci 288662306a36Sopenharmony_ci return 0; 288762306a36Sopenharmony_ci 288862306a36Sopenharmony_ciout_napi_del: 288962306a36Sopenharmony_ci if (info->nc_queues) 289062306a36Sopenharmony_ci netif_napi_del(&priv->napi[RAVB_NC]); 289162306a36Sopenharmony_ci 289262306a36Sopenharmony_ci netif_napi_del(&priv->napi[RAVB_BE]); 289362306a36Sopenharmony_ci ravb_mdio_release(priv); 289462306a36Sopenharmony_ciout_dma_free: 289562306a36Sopenharmony_ci dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, 289662306a36Sopenharmony_ci priv->desc_bat_dma); 289762306a36Sopenharmony_ci 289862306a36Sopenharmony_ci /* Stop PTP Clock driver */ 289962306a36Sopenharmony_ci if (info->ccc_gac) 290062306a36Sopenharmony_ci ravb_ptp_stop(ndev); 290162306a36Sopenharmony_ciout_disable_gptp_clk: 290262306a36Sopenharmony_ci clk_disable_unprepare(priv->gptp_clk); 290362306a36Sopenharmony_ciout_disable_refclk: 290462306a36Sopenharmony_ci clk_disable_unprepare(priv->refclk); 290562306a36Sopenharmony_ciout_release: 290662306a36Sopenharmony_ci pm_runtime_put(&pdev->dev); 290762306a36Sopenharmony_ciout_rpm_disable: 290862306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 290962306a36Sopenharmony_ci reset_control_assert(rstc); 291062306a36Sopenharmony_ciout_free_netdev: 291162306a36Sopenharmony_ci free_netdev(ndev); 291262306a36Sopenharmony_ci return error; 291362306a36Sopenharmony_ci} 291462306a36Sopenharmony_ci 291562306a36Sopenharmony_cistatic int ravb_remove(struct platform_device *pdev) 291662306a36Sopenharmony_ci{ 291762306a36Sopenharmony_ci struct net_device *ndev = platform_get_drvdata(pdev); 291862306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 291962306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 292062306a36Sopenharmony_ci 292162306a36Sopenharmony_ci unregister_netdev(ndev); 292262306a36Sopenharmony_ci if (info->nc_queues) 292362306a36Sopenharmony_ci netif_napi_del(&priv->napi[RAVB_NC]); 292462306a36Sopenharmony_ci netif_napi_del(&priv->napi[RAVB_BE]); 292562306a36Sopenharmony_ci 292662306a36Sopenharmony_ci ravb_mdio_release(priv); 292762306a36Sopenharmony_ci 292862306a36Sopenharmony_ci /* Stop PTP Clock driver */ 292962306a36Sopenharmony_ci if (info->ccc_gac) 293062306a36Sopenharmony_ci ravb_ptp_stop(ndev); 293162306a36Sopenharmony_ci 293262306a36Sopenharmony_ci dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, 293362306a36Sopenharmony_ci priv->desc_bat_dma); 293462306a36Sopenharmony_ci 293562306a36Sopenharmony_ci ravb_set_opmode(ndev, CCC_OPC_RESET); 293662306a36Sopenharmony_ci 293762306a36Sopenharmony_ci clk_disable_unprepare(priv->gptp_clk); 293862306a36Sopenharmony_ci clk_disable_unprepare(priv->refclk); 293962306a36Sopenharmony_ci 294062306a36Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 294162306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 294262306a36Sopenharmony_ci reset_control_assert(priv->rstc); 294362306a36Sopenharmony_ci free_netdev(ndev); 294462306a36Sopenharmony_ci platform_set_drvdata(pdev, NULL); 294562306a36Sopenharmony_ci 294662306a36Sopenharmony_ci return 0; 294762306a36Sopenharmony_ci} 294862306a36Sopenharmony_ci 294962306a36Sopenharmony_cistatic int ravb_wol_setup(struct net_device *ndev) 295062306a36Sopenharmony_ci{ 295162306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 295262306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 295362306a36Sopenharmony_ci 295462306a36Sopenharmony_ci /* Disable interrupts by clearing the interrupt masks. */ 295562306a36Sopenharmony_ci ravb_write(ndev, 0, RIC0); 295662306a36Sopenharmony_ci ravb_write(ndev, 0, RIC2); 295762306a36Sopenharmony_ci ravb_write(ndev, 0, TIC); 295862306a36Sopenharmony_ci 295962306a36Sopenharmony_ci /* Only allow ECI interrupts */ 296062306a36Sopenharmony_ci synchronize_irq(priv->emac_irq); 296162306a36Sopenharmony_ci if (info->nc_queues) 296262306a36Sopenharmony_ci napi_disable(&priv->napi[RAVB_NC]); 296362306a36Sopenharmony_ci napi_disable(&priv->napi[RAVB_BE]); 296462306a36Sopenharmony_ci ravb_write(ndev, ECSIPR_MPDIP, ECSIPR); 296562306a36Sopenharmony_ci 296662306a36Sopenharmony_ci /* Enable MagicPacket */ 296762306a36Sopenharmony_ci ravb_modify(ndev, ECMR, ECMR_MPDE, ECMR_MPDE); 296862306a36Sopenharmony_ci 296962306a36Sopenharmony_ci return enable_irq_wake(priv->emac_irq); 297062306a36Sopenharmony_ci} 297162306a36Sopenharmony_ci 297262306a36Sopenharmony_cistatic int ravb_wol_restore(struct net_device *ndev) 297362306a36Sopenharmony_ci{ 297462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 297562306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 297662306a36Sopenharmony_ci 297762306a36Sopenharmony_ci if (info->nc_queues) 297862306a36Sopenharmony_ci napi_enable(&priv->napi[RAVB_NC]); 297962306a36Sopenharmony_ci napi_enable(&priv->napi[RAVB_BE]); 298062306a36Sopenharmony_ci 298162306a36Sopenharmony_ci /* Disable MagicPacket */ 298262306a36Sopenharmony_ci ravb_modify(ndev, ECMR, ECMR_MPDE, 0); 298362306a36Sopenharmony_ci 298462306a36Sopenharmony_ci ravb_close(ndev); 298562306a36Sopenharmony_ci 298662306a36Sopenharmony_ci return disable_irq_wake(priv->emac_irq); 298762306a36Sopenharmony_ci} 298862306a36Sopenharmony_ci 298962306a36Sopenharmony_cistatic int __maybe_unused ravb_suspend(struct device *dev) 299062306a36Sopenharmony_ci{ 299162306a36Sopenharmony_ci struct net_device *ndev = dev_get_drvdata(dev); 299262306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 299362306a36Sopenharmony_ci int ret; 299462306a36Sopenharmony_ci 299562306a36Sopenharmony_ci if (!netif_running(ndev)) 299662306a36Sopenharmony_ci return 0; 299762306a36Sopenharmony_ci 299862306a36Sopenharmony_ci netif_device_detach(ndev); 299962306a36Sopenharmony_ci 300062306a36Sopenharmony_ci if (priv->wol_enabled) 300162306a36Sopenharmony_ci ret = ravb_wol_setup(ndev); 300262306a36Sopenharmony_ci else 300362306a36Sopenharmony_ci ret = ravb_close(ndev); 300462306a36Sopenharmony_ci 300562306a36Sopenharmony_ci if (priv->info->ccc_gac) 300662306a36Sopenharmony_ci ravb_ptp_stop(ndev); 300762306a36Sopenharmony_ci 300862306a36Sopenharmony_ci return ret; 300962306a36Sopenharmony_ci} 301062306a36Sopenharmony_ci 301162306a36Sopenharmony_cistatic int __maybe_unused ravb_resume(struct device *dev) 301262306a36Sopenharmony_ci{ 301362306a36Sopenharmony_ci struct net_device *ndev = dev_get_drvdata(dev); 301462306a36Sopenharmony_ci struct ravb_private *priv = netdev_priv(ndev); 301562306a36Sopenharmony_ci const struct ravb_hw_info *info = priv->info; 301662306a36Sopenharmony_ci int ret = 0; 301762306a36Sopenharmony_ci 301862306a36Sopenharmony_ci /* If WoL is enabled set reset mode to rearm the WoL logic */ 301962306a36Sopenharmony_ci if (priv->wol_enabled) { 302062306a36Sopenharmony_ci ret = ravb_set_opmode(ndev, CCC_OPC_RESET); 302162306a36Sopenharmony_ci if (ret) 302262306a36Sopenharmony_ci return ret; 302362306a36Sopenharmony_ci } 302462306a36Sopenharmony_ci 302562306a36Sopenharmony_ci /* All register have been reset to default values. 302662306a36Sopenharmony_ci * Restore all registers which where setup at probe time and 302762306a36Sopenharmony_ci * reopen device if it was running before system suspended. 302862306a36Sopenharmony_ci */ 302962306a36Sopenharmony_ci 303062306a36Sopenharmony_ci /* Set AVB config mode */ 303162306a36Sopenharmony_ci ret = ravb_set_config_mode(ndev); 303262306a36Sopenharmony_ci if (ret) 303362306a36Sopenharmony_ci return ret; 303462306a36Sopenharmony_ci 303562306a36Sopenharmony_ci if (info->gptp || info->ccc_gac) { 303662306a36Sopenharmony_ci /* Set GTI value */ 303762306a36Sopenharmony_ci ret = ravb_set_gti(ndev); 303862306a36Sopenharmony_ci if (ret) 303962306a36Sopenharmony_ci return ret; 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_ci /* Request GTI loading */ 304262306a36Sopenharmony_ci ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI); 304362306a36Sopenharmony_ci } 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_ci if (info->internal_delay) 304662306a36Sopenharmony_ci ravb_set_delay_mode(ndev); 304762306a36Sopenharmony_ci 304862306a36Sopenharmony_ci /* Restore descriptor base address table */ 304962306a36Sopenharmony_ci ravb_write(ndev, priv->desc_bat_dma, DBAT); 305062306a36Sopenharmony_ci 305162306a36Sopenharmony_ci if (priv->info->ccc_gac) 305262306a36Sopenharmony_ci ravb_ptp_init(ndev, priv->pdev); 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_ci if (netif_running(ndev)) { 305562306a36Sopenharmony_ci if (priv->wol_enabled) { 305662306a36Sopenharmony_ci ret = ravb_wol_restore(ndev); 305762306a36Sopenharmony_ci if (ret) 305862306a36Sopenharmony_ci return ret; 305962306a36Sopenharmony_ci } 306062306a36Sopenharmony_ci ret = ravb_open(ndev); 306162306a36Sopenharmony_ci if (ret < 0) 306262306a36Sopenharmony_ci return ret; 306362306a36Sopenharmony_ci ravb_set_rx_mode(ndev); 306462306a36Sopenharmony_ci netif_device_attach(ndev); 306562306a36Sopenharmony_ci } 306662306a36Sopenharmony_ci 306762306a36Sopenharmony_ci return ret; 306862306a36Sopenharmony_ci} 306962306a36Sopenharmony_ci 307062306a36Sopenharmony_cistatic int __maybe_unused ravb_runtime_nop(struct device *dev) 307162306a36Sopenharmony_ci{ 307262306a36Sopenharmony_ci /* Runtime PM callback shared between ->runtime_suspend() 307362306a36Sopenharmony_ci * and ->runtime_resume(). Simply returns success. 307462306a36Sopenharmony_ci * 307562306a36Sopenharmony_ci * This driver re-initializes all registers after 307662306a36Sopenharmony_ci * pm_runtime_get_sync() anyway so there is no need 307762306a36Sopenharmony_ci * to save and restore registers here. 307862306a36Sopenharmony_ci */ 307962306a36Sopenharmony_ci return 0; 308062306a36Sopenharmony_ci} 308162306a36Sopenharmony_ci 308262306a36Sopenharmony_cistatic const struct dev_pm_ops ravb_dev_pm_ops = { 308362306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(ravb_suspend, ravb_resume) 308462306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(ravb_runtime_nop, ravb_runtime_nop, NULL) 308562306a36Sopenharmony_ci}; 308662306a36Sopenharmony_ci 308762306a36Sopenharmony_cistatic struct platform_driver ravb_driver = { 308862306a36Sopenharmony_ci .probe = ravb_probe, 308962306a36Sopenharmony_ci .remove = ravb_remove, 309062306a36Sopenharmony_ci .driver = { 309162306a36Sopenharmony_ci .name = "ravb", 309262306a36Sopenharmony_ci .pm = &ravb_dev_pm_ops, 309362306a36Sopenharmony_ci .of_match_table = ravb_match_table, 309462306a36Sopenharmony_ci }, 309562306a36Sopenharmony_ci}; 309662306a36Sopenharmony_ci 309762306a36Sopenharmony_cimodule_platform_driver(ravb_driver); 309862306a36Sopenharmony_ci 309962306a36Sopenharmony_ciMODULE_AUTHOR("Mitsuhiro Kimura, Masaru Nagai"); 310062306a36Sopenharmony_ciMODULE_DESCRIPTION("Renesas Ethernet AVB driver"); 310162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 3102