embox

Форк
0
694 строки · 17.9 Кб
1
/**
2
 * @file
3
 * @brief Ethernet Media Access Controller for TMS320DM816x DaVinci
4
 *
5
 * @date 20.09.13
6
 * @author Ilia Vaprol
7
 */
8

9
#include <errno.h>
10
#include <unistd.h>
11
#include <stdio.h>
12
#include <string.h>
13

14
#include <embox/unit.h>
15

16
#include <hal/cache.h>
17
#include <kernel/irq.h>
18
#include <kernel/printk.h>
19
#include <hal/reg.h>
20

21
#include <mem/misc/pool.h>
22

23
#include <net/l0/net_entry.h>
24
#include <net/l2/ethernet.h>
25
#include <net/netdevice.h>
26
#include <net/inetdevice.h>
27
#include <net/skbuff.h>
28

29
#include <util/binalign.h>
30
#include <util/math.h>
31
#include <util/log.h>
32
#include <lib/libds/dlist.h>
33

34
#include <mem/vmem.h>
35
#include <hal/mmu.h>
36
#include <drivers/common/memory.h>
37

38
#include <mem/misc/pool.h>
39

40
#include "emac.h"
41
#include "emac_desc.h"
42

43
#include <framework/mod/options.h>
44

45
EMBOX_UNIT_INIT(ti816x_init);
46

47
#define MODOPS_PREP_BUFF_CNT	OPTION_GET(NUMBER, prep_buff_cnt)
48
#define RX_RING_SZ              MODOPS_PREP_BUFF_CNT
49

50
/**
51
 * EMAC0/MDIO Base Address
52
 */
53
#define EMAC_BASE	OPTION_GET(NUMBER, emac_base)
54
#define EMAC_CTRL_BASE	OPTION_GET(NUMBER, emac_ctrl_base)
55

56
/**
57
 * CPGMAC0 Interrupts
58
 */
59
#define MACRXTHR0 (OPTION_GET(NUMBER, irq_base) + 0) /* CPGMAC0 Receive threshold interrupt */
60
#define MACRXINT0 (OPTION_GET(NUMBER, irq_base) + 1) /* CPGMAC0 Receive pending interrupt */
61
#define MACTXINT0 (OPTION_GET(NUMBER, irq_base) + 2) /* CPGMAC0 Transmit pending interrupt */
62
#define MACMISC0  (OPTION_GET(NUMBER, irq_base) + 3) /* CPGMAC0 Stat, Host, MDIO LINKINT or MDIO USERINT */
63

64
#define DEFAULT_CHANNEL 0
65
#define DEFAULT_MASK    ((uint8_t)(1 << DEFAULT_CHANNEL))
66

67
#define RX_BUFF_LEN       0x800
68
#define RX_FRAME_MAX_LEN  \
69
	min(min(RX_BUFF_LEN, skb_max_size()), (ETH_FRAME_LEN + ETH_FCS_LEN))
70

71
struct emac_desc_head {
72
	uint8_t padding[64];
73
	struct emac_desc desc;
74
	uint8_t padding2[64];
75
	void *skb;
76
} __attribute__ ((aligned (0x4)));
77

78
struct ti816x_priv {
79
	volatile struct emac_desc *tx_cur_head;
80
	volatile struct emac_desc *tx_wait_head;
81
	volatile struct emac_desc *tx_wait_tail;
82
};
83

84
static struct emac_desc_head *head_from_desc(struct emac_desc *desc) {
85
	return (struct emac_desc_head *) (((char*)desc - 64));
86
}
87

88
static uint8_t emac_rx_data_buff[RX_BUFF_LEN][RX_RING_SZ] __attribute__ ((aligned (0x4)));
89
static struct emac_desc_head emac_rx_list[RX_RING_SZ];
90
POOL_DEF(emac_tx_desc_pool, struct emac_desc_head, MODOPS_PREP_BUFF_CNT + 0x1);
91

