embox

Форк
0
/
cadence_gem.c 
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      0x00000001
55

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		0x80000000
63
#define DESC_1_LENGTH	0x00001FFF
64

65
#define DESC_1_TX_WRAP	0x40000000
66
#define DESC_1_TX_LAST	0x00008000
67

68
#define DESC_0_RX_WRAP		0x00000002
69
#define DESC_0_RX_OWNERSHIP	0x00000001
70

71
#define GEM_INT_TXCMPL	0x00000080 /* Transmit Complete */
72
#define GEM_INT_TXUSED	0x00000008
73
#define GEM_INT_RXUSED	0x00000004
74
#define GEM_INT_RXCMPL	0x00000002
75

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 1600
86

87
int fst_xmit = 0;
88

89
struct dma_desc_rx {
90
	uint32_t addr;
91
	uint32_t flags;
92
} dma_desc_rx __attribute__((aligned(4)));
93

94
struct dma_desc_tx {
95
	uint32_t addr;
96
	uint32_t flags;
97
} dma_desc_tx __attribute__((aligned(4)));
98

99

100
unsigned char rx_buff[MAX_BUFF_SIZE] __attribute__((aligned(4)));
101
unsigned char tx_buff[MAX_BUFF_SIZE] __attribute__((aligned(4)));
102

103
static int cadence_gem_xmit(struct net_device *dev, struct sk_buff *skb) {
104
  uint32_t net_control;
105
  uint32_t tx_stat;
106

107
  tx_stat = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_TXSTATUS);
108
  tx_stat |= GEM_TXSTATUS_TXCMPL;
109
  REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_TXSTATUS), tx_stat);
110

111
  memset(tx_buff, 0, sizeof(char) * MAX_BUFF_SIZE);
112
  memcpy(tx_buff, skb->mac.raw, skb->len);
113

114
  dma_desc_tx.addr = (uint32_t) tx_buff;
115
  dma_desc_tx.flags &= 0xffffc000;
116
  dma_desc_tx.flags |= (skb->len);
117

118
  dma_desc_tx.flags |= GEM_TXDESC_LAST_BUF;
119
  dma_desc_tx.flags &= ~GEM_TXDESC_USED;
120

121
  //show_packet(skb->mac.raw, skb->len, "xmit");
122

123
  net_control = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL);
124
  net_control |= GEM_NWCTRL_TXSTART;
125
  REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL), net_control);
126

127
  skb_free(skb);
128
  return 0;
129
}
130

131
static void program_dma_cfg(void) {
132
	uint32_t val = 0;
133

134
	val |= GEM_DMA_CFG_RX_BUF_SIZE(MAX_BUFF_SIZE);
135
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_DMACFG), val);
136
}
137

138
static int cadence_gem_start(struct net_device *dev) {
139
	uint32_t net_control;
140
	uint32_t net_config;
141
	uint32_t net_ier;
142
	unsigned char mac_addr[6] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x02};
143

144
	program_dma_cfg();
145

146
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_SPADDR1LO), (uint32_t)*(uint32_t *)mac_addr);
147
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_SPADDR1HI), (uint16_t)*(uint16_t *)(mac_addr + 4));
148

149
	dma_desc_tx.flags = DESC_1_USED & DESC_1_TX_WRAP & DESC_1_TX_LAST;
150
	dma_desc_tx.addr = 0;
151
	dma_desc_tx.flags = 0;
152
	dma_desc_tx.flags = (0u << 31) | GEM_TXDESC_WRAP;
153

154
	dma_desc_rx.addr = (uint32_t)rx_buff | DESC_0_RX_WRAP;
155
	dma_desc_rx.flags = 0;
156

157
	net_config = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCFG);
158
	net_config |= GEM_NWCFG_STRIP_FCS;
159
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCFG), net_config);
160

161
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_RXQBASE), (uint32_t)&dma_desc_rx);
162
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_TXQBASE), (uint32_t)&dma_desc_tx);
163

164
	net_ier =REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_IER);
