19d61d138SRafał Miłecki // SPDX-License-Identifier: GPL-2.0-only 29d61d138SRafał Miłecki /* 39d61d138SRafał Miłecki * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl> 49d61d138SRafał Miłecki */ 59d61d138SRafał Miłecki 69d61d138SRafał Miłecki #include <linux/delay.h> 79d61d138SRafał Miłecki #include <linux/etherdevice.h> 814b3b46aSRafał Miłecki #include <linux/if_vlan.h> 99d61d138SRafał Miłecki #include <linux/interrupt.h> 109d61d138SRafał Miłecki #include <linux/module.h> 119d61d138SRafał Miłecki #include <linux/of.h> 123559c1eaSRafał Miłecki #include <linux/of_net.h> 139d61d138SRafał Miłecki #include <linux/platform_device.h> 149d61d138SRafał Miłecki #include <linux/slab.h> 159d61d138SRafał Miłecki #include <linux/string.h> 169d61d138SRafał Miłecki 179d61d138SRafał Miłecki #include "bcm4908_enet.h" 189d61d138SRafał Miłecki #include "unimac.h" 199d61d138SRafał Miłecki 209d61d138SRafał Miłecki #define ENET_DMA_CH_RX_CFG ENET_DMA_CH0_CFG 219d61d138SRafał Miłecki #define ENET_DMA_CH_TX_CFG ENET_DMA_CH1_CFG 229d61d138SRafał Miłecki #define ENET_DMA_CH_RX_STATE_RAM ENET_DMA_CH0_STATE_RAM 239d61d138SRafał Miłecki #define ENET_DMA_CH_TX_STATE_RAM ENET_DMA_CH1_STATE_RAM 249d61d138SRafał Miłecki 259d61d138SRafał Miłecki #define ENET_TX_BDS_NUM 200 269d61d138SRafał Miłecki #define ENET_RX_BDS_NUM 200 279d61d138SRafał Miłecki #define ENET_RX_BDS_NUM_MAX 8192 289d61d138SRafał Miłecki 299d61d138SRafał Miłecki #define ENET_DMA_INT_DEFAULTS (ENET_DMA_CH_CFG_INT_DONE | \ 309d61d138SRafał Miłecki ENET_DMA_CH_CFG_INT_NO_DESC | \ 319d61d138SRafał Miłecki ENET_DMA_CH_CFG_INT_BUFF_DONE) 329d61d138SRafał Miłecki #define ENET_DMA_MAX_BURST_LEN 8 /* in 64 bit words */ 339d61d138SRafał Miłecki 3414b3b46aSRafał Miłecki #define ENET_MTU_MAX ETH_DATA_LEN /* Is it possible to support 2044? */ 3514b3b46aSRafał Miłecki #define BRCM_MAX_TAG_LEN 6 3614b3b46aSRafał Miłecki #define ENET_MAX_ETH_OVERHEAD (ETH_HLEN + BRCM_MAX_TAG_LEN + VLAN_HLEN + \ 3714b3b46aSRafał Miłecki ETH_FCS_LEN + 4) /* 32 */ 389d61d138SRafał Miłecki 399d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_bd { 409d61d138SRafał Miłecki __le32 ctl; 419d61d138SRafał Miłecki __le32 addr; 429d61d138SRafał Miłecki } __packed; 439d61d138SRafał Miłecki 449d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_slot { 459d61d138SRafał Miłecki struct sk_buff *skb; 469d61d138SRafał Miłecki unsigned int len; 479d61d138SRafał Miłecki dma_addr_t dma_addr; 489d61d138SRafał Miłecki }; 499d61d138SRafał Miłecki 509d61d138SRafał Miłecki struct bcm4908_enet_dma_ring { 519d61d138SRafał Miłecki int is_tx; 529d61d138SRafał Miłecki int read_idx; 539d61d138SRafał Miłecki int write_idx; 549d61d138SRafał Miłecki int length; 559d61d138SRafał Miłecki u16 cfg_block; 569d61d138SRafał Miłecki u16 st_ram_block; 5712bb508bSRafał Miłecki struct napi_struct napi; 589d61d138SRafał Miłecki 599d61d138SRafał Miłecki union { 609d61d138SRafał Miłecki void *cpu_addr; 619d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_bd *buf_desc; 629d61d138SRafał Miłecki }; 639d61d138SRafał Miłecki dma_addr_t dma_addr; 649d61d138SRafał Miłecki 659d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_slot *slots; 669d61d138SRafał Miłecki }; 679d61d138SRafał Miłecki 689d61d138SRafał Miłecki struct bcm4908_enet { 699d61d138SRafał Miłecki struct device *dev; 709d61d138SRafał Miłecki struct net_device *netdev; 719d61d138SRafał Miłecki void __iomem *base; 7212bb508bSRafał Miłecki int irq_tx; 739d61d138SRafał Miłecki 749d61d138SRafał Miłecki struct bcm4908_enet_dma_ring tx_ring; 759d61d138SRafał Miłecki struct bcm4908_enet_dma_ring rx_ring; 769d61d138SRafał Miłecki }; 779d61d138SRafał Miłecki 789d61d138SRafał Miłecki /*** 799d61d138SRafał Miłecki * R/W ops 809d61d138SRafał Miłecki */ 819d61d138SRafał Miłecki 827b778ae4SRafał Miłecki static u32 enet_read(struct bcm4908_enet *enet, u16 offset) 839d61d138SRafał Miłecki { 849d61d138SRafał Miłecki return readl(enet->base + offset); 859d61d138SRafał Miłecki } 869d61d138SRafał Miłecki 877b778ae4SRafał Miłecki static void enet_write(struct bcm4908_enet *enet, u16 offset, u32 value) 889d61d138SRafał Miłecki { 899d61d138SRafał Miłecki writel(value, enet->base + offset); 909d61d138SRafał Miłecki } 919d61d138SRafał Miłecki 927b778ae4SRafał Miłecki static void enet_maskset(struct bcm4908_enet *enet, u16 offset, u32 mask, u32 set) 939d61d138SRafał Miłecki { 949d61d138SRafał Miłecki u32 val; 959d61d138SRafał Miłecki 969d61d138SRafał Miłecki WARN_ON(set & ~mask); 979d61d138SRafał Miłecki 989d61d138SRafał Miłecki val = enet_read(enet, offset); 999d61d138SRafał Miłecki val = (val & ~mask) | (set & mask); 1009d61d138SRafał Miłecki enet_write(enet, offset, val); 1019d61d138SRafał Miłecki } 1029d61d138SRafał Miłecki 1037b778ae4SRafał Miłecki static void enet_set(struct bcm4908_enet *enet, u16 offset, u32 set) 1049d61d138SRafał Miłecki { 1059d61d138SRafał Miłecki enet_maskset(enet, offset, set, set); 1069d61d138SRafał Miłecki } 1079d61d138SRafał Miłecki 1087b778ae4SRafał Miłecki static u32 enet_umac_read(struct bcm4908_enet *enet, u16 offset) 1099d61d138SRafał Miłecki { 1109d61d138SRafał Miłecki return enet_read(enet, ENET_UNIMAC + offset); 1119d61d138SRafał Miłecki } 1129d61d138SRafał Miłecki 1137b778ae4SRafał Miłecki static void enet_umac_write(struct bcm4908_enet *enet, u16 offset, u32 value) 1149d61d138SRafał Miłecki { 1159d61d138SRafał Miłecki enet_write(enet, ENET_UNIMAC + offset, value); 1169d61d138SRafał Miłecki } 1179d61d138SRafał Miłecki 1187b778ae4SRafał Miłecki static void enet_umac_set(struct bcm4908_enet *enet, u16 offset, u32 set) 1199d61d138SRafał Miłecki { 1209d61d138SRafał Miłecki enet_set(enet, ENET_UNIMAC + offset, set); 1219d61d138SRafał Miłecki } 1229d61d138SRafał Miłecki 1239d61d138SRafał Miłecki /*** 1249d61d138SRafał Miłecki * Helpers 1259d61d138SRafał Miłecki */ 1269d61d138SRafał Miłecki 12714b3b46aSRafał Miłecki static void bcm4908_enet_set_mtu(struct bcm4908_enet *enet, int mtu) 12814b3b46aSRafał Miłecki { 12914b3b46aSRafał Miłecki enet_umac_write(enet, UMAC_MAX_FRAME_LEN, mtu + ENET_MAX_ETH_OVERHEAD); 13014b3b46aSRafał Miłecki } 13114b3b46aSRafał Miłecki 1329d61d138SRafał Miłecki /*** 13312bb508bSRafał Miłecki * DMA ring ops 13412bb508bSRafał Miłecki */ 13512bb508bSRafał Miłecki 13612bb508bSRafał Miłecki static void bcm4908_enet_dma_ring_intrs_on(struct bcm4908_enet *enet, 13712bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *ring) 13812bb508bSRafał Miłecki { 13912bb508bSRafał Miłecki enet_write(enet, ring->cfg_block + ENET_DMA_CH_CFG_INT_MASK, ENET_DMA_INT_DEFAULTS); 14012bb508bSRafał Miłecki } 14112bb508bSRafał Miłecki 14212bb508bSRafał Miłecki static void bcm4908_enet_dma_ring_intrs_off(struct bcm4908_enet *enet, 14312bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *ring) 14412bb508bSRafał Miłecki { 14512bb508bSRafał Miłecki enet_write(enet, ring->cfg_block + ENET_DMA_CH_CFG_INT_MASK, 0); 14612bb508bSRafał Miłecki } 14712bb508bSRafał Miłecki 14812bb508bSRafał Miłecki static void bcm4908_enet_dma_ring_intrs_ack(struct bcm4908_enet *enet, 14912bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *ring) 15012bb508bSRafał Miłecki { 15112bb508bSRafał Miłecki enet_write(enet, ring->cfg_block + ENET_DMA_CH_CFG_INT_STAT, ENET_DMA_INT_DEFAULTS); 15212bb508bSRafał Miłecki } 15312bb508bSRafał Miłecki 15412bb508bSRafał Miłecki /*** 1559d61d138SRafał Miłecki * DMA 1569d61d138SRafał Miłecki */ 1579d61d138SRafał Miłecki 1589d61d138SRafał Miłecki static int bcm4908_dma_alloc_buf_descs(struct bcm4908_enet *enet, 1599d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *ring) 1609d61d138SRafał Miłecki { 1619d61d138SRafał Miłecki int size = ring->length * sizeof(struct bcm4908_enet_dma_ring_bd); 1629d61d138SRafał Miłecki struct device *dev = enet->dev; 1639d61d138SRafał Miłecki 1649d61d138SRafał Miłecki ring->cpu_addr = dma_alloc_coherent(dev, size, &ring->dma_addr, GFP_KERNEL); 1659d61d138SRafał Miłecki if (!ring->cpu_addr) 1669d61d138SRafał Miłecki return -ENOMEM; 1679d61d138SRafał Miłecki 1689d61d138SRafał Miłecki if (((uintptr_t)ring->cpu_addr) & (0x40 - 1)) { 1699d61d138SRafał Miłecki dev_err(dev, "Invalid DMA ring alignment\n"); 1709d61d138SRafał Miłecki goto err_free_buf_descs; 1719d61d138SRafał Miłecki } 1729d61d138SRafał Miłecki 1739d61d138SRafał Miłecki ring->slots = kzalloc(ring->length * sizeof(*ring->slots), GFP_KERNEL); 1749d61d138SRafał Miłecki if (!ring->slots) 1759d61d138SRafał Miłecki goto err_free_buf_descs; 1769d61d138SRafał Miłecki 1779d61d138SRafał Miłecki return 0; 1789d61d138SRafał Miłecki 1799d61d138SRafał Miłecki err_free_buf_descs: 1809d61d138SRafał Miłecki dma_free_coherent(dev, size, ring->cpu_addr, ring->dma_addr); 181b25b343dSLv Yunlong ring->cpu_addr = NULL; 1829d61d138SRafał Miłecki return -ENOMEM; 1839d61d138SRafał Miłecki } 1849d61d138SRafał Miłecki 1859d61d138SRafał Miłecki static void bcm4908_enet_dma_free(struct bcm4908_enet *enet) 1869d61d138SRafał Miłecki { 1879d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *tx_ring = &enet->tx_ring; 1889d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *rx_ring = &enet->rx_ring; 1899d61d138SRafał Miłecki struct device *dev = enet->dev; 1909d61d138SRafał Miłecki int size; 1919d61d138SRafał Miłecki 1929d61d138SRafał Miłecki size = rx_ring->length * sizeof(struct bcm4908_enet_dma_ring_bd); 1939d61d138SRafał Miłecki if (rx_ring->cpu_addr) 1949d61d138SRafał Miłecki dma_free_coherent(dev, size, rx_ring->cpu_addr, rx_ring->dma_addr); 1959d61d138SRafał Miłecki kfree(rx_ring->slots); 1969d61d138SRafał Miłecki 1979d61d138SRafał Miłecki size = tx_ring->length * sizeof(struct bcm4908_enet_dma_ring_bd); 1989d61d138SRafał Miłecki if (tx_ring->cpu_addr) 1999d61d138SRafał Miłecki dma_free_coherent(dev, size, tx_ring->cpu_addr, tx_ring->dma_addr); 2009d61d138SRafał Miłecki kfree(tx_ring->slots); 2019d61d138SRafał Miłecki } 2029d61d138SRafał Miłecki 2039d61d138SRafał Miłecki static int bcm4908_enet_dma_alloc(struct bcm4908_enet *enet) 2049d61d138SRafał Miłecki { 2059d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *tx_ring = &enet->tx_ring; 2069d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *rx_ring = &enet->rx_ring; 2079d61d138SRafał Miłecki struct device *dev = enet->dev; 2089d61d138SRafał Miłecki int err; 2099d61d138SRafał Miłecki 2109d61d138SRafał Miłecki tx_ring->length = ENET_TX_BDS_NUM; 2119d61d138SRafał Miłecki tx_ring->is_tx = 1; 2129d61d138SRafał Miłecki tx_ring->cfg_block = ENET_DMA_CH_TX_CFG; 2139d61d138SRafał Miłecki tx_ring->st_ram_block = ENET_DMA_CH_TX_STATE_RAM; 2149d61d138SRafał Miłecki err = bcm4908_dma_alloc_buf_descs(enet, tx_ring); 2159d61d138SRafał Miłecki if (err) { 2169d61d138SRafał Miłecki dev_err(dev, "Failed to alloc TX buf descriptors: %d\n", err); 2179d61d138SRafał Miłecki return err; 2189d61d138SRafał Miłecki } 2199d61d138SRafał Miłecki 2209d61d138SRafał Miłecki rx_ring->length = ENET_RX_BDS_NUM; 2219d61d138SRafał Miłecki rx_ring->is_tx = 0; 2229d61d138SRafał Miłecki rx_ring->cfg_block = ENET_DMA_CH_RX_CFG; 2239d61d138SRafał Miłecki rx_ring->st_ram_block = ENET_DMA_CH_RX_STATE_RAM; 2249d61d138SRafał Miłecki err = bcm4908_dma_alloc_buf_descs(enet, rx_ring); 2259d61d138SRafał Miłecki if (err) { 2269d61d138SRafał Miłecki dev_err(dev, "Failed to alloc RX buf descriptors: %d\n", err); 2279d61d138SRafał Miłecki bcm4908_enet_dma_free(enet); 2289d61d138SRafał Miłecki return err; 2299d61d138SRafał Miłecki } 2309d61d138SRafał Miłecki 2319d61d138SRafał Miłecki return 0; 2329d61d138SRafał Miłecki } 2339d61d138SRafał Miłecki 2349d61d138SRafał Miłecki static void bcm4908_enet_dma_reset(struct bcm4908_enet *enet) 2359d61d138SRafał Miłecki { 2369d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *rings[] = { &enet->rx_ring, &enet->tx_ring }; 2379d61d138SRafał Miłecki int i; 2389d61d138SRafał Miłecki 2399d61d138SRafał Miłecki /* Disable the DMA controller and channel */ 2409d61d138SRafał Miłecki for (i = 0; i < ARRAY_SIZE(rings); i++) 2419d61d138SRafał Miłecki enet_write(enet, rings[i]->cfg_block + ENET_DMA_CH_CFG, 0); 2429d61d138SRafał Miłecki enet_maskset(enet, ENET_DMA_CONTROLLER_CFG, ENET_DMA_CTRL_CFG_MASTER_EN, 0); 2439d61d138SRafał Miłecki 2449d61d138SRafał Miłecki /* Reset channels state */ 2459d61d138SRafał Miłecki for (i = 0; i < ARRAY_SIZE(rings); i++) { 2469d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *ring = rings[i]; 2479d61d138SRafał Miłecki 2489d61d138SRafał Miłecki enet_write(enet, ring->st_ram_block + ENET_DMA_CH_STATE_RAM_BASE_DESC_PTR, 0); 2499d61d138SRafał Miłecki enet_write(enet, ring->st_ram_block + ENET_DMA_CH_STATE_RAM_STATE_DATA, 0); 2509d61d138SRafał Miłecki enet_write(enet, ring->st_ram_block + ENET_DMA_CH_STATE_RAM_DESC_LEN_STATUS, 0); 2519d61d138SRafał Miłecki enet_write(enet, ring->st_ram_block + ENET_DMA_CH_STATE_RAM_DESC_BASE_BUFPTR, 0); 2529d61d138SRafał Miłecki } 2539d61d138SRafał Miłecki } 2549d61d138SRafał Miłecki 2559d61d138SRafał Miłecki static int bcm4908_enet_dma_alloc_rx_buf(struct bcm4908_enet *enet, unsigned int idx) 2569d61d138SRafał Miłecki { 2579d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_bd *buf_desc = &enet->rx_ring.buf_desc[idx]; 2589d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_slot *slot = &enet->rx_ring.slots[idx]; 2599d61d138SRafał Miłecki struct device *dev = enet->dev; 2609d61d138SRafał Miłecki u32 tmp; 2619d61d138SRafał Miłecki int err; 2629d61d138SRafał Miłecki 26314b3b46aSRafał Miłecki slot->len = ENET_MTU_MAX + ENET_MAX_ETH_OVERHEAD; 2649d61d138SRafał Miłecki 2659d61d138SRafał Miłecki slot->skb = netdev_alloc_skb(enet->netdev, slot->len); 2669d61d138SRafał Miłecki if (!slot->skb) 2679d61d138SRafał Miłecki return -ENOMEM; 2689d61d138SRafał Miłecki 2699d61d138SRafał Miłecki slot->dma_addr = dma_map_single(dev, slot->skb->data, slot->len, DMA_FROM_DEVICE); 2709d61d138SRafał Miłecki err = dma_mapping_error(dev, slot->dma_addr); 2719d61d138SRafał Miłecki if (err) { 2729d61d138SRafał Miłecki dev_err(dev, "Failed to map DMA buffer: %d\n", err); 2739d61d138SRafał Miłecki kfree_skb(slot->skb); 2749d61d138SRafał Miłecki slot->skb = NULL; 2759d61d138SRafał Miłecki return err; 2769d61d138SRafał Miłecki } 2779d61d138SRafał Miłecki 2789d61d138SRafał Miłecki tmp = slot->len << DMA_CTL_LEN_DESC_BUFLENGTH_SHIFT; 2799d61d138SRafał Miłecki tmp |= DMA_CTL_STATUS_OWN; 2809d61d138SRafał Miłecki if (idx == enet->rx_ring.length - 1) 2819d61d138SRafał Miłecki tmp |= DMA_CTL_STATUS_WRAP; 2829d61d138SRafał Miłecki buf_desc->ctl = cpu_to_le32(tmp); 2839d61d138SRafał Miłecki buf_desc->addr = cpu_to_le32(slot->dma_addr); 2849d61d138SRafał Miłecki 2859d61d138SRafał Miłecki return 0; 2869d61d138SRafał Miłecki } 2879d61d138SRafał Miłecki 2889d61d138SRafał Miłecki static void bcm4908_enet_dma_ring_init(struct bcm4908_enet *enet, 2899d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *ring) 2909d61d138SRafał Miłecki { 2919d61d138SRafał Miłecki int reset_channel = 0; /* We support only 1 main channel (with TX and RX) */ 2929d61d138SRafał Miłecki int reset_subch = ring->is_tx ? 1 : 0; 2939d61d138SRafał Miłecki 2949d61d138SRafał Miłecki /* Reset the DMA channel */ 2959d61d138SRafał Miłecki enet_write(enet, ENET_DMA_CTRL_CHANNEL_RESET, BIT(reset_channel * 2 + reset_subch)); 2969d61d138SRafał Miłecki enet_write(enet, ENET_DMA_CTRL_CHANNEL_RESET, 0); 2979d61d138SRafał Miłecki 2989d61d138SRafał Miłecki enet_write(enet, ring->cfg_block + ENET_DMA_CH_CFG, 0); 2999d61d138SRafał Miłecki enet_write(enet, ring->cfg_block + ENET_DMA_CH_CFG_MAX_BURST, ENET_DMA_MAX_BURST_LEN); 3009d61d138SRafał Miłecki enet_write(enet, ring->cfg_block + ENET_DMA_CH_CFG_INT_MASK, 0); 3019d61d138SRafał Miłecki 3029d61d138SRafał Miłecki enet_write(enet, ring->st_ram_block + ENET_DMA_CH_STATE_RAM_BASE_DESC_PTR, 3039d61d138SRafał Miłecki (uint32_t)ring->dma_addr); 304*ddeacc4fSRafał Miłecki 305*ddeacc4fSRafał Miłecki ring->read_idx = 0; 306*ddeacc4fSRafał Miłecki ring->write_idx = 0; 3079d61d138SRafał Miłecki } 3089d61d138SRafał Miłecki 3099d61d138SRafał Miłecki static void bcm4908_enet_dma_uninit(struct bcm4908_enet *enet) 3109d61d138SRafał Miłecki { 3119d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *rx_ring = &enet->rx_ring; 3129d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_slot *slot; 3139d61d138SRafał Miłecki struct device *dev = enet->dev; 3149d61d138SRafał Miłecki int i; 3159d61d138SRafał Miłecki 3169d61d138SRafał Miłecki for (i = rx_ring->length - 1; i >= 0; i--) { 3179d61d138SRafał Miłecki slot = &rx_ring->slots[i]; 3189d61d138SRafał Miłecki if (!slot->skb) 3199d61d138SRafał Miłecki continue; 3209d61d138SRafał Miłecki dma_unmap_single(dev, slot->dma_addr, slot->len, DMA_FROM_DEVICE); 3219d61d138SRafał Miłecki kfree_skb(slot->skb); 3229d61d138SRafał Miłecki slot->skb = NULL; 3239d61d138SRafał Miłecki } 3249d61d138SRafał Miłecki } 3259d61d138SRafał Miłecki 3269d61d138SRafał Miłecki static int bcm4908_enet_dma_init(struct bcm4908_enet *enet) 3279d61d138SRafał Miłecki { 3289d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *rx_ring = &enet->rx_ring; 3299d61d138SRafał Miłecki struct device *dev = enet->dev; 3309d61d138SRafał Miłecki int err; 3319d61d138SRafał Miłecki int i; 3329d61d138SRafał Miłecki 3339d61d138SRafał Miłecki for (i = 0; i < rx_ring->length; i++) { 3349d61d138SRafał Miłecki err = bcm4908_enet_dma_alloc_rx_buf(enet, i); 3359d61d138SRafał Miłecki if (err) { 3369d61d138SRafał Miłecki dev_err(dev, "Failed to alloc RX buffer: %d\n", err); 3379d61d138SRafał Miłecki bcm4908_enet_dma_uninit(enet); 3389d61d138SRafał Miłecki return err; 3399d61d138SRafał Miłecki } 3409d61d138SRafał Miłecki } 3419d61d138SRafał Miłecki 3429d61d138SRafał Miłecki bcm4908_enet_dma_ring_init(enet, &enet->tx_ring); 3439d61d138SRafał Miłecki bcm4908_enet_dma_ring_init(enet, &enet->rx_ring); 3449d61d138SRafał Miłecki 3459d61d138SRafał Miłecki return 0; 3469d61d138SRafał Miłecki } 3479d61d138SRafał Miłecki 348e3948811SRafał Miłecki static void bcm4908_enet_dma_tx_ring_enable(struct bcm4908_enet *enet, 3499d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *ring) 3509d61d138SRafał Miłecki { 3519d61d138SRafał Miłecki enet_write(enet, ring->cfg_block + ENET_DMA_CH_CFG, ENET_DMA_CH_CFG_ENABLE); 3529d61d138SRafał Miłecki } 3539d61d138SRafał Miłecki 3549d61d138SRafał Miłecki static void bcm4908_enet_dma_tx_ring_disable(struct bcm4908_enet *enet, 3559d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *ring) 3569d61d138SRafał Miłecki { 3579d61d138SRafał Miłecki enet_write(enet, ring->cfg_block + ENET_DMA_CH_CFG, 0); 3589d61d138SRafał Miłecki } 3599d61d138SRafał Miłecki 3609d61d138SRafał Miłecki static void bcm4908_enet_dma_rx_ring_enable(struct bcm4908_enet *enet, 3619d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *ring) 3629d61d138SRafał Miłecki { 3639d61d138SRafał Miłecki enet_set(enet, ring->cfg_block + ENET_DMA_CH_CFG, ENET_DMA_CH_CFG_ENABLE); 3649d61d138SRafał Miłecki } 3659d61d138SRafał Miłecki 3669d61d138SRafał Miłecki static void bcm4908_enet_dma_rx_ring_disable(struct bcm4908_enet *enet, 3679d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *ring) 3689d61d138SRafał Miłecki { 3699d61d138SRafał Miłecki unsigned long deadline; 3709d61d138SRafał Miłecki u32 tmp; 3719d61d138SRafał Miłecki 3729d61d138SRafał Miłecki enet_maskset(enet, ring->cfg_block + ENET_DMA_CH_CFG, ENET_DMA_CH_CFG_ENABLE, 0); 3739d61d138SRafał Miłecki 3749d61d138SRafał Miłecki deadline = jiffies + usecs_to_jiffies(2000); 3759d61d138SRafał Miłecki do { 3769d61d138SRafał Miłecki tmp = enet_read(enet, ring->cfg_block + ENET_DMA_CH_CFG); 3779d61d138SRafał Miłecki if (!(tmp & ENET_DMA_CH_CFG_ENABLE)) 3789d61d138SRafał Miłecki return; 3799d61d138SRafał Miłecki enet_maskset(enet, ring->cfg_block + ENET_DMA_CH_CFG, ENET_DMA_CH_CFG_ENABLE, 0); 3809d61d138SRafał Miłecki usleep_range(10, 30); 3819d61d138SRafał Miłecki } while (!time_after_eq(jiffies, deadline)); 3829d61d138SRafał Miłecki 3839d61d138SRafał Miłecki dev_warn(enet->dev, "Timeout waiting for DMA TX stop\n"); 3849d61d138SRafał Miłecki } 3859d61d138SRafał Miłecki 3869d61d138SRafał Miłecki /*** 3879d61d138SRafał Miłecki * Ethernet driver 3889d61d138SRafał Miłecki */ 3899d61d138SRafał Miłecki 3909d61d138SRafał Miłecki static void bcm4908_enet_gmac_init(struct bcm4908_enet *enet) 3919d61d138SRafał Miłecki { 3929d61d138SRafał Miłecki u32 cmd; 3939d61d138SRafał Miłecki 39414b3b46aSRafał Miłecki bcm4908_enet_set_mtu(enet, enet->netdev->mtu); 39514b3b46aSRafał Miłecki 3969d61d138SRafał Miłecki cmd = enet_umac_read(enet, UMAC_CMD); 3979d61d138SRafał Miłecki enet_umac_write(enet, UMAC_CMD, cmd | CMD_SW_RESET); 3989d61d138SRafał Miłecki enet_umac_write(enet, UMAC_CMD, cmd & ~CMD_SW_RESET); 3999d61d138SRafał Miłecki 4009d61d138SRafał Miłecki enet_set(enet, ENET_FLUSH, ENET_FLUSH_RXFIFO_FLUSH | ENET_FLUSH_TXFIFO_FLUSH); 4019d61d138SRafał Miłecki enet_maskset(enet, ENET_FLUSH, ENET_FLUSH_RXFIFO_FLUSH | ENET_FLUSH_TXFIFO_FLUSH, 0); 4029d61d138SRafał Miłecki 4039d61d138SRafał Miłecki enet_set(enet, ENET_MIB_CTRL, ENET_MIB_CTRL_CLR_MIB); 4049d61d138SRafał Miłecki enet_maskset(enet, ENET_MIB_CTRL, ENET_MIB_CTRL_CLR_MIB, 0); 4059d61d138SRafał Miłecki 4069d61d138SRafał Miłecki cmd = enet_umac_read(enet, UMAC_CMD); 4079d61d138SRafał Miłecki cmd &= ~(CMD_SPEED_MASK << CMD_SPEED_SHIFT); 4089d61d138SRafał Miłecki cmd &= ~CMD_TX_EN; 4099d61d138SRafał Miłecki cmd &= ~CMD_RX_EN; 4109d61d138SRafał Miłecki cmd |= CMD_SPEED_1000 << CMD_SPEED_SHIFT; 4119d61d138SRafał Miłecki enet_umac_write(enet, UMAC_CMD, cmd); 4129d61d138SRafał Miłecki 4139d61d138SRafał Miłecki enet_maskset(enet, ENET_GMAC_STATUS, 4149d61d138SRafał Miłecki ENET_GMAC_STATUS_ETH_SPEED_MASK | 4159d61d138SRafał Miłecki ENET_GMAC_STATUS_HD | 4169d61d138SRafał Miłecki ENET_GMAC_STATUS_AUTO_CFG_EN | 4179d61d138SRafał Miłecki ENET_GMAC_STATUS_LINK_UP, 4189d61d138SRafał Miłecki ENET_GMAC_STATUS_ETH_SPEED_1000 | 4199d61d138SRafał Miłecki ENET_GMAC_STATUS_AUTO_CFG_EN | 4209d61d138SRafał Miłecki ENET_GMAC_STATUS_LINK_UP); 4219d61d138SRafał Miłecki } 4229d61d138SRafał Miłecki 4239d61d138SRafał Miłecki static irqreturn_t bcm4908_enet_irq_handler(int irq, void *dev_id) 4249d61d138SRafał Miłecki { 4259d61d138SRafał Miłecki struct bcm4908_enet *enet = dev_id; 42612bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *ring; 4279d61d138SRafał Miłecki 42812bb508bSRafał Miłecki ring = (irq == enet->irq_tx) ? &enet->tx_ring : &enet->rx_ring; 4299d61d138SRafał Miłecki 43012bb508bSRafał Miłecki bcm4908_enet_dma_ring_intrs_off(enet, ring); 43112bb508bSRafał Miłecki bcm4908_enet_dma_ring_intrs_ack(enet, ring); 43212bb508bSRafał Miłecki 43312bb508bSRafał Miłecki napi_schedule(&ring->napi); 4349d61d138SRafał Miłecki 4359d61d138SRafał Miłecki return IRQ_HANDLED; 4369d61d138SRafał Miłecki } 4379d61d138SRafał Miłecki 4389d61d138SRafał Miłecki static int bcm4908_enet_open(struct net_device *netdev) 4399d61d138SRafał Miłecki { 4409d61d138SRafał Miłecki struct bcm4908_enet *enet = netdev_priv(netdev); 44112bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *tx_ring = &enet->tx_ring; 44212bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *rx_ring = &enet->rx_ring; 4439d61d138SRafał Miłecki struct device *dev = enet->dev; 4449d61d138SRafał Miłecki int err; 4459d61d138SRafał Miłecki 4469d61d138SRafał Miłecki err = request_irq(netdev->irq, bcm4908_enet_irq_handler, 0, "enet", enet); 4479d61d138SRafał Miłecki if (err) { 4489d61d138SRafał Miłecki dev_err(dev, "Failed to request IRQ %d: %d\n", netdev->irq, err); 4499d61d138SRafał Miłecki return err; 4509d61d138SRafał Miłecki } 4519d61d138SRafał Miłecki 45212bb508bSRafał Miłecki if (enet->irq_tx > 0) { 45312bb508bSRafał Miłecki err = request_irq(enet->irq_tx, bcm4908_enet_irq_handler, 0, 45412bb508bSRafał Miłecki "tx", enet); 45512bb508bSRafał Miłecki if (err) { 45612bb508bSRafał Miłecki dev_err(dev, "Failed to request IRQ %d: %d\n", 45712bb508bSRafał Miłecki enet->irq_tx, err); 45812bb508bSRafał Miłecki free_irq(netdev->irq, enet); 45912bb508bSRafał Miłecki return err; 46012bb508bSRafał Miłecki } 46112bb508bSRafał Miłecki } 46212bb508bSRafał Miłecki 4639d61d138SRafał Miłecki bcm4908_enet_gmac_init(enet); 4649d61d138SRafał Miłecki bcm4908_enet_dma_reset(enet); 4659d61d138SRafał Miłecki bcm4908_enet_dma_init(enet); 4669d61d138SRafał Miłecki 4679d61d138SRafał Miłecki enet_umac_set(enet, UMAC_CMD, CMD_TX_EN | CMD_RX_EN); 4689d61d138SRafał Miłecki 4699d61d138SRafał Miłecki enet_set(enet, ENET_DMA_CONTROLLER_CFG, ENET_DMA_CTRL_CFG_MASTER_EN); 4709d61d138SRafał Miłecki enet_maskset(enet, ENET_DMA_CONTROLLER_CFG, ENET_DMA_CTRL_CFG_FLOWC_CH1_EN, 0); 4719d61d138SRafał Miłecki 47212bb508bSRafał Miłecki if (enet->irq_tx > 0) { 47312bb508bSRafał Miłecki napi_enable(&tx_ring->napi); 47412bb508bSRafał Miłecki bcm4908_enet_dma_ring_intrs_ack(enet, tx_ring); 47512bb508bSRafał Miłecki bcm4908_enet_dma_ring_intrs_on(enet, tx_ring); 47612bb508bSRafał Miłecki } 47712bb508bSRafał Miłecki 47812bb508bSRafał Miłecki bcm4908_enet_dma_rx_ring_enable(enet, rx_ring); 47912bb508bSRafał Miłecki napi_enable(&rx_ring->napi); 4809d61d138SRafał Miłecki netif_carrier_on(netdev); 4819d61d138SRafał Miłecki netif_start_queue(netdev); 48212bb508bSRafał Miłecki bcm4908_enet_dma_ring_intrs_ack(enet, rx_ring); 48312bb508bSRafał Miłecki bcm4908_enet_dma_ring_intrs_on(enet, rx_ring); 4849d61d138SRafał Miłecki 4859d61d138SRafał Miłecki return 0; 4869d61d138SRafał Miłecki } 4879d61d138SRafał Miłecki 4889d61d138SRafał Miłecki static int bcm4908_enet_stop(struct net_device *netdev) 4899d61d138SRafał Miłecki { 4909d61d138SRafał Miłecki struct bcm4908_enet *enet = netdev_priv(netdev); 49112bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *tx_ring = &enet->tx_ring; 49212bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *rx_ring = &enet->rx_ring; 4939d61d138SRafał Miłecki 4949d61d138SRafał Miłecki netif_stop_queue(netdev); 4959d61d138SRafał Miłecki netif_carrier_off(netdev); 49612bb508bSRafał Miłecki napi_disable(&rx_ring->napi); 49712bb508bSRafał Miłecki napi_disable(&tx_ring->napi); 4989d61d138SRafał Miłecki 4999d61d138SRafał Miłecki bcm4908_enet_dma_rx_ring_disable(enet, &enet->rx_ring); 5009d61d138SRafał Miłecki bcm4908_enet_dma_tx_ring_disable(enet, &enet->tx_ring); 5019d61d138SRafał Miłecki 5029d61d138SRafał Miłecki bcm4908_enet_dma_uninit(enet); 5039d61d138SRafał Miłecki 50412bb508bSRafał Miłecki free_irq(enet->irq_tx, enet); 5059d61d138SRafał Miłecki free_irq(enet->netdev->irq, enet); 5069d61d138SRafał Miłecki 5079d61d138SRafał Miłecki return 0; 5089d61d138SRafał Miłecki } 5099d61d138SRafał Miłecki 5109d61d138SRafał Miłecki static int bcm4908_enet_start_xmit(struct sk_buff *skb, struct net_device *netdev) 5119d61d138SRafał Miłecki { 5129d61d138SRafał Miłecki struct bcm4908_enet *enet = netdev_priv(netdev); 5139d61d138SRafał Miłecki struct bcm4908_enet_dma_ring *ring = &enet->tx_ring; 5149d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_slot *slot; 5159d61d138SRafał Miłecki struct device *dev = enet->dev; 5169d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_bd *buf_desc; 5179d61d138SRafał Miłecki int free_buf_descs; 5189d61d138SRafał Miłecki u32 tmp; 5199d61d138SRafał Miłecki 5209d61d138SRafał Miłecki /* Free transmitted skbs */ 52112bb508bSRafał Miłecki if (enet->irq_tx < 0 && 52212bb508bSRafał Miłecki !(le32_to_cpu(ring->buf_desc[ring->read_idx].ctl) & DMA_CTL_STATUS_OWN)) 52312bb508bSRafał Miłecki napi_schedule(&enet->tx_ring.napi); 5249d61d138SRafał Miłecki 5259d61d138SRafał Miłecki /* Don't use the last empty buf descriptor */ 5269d61d138SRafał Miłecki if (ring->read_idx <= ring->write_idx) 5279d61d138SRafał Miłecki free_buf_descs = ring->read_idx - ring->write_idx + ring->length; 5289d61d138SRafał Miłecki else 5299d61d138SRafał Miłecki free_buf_descs = ring->read_idx - ring->write_idx; 53012bb508bSRafał Miłecki if (free_buf_descs < 2) { 53112bb508bSRafał Miłecki netif_stop_queue(netdev); 5329d61d138SRafał Miłecki return NETDEV_TX_BUSY; 53312bb508bSRafał Miłecki } 5349d61d138SRafał Miłecki 5359d61d138SRafał Miłecki /* Hardware removes OWN bit after sending data */ 5369d61d138SRafał Miłecki buf_desc = &ring->buf_desc[ring->write_idx]; 5379d61d138SRafał Miłecki if (unlikely(le32_to_cpu(buf_desc->ctl) & DMA_CTL_STATUS_OWN)) { 5389d61d138SRafał Miłecki netif_stop_queue(netdev); 5399d61d138SRafał Miłecki return NETDEV_TX_BUSY; 5409d61d138SRafał Miłecki } 5419d61d138SRafał Miłecki 5429d61d138SRafał Miłecki slot = &ring->slots[ring->write_idx]; 5439d61d138SRafał Miłecki slot->skb = skb; 5449d61d138SRafał Miłecki slot->len = skb->len; 5459d61d138SRafał Miłecki slot->dma_addr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE); 5469d61d138SRafał Miłecki if (unlikely(dma_mapping_error(dev, slot->dma_addr))) 5479d61d138SRafał Miłecki return NETDEV_TX_BUSY; 5489d61d138SRafał Miłecki 5499d61d138SRafał Miłecki tmp = skb->len << DMA_CTL_LEN_DESC_BUFLENGTH_SHIFT; 5509d61d138SRafał Miłecki tmp |= DMA_CTL_STATUS_OWN; 5519d61d138SRafał Miłecki tmp |= DMA_CTL_STATUS_SOP; 5529d61d138SRafał Miłecki tmp |= DMA_CTL_STATUS_EOP; 5539d61d138SRafał Miłecki tmp |= DMA_CTL_STATUS_APPEND_CRC; 5549d61d138SRafał Miłecki if (ring->write_idx + 1 == ring->length - 1) 5559d61d138SRafał Miłecki tmp |= DMA_CTL_STATUS_WRAP; 5569d61d138SRafał Miłecki 5579d61d138SRafał Miłecki buf_desc->addr = cpu_to_le32((uint32_t)slot->dma_addr); 5589d61d138SRafał Miłecki buf_desc->ctl = cpu_to_le32(tmp); 5599d61d138SRafał Miłecki 560e3948811SRafał Miłecki bcm4908_enet_dma_tx_ring_enable(enet, &enet->tx_ring); 5619d61d138SRafał Miłecki 5629d61d138SRafał Miłecki if (++ring->write_idx == ring->length - 1) 5639d61d138SRafał Miłecki ring->write_idx = 0; 5649d61d138SRafał Miłecki enet->netdev->stats.tx_bytes += skb->len; 5659d61d138SRafał Miłecki enet->netdev->stats.tx_packets++; 5669d61d138SRafał Miłecki 5679d61d138SRafał Miłecki return NETDEV_TX_OK; 5689d61d138SRafał Miłecki } 5699d61d138SRafał Miłecki 57012bb508bSRafał Miłecki static int bcm4908_enet_poll_rx(struct napi_struct *napi, int weight) 5719d61d138SRafał Miłecki { 57212bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *rx_ring = container_of(napi, struct bcm4908_enet_dma_ring, napi); 57312bb508bSRafał Miłecki struct bcm4908_enet *enet = container_of(rx_ring, struct bcm4908_enet, rx_ring); 5749d61d138SRafał Miłecki struct device *dev = enet->dev; 5759d61d138SRafał Miłecki int handled = 0; 5769d61d138SRafał Miłecki 5779d61d138SRafał Miłecki while (handled < weight) { 5789d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_bd *buf_desc; 5799d61d138SRafał Miłecki struct bcm4908_enet_dma_ring_slot slot; 5809d61d138SRafał Miłecki u32 ctl; 5819d61d138SRafał Miłecki int len; 5829d61d138SRafał Miłecki int err; 5839d61d138SRafał Miłecki 5849d61d138SRafał Miłecki buf_desc = &enet->rx_ring.buf_desc[enet->rx_ring.read_idx]; 5859d61d138SRafał Miłecki ctl = le32_to_cpu(buf_desc->ctl); 5869d61d138SRafał Miłecki if (ctl & DMA_CTL_STATUS_OWN) 5879d61d138SRafał Miłecki break; 5889d61d138SRafał Miłecki 5899d61d138SRafał Miłecki slot = enet->rx_ring.slots[enet->rx_ring.read_idx]; 5909d61d138SRafał Miłecki 5919d61d138SRafał Miłecki /* Provide new buffer before unpinning the old one */ 5929d61d138SRafał Miłecki err = bcm4908_enet_dma_alloc_rx_buf(enet, enet->rx_ring.read_idx); 5939d61d138SRafał Miłecki if (err) 5949d61d138SRafał Miłecki break; 5959d61d138SRafał Miłecki 5969d61d138SRafał Miłecki if (++enet->rx_ring.read_idx == enet->rx_ring.length) 5979d61d138SRafał Miłecki enet->rx_ring.read_idx = 0; 5989d61d138SRafał Miłecki 5999d61d138SRafał Miłecki len = (ctl & DMA_CTL_LEN_DESC_BUFLENGTH) >> DMA_CTL_LEN_DESC_BUFLENGTH_SHIFT; 6009d61d138SRafał Miłecki 60114b3b46aSRafał Miłecki if (len < ETH_ZLEN || 6029d61d138SRafał Miłecki (ctl & (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) != (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) { 6034dc7f09bSRafał Miłecki kfree_skb(slot.skb); 6049d61d138SRafał Miłecki enet->netdev->stats.rx_dropped++; 6059d61d138SRafał Miłecki break; 6069d61d138SRafał Miłecki } 6079d61d138SRafał Miłecki 6089d61d138SRafał Miłecki dma_unmap_single(dev, slot.dma_addr, slot.len, DMA_FROM_DEVICE); 6099d61d138SRafał Miłecki 610195e2d9fSRafał Miłecki skb_put(slot.skb, len - ETH_FCS_LEN); 6119d61d138SRafał Miłecki slot.skb->protocol = eth_type_trans(slot.skb, enet->netdev); 6129d61d138SRafał Miłecki netif_receive_skb(slot.skb); 6139d61d138SRafał Miłecki 6149d61d138SRafał Miłecki enet->netdev->stats.rx_packets++; 6159d61d138SRafał Miłecki enet->netdev->stats.rx_bytes += len; 6164d9274ceSRafał Miłecki 6174d9274ceSRafał Miłecki handled++; 6189d61d138SRafał Miłecki } 6199d61d138SRafał Miłecki 6209d61d138SRafał Miłecki if (handled < weight) { 6219d61d138SRafał Miłecki napi_complete_done(napi, handled); 62212bb508bSRafał Miłecki bcm4908_enet_dma_ring_intrs_on(enet, rx_ring); 6239d61d138SRafał Miłecki } 6249d61d138SRafał Miłecki 625d313d16bSRafał Miłecki /* Hardware could disable ring if it run out of descriptors */ 626d313d16bSRafał Miłecki bcm4908_enet_dma_rx_ring_enable(enet, &enet->rx_ring); 627d313d16bSRafał Miłecki 6289d61d138SRafał Miłecki return handled; 6299d61d138SRafał Miłecki } 6309d61d138SRafał Miłecki 63112bb508bSRafał Miłecki static int bcm4908_enet_poll_tx(struct napi_struct *napi, int weight) 63212bb508bSRafał Miłecki { 63312bb508bSRafał Miłecki struct bcm4908_enet_dma_ring *tx_ring = container_of(napi, struct bcm4908_enet_dma_ring, napi); 63412bb508bSRafał Miłecki struct bcm4908_enet *enet = container_of(tx_ring, struct bcm4908_enet, tx_ring); 63512bb508bSRafał Miłecki struct bcm4908_enet_dma_ring_bd *buf_desc; 63612bb508bSRafał Miłecki struct bcm4908_enet_dma_ring_slot *slot; 63712bb508bSRafał Miłecki struct device *dev = enet->dev; 63812bb508bSRafał Miłecki unsigned int bytes = 0; 63912bb508bSRafał Miłecki int handled = 0; 64012bb508bSRafał Miłecki 64112bb508bSRafał Miłecki while (handled < weight && tx_ring->read_idx != tx_ring->write_idx) { 64212bb508bSRafał Miłecki buf_desc = &tx_ring->buf_desc[tx_ring->read_idx]; 64312bb508bSRafał Miłecki if (le32_to_cpu(buf_desc->ctl) & DMA_CTL_STATUS_OWN) 64412bb508bSRafał Miłecki break; 64512bb508bSRafał Miłecki slot = &tx_ring->slots[tx_ring->read_idx]; 64612bb508bSRafał Miłecki 64712bb508bSRafał Miłecki dma_unmap_single(dev, slot->dma_addr, slot->len, DMA_TO_DEVICE); 64812bb508bSRafał Miłecki dev_kfree_skb(slot->skb); 64912bb508bSRafał Miłecki bytes += slot->len; 65012bb508bSRafał Miłecki if (++tx_ring->read_idx == tx_ring->length) 65112bb508bSRafał Miłecki tx_ring->read_idx = 0; 65212bb508bSRafał Miłecki 65312bb508bSRafał Miłecki handled++; 65412bb508bSRafał Miłecki } 65512bb508bSRafał Miłecki 65612bb508bSRafał Miłecki if (handled < weight) { 65712bb508bSRafał Miłecki napi_complete_done(napi, handled); 65812bb508bSRafał Miłecki bcm4908_enet_dma_ring_intrs_on(enet, tx_ring); 65912bb508bSRafał Miłecki } 66012bb508bSRafał Miłecki 66112bb508bSRafał Miłecki if (netif_queue_stopped(enet->netdev)) 66212bb508bSRafał Miłecki netif_wake_queue(enet->netdev); 66312bb508bSRafał Miłecki 66412bb508bSRafał Miłecki return handled; 66512bb508bSRafał Miłecki } 66612bb508bSRafał Miłecki 66714b3b46aSRafał Miłecki static int bcm4908_enet_change_mtu(struct net_device *netdev, int new_mtu) 66814b3b46aSRafał Miłecki { 66914b3b46aSRafał Miłecki struct bcm4908_enet *enet = netdev_priv(netdev); 67014b3b46aSRafał Miłecki 67114b3b46aSRafał Miłecki bcm4908_enet_set_mtu(enet, new_mtu); 67214b3b46aSRafał Miłecki 67314b3b46aSRafał Miłecki return 0; 67414b3b46aSRafał Miłecki } 67514b3b46aSRafał Miłecki 676e3948811SRafał Miłecki static const struct net_device_ops bcm4908_enet_netdev_ops = { 6779d61d138SRafał Miłecki .ndo_open = bcm4908_enet_open, 6789d61d138SRafał Miłecki .ndo_stop = bcm4908_enet_stop, 6799d61d138SRafał Miłecki .ndo_start_xmit = bcm4908_enet_start_xmit, 6809d61d138SRafał Miłecki .ndo_set_mac_address = eth_mac_addr, 68114b3b46aSRafał Miłecki .ndo_change_mtu = bcm4908_enet_change_mtu, 6829d61d138SRafał Miłecki }; 6839d61d138SRafał Miłecki 6849d61d138SRafał Miłecki static int bcm4908_enet_probe(struct platform_device *pdev) 6859d61d138SRafał Miłecki { 6869d61d138SRafał Miłecki struct device *dev = &pdev->dev; 6879d61d138SRafał Miłecki struct net_device *netdev; 6889d61d138SRafał Miłecki struct bcm4908_enet *enet; 6899d61d138SRafał Miłecki int err; 6909d61d138SRafał Miłecki 6919d61d138SRafał Miłecki netdev = devm_alloc_etherdev(dev, sizeof(*enet)); 6929d61d138SRafał Miłecki if (!netdev) 6939d61d138SRafał Miłecki return -ENOMEM; 6949d61d138SRafał Miłecki 6959d61d138SRafał Miłecki enet = netdev_priv(netdev); 6969d61d138SRafał Miłecki enet->dev = dev; 6979d61d138SRafał Miłecki enet->netdev = netdev; 6989d61d138SRafał Miłecki 6999d61d138SRafał Miłecki enet->base = devm_platform_ioremap_resource(pdev, 0); 7009d61d138SRafał Miłecki if (IS_ERR(enet->base)) { 7019d61d138SRafał Miłecki dev_err(dev, "Failed to map registers: %ld\n", PTR_ERR(enet->base)); 7029d61d138SRafał Miłecki return PTR_ERR(enet->base); 7039d61d138SRafał Miłecki } 7049d61d138SRafał Miłecki 7059d61d138SRafał Miłecki netdev->irq = platform_get_irq_byname(pdev, "rx"); 7069d61d138SRafał Miłecki if (netdev->irq < 0) 7079d61d138SRafał Miłecki return netdev->irq; 7089d61d138SRafał Miłecki 70912bb508bSRafał Miłecki enet->irq_tx = platform_get_irq_byname(pdev, "tx"); 71012bb508bSRafał Miłecki 7119d61d138SRafał Miłecki dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); 7129d61d138SRafał Miłecki 7139d61d138SRafał Miłecki err = bcm4908_enet_dma_alloc(enet); 7149d61d138SRafał Miłecki if (err) 7159d61d138SRafał Miłecki return err; 7169d61d138SRafał Miłecki 7179d61d138SRafał Miłecki SET_NETDEV_DEV(netdev, &pdev->dev); 71883216e39SMichael Walle err = of_get_mac_address(dev->of_node, netdev->dev_addr); 71983216e39SMichael Walle if (err) 7209d61d138SRafał Miłecki eth_hw_addr_random(netdev); 721e3948811SRafał Miłecki netdev->netdev_ops = &bcm4908_enet_netdev_ops; 7229d61d138SRafał Miłecki netdev->min_mtu = ETH_ZLEN; 72314b3b46aSRafał Miłecki netdev->mtu = ETH_DATA_LEN; 7249d61d138SRafał Miłecki netdev->max_mtu = ENET_MTU_MAX; 72512bb508bSRafał Miłecki netif_tx_napi_add(netdev, &enet->tx_ring.napi, bcm4908_enet_poll_tx, NAPI_POLL_WEIGHT); 72612bb508bSRafał Miłecki netif_napi_add(netdev, &enet->rx_ring.napi, bcm4908_enet_poll_rx, NAPI_POLL_WEIGHT); 7279d61d138SRafał Miłecki 7289d61d138SRafał Miłecki err = register_netdev(netdev); 7299d61d138SRafał Miłecki if (err) { 7309d61d138SRafał Miłecki bcm4908_enet_dma_free(enet); 7319d61d138SRafał Miłecki return err; 7329d61d138SRafał Miłecki } 7339d61d138SRafał Miłecki 7349d61d138SRafał Miłecki platform_set_drvdata(pdev, enet); 7359d61d138SRafał Miłecki 7369d61d138SRafał Miłecki return 0; 7379d61d138SRafał Miłecki } 7389d61d138SRafał Miłecki 7399d61d138SRafał Miłecki static int bcm4908_enet_remove(struct platform_device *pdev) 7409d61d138SRafał Miłecki { 7419d61d138SRafał Miłecki struct bcm4908_enet *enet = platform_get_drvdata(pdev); 7429d61d138SRafał Miłecki 7439d61d138SRafał Miłecki unregister_netdev(enet->netdev); 74412bb508bSRafał Miłecki netif_napi_del(&enet->rx_ring.napi); 74512bb508bSRafał Miłecki netif_napi_del(&enet->tx_ring.napi); 7469d61d138SRafał Miłecki bcm4908_enet_dma_free(enet); 7479d61d138SRafał Miłecki 7489d61d138SRafał Miłecki return 0; 7499d61d138SRafał Miłecki } 7509d61d138SRafał Miłecki 7519d61d138SRafał Miłecki static const struct of_device_id bcm4908_enet_of_match[] = { 7529d61d138SRafał Miłecki { .compatible = "brcm,bcm4908-enet"}, 7539d61d138SRafał Miłecki {}, 7549d61d138SRafał Miłecki }; 7559d61d138SRafał Miłecki 7569d61d138SRafał Miłecki static struct platform_driver bcm4908_enet_driver = { 7579d61d138SRafał Miłecki .driver = { 7589d61d138SRafał Miłecki .name = "bcm4908_enet", 7599d61d138SRafał Miłecki .of_match_table = bcm4908_enet_of_match, 7609d61d138SRafał Miłecki }, 7619d61d138SRafał Miłecki .probe = bcm4908_enet_probe, 7629d61d138SRafał Miłecki .remove = bcm4908_enet_remove, 7639d61d138SRafał Miłecki }; 7649d61d138SRafał Miłecki module_platform_driver(bcm4908_enet_driver); 7659d61d138SRafał Miłecki 7669d61d138SRafał Miłecki MODULE_LICENSE("GPL v2"); 7679d61d138SRafał Miłecki MODULE_DEVICE_TABLE(of, bcm4908_enet_of_match); 768