92
static struct emac_desc_head *emac_hdesc_tx_alloc(void) {
93
	ipl_t sp;
94
	struct emac_desc_head *res;
95

96
	sp = ipl_save();
97
	{
98
		res = pool_alloc(&emac_tx_desc_pool);
99
	}
100
	ipl_restore(sp);
101

102
	return res;
103
}
104

105
static void emac_hdesc_tx_free(struct emac_desc_head *obj) {
106
	ipl_t sp;
107
	assert(obj);
108

109
	sp = ipl_save();
110
	{
111
		pool_free(&emac_tx_desc_pool, obj);
112
	}
113
	ipl_restore(sp);
114
}
115

116
static void emac_desc_set_next(struct emac_desc *desc, void *next) {
117
	desc->next = (uintptr_t) next;
118
	dcache_flush(desc, sizeof(struct emac_desc));
119
}
120

121
static void ti816x_config(struct net_device *dev);
122

123
static void emac_ctrl_enable_irq(void) {
124
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMRXTHRESHINTEN, 0xff);
125
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMRXINTEN, 0xff);
126
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMTXINTEN, 0xff);
127
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMMISCINTEN, 0xf);
128
}
129

130
static void emac_ctrl_disable_irq(void) {
131
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMRXTHRESHINTEN, 0x0);
132
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMRXINTEN, 0x0);
133
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMTXINTEN, 0x0);
134
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMMISCINTEN, 0x0);
135
}
136

137
static inline void emac_ctrl_enable_pacing(void) {
138
	/* enable rx/tx pacing; set pacing period */
139
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMINTCTRL,
140
			EMAC_CMINTCTRL_C0_RX | EMAC_CMINTCTRL_C0_TX |
141
			EMAC_CMINTCTRL_INTPRESCALE(125 * 4));
142

143
	/* set maximum number of rx/tx interrupts */
144
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMRXINTMAX, EMAC_CMRXINTMAX_RXIMAX(4));
145
	REG_STORE(EMAC_CTRL_BASE + EMAC_R_CMTXINTMAX, EMAC_CMTXINTMAX_TXIMAX(4));
146
}
147

148
static void emac_eoi(int flag) {
149
	REG_STORE(EMAC_BASE + EMAC_R_MACEOIVECTOR, flag);
150

151
#if EMAC_VERSION == 1
152
	if (flag == EMAC_MACEOIVEC_TXEOI) {
153
		REG_STORE(LVL_INTR_CLEAR, 1 << 3);
154
	} else if (flag == EMAC_MACEOIVEC_RXTHRESHEOI) {
155
		REG_STORE(LVL_INTR_CLEAR, 1 << 2);
156
	} else if (flag == EMAC_MACEOIVEC_RXEOI) {
157
		REG_STORE(LVL_INTR_CLEAR, 1 << 1);
158
	} else if (flag == EMAC_MACEOIVEC_MISCEOI) {
159
		REG_STORE(LVL_INTR_CLEAR, 1 << 0);
160
	}
161
#endif
162
}
163

164
static void cm_load_mac(struct net_device *dev) {
165
	unsigned long mac_hi, mac_lo;
166

167
#if EMAC_VERSION == 0
168
	mac_hi = REG_LOAD(CM_BASE + CM_R_MACID0_HI);
169
	mac_lo = REG_LOAD(CM_BASE + CM_R_MACID0_LO);
170
#else
171
	mac_hi = 0xdeadca;
172
	mac_lo = 0xfebabe;
173
#endif
174
	assert(dev != NULL);
175
	dev->dev_addr[0] = mac_hi & 0xff;
176
	dev->dev_addr[1] = (mac_hi >> 8) & 0xff;
177
	dev->dev_addr[2] = (mac_hi >> 16) & 0xff;
178
	dev->dev_addr[3] = mac_hi >> 24;
179
	dev->dev_addr[4] = mac_lo & 0xff;
180
	dev->dev_addr[5] = mac_lo >> 8;
181
}
182

