1 #include <minix/drivers.h>
2 #include <minix/netdriver.h>
3 #include <minix/board.h>
7 #include "lan8710a_reg.h"
10 static int lan8710a_init(unsigned int instance
, netdriver_addr_t
*addr
,
11 uint32_t *caps
, unsigned int *ticks
);
12 static void lan8710a_stop(void);
13 static ssize_t
lan8710a_recv(struct netdriver_data
*data
, size_t max
);
14 static int lan8710a_send(struct netdriver_data
*data
, size_t size
);
15 static void lan8710a_intr(unsigned int mask
);
16 static void lan8710a_tick(void);
18 static void lan8710a_enable_interrupt(int interrupt
);
19 static void lan8710a_map_regs(void);
20 static void lan8710a_dma_config_tx(u8_t desc_idx
);
21 static void lan8710a_dma_reset_init(void);
22 static void lan8710a_init_addr(netdriver_addr_t
*addr
, unsigned int instance
);
23 static void lan8710a_init_desc(void);
24 static void lan8710a_init_mdio(void);
25 static int lan8710a_init_hw(netdriver_addr_t
*addr
, unsigned int instance
);
26 static void lan8710a_reset_hw(void);
28 static void lan8710a_phy_write(u32_t reg
, u32_t value
);
29 static u32_t
lan8710a_phy_read(u32_t reg
);
31 static u32_t
lan8710a_reg_read(volatile u32_t
*reg
);
32 static void lan8710a_reg_write(volatile u32_t
*reg
, u32_t value
);
33 static void lan8710a_reg_set(volatile u32_t
*reg
, u32_t value
);
34 static void lan8710a_reg_unset(volatile u32_t
*reg
, u32_t value
);
37 static lan8710a_t lan8710a_state
;
39 static const struct netdriver lan8710a_table
= {
41 .ndr_init
= lan8710a_init
,
42 .ndr_stop
= lan8710a_stop
,
43 .ndr_recv
= lan8710a_recv
,
44 .ndr_send
= lan8710a_send
,
45 .ndr_intr
= lan8710a_intr
,
46 .ndr_tick
= lan8710a_tick
49 /*============================================================================*
51 *============================================================================*/
53 main(int argc
, char *argv
[])
55 struct machine machine
;
57 env_setargs(argc
, argv
);
59 sys_getmachine(&machine
);
60 if (BOARD_IS_BB(machine
.board_id
))
61 netdriver_task(&lan8710a_table
);
66 /*============================================================================*
68 *============================================================================*/
70 lan8710a_init(unsigned int instance
, netdriver_addr_t
* addr
, uint32_t * caps
,
73 /* Initialize the ethernet driver. */
76 memset(&lan8710a_state
, 0, sizeof(lan8710a_state
));
78 /* Initialize driver. */
81 lan8710a_init_hw(addr
, instance
);
83 *caps
= NDEV_CAP_MCAST
| NDEV_CAP_BCAST
;
84 *ticks
= sys_hz(); /* update statistics once a second */
88 /*============================================================================*
89 * lan8710a_enable_interrupt *
90 *============================================================================*/
92 lan8710a_enable_interrupt(int interrupt
)
96 if (interrupt
& RX_INT
) {
97 if ((r
= sys_irqenable(&lan8710a_state
.irq_rx_hook
)) != OK
) {
98 panic("sys_irqenable failed: %d", r
);
101 if (interrupt
& TX_INT
) {
102 if ((r
= sys_irqenable(&lan8710a_state
.irq_tx_hook
)) != OK
) {
103 panic("sys_irqenable failed: %d", r
);
108 /*============================================================================*
110 *============================================================================*/
112 lan8710a_intr(unsigned int mask
)
116 /* Check the card for interrupt reason(s). */
117 u32_t rx_stat
= lan8710a_reg_read(CPSW_WR_C0_RX_STAT
);
118 u32_t tx_stat
= lan8710a_reg_read(CPSW_WR_C0_TX_STAT
);
121 /* Handle interrupts. */
123 cp
= lan8710a_reg_read(CPDMA_STRAM_RX_CP(0));
127 lan8710a_reg_write(CPDMA_STRAM_RX_CP(0), cp
);
128 lan8710a_reg_write(CPDMA_EOI_VECTOR
, RX_INT
);
131 cp
= lan8710a_reg_read(CPDMA_STRAM_TX_CP(0));
133 /* Disabling channels, where Tx interrupt occurred */
134 lan8710a_reg_set(CPDMA_TX_INTMASK_CLEAR
, tx_stat
);
138 lan8710a_reg_write(CPDMA_STRAM_TX_CP(0), cp
);
139 lan8710a_reg_write(CPDMA_EOI_VECTOR
, TX_INT
);
142 dma_status
= lan8710a_reg_read(CPDMA_STATUS
);
144 if (dma_status
& CPDMA_ERROR
) {
145 LAN8710A_DEBUG_PRINT(("CPDMA error: 0x%X, reset", dma_status
));
146 lan8710a_dma_reset_init();
149 /* Re-enable Rx interrupt. */
150 if (mask
& (1 << RX_INT
))
151 lan8710a_enable_interrupt(RX_INT
);
153 /* Re-enable Tx interrupt. */
154 if (mask
& (1 << TX_INT
))
155 lan8710a_enable_interrupt(TX_INT
);
158 /*============================================================================*
159 * lan8710a_init_addr *
160 *============================================================================*/
162 lan8710a_init_addr(netdriver_addr_t
* addr
, unsigned int instance
)
164 static char eakey
[]= LAN8710A_ENVVAR
"#_EA";
165 static char eafmt
[]= "x:x:x:x:x:x";
170 * Do we have a user defined ethernet address?
172 eakey
[sizeof(LAN8710A_ENVVAR
)-1] = '0' + instance
;
174 for (i
= 0; i
< 6; i
++) {
175 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
178 addr
->na_addr
[i
] = v
;
184 * No; get the address from the chip itself.
186 addr
->na_addr
[0] = lan8710a_reg_read(CTRL_MAC_ID0_HI
) & 0xFF;
187 addr
->na_addr
[1] = (lan8710a_reg_read(CTRL_MAC_ID0_HI
) >> 8) & 0xFF;
188 addr
->na_addr
[2] = (lan8710a_reg_read(CTRL_MAC_ID0_HI
) >> 16) & 0xFF;
189 addr
->na_addr
[3] = (lan8710a_reg_read(CTRL_MAC_ID0_HI
) >> 24) & 0xFF;
190 addr
->na_addr
[4] = lan8710a_reg_read(CTRL_MAC_ID0_LO
) & 0xFF;
191 addr
->na_addr
[5] = (lan8710a_reg_read(CTRL_MAC_ID0_LO
) >> 8) & 0xFF;
194 /*============================================================================*
195 * lan8710a_map_regs *
196 *============================================================================*/
198 lan8710a_map_regs(void)
200 struct minix_mem_range mr
;
201 mr
.mr_base
= CM_PER_BASE_ADR
;
202 mr
.mr_limit
= CM_PER_BASE_ADR
+ MEMORY_LIMIT
;
204 if (sys_privctl(SELF
, SYS_PRIV_ADD_MEM
, &mr
) != 0) {
205 panic("Unable to request permission to map memory");
207 lan8710a_state
.regs_cp_per
=
208 (vir_bytes
)vm_map_phys(SELF
, (void *)CM_PER_BASE_ADR
, 512);
209 if ((void *)lan8710a_state
.regs_cp_per
== MAP_FAILED
) {
210 panic("lan8710a_state.regs_cp_per: vm_map_phys failed");
212 lan8710a_state
.regs_cpdma_stram
=
213 (vir_bytes
)vm_map_phys(SELF
, (void *)CPDMA_STRAM_BASE_ADR
, 512);
214 if ((void *)lan8710a_state
.regs_cpdma_stram
== MAP_FAILED
) {
215 panic("lan8710a_state.regs_cpdma_stram: vm_map_phys failed");
217 lan8710a_state
.regs_cpsw_cpdma
=
218 (vir_bytes
)vm_map_phys(SELF
, (void *)CPSW_CPDMA_BASE_ADR
, 512);
219 if ((void *)lan8710a_state
.regs_cpsw_cpdma
== MAP_FAILED
) {
220 panic("lan8710a_state.regs_cpsw_cpdma: vm_map_phys failed");
222 lan8710a_state
.regs_cpsw_ale
=
223 (vir_bytes
)vm_map_phys(SELF
, (void *)CPSW_ALE_BASE_ADR
, 256);
224 if ((void *)lan8710a_state
.regs_cpsw_ale
== MAP_FAILED
) {
225 panic("lan8710a_state.regs_cpsw_ale: vm_map_phys failed");
227 lan8710a_state
.regs_cpsw_sl
=
228 (vir_bytes
)vm_map_phys(SELF
, (void *)CPSW_SL_BASE_ADR
, 512);
229 if ((void *)lan8710a_state
.regs_cpsw_sl
== MAP_FAILED
) {
230 panic("lan8710a_state.regs_cpsw_sl: vm_map_phys failed");
232 lan8710a_state
.regs_cpsw_ss
=
233 (vir_bytes
)vm_map_phys(SELF
, (void *)CPSW_SS_BASE_ADR
, 512);
234 if ((void *)lan8710a_state
.regs_cpsw_ss
== MAP_FAILED
) {
235 panic("lan8710a_state.regs_cpsw_ss: vm_map_phys failed");
237 lan8710a_state
.regs_cpsw_wr
=
238 (vir_bytes
)vm_map_phys(SELF
, (void *)CPSW_WR_BASE_ADR
, 512);
239 if ((void *)lan8710a_state
.regs_cpsw_wr
== MAP_FAILED
) {
240 panic("lan8710a_state.regs_cpsw_wr: vm_map_phys failed");
242 lan8710a_state
.regs_ctrl_mod
=
243 (vir_bytes
)vm_map_phys(SELF
, (void *)CTRL_MOD_BASE_ADR
, 2560);
244 if ((void *)lan8710a_state
.regs_ctrl_mod
== MAP_FAILED
) {
245 panic("lan8710a_state.regs_ctrl_mod: vm_map_phys failed");
247 lan8710a_state
.regs_intc
=
248 (vir_bytes
)vm_map_phys(SELF
, (void *)INTC_BASE_ADR
, 512);
249 if ((void *)lan8710a_state
.regs_intc
== MAP_FAILED
) {
250 panic("lan8710a_state.regs_intc: vm_map_phys failed");
252 lan8710a_state
.regs_mdio
=
253 (vir_bytes
)vm_map_phys(SELF
, (void *)MDIO_BASE_ADDR
, 512);
254 if ((void *)lan8710a_state
.regs_mdio
== MAP_FAILED
) {
255 panic("lan8710a_state.regs_mdio: vm_map_phys failed");
258 mr
.mr_base
= BEGINNING_DESC_MEM
;
259 mr
.mr_limit
= BEGINNING_DESC_MEM
+ DESC_MEMORY_LIMIT
;
261 if (sys_privctl(SELF
, SYS_PRIV_ADD_MEM
, &mr
) != 0) {
262 panic("Unable to request permission to map memory");
264 lan8710a_state
.rx_desc_phy
= BEGINNING_RX_DESC_MEM
;
265 lan8710a_state
.tx_desc_phy
= BEGINNING_TX_DESC_MEM
;
266 lan8710a_state
.rx_desc
= (lan8710a_desc_t
*)vm_map_phys(SELF
,
267 (void *)lan8710a_state
.rx_desc_phy
, 1024);
268 if ((void *)lan8710a_state
.rx_desc
== MAP_FAILED
) {
269 panic("lan8710a_state.rx_desc: vm_map_phys failed");
271 lan8710a_state
.tx_desc
= (lan8710a_desc_t
*)vm_map_phys(SELF
,
272 (void *)lan8710a_state
.tx_desc_phy
, 1024);
273 if ((void *)lan8710a_state
.tx_desc
== MAP_FAILED
) {
274 panic("lan8710a_state.tx_desc: vm_map_phys failed");
277 mr
.mr_base
= CPSW_STATS_BASE_ADR
;
278 mr
.mr_limit
= CPSW_STATS_BASE_ADR
+ CPSW_STATS_MEM_LIMIT
;
280 if (sys_privctl(SELF
, SYS_PRIV_ADD_MEM
, &mr
) != 0) {
281 panic("Unable to request permission to map memory");
283 lan8710a_state
.regs_cpsw_stats
=
284 (vir_bytes
)vm_map_phys(SELF
, (void *)CPSW_STATS_BASE_ADR
, 256);
285 if ((void *)lan8710a_state
.regs_cpsw_stats
== MAP_FAILED
) {
286 panic("lan8710a_state.regs_cpsw_stats: vm_map_phys failed");
290 /*============================================================================*
291 * lan8710a_update_stats *
292 *============================================================================*/
294 lan8710a_update_stats(void)
299 * AM335x Technical Reference (SPRUH73J) Sec. 14.3.2.20: statistics
300 * registers are decrement-on-write when any of the statistics port
301 * enable bits are set.
303 val
= lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR
);
304 lan8710a_reg_write(CPSW_STAT_RX_CRC_ERR
, val
);
305 netdriver_stat_ierror(val
);
307 val
= lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR
);
308 lan8710a_reg_write(CPSW_STAT_RX_AGNCD_ERR
, val
);
309 netdriver_stat_ierror(val
);
311 val
= lan8710a_reg_read(CPSW_STAT_RX_OVERSIZE
);
312 lan8710a_reg_write(CPSW_STAT_RX_OVERSIZE
, val
);
313 netdriver_stat_ierror(val
);
315 val
= lan8710a_reg_read(CPSW_STAT_COLLISIONS
);
316 lan8710a_reg_write(CPSW_STAT_COLLISIONS
, val
);
317 netdriver_stat_coll(val
);
320 /*============================================================================*
322 *============================================================================*/
327 /* Update statistics. */
328 lan8710a_update_stats();
331 /*============================================================================*
333 *============================================================================*/
337 /* Reset hardware. */
341 /*============================================================================*
342 * lan8710a_dma_config_tx *
343 *============================================================================*/
345 lan8710a_dma_config_tx(u8_t desc_idx
)
347 phys_bytes phys_addr
;
349 for (i
= 0; i
< TX_DMA_CHANNELS
; ++i
) {
350 if (!lan8710a_reg_read(CPDMA_STRAM_TX_HDP(i
))) break;
352 if (i
== TX_DMA_CHANNELS
) {
353 panic("There are no free TX DMA channels.");
356 /* Enabling only one channel Tx interrupt */
357 lan8710a_reg_write(CPDMA_TX_INTMASK_SET
, 1 << i
);
358 /* Routing only one channel Tx int to TX_PULSE signal */
359 lan8710a_reg_write(CPSW_WR_C0_TX_EN
, 1 << i
);
362 phys_addr
= lan8710a_state
.tx_desc_phy
+
363 (desc_idx
* sizeof(lan8710a_desc_t
));
364 lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i
), (u32_t
)phys_addr
);
367 /*============================================================================*
368 * lan8710a_dma_reset_init *
369 *============================================================================*/
371 lan8710a_dma_reset_init(void)
374 lan8710a_reg_write(CPDMA_SOFT_RESET
, SOFT_RESET
);
375 while ((lan8710a_reg_read(CPDMA_SOFT_RESET
) & SOFT_RESET
));
378 * Initialize the HDPs (Header Description Pointers) and
379 * CPs (Completion Pointers) to NULL.
381 for (i
= 0; i
< DMA_MAX_CHANNELS
; ++i
) {
382 lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i
), 0);
383 lan8710a_reg_write(CPDMA_STRAM_RX_HDP(i
), 0);
384 lan8710a_reg_write(CPDMA_STRAM_TX_CP(i
), 0);
385 lan8710a_reg_write(CPDMA_STRAM_RX_CP(i
), 0);
388 lan8710a_reg_write(CPDMA_RX_INTMASK_CLEAR
, 0xFFFFFFFF);
389 lan8710a_reg_write(CPDMA_TX_INTMASK_CLEAR
, 0xFFFFFFFF);
391 /* Configure the CPDMA controller. */
392 lan8710a_reg_set(CPDMA_RX_CONTROL
, CPDMA_RX_EN
); /* RX Enabled */
393 lan8710a_reg_set(CPDMA_TX_CONTROL
, CPDMA_TX_EN
); /* TX Enabled */
395 /* Enabling first channel Rx interrupt */
396 lan8710a_reg_set(CPDMA_RX_INTMASK_SET
, CPDMA_FIRST_CHAN_INT
);
399 * Writing the address of the first buffer descriptor in the queue
400 * (nonzero value)to the channel’s head descriptor pointer in the
401 * channel’s Rx DMA state.
403 lan8710a_reg_write(CPDMA_STRAM_RX_HDP(0),
404 (u32_t
)lan8710a_state
.rx_desc_phy
);
406 lan8710a_state
.rx_desc_idx
= 0;
407 lan8710a_state
.tx_desc_idx
= 0;
410 /*============================================================================*
411 * lan8710a_init_desc *
412 *============================================================================*/
414 lan8710a_init_desc(void)
416 lan8710a_desc_t
*p_rx_desc
;
417 lan8710a_desc_t
*p_tx_desc
;
418 phys_bytes buf_phys_addr
;
421 /* Attempt to allocate. */
422 if ((lan8710a_state
.p_rx_buf
= alloc_contig((LAN8710A_NUM_RX_DESC
423 * LAN8710A_IOBUF_SIZE
), AC_ALIGN4K
,
424 &buf_phys_addr
)) == NULL
) {
425 panic("failed to allocate RX buffers.");
427 for (i
= 0; i
< LAN8710A_NUM_RX_DESC
; i
++) {
428 p_rx_desc
= &(lan8710a_state
.rx_desc
[i
]);
429 memset(p_rx_desc
, 0x0, sizeof(lan8710a_desc_t
));
430 p_rx_desc
->pkt_len_flags
= LAN8710A_DESC_FLAG_OWN
;
431 p_rx_desc
->buffer_length_off
= LAN8710A_IOBUF_SIZE
;
432 p_rx_desc
->buffer_pointer
= (u32_t
)(buf_phys_addr
+
433 (i
* LAN8710A_IOBUF_SIZE
));
435 p_rx_desc
->next_pointer
=
436 (u32_t
)((i
== (LAN8710A_NUM_RX_DESC
- 1)) ?
437 (lan8710a_state
.rx_desc_phy
) :
438 (lan8710a_state
.rx_desc_phy
+
439 ((i
+ 1) * sizeof(lan8710a_desc_t
))));
442 /* Attempt to allocate. */
443 if ((lan8710a_state
.p_tx_buf
= alloc_contig((LAN8710A_NUM_TX_DESC
444 * LAN8710A_IOBUF_SIZE
), AC_ALIGN4K
,
445 &buf_phys_addr
)) == NULL
) {
446 panic("failed to allocate TX buffers");
448 for (i
= 0; i
< LAN8710A_NUM_TX_DESC
; i
++) {
449 p_tx_desc
= &(lan8710a_state
.tx_desc
[i
]);
450 memset(p_tx_desc
, 0x0, sizeof(lan8710a_desc_t
));
451 p_tx_desc
->buffer_pointer
= (u32_t
)(buf_phys_addr
+
452 (i
* LAN8710A_IOBUF_SIZE
));
454 lan8710a_state
.rx_desc_idx
= 0;
455 lan8710a_state
.tx_desc_idx
= 0;
458 /*============================================================================*
460 *============================================================================*/
462 lan8710a_init_hw(netdriver_addr_t
* addr
, unsigned int instance
)
467 * Set the interrupt handler and policy. Do not automatically
468 * re-enable interrupts. Return the IRQ line number on interrupts.
470 lan8710a_state
.irq_rx_hook
= RX_INT
;
471 if ((r
= sys_irqsetpolicy(LAN8710A_RX_INTR
, 0,
472 &lan8710a_state
.irq_rx_hook
)) != OK
) {
473 panic("sys_irqsetpolicy failed: %d", r
);
475 lan8710a_state
.irq_tx_hook
= TX_INT
;
476 if ((r
= sys_irqsetpolicy(LAN8710A_TX_INTR
, 0,
477 &lan8710a_state
.irq_tx_hook
)) != OK
) {
478 panic("sys_irqsetpolicy failed: %d", r
);
481 /* Reset hardware. */
485 * Select the Interface (GMII/RGMII/MII) Mode in the Control Module.
486 * Port1 GMII/MII Mode, Port2 not used.
488 lan8710a_reg_write(GMII_SEL
, (GMII2_SEL_BIT1
| GMII2_SEL_BIT0
));
491 * Configure pads (PIN muxing) as per the Interface Selected using the
492 * appropriate pin muxing conf_xxx registers in the Control Module.
494 * CONF_MOD_SLEW_CTRL when 0 - Fast Mode, when 1 - Slow Mode
495 * CONF_MOD_RX_ACTIVE when 0 - Only output, when 1 - Also input
496 * CONF_MOD_PU_TYPESEL when 0 - Pull-down, when 1 - Pull-up
497 * CONF_MOD_PUDEN when 0 Pull* enabled, when 1 Pull* disabled
498 * CONF_MOD_MMODE_MII selects pin to work for MII interface
500 lan8710a_reg_unset(CONF_MII1_COL
, CONF_MOD_SLEW_CTRL
);
501 lan8710a_reg_set(CONF_MII1_COL
, CONF_MOD_RX_ACTIVE
);
502 lan8710a_reg_set(CONF_MII1_COL
, CONF_MOD_PU_TYPESEL
);
503 lan8710a_reg_unset(CONF_MII1_COL
, CONF_MOD_PUDEN
);
504 lan8710a_reg_unset(CONF_MII1_COL
, CONF_MOD_MMODE_MII
);
506 lan8710a_reg_unset(CONF_MII1_CRS
, CONF_MOD_SLEW_CTRL
);
507 lan8710a_reg_set(CONF_MII1_CRS
, CONF_MOD_RX_ACTIVE
);
508 lan8710a_reg_set(CONF_MII1_CRS
, CONF_MOD_PU_TYPESEL
);
509 lan8710a_reg_unset(CONF_MII1_CRS
, CONF_MOD_PUDEN
);
510 lan8710a_reg_unset(CONF_MII1_CRS
, CONF_MOD_MMODE_MII
);
512 lan8710a_reg_unset(CONF_MII1_RX_ER
, CONF_MOD_SLEW_CTRL
);
513 lan8710a_reg_set(CONF_MII1_RX_ER
, CONF_MOD_RX_ACTIVE
);
514 lan8710a_reg_set(CONF_MII1_RX_ER
, CONF_MOD_PU_TYPESEL
);
515 lan8710a_reg_unset(CONF_MII1_RX_ER
, CONF_MOD_PUDEN
);
516 lan8710a_reg_unset(CONF_MII1_RX_ER
, CONF_MOD_MMODE_MII
);
518 lan8710a_reg_unset(CONF_MII1_TX_EN
, CONF_MOD_SLEW_CTRL
);
519 lan8710a_reg_unset(CONF_MII1_TX_EN
, CONF_MOD_RX_ACTIVE
);
520 lan8710a_reg_set(CONF_MII1_TX_EN
, CONF_MOD_PUDEN
);
521 lan8710a_reg_unset(CONF_MII1_TX_EN
, CONF_MOD_MMODE_MII
);
523 lan8710a_reg_unset(CONF_MII1_RX_DV
, CONF_MOD_SLEW_CTRL
);
524 lan8710a_reg_set(CONF_MII1_RX_DV
, CONF_MOD_RX_ACTIVE
);
525 lan8710a_reg_set(CONF_MII1_RX_DV
, CONF_MOD_PU_TYPESEL
);
526 lan8710a_reg_unset(CONF_MII1_RX_DV
, CONF_MOD_PUDEN
);
527 lan8710a_reg_unset(CONF_MII1_RX_DV
, CONF_MOD_MMODE_MII
);
529 lan8710a_reg_unset(CONF_MII1_TXD3
, CONF_MOD_SLEW_CTRL
);
530 lan8710a_reg_unset(CONF_MII1_TXD3
, CONF_MOD_RX_ACTIVE
);
531 lan8710a_reg_set(CONF_MII1_TXD3
, CONF_MOD_PUDEN
);
532 lan8710a_reg_unset(CONF_MII1_TXD3
, CONF_MOD_MMODE_MII
);
534 lan8710a_reg_unset(CONF_MII1_TXD2
, CONF_MOD_SLEW_CTRL
);
535 lan8710a_reg_unset(CONF_MII1_TXD2
, CONF_MOD_RX_ACTIVE
);
536 lan8710a_reg_set(CONF_MII1_TXD2
, CONF_MOD_PUDEN
);
537 lan8710a_reg_unset(CONF_MII1_TXD2
, CONF_MOD_MMODE_MII
);
539 lan8710a_reg_unset(CONF_MII1_TXD1
, CONF_MOD_SLEW_CTRL
);
540 lan8710a_reg_unset(CONF_MII1_TXD1
, CONF_MOD_RX_ACTIVE
);
541 lan8710a_reg_set(CONF_MII1_TXD1
, CONF_MOD_PUDEN
);
542 lan8710a_reg_unset(CONF_MII1_TXD1
, CONF_MOD_MMODE_MII
);
544 lan8710a_reg_unset(CONF_MII1_TXD0
, CONF_MOD_SLEW_CTRL
);
545 lan8710a_reg_unset(CONF_MII1_TXD0
, CONF_MOD_RX_ACTIVE
);
546 lan8710a_reg_set(CONF_MII1_TXD0
, CONF_MOD_PUDEN
);
547 lan8710a_reg_unset(CONF_MII1_TXD0
, CONF_MOD_MMODE_MII
);
549 lan8710a_reg_unset(CONF_MII1_TX_CLK
, CONF_MOD_SLEW_CTRL
);
550 lan8710a_reg_set(CONF_MII1_TX_CLK
, CONF_MOD_RX_ACTIVE
);
551 lan8710a_reg_set(CONF_MII1_TX_CLK
, CONF_MOD_PUDEN
);
552 lan8710a_reg_unset(CONF_MII1_TX_CLK
, CONF_MOD_MMODE_MII
);
554 lan8710a_reg_unset(CONF_MII1_RX_CLK
, CONF_MOD_SLEW_CTRL
);
555 lan8710a_reg_set(CONF_MII1_RX_CLK
, CONF_MOD_RX_ACTIVE
);
556 lan8710a_reg_set(CONF_MII1_RX_CLK
, CONF_MOD_PUDEN
);
557 lan8710a_reg_unset(CONF_MII1_RX_CLK
, CONF_MOD_MMODE_MII
);
559 lan8710a_reg_unset(CONF_MII1_RXD3
, CONF_MOD_SLEW_CTRL
);
560 lan8710a_reg_set(CONF_MII1_RXD3
, CONF_MOD_RX_ACTIVE
);
561 lan8710a_reg_set(CONF_MII1_RXD3
, CONF_MOD_PU_TYPESEL
);
562 lan8710a_reg_unset(CONF_MII1_RXD3
, CONF_MOD_PUDEN
);
563 lan8710a_reg_unset(CONF_MII1_RXD3
, CONF_MOD_MMODE_MII
);
565 lan8710a_reg_unset(CONF_MII1_RXD2
, CONF_MOD_SLEW_CTRL
);
566 lan8710a_reg_set(CONF_MII1_RXD2
, CONF_MOD_RX_ACTIVE
);
567 lan8710a_reg_set(CONF_MII1_RXD2
, CONF_MOD_PU_TYPESEL
);
568 lan8710a_reg_unset(CONF_MII1_RXD2
, CONF_MOD_PUDEN
);
569 lan8710a_reg_unset(CONF_MII1_RXD2
, CONF_MOD_MMODE_MII
);
571 lan8710a_reg_unset(CONF_MII1_RXD1
, CONF_MOD_SLEW_CTRL
);
572 lan8710a_reg_set(CONF_MII1_RXD1
, CONF_MOD_RX_ACTIVE
);
573 lan8710a_reg_set(CONF_MII1_RXD1
, CONF_MOD_PU_TYPESEL
);
574 lan8710a_reg_unset(CONF_MII1_RXD1
, CONF_MOD_PUDEN
);
575 lan8710a_reg_unset(CONF_MII1_RXD1
, CONF_MOD_MMODE_MII
);
577 lan8710a_reg_unset(CONF_MII1_RXD0
, CONF_MOD_SLEW_CTRL
);
578 lan8710a_reg_set(CONF_MII1_RXD0
, CONF_MOD_RX_ACTIVE
);
579 lan8710a_reg_set(CONF_MII1_RXD0
, CONF_MOD_PU_TYPESEL
);
580 lan8710a_reg_unset(CONF_MII1_RXD0
, CONF_MOD_PUDEN
);
581 lan8710a_reg_unset(CONF_MII1_RXD0
, CONF_MOD_MMODE_MII
);
583 lan8710a_reg_unset(CONF_MDIO
, CONF_MOD_SLEW_CTRL
);
584 lan8710a_reg_set(CONF_MDIO
, CONF_MOD_RX_ACTIVE
);
585 lan8710a_reg_set(CONF_MDIO
, CONF_MOD_PU_TYPESEL
);
586 lan8710a_reg_unset(CONF_MDIO
, CONF_MOD_PUDEN
);
587 lan8710a_reg_unset(CONF_MDIO
, CONF_MOD_MMODE_MII
);
589 lan8710a_reg_unset(CONF_MDC
, CONF_MOD_SLEW_CTRL
);
590 lan8710a_reg_unset(CONF_MDC
, CONF_MOD_RX_ACTIVE
);
591 lan8710a_reg_set(CONF_MDC
, CONF_MOD_PUDEN
);
592 lan8710a_reg_unset(CONF_MDC
, CONF_MOD_MMODE_MII
);
594 /* Apply soft reset to 3PSW Subsytem, CPSW_3G, CPGMAC_SL, and CPDMA. */
595 lan8710a_reg_write(CPSW_SS_SOFT_RESET
, SOFT_RESET
);
596 lan8710a_reg_write(CPSW_SL_SOFT_RESET(1), SOFT_RESET
);
597 lan8710a_reg_write(CPSW_SL_SOFT_RESET(2), SOFT_RESET
);
599 /* Wait for software resets completion */
600 while ((lan8710a_reg_read(CPSW_SS_SOFT_RESET
) & SOFT_RESET
) ||
601 (lan8710a_reg_read(CPSW_SL_SOFT_RESET(1)) & SOFT_RESET
) ||
602 (lan8710a_reg_read(CPSW_SL_SOFT_RESET(2)) & SOFT_RESET
));
604 /* Configure the Statistics Port Enable register. */
605 /* Enable port 0 and 1 statistics. */
606 lan8710a_reg_write(CPSW_SS_STAT_PORT_EN
, (CPSW_P1_STAT_EN
|
612 * All packets received on ports 1 are
613 * sent to the host (only to the host).
615 lan8710a_reg_write(CPSW_ALE_CONTROL
, (CPSW_ALE_ENABLE
|
617 /* Port 0 (host) in forwarding mode. */
618 lan8710a_reg_write(CPSW_ALE_PORTCTL0
, CPSW_ALE_PORT_FWD
);
619 /* Port 1 in forwarding mode. */
620 lan8710a_reg_write(CPSW_ALE_PORTCTL1
, CPSW_ALE_PORT_FWD
);
623 * Configure CPSW_SL Register
626 lan8710a_reg_write(CPSW_SL_MACCONTROL(1), CPSW_SL_FULLDUPLEX
);
628 /* Initialize MDIO Protocol */
629 lan8710a_init_mdio();
631 /* Getting MAC Address */
632 lan8710a_init_addr(addr
, instance
);
634 /* Initialize descriptors */
635 lan8710a_init_desc();
637 /* Reset and initialize CPDMA */
638 lan8710a_dma_reset_init();
641 * Configure the Interrupts.
642 * Routing all channel Rx int to RX_PULSE signal.
644 lan8710a_reg_set(CPSW_WR_C0_RX_EN
, CPSW_FIRST_CHAN_INT
);
647 * Enabling LAN8710A Auto-negotiation
649 lan8710a_phy_write(LAN8710A_CTRL_REG
, LAN8710A_AUTO_NEG
);
651 /* Waiting for auto-negotiaion completion. */
652 for (i
= 0; !(lan8710a_phy_read(LAN8710A_STATUS_REG
) &
653 LAN8710A_AUTO_NEG_COMPL
); ++i
) {
655 LAN8710A_DEBUG_PRINT(("Autonegotiation failed"));
658 micro_delay(1666666);
661 /* GMII RX and TX release from reset. */
662 lan8710a_reg_set(CPSW_SL_MACCONTROL(1), CPSW_SL_GMII_EN
);
664 /* Enable interrupts. */
665 lan8710a_enable_interrupt(RX_INT
| TX_INT
);
670 /*============================================================================*
671 * lan8710a_init_mdio *
672 *============================================================================*/
674 lan8710a_init_mdio(void)
679 /* Clearing MDIOCONTROL register */
680 lan8710a_reg_write(MDIOCONTROL
, 0);
681 /* Configure the PREAMBLE and CLKDIV in the MDIO control register */
682 lan8710a_reg_unset(MDIOCONTROL
, MDIO_PREAMBLE
); /* CLKDIV default */
683 /* Enable sending MDIO frame preambles */
684 lan8710a_reg_set(MDIOCONTROL
, (MDCLK_DIVIDER
| MDIO_ENABLE
));
685 /* Enable the MDIO module by setting the ENABLE bit in MDIOCONTROL */
687 while (!(r
= lan8710a_reg_read(MDIOALIVE
)));
689 /* Get PHY address */
693 lan8710a_state
.phy_address
= address
;
695 /* Setup appropiate address in MDIOUSERPHYSEL0 */
696 lan8710a_reg_set(MDIOUSERPHYSEL0
, address
);
699 /*============================================================================*
701 *============================================================================*/
703 lan8710a_send(struct netdriver_data
* data
, size_t size
)
705 lan8710a_t
*e
= &lan8710a_state
;
706 lan8710a_desc_t
*p_tx_desc
;
709 /* setup descriptors */
710 p_tx_desc
= &(e
->tx_desc
[e
->tx_desc_idx
]);
713 * Check if descriptor is available for host and suspend if not.
715 if (LAN8710A_DESC_FLAG_OWN
& p_tx_desc
->pkt_len_flags
)
718 /* Drop packets that exceed the size of our transmission buffer. */
719 if (size
> LAN8710A_IOBUF_SIZE
) {
720 printf("%s: dropping large packet (%zu)\n",
721 netdriver_name(), size
);
726 /* virtual address of buffer */
727 buf
= e
->p_tx_buf
+ e
->tx_desc_idx
* LAN8710A_IOBUF_SIZE
;
729 netdriver_copyin(data
, 0, buf
, size
);
731 /* set descriptor length */
732 p_tx_desc
->buffer_length_off
= size
;
734 p_tx_desc
->pkt_len_flags
= (LAN8710A_DESC_FLAG_OWN
|
735 LAN8710A_DESC_FLAG_SOP
|
736 LAN8710A_DESC_FLAG_EOP
|
739 p_tx_desc
->pkt_len_flags
|= size
;
741 /* setup DMA transfer */
742 lan8710a_dma_config_tx(e
->tx_desc_idx
);
745 if (LAN8710A_NUM_TX_DESC
== e
->tx_desc_idx
)
751 /*============================================================================*
753 *============================================================================*/
755 lan8710a_recv(struct netdriver_data
* data
, size_t max
)
757 lan8710a_t
*e
= &lan8710a_state
;
758 lan8710a_desc_t
*p_rx_desc
;
761 size_t off
, size
, chunk
;
764 * Only handle one packet at a time.
766 p_rx_desc
= &(e
->rx_desc
[e
->rx_desc_idx
]);
767 /* find next OWN descriptor with SOP flag */
768 while ((0 == (LAN8710A_DESC_FLAG_SOP
& p_rx_desc
->pkt_len_flags
)) &&
769 (0 == (LAN8710A_DESC_FLAG_OWN
& p_rx_desc
->pkt_len_flags
))) {
770 p_rx_desc
->buffer_length_off
= LAN8710A_IOBUF_SIZE
;
771 /* set ownership of current descriptor to EMAC */
772 p_rx_desc
->pkt_len_flags
= LAN8710A_DESC_FLAG_OWN
;
775 if (LAN8710A_NUM_RX_DESC
== e
->rx_desc_idx
)
777 p_rx_desc
= &(e
->rx_desc
[e
->rx_desc_idx
]);
780 if (0 == (LAN8710A_DESC_FLAG_SOP
& p_rx_desc
->pkt_len_flags
)) {
781 /* SOP was not found */
786 * Copy data from descriptors, from SOP to EOP inclusive.
787 * TODO: make sure that the presence of a SOP slot implies the presence
788 * of an EOP slot, because we are not checking for ownership below..
794 buf
= e
->p_rx_buf
+ e
->rx_desc_idx
* LAN8710A_IOBUF_SIZE
+ off
;
795 chunk
= p_rx_desc
->buffer_length_off
& 0xFFFF;
797 /* Truncate packets that are too large. */
798 if (chunk
> max
- size
)
802 netdriver_copyout(data
, size
, buf
, chunk
);
807 flags
= p_rx_desc
->pkt_len_flags
;
809 /* Whole buffer move to the next descriptor */
810 p_rx_desc
->buffer_length_off
= LAN8710A_IOBUF_SIZE
;
811 /* set ownership of current desc to EMAC */
812 p_rx_desc
->pkt_len_flags
= LAN8710A_DESC_FLAG_OWN
;
815 if (LAN8710A_NUM_RX_DESC
== e
->rx_desc_idx
)
817 p_rx_desc
= &(e
->rx_desc
[e
->rx_desc_idx
]);
819 /* if EOP flag is set -> stop processing */
820 if (flags
& LAN8710A_DESC_FLAG_EOP
)
824 * TODO: the upper 16 bits of buffer_length_off are used *only*
825 * for descriptors *after* the first one; I'm retaining this
826 * behavior because I don't have the chip's spec, but it may be
827 * better to simplify/correct this behavior. --David
829 off
= p_rx_desc
->buffer_length_off
>> 16;
835 /*============================================================================*
836 * lan8710a_phy_write *
837 *============================================================================*/
839 lan8710a_phy_write(u32_t reg
, u32_t value
)
841 if (!(lan8710a_reg_read(MDIOUSERACCESS0
) & MDIO_GO
)) {
842 /* Clearing MDIOUSERACCESS0 register */
843 lan8710a_reg_write(MDIOUSERACCESS0
, 0);
844 /* Setting proper values in MDIOUSERACCESS0 */
845 lan8710a_reg_set(MDIOUSERACCESS0
, MDIO_WRITE
);
846 lan8710a_reg_set(MDIOUSERACCESS0
, reg
<< MDIO_REGADR
);
847 lan8710a_reg_set(MDIOUSERACCESS0
,
848 lan8710a_state
.phy_address
<< MDIO_PHYADR
);
849 /* Data written only 16 bits. */
850 lan8710a_reg_set(MDIOUSERACCESS0
,
851 (value
& 0xFFFF) << MDIO_DATA
);
852 lan8710a_reg_set(MDIOUSERACCESS0
, MDIO_GO
);
854 /* Waiting for writing completion */
855 while (lan8710a_reg_read(MDIOUSERACCESS0
) & MDIO_GO
);
859 /*============================================================================*
860 * lan8710a_phy_read *
861 *============================================================================*/
863 lan8710a_phy_read(u32_t reg
)
865 u32_t value
= 0xFFFFFFFF;
867 if (!(lan8710a_reg_read(MDIOUSERACCESS0
) & MDIO_GO
)) {
868 /* Clearing MDIOUSERACCESS0 register */
869 lan8710a_reg_write(MDIOUSERACCESS0
, 0);
870 /* Setting proper values in MDIOUSERACCESS0 */
871 lan8710a_reg_unset(MDIOUSERACCESS0
, MDIO_WRITE
);
872 /* Reg number must be 5 bit long */
873 lan8710a_reg_set(MDIOUSERACCESS0
, (reg
& 0x1F) << MDIO_REGADR
);
874 /* Addr must be 5 bit long */
875 lan8710a_reg_set(MDIOUSERACCESS0
,
876 (lan8710a_state
.phy_address
& 0x1F) << MDIO_PHYADR
);
877 lan8710a_reg_set(MDIOUSERACCESS0
, MDIO_GO
);
879 /* Waiting for reading completion */
880 while ((lan8710a_reg_read(MDIOUSERACCESS0
) & MDIO_GO
)
881 && !(lan8710a_reg_read(MDIOUSERACCESS0
) & MDIO_ACK
));
884 value
= lan8710a_reg_read(MDIOUSERACCESS0
) & 0xFFFF;
889 /*============================================================================*
890 * lan8710a_reset_hw *
891 *============================================================================*/
893 lan8710a_reset_hw(void)
895 /* Assert a Device Reset signal. */
896 lan8710a_phy_write(LAN8710A_CTRL_REG
, LAN8710A_SOFT_RESET
);
898 /* Waiting for reset completion. */
899 while (lan8710a_phy_read(LAN8710A_CTRL_REG
) & LAN8710A_SOFT_RESET
);
902 /*============================================================================*
903 * lan8710a_reg_read *
904 *============================================================================*/
906 lan8710a_reg_read(volatile u32_t
*reg
)
910 /* Read from memory mapped register. */
913 /* Return the result. */
917 /*============================================================================*
918 * lan8710a_reg_write *
919 *============================================================================*/
921 lan8710a_reg_write(volatile u32_t
*reg
, u32_t value
)
923 /* Write to memory mapped register. */
927 /*============================================================================*
929 *============================================================================*/
931 lan8710a_reg_set(volatile u32_t
*reg
, u32_t value
)
935 /* First read the current value. */
936 data
= lan8710a_reg_read(reg
);
938 /* Set value, and write back. */
939 lan8710a_reg_write(reg
, data
| value
);
942 /*============================================================================*
943 * lan8710a_reg_unset *
944 *============================================================================*/
946 lan8710a_reg_unset(volatile u32_t
*reg
, u32_t value
)
950 /* First read the current value. */
951 data
= lan8710a_reg_read(reg
);
953 /* Unset value, and write back. */
954 lan8710a_reg_write(reg
, data
& ~value
);