165
	net_ier |= GEM_INT_TXCMPL | GEM_INT_TXUSED | GEM_INT_RXUSED | GEM_INT_RXCMPL;
166
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_IER), net_ier);
167

168
	net_control = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL);
169
	net_control |= GEM_NWCTRL_TXENA;
170
	net_control |= GEM_NWCTRL_RXENA;
171
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL), net_control);
172

173
	return 0;
174
}
175

176
static int cadence_gem_set_macaddr(struct net_device *dev, const void *addr) {
177
	return 0;
178
}
179

180
static const struct net_driver cadence_gem_drv_ops = {
181
	.xmit = cadence_gem_xmit,
182
	.start = cadence_gem_start,
183
	.set_macaddr = cadence_gem_set_macaddr
184
};
185

186
static int cadence_gem_rx(struct net_device *dev) {
187
	uint32_t net_control;
188
	struct sk_buff *skb;
189

190
	if (!(dma_desc_rx.addr & DESC_0_RX_OWNERSHIP)){
191
		dma_desc_tx.flags &= ~DESC_1_LENGTH;
192
		dma_desc_rx.addr &= ~DESC_0_RX_OWNERSHIP;
193
		return 0;
194
	}
195

196
	uint32_t ctl = dma_desc_rx.flags;
197
	if ((ctl & (GEM_RXDESC_SOF | GEM_RXDESC_EOF)) !=
198
		(GEM_RXDESC_SOF | GEM_RXDESC_EOF)) {
199
		return 0;
200
	}
201

202
	skb = skb_alloc(dma_desc_rx.flags & DESC_1_LENGTH);
203

204
	if (!skb) {
205
			dev->stats.rx_dropped++;
206
			return -ENOMEM;
207
	}
208

209
	skb->len = (dma_desc_rx.flags & DESC_1_LENGTH);
210

211
	memcpy(skb->mac.raw, rx_buff, skb->len);
212

213
	dma_desc_rx.addr = (uint32_t)rx_buff | DESC_0_RX_WRAP;
214
	dma_desc_tx.flags &= ~DESC_1_LENGTH;
215

216
	net_control = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL);
217
	net_control |= GEM_NWCTRL_RXENA;
218
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_NWCTRL), net_control);
219

220
	//show_packet(skb->mac.raw, skb->len, "rx");
221
	skb->dev = dev;
222
	netif_rx(skb);
223

224
	dev->stats.rx_packets++;
225
	dev->stats.rx_bytes += skb->len;
226

227
	return 0;
228
}
229

230
static irq_return_t cadence_gem_interrupt_handler(unsigned int irq,
231
												  void *dev_id) {
232
	struct net_device *dev = dev_id;
233
	uint32_t istatus;
234

235
	/* Read and clear registers */
236
	istatus = REG32_LOAD((uint32_t)BASE_ADDR + (uint32_t)GEM_INTR_STAT);
237
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_INTR_STAT), istatus);
238
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_RX_STAT), istatus);
239
	REG32_STORE(((uint32_t)BASE_ADDR + (uint32_t)GEM_RX_STAT), 0xf);
240

241
	cadence_gem_rx(dev);
242

243
	return 0;
244
}
245

246
static int cadence_gem_init(void) {
247
	struct net_device *netdev;
248
	int err;
249

250
	netdev = etherdev_alloc(0);
251
	if (!netdev) {
252
		return -ENOMEM;
253
	}
254

255
	netdev->base_addr = BASE_ADDR;
256
	netdev->irq = SIFIVE_U_GEM_IRQ;
257
	netdev->drv_ops = &cadence_gem_drv_ops;
258

259
	err = irq_attach(SIFIVE_U_GEM_IRQ, cadence_gem_interrupt_handler, 
260
									 0, netdev, "cadence_gem");
261
	if (err) {
262
		return err;
263
	}
264

265
	return inetdev_register_dev(netdev);
266
}
267

268
EMBOX_UNIT_INIT(cadence_gem_init);
269

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.