183
static void emac_reset(void) {
184
	REG_STORE(EMAC_BASE + EMAC_R_SOFTRESET, 1);
185
	while (REG_LOAD(EMAC_BASE + EMAC_R_SOFTRESET) & 1);
186
}
187

188
static void emac_clear_hdp(void) {
189
	int i;
190

191
	for (i = 0; i < EMAC_CHANNEL_COUNT; ++i) {
192
		REG_STORE(EMAC_BASE + EMAC_R_TXHDP(i), 0);
193
		REG_STORE(EMAC_BASE + EMAC_R_RXHDP(i), 0);
194
	}
195
}
196

197
static void emac_clear_ctrl_regs(void) {
198
	REG_STORE(EMAC_BASE + EMAC_R_TXCONTROL, 0);
199
	REG_STORE(EMAC_BASE + EMAC_R_RXCONTROL, 0);
200
	REG_STORE(EMAC_BASE + EMAC_R_MACCONTROL, 0);
201
}
202

203
static void emac_set_stat_regs(unsigned long v) {
204
	int i;
205

206
	for (i = 0; i < 36; ++i) {
207
		REG_STORE(EMAC_BASE + 0x200 + 0x4 * i, v);
208
	}
209
}
210

211
#define MACINDEX(x) ((x & 0x1f) << 0)
212
#define VALID (0x1 << 20)
213
#define MATCHFILT (0x1 << 19)
214
#define CHANNEL(x) ((x & 0x7) << 16)
215
static void emac_set_macaddr(unsigned char (*addr)[6]) {
216
	int i;
217
	unsigned long mac_hi, mac_lo;
218

219
	mac_hi = ((*addr)[2] << 24) | ((*addr)[3] << 16)
220
			| ((*addr)[4] << 8) | ((*addr)[5] << 0);
221
	mac_lo = ((*addr)[0] << 8) | ((*addr)[1] << 0);
222

223
	for (i = 0; i < EMAC_CHANNEL_COUNT; ++i) {
224
		REG_STORE(EMAC_BASE + EMAC_R_MACINDEX, MACINDEX(i));
225
		REG_STORE(EMAC_BASE + EMAC_R_MACADDRHI, mac_hi);
226
		REG_STORE(EMAC_BASE + EMAC_R_MACADDRLO,
227
				mac_lo | VALID | MATCHFILT | CHANNEL(i));
228
	}
229

230
	log_debug("set macaddr %06x %06x", mac_hi, mac_lo);
231

232
	REG_STORE(EMAC_BASE + EMAC_R_MACSRCADDRHI, mac_hi);
233
	REG_STORE(EMAC_BASE + EMAC_R_MACSRCADDRLO, mac_lo);
234
}
235

236
static void emac_init_rx_regs(void) {
237
	int i;
238

239
	/* disable filtering */
240
	REG_STORE(EMAC_BASE + EMAC_R_RXFILTERLOWTHRESH, 0);
241

242
	for (i = 0; i < EMAC_CHANNEL_COUNT; ++i) {
243
		REG_STORE(EMAC_BASE + EMAC_R_RXFLOWTHRESH(i), 0);
244
		REG_STORE(EMAC_BASE + EMAC_R_RXFREEBUFFER(i), MODOPS_PREP_BUFF_CNT);
245
	}
246
}
247

248
static void emac_clear_machash(void) {
249
	REG_STORE(EMAC_BASE + EMAC_R_MACHASH1, 0);
250
	REG_STORE(EMAC_BASE + EMAC_R_MACHASH2, 0);
251
}
252

253
static void emac_set_rxbufoff(unsigned long v) {
254
	REG_STORE(EMAC_BASE + EMAC_R_RXBUFFEROFFSET, v);
255
}
256

257
static void emac_clear_and_enable_rxunicast(void) {
258
	REG_STORE(EMAC_BASE + EMAC_R_RXUNICASTCLEAR, 0xff);
259
	REG_STORE(EMAC_BASE + EMAC_R_RXUNICASTSET, 0xff);
260
}
261

