embox
268 строк · 7.7 Кб
1/**
2* @file cadence_gem.c
3*
4* @date 06.03.20
5* @author: Nastya Nizharadze
6*
7* Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
8*/
9
10#include <errno.h>11#include <stdint.h>12#include <util/log.h>13
14#include <kernel/irq.h>15#include <net/skbuff.h>16#include <net/l0/net_entry.h>17#include <net/l2/ethernet.h>18#include <net/inetdevice.h>19#include <net/util/show_packet.h>20#include <asm/regs.h>21#include <string.h>22
23#include <embox/unit.h>24#include <net/skbuff.h>25#include <net/netdevice.h>26#include <asm/io.h>27#include <hal/reg.h>28
29#include <stdio.h>30#include <kernel/printk.h>31
32#define BASE_ADDR OPTION_GET(NUMBER,base_addr)33#define SIFIVE_U_GEM_IRQ OPTION_GET(NUMBER,irq_num)34
35#define GEM_NWCTRL 0x00000000 /* Network Control */36#define GEM_NWCFG 0x00000004 /* Network Config */37#define GEM_NWSTATUS 0x00000008 /* Network Status */38#define GEM_USERIO 0x0000000C /* User IO */39#define GEM_DMACFG 0x00000010 /* DMA Control */40#define GEM_TXSTATUS 0x00000014 /* TX Status */41#define GEM_RXQBASE 0x00000018 /* RX Q Base address */42#define GEM_TXQBASE 0x0000001C /* TX Q Base address */43#define GEM_RXSTATUS 0x00000020 /* RX Status */44#define GEM_ISR 0x00000024 /* Interrupt Status */45#define GEM_IER 0x00000028 /* Interrupt Enable */46#define GEM_IDR 0x0000002C /* Interrupt Disable */47#define GEM_IMR 0x00000030 /* Interrupt Mask */48#define GEM_PHYMNTNC 0x00000034 /* Phy Maintenance */49
50#define GEM_SPADDR1LO 0x00000088 /* Specific addr 1 low reg */51#define GEM_SPADDR1HI 0x0000008C /* Specific addr 1 high reg */52
53#define GEM_TXSTATUS_TXCMPL 0x00000020 /* Transmit Complete */54#define GEM_TXSTATUS_USED 0x0000000155
56#define GEM_NWCTRL_TXENA 0x00000008 /* Transmit Enable */57#define GEM_NWCTRL_TXSTART 0x00000200 /* Transmit Enable */58#define GEM_NWCTRL_RXENA 0x00000004 /* Receive Enable */59
60#define GEM_NWCFG_STRIP_FCS 0x00020000 /* Strip FCS field */61
62#define DESC_1_USED 0x8000000063#define DESC_1_LENGTH 0x00001FFF64
65#define DESC_1_TX_WRAP 0x4000000066#define DESC_1_TX_LAST 0x0000800067
68#define DESC_0_RX_WRAP 0x0000000269#define DESC_0_RX_OWNERSHIP 0x0000000170
71#define GEM_INT_TXCMPL 0x00000080 /* Transmit Complete */72#define GEM_INT_TXUSED 0x0000000873#define GEM_INT_RXUSED 0x0000000474#define GEM_INT_RXCMPL 0x0000000275
76#define GEM_TXDESC_LAST_BUF (1 << 15) /* last in frame */77#define GEM_TXDESC_USED (1U << 31) /* done txmitting */78#define GEM_TXDESC_WRAP (1 << 30) /* end descr ring */79#define GEM_RXDESC_EOF (1 << 15) /* end of frame */80#define GEM_RXDESC_SOF (1 << 14) /* start of frame */81#define GEM_INTR_STAT 0x024 /* Interrupt Status */82#define GEM_RX_STAT 0x020 /* Receive Status */83#define GEM_DMA_CFG_RX_BUF_SIZE(sz) ((((sz) + 63) / 64) << 16)84
85#define MAX_BUFF_SIZE 160086
87int fst_xmit = 0;88
89struct dma_desc_rx {90uint32_t addr;91uint32_t flags;92} dma_desc_rx __attribute__((aligned(4)));93
94struct dma_desc_tx {95uint32_t addr;96uint32_t flags;97} dma_desc_tx __attribute__((aligned(4)));98
99
100unsigned char rx_buff[MAX_BUFF_SIZE] __attribute__((aligned(4)));101unsigned char tx_buff[MAX_BUFF_SIZE] __attribute__((aligned(4)));102
103static int cadence_gem_xmit(struct net_device *dev, struct sk_buff *skb) {104uint32_t net_control;105uint32_t tx_stat;106
107tx_stat = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_TXSTATUS);108tx_stat |= GEM_TXSTATUS_TXCMPL;109REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_TXSTATUS), tx_stat);110
111memset(tx_buff, 0, sizeof(char) * MAX_BUFF_SIZE);112memcpy(tx_buff, skb->mac.raw, skb->len);113
114dma_desc_tx.addr = (uint32_t) tx_buff;115dma_desc_tx.flags &= 0xffffc000;116dma_desc_tx.flags |= (skb->len);117
118dma_desc_tx.flags |= GEM_TXDESC_LAST_BUF;119dma_desc_tx.flags &= ~GEM_TXDESC_USED;120
121//show_packet(skb->mac.raw, skb->len, "xmit");122
123net_control = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL);124net_control |= GEM_NWCTRL_TXSTART;125REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL), net_control);126
127skb_free(skb);128return 0;129}
130
131static void program_dma_cfg(void) {132uint32_t val = 0;133
134val |= GEM_DMA_CFG_RX_BUF_SIZE(MAX_BUFF_SIZE);135REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_DMACFG), val);136}
137
138static int cadence_gem_start(struct net_device *dev) {139uint32_t net_control;140uint32_t net_config;141uint32_t net_ier;142unsigned char mac_addr[6] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x02};143
144program_dma_cfg();145
146REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_SPADDR1LO), (uint32_t)*(uint32_t *)mac_addr);147REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_SPADDR1HI), (uint16_t)*(uint16_t *)(mac_addr + 4));148
149dma_desc_tx.flags = DESC_1_USED & DESC_1_TX_WRAP & DESC_1_TX_LAST;150dma_desc_tx.addr = 0;151dma_desc_tx.flags = 0;152dma_desc_tx.flags = (0u << 31) | GEM_TXDESC_WRAP;153
154dma_desc_rx.addr = (uint32_t)rx_buff | DESC_0_RX_WRAP;155dma_desc_rx.flags = 0;156
157net_config = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCFG);158net_config |= GEM_NWCFG_STRIP_FCS;159REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCFG), net_config);160
161REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_RXQBASE), (uint32_t)&dma_desc_rx);162REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_TXQBASE), (uint32_t)&dma_desc_tx);163
164net_ier =REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_IER);165net_ier |= GEM_INT_TXCMPL | GEM_INT_TXUSED | GEM_INT_RXUSED | GEM_INT_RXCMPL;166REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_IER), net_ier);167
168net_control = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL);169net_control |= GEM_NWCTRL_TXENA;170net_control |= GEM_NWCTRL_RXENA;171REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL), net_control);172
173return 0;174}
175
176static int cadence_gem_set_macaddr(struct net_device *dev, const void *addr) {177return 0;178}
179
180static const struct net_driver cadence_gem_drv_ops = {181.xmit = cadence_gem_xmit,182.start = cadence_gem_start,183.set_macaddr = cadence_gem_set_macaddr184};185
186static int cadence_gem_rx(struct net_device *dev) {187uint32_t net_control;188struct sk_buff *skb;189
190if (!(dma_desc_rx.addr & DESC_0_RX_OWNERSHIP)){191dma_desc_tx.flags &= ~DESC_1_LENGTH;192dma_desc_rx.addr &= ~DESC_0_RX_OWNERSHIP;193return 0;194}195
196uint32_t ctl = dma_desc_rx.flags;197if ((ctl & (GEM_RXDESC_SOF | GEM_RXDESC_EOF)) !=198(GEM_RXDESC_SOF | GEM_RXDESC_EOF)) {199return 0;200}201
202skb = skb_alloc(dma_desc_rx.flags & DESC_1_LENGTH);203
204if (!skb) {205dev->stats.rx_dropped++;206return -ENOMEM;207}208
209skb->len = (dma_desc_rx.flags & DESC_1_LENGTH);210
211memcpy(skb->mac.raw, rx_buff, skb->len);212
213dma_desc_rx.addr = (uint32_t)rx_buff | DESC_0_RX_WRAP;214dma_desc_tx.flags &= ~DESC_1_LENGTH;215
216net_control = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL);217net_control |= GEM_NWCTRL_RXENA;218REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL), net_control);219
220//show_packet(skb->mac.raw, skb->len, "rx");221skb->dev = dev;222netif_rx(skb);223
224dev->stats.rx_packets++;225dev->stats.rx_bytes += skb->len;226
227return 0;228}
229
230static irq_return_t cadence_gem_interrupt_handler(unsigned int irq,231void *dev_id) {232struct net_device *dev = dev_id;233uint32_t istatus;234
235/* Read and clear registers */236istatus = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_INTR_STAT);237REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_INTR_STAT), istatus);238REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_RX_STAT), istatus);239REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_RX_STAT), 0xf);240
241cadence_gem_rx(dev);242
243return 0;244}
245
246static int cadence_gem_init(void) {247struct net_device *netdev;248int err;249
250netdev = etherdev_alloc(0);251if (!netdev) {252return -ENOMEM;253}254
255netdev->base_addr = BASE_ADDR;256netdev->irq = SIFIVE_U_GEM_IRQ;257netdev->drv_ops = &cadence_gem_drv_ops;258
259err = irq_attach(SIFIVE_U_GEM_IRQ, cadence_gem_interrupt_handler,2600, netdev, "cadence_gem");261if (err) {262return err;263}264
265return inetdev_register_dev(netdev);266}
267
268EMBOX_UNIT_INIT(cadence_gem_init);269