262
static void emac_enable_rxmbp(void) {
263
	REG_STORE(EMAC_BASE + EMAC_R_RXMBPENABLE, RXMBP_INIT);
264
}
265

266
#define GIG_FORCE (0x1 << 17)
267
#define GIG (0x1 << 7)
268
#define TXPACE (0x1 << 6)
269
#define GMIIEN (0x1 << 5)
270
#define FULLDUPLEX (0x1 << 0)
271
void emac_set_macctrl(unsigned long v) {
272
	REG_STORE(EMAC_BASE + EMAC_R_MACCONTROL, v);
273
}
274

275
static void emac_enable_rx_and_tx_irq(void) {
276
	/* mask unused channel */
277
	REG_STORE(EMAC_BASE + EMAC_R_TXINTMASKCLEAR, ~DEFAULT_MASK);
278
	REG_STORE(EMAC_BASE + EMAC_R_RXINTMASKCLEAR, ~DEFAULT_MASK);
279

280
	/* allow all rx and tx interrupts */
281
	REG_STORE(EMAC_BASE + EMAC_R_TXINTMASKSET, DEFAULT_MASK);
282
	REG_STORE(EMAC_BASE + EMAC_R_RXINTMASKSET, DEFAULT_MASK);
283

284
	/* allow host error and statistic interrupt */
285
	REG_STORE(EMAC_BASE + EMAC_R_MACINTMASKSET, EMAC_MACINT_HOSTMASK | EMAC_MACINT_STATMASK);
286
}
287

288
static void emac_enable_rx_and_tx_dma(void) {
289
	REG_STORE(EMAC_BASE + EMAC_R_RXCONTROL, EMAC_RXCONTROL_RXEN);
290
	REG_STORE(EMAC_BASE + EMAC_R_TXCONTROL, EMAC_TXCONTROL_TXEN);
291
}
292

293
static void emac_desc_build(struct emac_desc *desc, uint8_t *data,
294
		size_t data_len, size_t packet_len, int flags) {
295
	assert(desc != NULL);
296
	assert(binalign_check_bound((uintptr_t)desc, 4));
297
	assert(data_len != 0);
298
	assert(flags & EMAC_DESC_F_OWNER);
299

300
	desc->next = 0;
301
	desc->data = (uintptr_t)data;
302
	desc->data_len = data_len;
303
	desc->packet_len = packet_len;
304
	desc->data_off = 0;
305
	desc->flags = flags;
306

307
	dcache_flush(desc, sizeof(struct emac_desc));
308
}
309

310
static void emac_queue_activate(struct emac_desc *desc, uint32_t reg_hdp) {
311
	assert(desc != NULL);
312
	REG_STORE(EMAC_BASE + reg_hdp, (uintptr_t)desc);
313
	dcache_flush((void*)(EMAC_BASE + reg_hdp), sizeof (uintptr_t));
314
}
315

316
static void emac_alloc_rx_queue(struct ti816x_priv *dev_priv) {
317
	int i;
318
	assert(dev_priv);
319

320
	for (i = 0; i < RX_RING_SZ; i++) {
321
		struct emac_desc *desc;
322
		struct emac_desc *next;
323
		int idx_next = (i + 1) % RX_RING_SZ;
324

325
		desc = &emac_rx_list[i].desc;
326
		next = &emac_rx_list[idx_next].desc;
327

328
		emac_rx_list[i].skb = emac_rx_data_buff[i];
329
		emac_desc_build(desc, emac_rx_data_buff[i],
330
				RX_BUFF_LEN, 0, EMAC_DESC_F_OWNER);
331
		emac_desc_set_next(desc, next);
332
	}
333

334
	emac_queue_activate(&emac_rx_list[0].desc, EMAC_R_RXHDP(DEFAULT_CHANNEL));
335
}
336

337
static int ti816x_xmit(struct net_device *dev, struct sk_buff *skb) {
338
	size_t data_len;
339
	struct emac_desc_head *hdesc;
340
	struct emac_desc *desc;
341
	struct ti816x_priv *dev_priv;
342
	ipl_t ipl;
343

344
	hdesc = emac_hdesc_tx_alloc();
345
	if (!hdesc) {
346
		skb_free(skb);
347
		return 0;
348
	}
349
	hdesc->skb = skb;
350
	desc = &hdesc->desc;
351

352
	data_len = max(skb->len, ETH_ZLEN);
353
	dcache_flush(skb_data_cast_in(skb->data), data_len);
354

355
	emac_desc_build(desc, skb_data_cast_in(skb->data), data_len, data_len,
356
			EMAC_DESC_F_SOP | EMAC_DESC_F_EOP | EMAC_DESC_F_OWNER);
357

358
	dev_priv = netdev_priv(dev);
359
	assert(dev_priv != NULL);
360

361
	ipl = ipl_save();
362
	{
363
		if (dev_priv->tx_cur_head) {
364
			/* Add packet to the waiting queue */
365
			if (dev_priv->tx_wait_head) {
366
				emac_desc_set_next((struct emac_desc *)dev_priv->tx_wait_tail, desc);
367
			} else {
368
				dev_priv->tx_wait_head = desc;
369
			}
370
			dev_priv->tx_wait_tail = desc;
371
		} else {
372
			/* Process packet immediately */
373
			dev_priv->tx_cur_head = desc;
374
			emac_queue_activate(desc, EMAC_R_TXHDP(DEFAULT_CHANNEL));
375
		}
376
	}
377
	ipl_restore(ipl);
378

379
	return 0;
380
}
381

382
static int ti816x_set_macaddr(struct net_device *dev, const void *addr) {
383
	emac_set_macaddr((unsigned char (*)[6])addr);
384
	return 0;
385
}
386

387
static int ti816x_open(struct net_device *dev) {
388
	emac_ctrl_enable_irq();
389
	return 0;
390
}
391

392
static int ti816x_stop(struct net_device *dev) {
393
	emac_ctrl_disable_irq();
394
	return 0;
395
}
396

397
static const struct net_driver ti816x_ops = {
398
	.xmit = ti816x_xmit,
399
	.start = ti816x_open,
400
	.stop = ti816x_stop,
401
	.set_macaddr = ti816x_set_macaddr
402
};
403

404
static irq_return_t ti816x_interrupt_macrxthr0(unsigned int irq_num,
405
		void *dev_id) {
406
	assert(DEFAULT_MASK == REG_LOAD(EMAC_CTRL_BASE
407
				+ EMAC_R_CMRXTHRESHINTSTAT));
408

409
	log_debug("ti816x_interrupt_macrxthr0: unhandled interrupt");
410

411
	emac_eoi(EMAC_MACEOIVEC_RXTHRESHEOI);
412

413
	return IRQ_HANDLED;
414
}
415

416
#define CHECK_RXOK(x) \
417
	(!(~(x) & (EMAC_DESC_F_SOP | EMAC_DESC_F_EOP)))
418
#define CHECK_RXERR(x) \
419
	((x) & (EMAC_DESC_F_OWNER | EMAC_DESC_F_TDOWNCMPLT       \
420
			| EMAC_DESC_F_JABBER       \
421
			| EMAC_DESC_F_OVERSIZE | EMAC_DESC_F_FRAGMENT    \
422
			| EMAC_DESC_F_UNDERSIZED | EMAC_DESC_F_CONTROL   \
423
			| EMAC_DESC_F_OVERRUN | EMAC_DESC_F_CODEERROR    \
424
			| EMAC_DESC_F_ALIGNERROR | EMAC_DESC_F_CRCERROR))
425
#define CHECK_RXERR_2(x) \
426
	((x) & (EMAC_DESC_F_OWNER | EMAC_DESC_F_TDOWNCMPLT       \
427
			| EMAC_DESC_F_JABBER       \
428
			| EMAC_DESC_F_OVERSIZE | EMAC_DESC_F_FRAGMENT    \
429
			| EMAC_DESC_F_UNDERSIZED | EMAC_DESC_F_CONTROL   \
430
			| EMAC_DESC_F_OVERRUN | EMAC_DESC_F_CODEERROR    \
431
			| EMAC_DESC_F_ALIGNERROR))
432

433
static irq_return_t ti816x_interrupt_macrxint0(unsigned int irq_num,
434
		void *dev_id) {
435
	struct ti816x_priv *dev_priv;
436
	struct emac_desc *desc;
437
	struct emac_desc *next;
438
	struct emac_desc_head *hdesc;
439
	struct sk_buff *skb;
440

441
	assert(DEFAULT_MASK == REG_LOAD(EMAC_CTRL_BASE
442
				+ EMAC_R_CMRXINTSTAT));
443

444
	dev_priv = netdev_priv(dev_id);
445
	assert(dev_priv != NULL);
446

447
	desc = (struct emac_desc *)REG_LOAD(EMAC_BASE + EMAC_R_RXCP(DEFAULT_CHANNEL));
448
	do {
449
		dcache_inval(desc, sizeof (struct emac_desc));
450

451
		if (desc->flags & EMAC_DESC_F_EOQ) {
452
			break;
453
		}
454
		if (desc->flags & EMAC_DESC_F_PASSCRC) {
455
			desc->data_len -= 4;
456
		}
457

458
		assert(!(desc->flags & EMAC_DESC_F_TDOWNCMPLT));
459
		assert(!(desc->flags & EMAC_DESC_F_EOQ));
460

461
		if (!CHECK_RXERR_2(desc->flags)) {
462
			if (desc->data_len > RX_FRAME_MAX_LEN) {
463
				log_debug("<too long frame %x>", desc->flags);
464
			} else {
465
				dcache_inval((void*)desc->data, desc->data_len);
466

467
				skb = skb_alloc(desc->data_len);
468
				assert(skb);
469
				skb->len = desc->data_len;
470
				skb->dev = dev_id;
471
				memcpy(skb_data_cast_in(skb->data),
472
					(void*)desc->data, desc->data_len);
473
				netif_rx(skb);
474
			}
475
		} else {
476
			log_debug("<ASSERT %x>", desc->flags);
477
		}
478

479
		next = (void*) desc->next;
480

481
		hdesc = head_from_desc(desc);
482
		emac_desc_build(desc, hdesc->skb, RX_FRAME_MAX_LEN, 0, EMAC_DESC_F_OWNER);
483
		emac_desc_set_next(desc, next);
484

485
		REG_STORE(EMAC_BASE + EMAC_R_RXCP(DEFAULT_CHANNEL), (uintptr_t)desc);
486

487
		desc = next;
488
	} while (desc !=
489
			(struct emac_desc *)REG_LOAD(EMAC_BASE + EMAC_R_RXCP(DEFAULT_CHANNEL)));
490

491
	emac_eoi(EMAC_MACEOIVEC_RXEOI);
492

493
	return IRQ_HANDLED;
494
}
495

496

497
#define CHECK_TXERR(x) \
498
	((x) & (EMAC_DESC_F_OWNER | EMAC_DESC_F_TDOWNCMPLT))
499

500
static irq_return_t ti816x_interrupt_mactxint0(unsigned int irq_num,
501
		void *dev_id) {
502
	struct ti816x_priv *dev_priv;
503
	int eoq;
504
	ipl_t sp;
505
	struct emac_desc *desc;
506
	struct emac_desc_head *hdesc;
507

508
	assert(DEFAULT_MASK == REG_LOAD(EMAC_CTRL_BASE + EMAC_R_CMTXINTSTAT));
509

510
	dev_priv = netdev_priv(dev_id);
511
	assert(dev_priv != NULL);
512

513
	desc = 	(struct emac_desc *)REG_LOAD(EMAC_BASE + EMAC_R_TXCP(DEFAULT_CHANNEL));
514
	dcache_inval(desc, sizeof *desc);
515
	assert(!CHECK_TXERR(desc->flags));
516

517
	eoq = desc->flags & EMAC_DESC_F_EOQ;
518

519
	REG_STORE(EMAC_BASE + EMAC_R_TXCP(DEFAULT_CHANNEL), (uintptr_t)desc);
520

521
	emac_eoi(EMAC_MACEOIVEC_TXEOI);
522

523
	if (!eoq) {
524
		assert(desc->next);
525
		goto out;
526
	}
527
	assert(!desc->next);
528
	sp = ipl_save();
529
	{
530
		dev_priv->tx_cur_head = dev_priv->tx_wait_head;
531
		if (dev_priv->tx_wait_head) {
532
			dev_priv->tx_wait_head = NULL;
533
			dev_priv->tx_wait_tail = NULL;
534
			emac_queue_activate((struct emac_desc *)dev_priv->tx_cur_head,
535
					EMAC_R_TXHDP(DEFAULT_CHANNEL));
536
		}
537
	}
538
	ipl_restore(sp);
539

540
out:
541
	hdesc = head_from_desc(desc);
542
	skb_free(hdesc->skb);
543
	emac_hdesc_tx_free(hdesc);
544

545
	return IRQ_HANDLED;
546
}
547

548
static irq_return_t ti816x_interrupt_macmisc0(unsigned int irq_num,
549
		void *dev_id) {
550
	unsigned long macinvector;
551

552
	macinvector = REG_LOAD(EMAC_BASE + EMAC_R_MACINVECTOR);
553

554
	if (macinvector & EMAC_MACINV_STATPEND) {
555
		emac_set_stat_regs(0xffffffff);
556
		macinvector &= ~EMAC_MACINV_STATPEND;
557
	}
558
	if (macinvector & EMAC_MACINV_HOSTPEND) {
559
		unsigned long macstatus;
560

561
		macstatus = REG_LOAD(EMAC_BASE + EMAC_R_MACSTATUS);
562
		log_raw(LOG_ERR,
563
		    "\tMACSTATUS: %#lx\n"
564
		    "\t\tidle %lx\n"
565
		    "\t\ttxerrcode %lx; txerrch %lx\n"
566
		    "\t\trxerrcode %lx; rxerrch %lx\n"
567
		    "\t\trgmiigig %lx; rgmiifullduplex %lx\n"
568
		    "\t\trxqosact %lx; rxflowact %lx; txflowact %lx\n",
569
		    macstatus, EMAC_MACSTAT_IDLE(macstatus),
570
		    EMAC_MACSTAT_TXERRCODE(macstatus), EMAC_MACSTAT_TXERRCH(macstatus),
571
		    EMAC_MACSTAT_RXERRCODE(macstatus), EMAC_MACSTAT_RXERRCH(macstatus),
572
		    EMAC_MACSTAT_RGMIIGIG(macstatus),
573
		    EMAC_MACSTAT_RGMIIFULLDUPLEX(macstatus),
574
		    EMAC_MACSTAT_RXQOSACT(macstatus), EMAC_MACSTAT_RXFLOWACT(macstatus),
575
		    EMAC_MACSTAT_TXFLOWACT(macstatus));
576

577
		emac_reset();
578
		ti816x_config((struct net_device *)dev_id);
579

580
		macinvector &= ~EMAC_MACINV_HOSTPEND;
581
	}
582
	if (macinvector & (EMAC_MACINV_RXPEND | EMAC_MACINV_TXPEND)) {
583
		/* umm.. ok */
584
		macinvector &= ~(EMAC_MACINV_RXPEND | EMAC_MACINV_TXPEND);
585
	}
586
	if (macinvector) {
587
		log_raw(LOG_DEBUG,
588
		    "ti816x_interrupt_macmisc0: unhandled interrupt\n"
589
		    "\tMACINVECTOR: %#lx\n"
590
		    "\tCMMISCINTSTAT: %#lx\n",
591
		    macinvector, REG_LOAD(EMAC_CTRL_BASE + EMAC_R_CMMISCINTSTAT));
592
	}
593

594
	emac_eoi(EMAC_MACEOIVEC_MISCEOI);
595

596
	return IRQ_HANDLED;
597
}
598

599
static void emac_set_max_frame_len(int m) {
600
	REG_STORE(EMAC_BASE + EMAC_R_RXMAXLEN, m);
601
}
602

603
static void ti816x_config(struct net_device *dev) {
604
	struct ti816x_priv *ti816x_priv;
605
	unsigned char bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
606

607
	ti816x_priv = netdev_priv(dev);
608
	/* reset EMAC module */
609
	emac_reset();
610

611
	/* disable all the EMAC/MDIO interrupts in the control module */
612
	emac_ctrl_disable_irq();
613

614
	/* initialization of the EMAC control module */
615
	emac_ctrl_enable_pacing();
616

617
	/* load device MAC-address */
618
	cm_load_mac(dev);
619

620
	/* initialization of EMAC and MDIO modules */
621
	emac_clear_ctrl_regs();
622
	emac_clear_hdp();
623
	emac_set_stat_regs(0);
624
	emac_set_macaddr(&bcast_addr);
625
	emac_init_rx_regs();
626
	emac_clear_machash();
627
	emac_set_rxbufoff(0);
628
	emac_set_max_frame_len(RX_FRAME_MAX_LEN);
629
	emac_clear_and_enable_rxunicast();
630
	emac_enable_rxmbp();
631
	emac_mdio_config();
632
	emac_alloc_rx_queue(ti816x_priv);
633
	emac_enable_rx_and_tx_irq();
634
	emac_enable_rx_and_tx_dma();
635

636
	REG_ORIN(EMAC_BASE + EMAC_R_MACCONTROL, 0x20);
637

638
	/* enable all the EMAC/MDIO interrupts in the control module */
639
	/* emac_ctrl_enable_irq(); -- would done when opening */
640
}
641

642
static int ti816x_init(void) {
643
	int ret;
644
	struct net_device *nic;
645
	struct ti816x_priv *nic_priv;
646

647
	nic = etherdev_alloc(sizeof *nic_priv);
648
	if (nic == NULL) {
649
		return -ENOMEM;
650
	}
651

652
	nic->drv_ops = &ti816x_ops;
653
	nic->irq = MACRXTHR0;
654
	nic->base_addr = EMAC_BASE;
655

656
	nic_priv = netdev_priv(nic);
657
	assert(nic_priv != NULL);
658
	memset(nic_priv, 0, sizeof *nic_priv);
659

660
	ti816x_config(nic);
661

662
	ret = irq_attach(MACRXTHR0, ti816x_interrupt_macrxthr0, 0,
663
			nic, "ti816x");
664
	if (ret < 0) {
665
		return ret;
666
	}
667
	ret = irq_attach(MACRXINT0, ti816x_interrupt_macrxint0, 0,
668
			nic, "ti816x");
669
	if (ret < 0) {
670
		return ret;
671
	}
672
	ret = irq_attach(MACTXINT0, ti816x_interrupt_mactxint0, 0,
673
			nic, "ti816x");
674
	if (ret < 0) {
675
		return ret;
676
	}
677
	ret = irq_attach(MACMISC0, ti816x_interrupt_macmisc0, 0,
678
			nic, "ti816x");
679
	if (ret < 0) {
680
		return ret;
681
	}
682

683
	return inetdev_register_dev(nic);
684
}
685

686
PERIPH_MEMORY_DEFINE(emac_region, EMAC_BASE, 0x800);
687

688
PERIPH_MEMORY_DEFINE(emac_ctrl_region, EMAC_CTRL_BASE, 0x800);
689

690
#if EMAC_VERSION == 1
691
/* Neccessary to clear interrupts */
692
PERIPH_MEMORY_DEFINE(emac_cm_region, LVL_INTR_CLEAR, 4);
693

694
#endif
695

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

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

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

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