1433d6423SLionel Sambuc #include <minix/drivers.h>
2433d6423SLionel Sambuc #include <minix/netdriver.h>
3433d6423SLionel Sambuc #include <minix/board.h>
45af3c256SDavid van Moolenbroek #include <sys/mman.h>
5433d6423SLionel Sambuc #include "assert.h"
6433d6423SLionel Sambuc #include "lan8710a.h"
7433d6423SLionel Sambuc #include "lan8710a_reg.h"
8433d6423SLionel Sambuc
9433d6423SLionel Sambuc /* Local functions */
10f7df02e7SDavid van Moolenbroek static int lan8710a_init(unsigned int instance, netdriver_addr_t *addr,
11f7df02e7SDavid van Moolenbroek uint32_t *caps, unsigned int *ticks);
12433d6423SLionel Sambuc static void lan8710a_stop(void);
135af3c256SDavid van Moolenbroek static ssize_t lan8710a_recv(struct netdriver_data *data, size_t max);
145af3c256SDavid van Moolenbroek static int lan8710a_send(struct netdriver_data *data, size_t size);
155af3c256SDavid van Moolenbroek static void lan8710a_intr(unsigned int mask);
16f7df02e7SDavid van Moolenbroek static void lan8710a_tick(void);
175af3c256SDavid van Moolenbroek
185af3c256SDavid van Moolenbroek static void lan8710a_enable_interrupt(int interrupt);
195af3c256SDavid van Moolenbroek static void lan8710a_map_regs(void);
20433d6423SLionel Sambuc static void lan8710a_dma_config_tx(u8_t desc_idx);
21433d6423SLionel Sambuc static void lan8710a_dma_reset_init(void);
22f7df02e7SDavid van Moolenbroek static void lan8710a_init_addr(netdriver_addr_t *addr, unsigned int instance);
23433d6423SLionel Sambuc static void lan8710a_init_desc(void);
24433d6423SLionel Sambuc static void lan8710a_init_mdio(void);
25f7df02e7SDavid van Moolenbroek static int lan8710a_init_hw(netdriver_addr_t *addr, unsigned int instance);
265af3c256SDavid van Moolenbroek static void lan8710a_reset_hw(void);
27433d6423SLionel Sambuc
28433d6423SLionel Sambuc static void lan8710a_phy_write(u32_t reg, u32_t value);
29433d6423SLionel Sambuc static u32_t lan8710a_phy_read(u32_t reg);
30433d6423SLionel Sambuc
31433d6423SLionel Sambuc static u32_t lan8710a_reg_read(volatile u32_t *reg);
32433d6423SLionel Sambuc static void lan8710a_reg_write(volatile u32_t *reg, u32_t value);
33433d6423SLionel Sambuc static void lan8710a_reg_set(volatile u32_t *reg, u32_t value);
34433d6423SLionel Sambuc static void lan8710a_reg_unset(volatile u32_t *reg, u32_t value);
35433d6423SLionel Sambuc
36433d6423SLionel Sambuc /* Local variables */
37433d6423SLionel Sambuc static lan8710a_t lan8710a_state;
38433d6423SLionel Sambuc
395af3c256SDavid van Moolenbroek static const struct netdriver lan8710a_table = {
40f7df02e7SDavid van Moolenbroek .ndr_name = "cpsw",
415af3c256SDavid van Moolenbroek .ndr_init = lan8710a_init,
425af3c256SDavid van Moolenbroek .ndr_stop = lan8710a_stop,
435af3c256SDavid van Moolenbroek .ndr_recv = lan8710a_recv,
445af3c256SDavid van Moolenbroek .ndr_send = lan8710a_send,
45f7df02e7SDavid van Moolenbroek .ndr_intr = lan8710a_intr,
46f7df02e7SDavid van Moolenbroek .ndr_tick = lan8710a_tick
475af3c256SDavid van Moolenbroek };
48433d6423SLionel Sambuc
49433d6423SLionel Sambuc /*============================================================================*
50433d6423SLionel Sambuc * main *
51433d6423SLionel Sambuc *============================================================================*/
52433d6423SLionel Sambuc int
main(int argc,char * argv[])53433d6423SLionel Sambuc main(int argc, char *argv[])
54433d6423SLionel Sambuc {
55433d6423SLionel Sambuc struct machine machine;
56433d6423SLionel Sambuc
57433d6423SLionel Sambuc env_setargs(argc, argv);
58433d6423SLionel Sambuc
595af3c256SDavid van Moolenbroek sys_getmachine(&machine);
605af3c256SDavid van Moolenbroek if (BOARD_IS_BB(machine.board_id))
615af3c256SDavid van Moolenbroek netdriver_task(&lan8710a_table);
62433d6423SLionel Sambuc
63433d6423SLionel Sambuc return EXIT_SUCCESS;
64433d6423SLionel Sambuc }
65433d6423SLionel Sambuc
66433d6423SLionel Sambuc /*============================================================================*
675af3c256SDavid van Moolenbroek * lan8710a_init *
68433d6423SLionel Sambuc *============================================================================*/
69433d6423SLionel Sambuc static int
lan8710a_init(unsigned int instance,netdriver_addr_t * addr,uint32_t * caps,unsigned int * ticks)70f7df02e7SDavid van Moolenbroek lan8710a_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
71f7df02e7SDavid van Moolenbroek unsigned int * ticks)
72433d6423SLionel Sambuc {
73433d6423SLionel Sambuc /* Initialize the ethernet driver. */
74433d6423SLionel Sambuc
75433d6423SLionel Sambuc /* Clear state. */
76433d6423SLionel Sambuc memset(&lan8710a_state, 0, sizeof(lan8710a_state));
77433d6423SLionel Sambuc
78433d6423SLionel Sambuc /* Initialize driver. */
795af3c256SDavid van Moolenbroek lan8710a_map_regs();
80433d6423SLionel Sambuc
81f7df02e7SDavid van Moolenbroek lan8710a_init_hw(addr, instance);
82433d6423SLionel Sambuc
83f7df02e7SDavid van Moolenbroek *caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
84f7df02e7SDavid van Moolenbroek *ticks = sys_hz(); /* update statistics once a second */
85433d6423SLionel Sambuc return OK;
86433d6423SLionel Sambuc }
87433d6423SLionel Sambuc
88433d6423SLionel Sambuc /*============================================================================*
89433d6423SLionel Sambuc * lan8710a_enable_interrupt *
90433d6423SLionel Sambuc *============================================================================*/
91433d6423SLionel Sambuc static void
lan8710a_enable_interrupt(int interrupt)925af3c256SDavid van Moolenbroek lan8710a_enable_interrupt(int interrupt)
93433d6423SLionel Sambuc {
94433d6423SLionel Sambuc int r;
95433d6423SLionel Sambuc
96433d6423SLionel Sambuc if (interrupt & RX_INT) {
97433d6423SLionel Sambuc if ((r = sys_irqenable(&lan8710a_state.irq_rx_hook)) != OK) {
98433d6423SLionel Sambuc panic("sys_irqenable failed: %d", r);
99433d6423SLionel Sambuc }
100433d6423SLionel Sambuc }
101433d6423SLionel Sambuc if (interrupt & TX_INT) {
102433d6423SLionel Sambuc if ((r = sys_irqenable(&lan8710a_state.irq_tx_hook)) != OK) {
103433d6423SLionel Sambuc panic("sys_irqenable failed: %d", r);
104433d6423SLionel Sambuc }
105433d6423SLionel Sambuc }
106433d6423SLionel Sambuc }
1075af3c256SDavid van Moolenbroek
108433d6423SLionel Sambuc /*============================================================================*
1095af3c256SDavid van Moolenbroek * lan8710a_intr *
110433d6423SLionel Sambuc *============================================================================*/
111433d6423SLionel Sambuc static void
lan8710a_intr(unsigned int mask)1125af3c256SDavid van Moolenbroek lan8710a_intr(unsigned int mask)
113433d6423SLionel Sambuc {
114433d6423SLionel Sambuc u32_t dma_status;
115433d6423SLionel Sambuc
116433d6423SLionel Sambuc /* Check the card for interrupt reason(s). */
117433d6423SLionel Sambuc u32_t rx_stat = lan8710a_reg_read(CPSW_WR_C0_RX_STAT);
118433d6423SLionel Sambuc u32_t tx_stat = lan8710a_reg_read(CPSW_WR_C0_TX_STAT);
119433d6423SLionel Sambuc u32_t cp;
120433d6423SLionel Sambuc
121433d6423SLionel Sambuc /* Handle interrupts. */
122433d6423SLionel Sambuc if (rx_stat) {
123433d6423SLionel Sambuc cp = lan8710a_reg_read(CPDMA_STRAM_RX_CP(0));
124433d6423SLionel Sambuc
1255af3c256SDavid van Moolenbroek netdriver_recv();
126433d6423SLionel Sambuc
127433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_STRAM_RX_CP(0), cp);
128433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_EOI_VECTOR, RX_INT);
129433d6423SLionel Sambuc }
130433d6423SLionel Sambuc if (tx_stat) {
131433d6423SLionel Sambuc cp = lan8710a_reg_read(CPDMA_STRAM_TX_CP(0));
132433d6423SLionel Sambuc
133433d6423SLionel Sambuc /* Disabling channels, where Tx interrupt occurred */
134433d6423SLionel Sambuc lan8710a_reg_set(CPDMA_TX_INTMASK_CLEAR, tx_stat);
135433d6423SLionel Sambuc
1365af3c256SDavid van Moolenbroek netdriver_send();
137433d6423SLionel Sambuc
138433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_STRAM_TX_CP(0), cp);
139433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_EOI_VECTOR, TX_INT);
140433d6423SLionel Sambuc }
141433d6423SLionel Sambuc
142433d6423SLionel Sambuc dma_status = lan8710a_reg_read(CPDMA_STATUS);
143433d6423SLionel Sambuc
144433d6423SLionel Sambuc if (dma_status & CPDMA_ERROR) {
145433d6423SLionel Sambuc LAN8710A_DEBUG_PRINT(("CPDMA error: 0x%X, reset", dma_status));
146433d6423SLionel Sambuc lan8710a_dma_reset_init();
147433d6423SLionel Sambuc }
148433d6423SLionel Sambuc
149433d6423SLionel Sambuc /* Re-enable Rx interrupt. */
1505af3c256SDavid van Moolenbroek if (mask & (1 << RX_INT))
151433d6423SLionel Sambuc lan8710a_enable_interrupt(RX_INT);
152433d6423SLionel Sambuc
153433d6423SLionel Sambuc /* Re-enable Tx interrupt. */
1545af3c256SDavid van Moolenbroek if (mask & (1 << TX_INT))
155433d6423SLionel Sambuc lan8710a_enable_interrupt(TX_INT);
156433d6423SLionel Sambuc }
157433d6423SLionel Sambuc
158433d6423SLionel Sambuc /*============================================================================*
159433d6423SLionel Sambuc * lan8710a_init_addr *
160433d6423SLionel Sambuc *============================================================================*/
161433d6423SLionel Sambuc static void
lan8710a_init_addr(netdriver_addr_t * addr,unsigned int instance)162f7df02e7SDavid van Moolenbroek lan8710a_init_addr(netdriver_addr_t * addr, unsigned int instance)
163433d6423SLionel Sambuc {
164433d6423SLionel Sambuc static char eakey[]= LAN8710A_ENVVAR "#_EA";
165433d6423SLionel Sambuc static char eafmt[]= "x:x:x:x:x:x";
166433d6423SLionel Sambuc int i;
167433d6423SLionel Sambuc long v;
168433d6423SLionel Sambuc
169433d6423SLionel Sambuc /*
170433d6423SLionel Sambuc * Do we have a user defined ethernet address?
171433d6423SLionel Sambuc */
172f7df02e7SDavid van Moolenbroek eakey[sizeof(LAN8710A_ENVVAR)-1] = '0' + instance;
173433d6423SLionel Sambuc
174433d6423SLionel Sambuc for (i= 0; i < 6; i++) {
175433d6423SLionel Sambuc if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
176433d6423SLionel Sambuc break;
177433d6423SLionel Sambuc else
178f7df02e7SDavid van Moolenbroek addr->na_addr[i] = v;
179433d6423SLionel Sambuc }
1805af3c256SDavid van Moolenbroek if (i == 6)
1815af3c256SDavid van Moolenbroek return;
1825af3c256SDavid van Moolenbroek
1835af3c256SDavid van Moolenbroek /*
1845af3c256SDavid van Moolenbroek * No; get the address from the chip itself.
1855af3c256SDavid van Moolenbroek */
186f7df02e7SDavid van Moolenbroek addr->na_addr[0] = lan8710a_reg_read(CTRL_MAC_ID0_HI) & 0xFF;
187f7df02e7SDavid van Moolenbroek addr->na_addr[1] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 8) & 0xFF;
188f7df02e7SDavid van Moolenbroek addr->na_addr[2] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 16) & 0xFF;
189f7df02e7SDavid van Moolenbroek addr->na_addr[3] = (lan8710a_reg_read(CTRL_MAC_ID0_HI) >> 24) & 0xFF;
190f7df02e7SDavid van Moolenbroek addr->na_addr[4] = lan8710a_reg_read(CTRL_MAC_ID0_LO) & 0xFF;
191f7df02e7SDavid van Moolenbroek addr->na_addr[5] = (lan8710a_reg_read(CTRL_MAC_ID0_LO) >> 8) & 0xFF;
192433d6423SLionel Sambuc }
193433d6423SLionel Sambuc
194433d6423SLionel Sambuc /*============================================================================*
195433d6423SLionel Sambuc * lan8710a_map_regs *
196433d6423SLionel Sambuc *============================================================================*/
197433d6423SLionel Sambuc static void
lan8710a_map_regs(void)198433d6423SLionel Sambuc lan8710a_map_regs(void)
199433d6423SLionel Sambuc {
200433d6423SLionel Sambuc struct minix_mem_range mr;
201433d6423SLionel Sambuc mr.mr_base = CM_PER_BASE_ADR;
202433d6423SLionel Sambuc mr.mr_limit = CM_PER_BASE_ADR + MEMORY_LIMIT;
203433d6423SLionel Sambuc
204433d6423SLionel Sambuc if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
205433d6423SLionel Sambuc panic("Unable to request permission to map memory");
206433d6423SLionel Sambuc }
207433d6423SLionel Sambuc lan8710a_state.regs_cp_per =
208433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)CM_PER_BASE_ADR, 512);
209433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_cp_per == MAP_FAILED) {
210433d6423SLionel Sambuc panic("lan8710a_state.regs_cp_per: vm_map_phys failed");
211433d6423SLionel Sambuc }
212433d6423SLionel Sambuc lan8710a_state.regs_cpdma_stram =
213433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)CPDMA_STRAM_BASE_ADR, 512);
214433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_cpdma_stram == MAP_FAILED) {
215433d6423SLionel Sambuc panic("lan8710a_state.regs_cpdma_stram: vm_map_phys failed");
216433d6423SLionel Sambuc }
217433d6423SLionel Sambuc lan8710a_state.regs_cpsw_cpdma =
218433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)CPSW_CPDMA_BASE_ADR, 512);
219433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_cpsw_cpdma == MAP_FAILED) {
220433d6423SLionel Sambuc panic("lan8710a_state.regs_cpsw_cpdma: vm_map_phys failed");
221433d6423SLionel Sambuc }
222433d6423SLionel Sambuc lan8710a_state.regs_cpsw_ale =
223433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)CPSW_ALE_BASE_ADR, 256);
224433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_cpsw_ale == MAP_FAILED) {
225433d6423SLionel Sambuc panic("lan8710a_state.regs_cpsw_ale: vm_map_phys failed");
226433d6423SLionel Sambuc }
227433d6423SLionel Sambuc lan8710a_state.regs_cpsw_sl =
228433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)CPSW_SL_BASE_ADR, 512);
229433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_cpsw_sl == MAP_FAILED) {
230433d6423SLionel Sambuc panic("lan8710a_state.regs_cpsw_sl: vm_map_phys failed");
231433d6423SLionel Sambuc }
232433d6423SLionel Sambuc lan8710a_state.regs_cpsw_ss =
233433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)CPSW_SS_BASE_ADR, 512);
234433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_cpsw_ss == MAP_FAILED) {
235433d6423SLionel Sambuc panic("lan8710a_state.regs_cpsw_ss: vm_map_phys failed");
236433d6423SLionel Sambuc }
237433d6423SLionel Sambuc lan8710a_state.regs_cpsw_wr =
238433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)CPSW_WR_BASE_ADR, 512);
239433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_cpsw_wr == MAP_FAILED) {
240433d6423SLionel Sambuc panic("lan8710a_state.regs_cpsw_wr: vm_map_phys failed");
241433d6423SLionel Sambuc }
242433d6423SLionel Sambuc lan8710a_state.regs_ctrl_mod =
243433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)CTRL_MOD_BASE_ADR, 2560);
244433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_ctrl_mod == MAP_FAILED) {
245433d6423SLionel Sambuc panic("lan8710a_state.regs_ctrl_mod: vm_map_phys failed");
246433d6423SLionel Sambuc }
247433d6423SLionel Sambuc lan8710a_state.regs_intc =
248433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)INTC_BASE_ADR, 512);
249433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_intc == MAP_FAILED) {
250433d6423SLionel Sambuc panic("lan8710a_state.regs_intc: vm_map_phys failed");
251433d6423SLionel Sambuc }
252433d6423SLionel Sambuc lan8710a_state.regs_mdio =
253433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)MDIO_BASE_ADDR, 512);
254433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_mdio == MAP_FAILED) {
255433d6423SLionel Sambuc panic("lan8710a_state.regs_mdio: vm_map_phys failed");
256433d6423SLionel Sambuc }
257433d6423SLionel Sambuc
258433d6423SLionel Sambuc mr.mr_base = BEGINNING_DESC_MEM;
259433d6423SLionel Sambuc mr.mr_limit = BEGINNING_DESC_MEM + DESC_MEMORY_LIMIT;
260433d6423SLionel Sambuc
261433d6423SLionel Sambuc if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
262433d6423SLionel Sambuc panic("Unable to request permission to map memory");
263433d6423SLionel Sambuc }
264433d6423SLionel Sambuc lan8710a_state.rx_desc_phy = BEGINNING_RX_DESC_MEM;
265433d6423SLionel Sambuc lan8710a_state.tx_desc_phy = BEGINNING_TX_DESC_MEM;
266433d6423SLionel Sambuc lan8710a_state.rx_desc = (lan8710a_desc_t *)vm_map_phys(SELF,
267433d6423SLionel Sambuc (void *)lan8710a_state.rx_desc_phy, 1024);
268433d6423SLionel Sambuc if ((void *)lan8710a_state.rx_desc == MAP_FAILED) {
269433d6423SLionel Sambuc panic("lan8710a_state.rx_desc: vm_map_phys failed");
270433d6423SLionel Sambuc }
271433d6423SLionel Sambuc lan8710a_state.tx_desc = (lan8710a_desc_t *)vm_map_phys(SELF,
272433d6423SLionel Sambuc (void *)lan8710a_state.tx_desc_phy, 1024);
273433d6423SLionel Sambuc if ((void *)lan8710a_state.tx_desc == MAP_FAILED) {
274433d6423SLionel Sambuc panic("lan8710a_state.tx_desc: vm_map_phys failed");
275433d6423SLionel Sambuc }
276433d6423SLionel Sambuc
277433d6423SLionel Sambuc mr.mr_base = CPSW_STATS_BASE_ADR;
278433d6423SLionel Sambuc mr.mr_limit = CPSW_STATS_BASE_ADR + CPSW_STATS_MEM_LIMIT;
279433d6423SLionel Sambuc
280433d6423SLionel Sambuc if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
281433d6423SLionel Sambuc panic("Unable to request permission to map memory");
282433d6423SLionel Sambuc }
283433d6423SLionel Sambuc lan8710a_state.regs_cpsw_stats =
284433d6423SLionel Sambuc (vir_bytes)vm_map_phys(SELF, (void *)CPSW_STATS_BASE_ADR, 256);
285433d6423SLionel Sambuc if ((void *)lan8710a_state.regs_cpsw_stats == MAP_FAILED) {
286433d6423SLionel Sambuc panic("lan8710a_state.regs_cpsw_stats: vm_map_phys failed");
287433d6423SLionel Sambuc }
288433d6423SLionel Sambuc }
289433d6423SLionel Sambuc
290433d6423SLionel Sambuc /*============================================================================*
291f7df02e7SDavid van Moolenbroek * lan8710a_update_stats *
292433d6423SLionel Sambuc *============================================================================*/
293433d6423SLionel Sambuc static void
lan8710a_update_stats(void)294f7df02e7SDavid van Moolenbroek lan8710a_update_stats(void)
295433d6423SLionel Sambuc {
296f7df02e7SDavid van Moolenbroek uint32_t val;
297f7df02e7SDavid van Moolenbroek
298f7df02e7SDavid van Moolenbroek /*
299f7df02e7SDavid van Moolenbroek * AM335x Technical Reference (SPRUH73J) Sec. 14.3.2.20: statistics
300f7df02e7SDavid van Moolenbroek * registers are decrement-on-write when any of the statistics port
301f7df02e7SDavid van Moolenbroek * enable bits are set.
302f7df02e7SDavid van Moolenbroek */
303f7df02e7SDavid van Moolenbroek val = lan8710a_reg_read(CPSW_STAT_RX_CRC_ERR);
304f7df02e7SDavid van Moolenbroek lan8710a_reg_write(CPSW_STAT_RX_CRC_ERR, val);
305f7df02e7SDavid van Moolenbroek netdriver_stat_ierror(val);
306f7df02e7SDavid van Moolenbroek
307f7df02e7SDavid van Moolenbroek val = lan8710a_reg_read(CPSW_STAT_RX_AGNCD_ERR);
308f7df02e7SDavid van Moolenbroek lan8710a_reg_write(CPSW_STAT_RX_AGNCD_ERR, val);
309f7df02e7SDavid van Moolenbroek netdriver_stat_ierror(val);
310f7df02e7SDavid van Moolenbroek
311f7df02e7SDavid van Moolenbroek val = lan8710a_reg_read(CPSW_STAT_RX_OVERSIZE);
312f7df02e7SDavid van Moolenbroek lan8710a_reg_write(CPSW_STAT_RX_OVERSIZE, val);
313f7df02e7SDavid van Moolenbroek netdriver_stat_ierror(val);
314f7df02e7SDavid van Moolenbroek
315f7df02e7SDavid van Moolenbroek val = lan8710a_reg_read(CPSW_STAT_COLLISIONS);
316f7df02e7SDavid van Moolenbroek lan8710a_reg_write(CPSW_STAT_COLLISIONS, val);
317f7df02e7SDavid van Moolenbroek netdriver_stat_coll(val);
318f7df02e7SDavid van Moolenbroek }
319f7df02e7SDavid van Moolenbroek
320f7df02e7SDavid van Moolenbroek /*============================================================================*
321f7df02e7SDavid van Moolenbroek * lan8710a_tick *
322f7df02e7SDavid van Moolenbroek *============================================================================*/
323f7df02e7SDavid van Moolenbroek static void
lan8710a_tick(void)324f7df02e7SDavid van Moolenbroek lan8710a_tick(void)
325f7df02e7SDavid van Moolenbroek {
326f7df02e7SDavid van Moolenbroek
327f7df02e7SDavid van Moolenbroek /* Update statistics. */
328f7df02e7SDavid van Moolenbroek lan8710a_update_stats();
329433d6423SLionel Sambuc }
330433d6423SLionel Sambuc
331433d6423SLionel Sambuc /*============================================================================*
332433d6423SLionel Sambuc * lan8710a_stop *
333433d6423SLionel Sambuc *============================================================================*/
334433d6423SLionel Sambuc static void
lan8710a_stop(void)335433d6423SLionel Sambuc lan8710a_stop(void)
336433d6423SLionel Sambuc {
337433d6423SLionel Sambuc /* Reset hardware. */
338433d6423SLionel Sambuc lan8710a_reset_hw();
339433d6423SLionel Sambuc }
340433d6423SLionel Sambuc
341433d6423SLionel Sambuc /*============================================================================*
342433d6423SLionel Sambuc * lan8710a_dma_config_tx *
343433d6423SLionel Sambuc *============================================================================*/
344433d6423SLionel Sambuc static void
lan8710a_dma_config_tx(u8_t desc_idx)3453c8950ccSBen Gras lan8710a_dma_config_tx(u8_t desc_idx)
346433d6423SLionel Sambuc {
347433d6423SLionel Sambuc phys_bytes phys_addr;
348433d6423SLionel Sambuc int i;
349433d6423SLionel Sambuc for (i = 0; i < TX_DMA_CHANNELS; ++i) {
350433d6423SLionel Sambuc if (!lan8710a_reg_read(CPDMA_STRAM_TX_HDP(i))) break;
351433d6423SLionel Sambuc }
352433d6423SLionel Sambuc if (i == TX_DMA_CHANNELS) {
353433d6423SLionel Sambuc panic("There are no free TX DMA channels.");
354433d6423SLionel Sambuc }
355433d6423SLionel Sambuc
356433d6423SLionel Sambuc /* Enabling only one channel Tx interrupt */
357433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_TX_INTMASK_SET, 1 << i);
358433d6423SLionel Sambuc /* Routing only one channel Tx int to TX_PULSE signal */
359433d6423SLionel Sambuc lan8710a_reg_write(CPSW_WR_C0_TX_EN, 1 << i);
360433d6423SLionel Sambuc
361433d6423SLionel Sambuc /* Setting HDP */
362433d6423SLionel Sambuc phys_addr = lan8710a_state.tx_desc_phy +
363433d6423SLionel Sambuc (desc_idx * sizeof(lan8710a_desc_t));
364433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i), (u32_t)phys_addr);
365433d6423SLionel Sambuc }
366433d6423SLionel Sambuc
367433d6423SLionel Sambuc /*============================================================================*
368433d6423SLionel Sambuc * lan8710a_dma_reset_init *
369433d6423SLionel Sambuc *============================================================================*/
370433d6423SLionel Sambuc static void
lan8710a_dma_reset_init(void)371433d6423SLionel Sambuc lan8710a_dma_reset_init(void)
372433d6423SLionel Sambuc {
373433d6423SLionel Sambuc int i;
374433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_SOFT_RESET, SOFT_RESET);
375433d6423SLionel Sambuc while ((lan8710a_reg_read(CPDMA_SOFT_RESET) & SOFT_RESET));
376433d6423SLionel Sambuc
377433d6423SLionel Sambuc /*
378433d6423SLionel Sambuc * Initialize the HDPs (Header Description Pointers) and
379433d6423SLionel Sambuc * CPs (Completion Pointers) to NULL.
380433d6423SLionel Sambuc */
381433d6423SLionel Sambuc for (i = 0; i < DMA_MAX_CHANNELS; ++i) {
382433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_STRAM_TX_HDP(i), 0);
383433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_STRAM_RX_HDP(i), 0);
384433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_STRAM_TX_CP(i), 0);
385433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_STRAM_RX_CP(i), 0);
386433d6423SLionel Sambuc }
387433d6423SLionel Sambuc
388433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
389433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
390433d6423SLionel Sambuc
391433d6423SLionel Sambuc /* Configure the CPDMA controller. */
392433d6423SLionel Sambuc lan8710a_reg_set(CPDMA_RX_CONTROL, CPDMA_RX_EN); /* RX Enabled */
393433d6423SLionel Sambuc lan8710a_reg_set(CPDMA_TX_CONTROL, CPDMA_TX_EN); /* TX Enabled */
394433d6423SLionel Sambuc
395433d6423SLionel Sambuc /* Enabling first channel Rx interrupt */
396433d6423SLionel Sambuc lan8710a_reg_set(CPDMA_RX_INTMASK_SET, CPDMA_FIRST_CHAN_INT);
397433d6423SLionel Sambuc
398433d6423SLionel Sambuc /*
399433d6423SLionel Sambuc * Writing the address of the first buffer descriptor in the queue
400433d6423SLionel Sambuc * (nonzero value)to the channel�s head descriptor pointer in the
401433d6423SLionel Sambuc * channel�s Rx DMA state.
402433d6423SLionel Sambuc */
403433d6423SLionel Sambuc lan8710a_reg_write(CPDMA_STRAM_RX_HDP(0),
404433d6423SLionel Sambuc (u32_t)lan8710a_state.rx_desc_phy);
405433d6423SLionel Sambuc
406433d6423SLionel Sambuc lan8710a_state.rx_desc_idx = 0;
407433d6423SLionel Sambuc lan8710a_state.tx_desc_idx = 0;
408433d6423SLionel Sambuc }
409433d6423SLionel Sambuc
410433d6423SLionel Sambuc /*============================================================================*
411433d6423SLionel Sambuc * lan8710a_init_desc *
412433d6423SLionel Sambuc *============================================================================*/
413433d6423SLionel Sambuc static void
lan8710a_init_desc(void)414433d6423SLionel Sambuc lan8710a_init_desc(void)
415433d6423SLionel Sambuc {
416433d6423SLionel Sambuc lan8710a_desc_t *p_rx_desc;
417433d6423SLionel Sambuc lan8710a_desc_t *p_tx_desc;
418433d6423SLionel Sambuc phys_bytes buf_phys_addr;
419433d6423SLionel Sambuc u8_t i;
420433d6423SLionel Sambuc
421433d6423SLionel Sambuc /* Attempt to allocate. */
422433d6423SLionel Sambuc if ((lan8710a_state.p_rx_buf = alloc_contig((LAN8710A_NUM_RX_DESC
423433d6423SLionel Sambuc * LAN8710A_IOBUF_SIZE), AC_ALIGN4K,
424433d6423SLionel Sambuc &buf_phys_addr)) == NULL) {
425433d6423SLionel Sambuc panic("failed to allocate RX buffers.");
426433d6423SLionel Sambuc }
427433d6423SLionel Sambuc for (i = 0; i < LAN8710A_NUM_RX_DESC; i++) {
428433d6423SLionel Sambuc p_rx_desc = &(lan8710a_state.rx_desc[i]);
429433d6423SLionel Sambuc memset(p_rx_desc, 0x0, sizeof(lan8710a_desc_t));
430433d6423SLionel Sambuc p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN;
431433d6423SLionel Sambuc p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE;
432433d6423SLionel Sambuc p_rx_desc->buffer_pointer = (u32_t)(buf_phys_addr +
433433d6423SLionel Sambuc (i * LAN8710A_IOBUF_SIZE));
434433d6423SLionel Sambuc
435433d6423SLionel Sambuc p_rx_desc->next_pointer =
436433d6423SLionel Sambuc (u32_t)((i == (LAN8710A_NUM_RX_DESC - 1)) ?
437433d6423SLionel Sambuc (lan8710a_state.rx_desc_phy) :
438433d6423SLionel Sambuc (lan8710a_state.rx_desc_phy +
439433d6423SLionel Sambuc ((i + 1) * sizeof(lan8710a_desc_t))));
440433d6423SLionel Sambuc }
441433d6423SLionel Sambuc
442433d6423SLionel Sambuc /* Attempt to allocate. */
443433d6423SLionel Sambuc if ((lan8710a_state.p_tx_buf = alloc_contig((LAN8710A_NUM_TX_DESC
444433d6423SLionel Sambuc * LAN8710A_IOBUF_SIZE), AC_ALIGN4K,
445433d6423SLionel Sambuc &buf_phys_addr)) == NULL) {
446433d6423SLionel Sambuc panic("failed to allocate TX buffers");
447433d6423SLionel Sambuc }
448433d6423SLionel Sambuc for (i = 0; i < LAN8710A_NUM_TX_DESC; i++) {
449433d6423SLionel Sambuc p_tx_desc = &(lan8710a_state.tx_desc[i]);
450433d6423SLionel Sambuc memset(p_tx_desc, 0x0, sizeof(lan8710a_desc_t));
451433d6423SLionel Sambuc p_tx_desc->buffer_pointer = (u32_t)(buf_phys_addr +
452433d6423SLionel Sambuc (i * LAN8710A_IOBUF_SIZE));
453433d6423SLionel Sambuc }
454433d6423SLionel Sambuc lan8710a_state.rx_desc_idx = 0;
455433d6423SLionel Sambuc lan8710a_state.tx_desc_idx = 0;
456433d6423SLionel Sambuc }
457433d6423SLionel Sambuc
458433d6423SLionel Sambuc /*============================================================================*
459433d6423SLionel Sambuc * lan8710a_init_hw *
460433d6423SLionel Sambuc *============================================================================*/
461433d6423SLionel Sambuc static int
lan8710a_init_hw(netdriver_addr_t * addr,unsigned int instance)462f7df02e7SDavid van Moolenbroek lan8710a_init_hw(netdriver_addr_t * addr, unsigned int instance)
463433d6423SLionel Sambuc {
464433d6423SLionel Sambuc int r, i;
465433d6423SLionel Sambuc
466433d6423SLionel Sambuc /*
467433d6423SLionel Sambuc * Set the interrupt handler and policy. Do not automatically
468433d6423SLionel Sambuc * re-enable interrupts. Return the IRQ line number on interrupts.
469433d6423SLionel Sambuc */
470433d6423SLionel Sambuc lan8710a_state.irq_rx_hook = RX_INT;
471433d6423SLionel Sambuc if ((r = sys_irqsetpolicy(LAN8710A_RX_INTR, 0,
472433d6423SLionel Sambuc &lan8710a_state.irq_rx_hook)) != OK) {
473433d6423SLionel Sambuc panic("sys_irqsetpolicy failed: %d", r);
474433d6423SLionel Sambuc }
475433d6423SLionel Sambuc lan8710a_state.irq_tx_hook = TX_INT;
476433d6423SLionel Sambuc if ((r = sys_irqsetpolicy(LAN8710A_TX_INTR, 0,
477433d6423SLionel Sambuc &lan8710a_state.irq_tx_hook)) != OK) {
478433d6423SLionel Sambuc panic("sys_irqsetpolicy failed: %d", r);
479433d6423SLionel Sambuc }
480433d6423SLionel Sambuc
481433d6423SLionel Sambuc /* Reset hardware. */
482433d6423SLionel Sambuc lan8710a_reset_hw();
483433d6423SLionel Sambuc
484433d6423SLionel Sambuc /*
485433d6423SLionel Sambuc * Select the Interface (GMII/RGMII/MII) Mode in the Control Module.
486433d6423SLionel Sambuc * Port1 GMII/MII Mode, Port2 not used.
487433d6423SLionel Sambuc */
488433d6423SLionel Sambuc lan8710a_reg_write(GMII_SEL, (GMII2_SEL_BIT1 | GMII2_SEL_BIT0));
489433d6423SLionel Sambuc
490433d6423SLionel Sambuc /*
491433d6423SLionel Sambuc * Configure pads (PIN muxing) as per the Interface Selected using the
492433d6423SLionel Sambuc * appropriate pin muxing conf_xxx registers in the Control Module.
493433d6423SLionel Sambuc *
494433d6423SLionel Sambuc * CONF_MOD_SLEW_CTRL when 0 - Fast Mode, when 1 - Slow Mode
495433d6423SLionel Sambuc * CONF_MOD_RX_ACTIVE when 0 - Only output, when 1 - Also input
496433d6423SLionel Sambuc * CONF_MOD_PU_TYPESEL when 0 - Pull-down, when 1 - Pull-up
497433d6423SLionel Sambuc * CONF_MOD_PUDEN when 0 Pull* enabled, when 1 Pull* disabled
498433d6423SLionel Sambuc * CONF_MOD_MMODE_MII selects pin to work for MII interface
499433d6423SLionel Sambuc */
500433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_SLEW_CTRL);
501433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_RX_ACTIVE);
502433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_COL, CONF_MOD_PU_TYPESEL);
503433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_PUDEN);
504433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_COL, CONF_MOD_MMODE_MII);
505433d6423SLionel Sambuc
506433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_SLEW_CTRL);
507433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_RX_ACTIVE);
508433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_CRS, CONF_MOD_PU_TYPESEL);
509433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_PUDEN);
510433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_CRS, CONF_MOD_MMODE_MII);
511433d6423SLionel Sambuc
512433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_SLEW_CTRL);
513433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_RX_ACTIVE);
514433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RX_ER, CONF_MOD_PU_TYPESEL);
515433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_PUDEN);
516433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RX_ER, CONF_MOD_MMODE_MII);
517433d6423SLionel Sambuc
518433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_SLEW_CTRL);
519433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_RX_ACTIVE);
520433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_TX_EN, CONF_MOD_PUDEN);
521433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TX_EN, CONF_MOD_MMODE_MII);
522433d6423SLionel Sambuc
523433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_SLEW_CTRL);
524433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_RX_ACTIVE);
525433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RX_DV, CONF_MOD_PU_TYPESEL);
526433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_PUDEN);
527433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RX_DV, CONF_MOD_MMODE_MII);
528433d6423SLionel Sambuc
529433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_SLEW_CTRL);
530433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_RX_ACTIVE);
531433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_TXD3, CONF_MOD_PUDEN);
532433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD3, CONF_MOD_MMODE_MII);
533433d6423SLionel Sambuc
534433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_SLEW_CTRL);
535433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_RX_ACTIVE);
536433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_TXD2, CONF_MOD_PUDEN);
537433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD2, CONF_MOD_MMODE_MII);
538433d6423SLionel Sambuc
539433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_SLEW_CTRL);
540433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_RX_ACTIVE);
541433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_TXD1, CONF_MOD_PUDEN);
542433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD1, CONF_MOD_MMODE_MII);
543433d6423SLionel Sambuc
544433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_SLEW_CTRL);
545433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_RX_ACTIVE);
546433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_TXD0, CONF_MOD_PUDEN);
547433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TXD0, CONF_MOD_MMODE_MII);
548433d6423SLionel Sambuc
549433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_SLEW_CTRL);
550433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_RX_ACTIVE);
551433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_TX_CLK, CONF_MOD_PUDEN);
552433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_TX_CLK, CONF_MOD_MMODE_MII);
553433d6423SLionel Sambuc
554433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_SLEW_CTRL);
555433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_RX_ACTIVE);
556433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RX_CLK, CONF_MOD_PUDEN);
557433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RX_CLK, CONF_MOD_MMODE_MII);
558433d6423SLionel Sambuc
559433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_SLEW_CTRL);
560433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_RX_ACTIVE);
561433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RXD3, CONF_MOD_PU_TYPESEL);
562433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_PUDEN);
563433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD3, CONF_MOD_MMODE_MII);
564433d6423SLionel Sambuc
565433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_SLEW_CTRL);
566433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_RX_ACTIVE);
567433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RXD2, CONF_MOD_PU_TYPESEL);
568433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_PUDEN);
569433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD2, CONF_MOD_MMODE_MII);
570433d6423SLionel Sambuc
571433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_SLEW_CTRL);
572433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_RX_ACTIVE);
573433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RXD1, CONF_MOD_PU_TYPESEL);
574433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_PUDEN);
575433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD1, CONF_MOD_MMODE_MII);
576433d6423SLionel Sambuc
577433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_SLEW_CTRL);
578433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_RX_ACTIVE);
579433d6423SLionel Sambuc lan8710a_reg_set(CONF_MII1_RXD0, CONF_MOD_PU_TYPESEL);
580433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_PUDEN);
581433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MII1_RXD0, CONF_MOD_MMODE_MII);
582433d6423SLionel Sambuc
583433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MDIO, CONF_MOD_SLEW_CTRL);
584433d6423SLionel Sambuc lan8710a_reg_set(CONF_MDIO, CONF_MOD_RX_ACTIVE);
585433d6423SLionel Sambuc lan8710a_reg_set(CONF_MDIO, CONF_MOD_PU_TYPESEL);
586433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MDIO, CONF_MOD_PUDEN);
587433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MDIO, CONF_MOD_MMODE_MII);
588433d6423SLionel Sambuc
589433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MDC, CONF_MOD_SLEW_CTRL);
590433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MDC, CONF_MOD_RX_ACTIVE);
591433d6423SLionel Sambuc lan8710a_reg_set(CONF_MDC, CONF_MOD_PUDEN);
592433d6423SLionel Sambuc lan8710a_reg_unset(CONF_MDC, CONF_MOD_MMODE_MII);
593433d6423SLionel Sambuc
594433d6423SLionel Sambuc /* Apply soft reset to 3PSW Subsytem, CPSW_3G, CPGMAC_SL, and CPDMA. */
595433d6423SLionel Sambuc lan8710a_reg_write(CPSW_SS_SOFT_RESET, SOFT_RESET);
596433d6423SLionel Sambuc lan8710a_reg_write(CPSW_SL_SOFT_RESET(1), SOFT_RESET);
597433d6423SLionel Sambuc lan8710a_reg_write(CPSW_SL_SOFT_RESET(2), SOFT_RESET);
598433d6423SLionel Sambuc
599433d6423SLionel Sambuc /* Wait for software resets completion */
600433d6423SLionel Sambuc while ((lan8710a_reg_read(CPSW_SS_SOFT_RESET) & SOFT_RESET) ||
601433d6423SLionel Sambuc (lan8710a_reg_read(CPSW_SL_SOFT_RESET(1)) & SOFT_RESET) ||
602433d6423SLionel Sambuc (lan8710a_reg_read(CPSW_SL_SOFT_RESET(2)) & SOFT_RESET));
603433d6423SLionel Sambuc
604433d6423SLionel Sambuc /* Configure the Statistics Port Enable register. */
605433d6423SLionel Sambuc /* Enable port 0 and 1 statistics. */
606433d6423SLionel Sambuc lan8710a_reg_write(CPSW_SS_STAT_PORT_EN, (CPSW_P1_STAT_EN |
607433d6423SLionel Sambuc CPSW_P0_STAT_EN));
608433d6423SLionel Sambuc
609433d6423SLionel Sambuc /*
610433d6423SLionel Sambuc * Configure the ALE.
611433d6423SLionel Sambuc * Enabling Ale.
612433d6423SLionel Sambuc * All packets received on ports 1 are
613433d6423SLionel Sambuc * sent to the host (only to the host).
614433d6423SLionel Sambuc */
615433d6423SLionel Sambuc lan8710a_reg_write(CPSW_ALE_CONTROL, (CPSW_ALE_ENABLE |
616433d6423SLionel Sambuc CPSW_ALE_BYPASS));
617433d6423SLionel Sambuc /* Port 0 (host) in forwarding mode. */
618433d6423SLionel Sambuc lan8710a_reg_write(CPSW_ALE_PORTCTL0, CPSW_ALE_PORT_FWD);
619433d6423SLionel Sambuc /* Port 1 in forwarding mode. */
620433d6423SLionel Sambuc lan8710a_reg_write(CPSW_ALE_PORTCTL1, CPSW_ALE_PORT_FWD);
621433d6423SLionel Sambuc
622433d6423SLionel Sambuc /*
623433d6423SLionel Sambuc * Configure CPSW_SL Register
624433d6423SLionel Sambuc * Full duplex mode.
625433d6423SLionel Sambuc */
626433d6423SLionel Sambuc lan8710a_reg_write(CPSW_SL_MACCONTROL(1), CPSW_SL_FULLDUPLEX);
627433d6423SLionel Sambuc
628433d6423SLionel Sambuc /* Initialize MDIO Protocol */
629433d6423SLionel Sambuc lan8710a_init_mdio();
630433d6423SLionel Sambuc
631433d6423SLionel Sambuc /* Getting MAC Address */
632f7df02e7SDavid van Moolenbroek lan8710a_init_addr(addr, instance);
633433d6423SLionel Sambuc
634433d6423SLionel Sambuc /* Initialize descriptors */
635433d6423SLionel Sambuc lan8710a_init_desc();
636433d6423SLionel Sambuc
637433d6423SLionel Sambuc /* Reset and initialize CPDMA */
638433d6423SLionel Sambuc lan8710a_dma_reset_init();
639433d6423SLionel Sambuc
640433d6423SLionel Sambuc /*
641433d6423SLionel Sambuc * Configure the Interrupts.
642433d6423SLionel Sambuc * Routing all channel Rx int to RX_PULSE signal.
643433d6423SLionel Sambuc */
644433d6423SLionel Sambuc lan8710a_reg_set(CPSW_WR_C0_RX_EN, CPSW_FIRST_CHAN_INT);
645433d6423SLionel Sambuc
646433d6423SLionel Sambuc /*
647433d6423SLionel Sambuc * Enabling LAN8710A Auto-negotiation
648433d6423SLionel Sambuc */
649433d6423SLionel Sambuc lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_AUTO_NEG);
650433d6423SLionel Sambuc
651433d6423SLionel Sambuc /* Waiting for auto-negotiaion completion. */
652433d6423SLionel Sambuc for (i = 0; !(lan8710a_phy_read(LAN8710A_STATUS_REG) &
653433d6423SLionel Sambuc LAN8710A_AUTO_NEG_COMPL); ++i) {
654433d6423SLionel Sambuc if (i == 100) {
655433d6423SLionel Sambuc LAN8710A_DEBUG_PRINT(("Autonegotiation failed"));
656433d6423SLionel Sambuc break;
657433d6423SLionel Sambuc }
658*d4dd6511Srlfnb micro_delay(1666666);
659433d6423SLionel Sambuc }
660433d6423SLionel Sambuc
661433d6423SLionel Sambuc /* GMII RX and TX release from reset. */
662433d6423SLionel Sambuc lan8710a_reg_set(CPSW_SL_MACCONTROL(1), CPSW_SL_GMII_EN);
663433d6423SLionel Sambuc
664433d6423SLionel Sambuc /* Enable interrupts. */
665433d6423SLionel Sambuc lan8710a_enable_interrupt(RX_INT | TX_INT);
666433d6423SLionel Sambuc
667433d6423SLionel Sambuc return TRUE;
668433d6423SLionel Sambuc }
669433d6423SLionel Sambuc
670433d6423SLionel Sambuc /*============================================================================*
671433d6423SLionel Sambuc * lan8710a_init_mdio *
672433d6423SLionel Sambuc *============================================================================*/
673433d6423SLionel Sambuc static void
lan8710a_init_mdio(void)674433d6423SLionel Sambuc lan8710a_init_mdio(void)
675433d6423SLionel Sambuc {
676433d6423SLionel Sambuc u16_t address = 0;
677433d6423SLionel Sambuc u32_t r;
678433d6423SLionel Sambuc
679433d6423SLionel Sambuc /* Clearing MDIOCONTROL register */
680433d6423SLionel Sambuc lan8710a_reg_write(MDIOCONTROL, 0);
681433d6423SLionel Sambuc /* Configure the PREAMBLE and CLKDIV in the MDIO control register */
682433d6423SLionel Sambuc lan8710a_reg_unset(MDIOCONTROL, MDIO_PREAMBLE); /* CLKDIV default */
683433d6423SLionel Sambuc /* Enable sending MDIO frame preambles */
684433d6423SLionel Sambuc lan8710a_reg_set(MDIOCONTROL, (MDCLK_DIVIDER | MDIO_ENABLE));
685433d6423SLionel Sambuc /* Enable the MDIO module by setting the ENABLE bit in MDIOCONTROL */
686433d6423SLionel Sambuc
687433d6423SLionel Sambuc while (!(r = lan8710a_reg_read(MDIOALIVE)));
688433d6423SLionel Sambuc
689433d6423SLionel Sambuc /* Get PHY address */
690433d6423SLionel Sambuc while (r >>= 1) {
691433d6423SLionel Sambuc ++address;
692433d6423SLionel Sambuc }
693433d6423SLionel Sambuc lan8710a_state.phy_address = address;
694433d6423SLionel Sambuc
695433d6423SLionel Sambuc /* Setup appropiate address in MDIOUSERPHYSEL0 */
696433d6423SLionel Sambuc lan8710a_reg_set(MDIOUSERPHYSEL0, address);
697433d6423SLionel Sambuc }
698433d6423SLionel Sambuc
699433d6423SLionel Sambuc /*============================================================================*
7005af3c256SDavid van Moolenbroek * lan8710a_send *
701433d6423SLionel Sambuc *============================================================================*/
7025af3c256SDavid van Moolenbroek static int
lan8710a_send(struct netdriver_data * data,size_t size)7035af3c256SDavid van Moolenbroek lan8710a_send(struct netdriver_data * data, size_t size)
704433d6423SLionel Sambuc {
705433d6423SLionel Sambuc lan8710a_t *e = &lan8710a_state;
706433d6423SLionel Sambuc lan8710a_desc_t *p_tx_desc;
7075af3c256SDavid van Moolenbroek u8_t *buf;
708433d6423SLionel Sambuc
709433d6423SLionel Sambuc /* setup descriptors */
710433d6423SLionel Sambuc p_tx_desc = &(e->tx_desc[e->tx_desc_idx]);
711433d6423SLionel Sambuc
712433d6423SLionel Sambuc /*
7135af3c256SDavid van Moolenbroek * Check if descriptor is available for host and suspend if not.
714433d6423SLionel Sambuc */
7155af3c256SDavid van Moolenbroek if (LAN8710A_DESC_FLAG_OWN & p_tx_desc->pkt_len_flags)
7165af3c256SDavid van Moolenbroek return SUSPEND;
7175af3c256SDavid van Moolenbroek
7185af3c256SDavid van Moolenbroek /* Drop packets that exceed the size of our transmission buffer. */
7195af3c256SDavid van Moolenbroek if (size > LAN8710A_IOBUF_SIZE) {
720f7df02e7SDavid van Moolenbroek printf("%s: dropping large packet (%zu)\n",
721f7df02e7SDavid van Moolenbroek netdriver_name(), size);
7225af3c256SDavid van Moolenbroek
7235af3c256SDavid van Moolenbroek return OK;
724433d6423SLionel Sambuc }
725433d6423SLionel Sambuc
726433d6423SLionel Sambuc /* virtual address of buffer */
7275af3c256SDavid van Moolenbroek buf = e->p_tx_buf + e->tx_desc_idx * LAN8710A_IOBUF_SIZE;
728433d6423SLionel Sambuc
7295af3c256SDavid van Moolenbroek netdriver_copyin(data, 0, buf, size);
730433d6423SLionel Sambuc
731433d6423SLionel Sambuc /* set descriptor length */
7325af3c256SDavid van Moolenbroek p_tx_desc->buffer_length_off = size;
733433d6423SLionel Sambuc /* set flags */
734433d6423SLionel Sambuc p_tx_desc->pkt_len_flags = (LAN8710A_DESC_FLAG_OWN |
735433d6423SLionel Sambuc LAN8710A_DESC_FLAG_SOP |
736433d6423SLionel Sambuc LAN8710A_DESC_FLAG_EOP |
737433d6423SLionel Sambuc TX_DESC_TO_PORT1 |
738433d6423SLionel Sambuc TX_DESC_TO_PORT_EN);
7395af3c256SDavid van Moolenbroek p_tx_desc->pkt_len_flags |= size;
740433d6423SLionel Sambuc
741433d6423SLionel Sambuc /* setup DMA transfer */
742433d6423SLionel Sambuc lan8710a_dma_config_tx(e->tx_desc_idx);
743433d6423SLionel Sambuc
744433d6423SLionel Sambuc e->tx_desc_idx++;
7455af3c256SDavid van Moolenbroek if (LAN8710A_NUM_TX_DESC == e->tx_desc_idx)
746433d6423SLionel Sambuc e->tx_desc_idx = 0;
7475af3c256SDavid van Moolenbroek
7485af3c256SDavid van Moolenbroek return OK;
749433d6423SLionel Sambuc }
750433d6423SLionel Sambuc
751433d6423SLionel Sambuc /*============================================================================*
7525af3c256SDavid van Moolenbroek * lan8710a_recv *
753433d6423SLionel Sambuc *============================================================================*/
7545af3c256SDavid van Moolenbroek static ssize_t
lan8710a_recv(struct netdriver_data * data,size_t max)7555af3c256SDavid van Moolenbroek lan8710a_recv(struct netdriver_data * data, size_t max)
756433d6423SLionel Sambuc {
757433d6423SLionel Sambuc lan8710a_t *e = &lan8710a_state;
758433d6423SLionel Sambuc lan8710a_desc_t *p_rx_desc;
759433d6423SLionel Sambuc u32_t flags;
7605af3c256SDavid van Moolenbroek u8_t *buf;
7615af3c256SDavid van Moolenbroek size_t off, size, chunk;
762433d6423SLionel Sambuc
763433d6423SLionel Sambuc /*
764433d6423SLionel Sambuc * Only handle one packet at a time.
765433d6423SLionel Sambuc */
766433d6423SLionel Sambuc p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
767433d6423SLionel Sambuc /* find next OWN descriptor with SOP flag */
7685af3c256SDavid van Moolenbroek while ((0 == (LAN8710A_DESC_FLAG_SOP & p_rx_desc->pkt_len_flags)) &&
7695af3c256SDavid van Moolenbroek (0 == (LAN8710A_DESC_FLAG_OWN & p_rx_desc->pkt_len_flags))) {
770433d6423SLionel Sambuc p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE;
771433d6423SLionel Sambuc /* set ownership of current descriptor to EMAC */
772433d6423SLionel Sambuc p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN;
773433d6423SLionel Sambuc
774433d6423SLionel Sambuc e->rx_desc_idx++;
775433d6423SLionel Sambuc if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx)
776433d6423SLionel Sambuc e->rx_desc_idx = 0;
777433d6423SLionel Sambuc p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
778433d6423SLionel Sambuc }
7795af3c256SDavid van Moolenbroek
780433d6423SLionel Sambuc if (0 == (LAN8710A_DESC_FLAG_SOP & p_rx_desc->pkt_len_flags)) {
781433d6423SLionel Sambuc /* SOP was not found */
7825af3c256SDavid van Moolenbroek return SUSPEND;
783433d6423SLionel Sambuc }
784433d6423SLionel Sambuc
785433d6423SLionel Sambuc /*
7865af3c256SDavid van Moolenbroek * Copy data from descriptors, from SOP to EOP inclusive.
7875af3c256SDavid van Moolenbroek * TODO: make sure that the presence of a SOP slot implies the presence
7885af3c256SDavid van Moolenbroek * of an EOP slot, because we are not checking for ownership below..
789433d6423SLionel Sambuc */
7905af3c256SDavid van Moolenbroek size = 0;
7915af3c256SDavid van Moolenbroek off = 0;
792433d6423SLionel Sambuc
7935af3c256SDavid van Moolenbroek for (;;) {
7945af3c256SDavid van Moolenbroek buf = e->p_rx_buf + e->rx_desc_idx * LAN8710A_IOBUF_SIZE + off;
7955af3c256SDavid van Moolenbroek chunk = p_rx_desc->buffer_length_off & 0xFFFF;
796433d6423SLionel Sambuc
7975af3c256SDavid van Moolenbroek /* Truncate packets that are too large. */
7985af3c256SDavid van Moolenbroek if (chunk > max - size)
7995af3c256SDavid van Moolenbroek chunk = max - size;
800433d6423SLionel Sambuc
8015af3c256SDavid van Moolenbroek if (chunk > 0) {
8025af3c256SDavid van Moolenbroek netdriver_copyout(data, size, buf, chunk);
8035af3c256SDavid van Moolenbroek
8045af3c256SDavid van Moolenbroek size += chunk;
805433d6423SLionel Sambuc }
8065af3c256SDavid van Moolenbroek
807433d6423SLionel Sambuc flags = p_rx_desc->pkt_len_flags;
8085af3c256SDavid van Moolenbroek
8095af3c256SDavid van Moolenbroek /* Whole buffer move to the next descriptor */
810433d6423SLionel Sambuc p_rx_desc->buffer_length_off = LAN8710A_IOBUF_SIZE;
8115af3c256SDavid van Moolenbroek /* set ownership of current desc to EMAC */
812433d6423SLionel Sambuc p_rx_desc->pkt_len_flags = LAN8710A_DESC_FLAG_OWN;
813433d6423SLionel Sambuc
814433d6423SLionel Sambuc e->rx_desc_idx++;
815433d6423SLionel Sambuc if (LAN8710A_NUM_RX_DESC == e->rx_desc_idx)
816433d6423SLionel Sambuc e->rx_desc_idx = 0;
817433d6423SLionel Sambuc p_rx_desc = &(e->rx_desc[e->rx_desc_idx]);
8185af3c256SDavid van Moolenbroek
8195af3c256SDavid van Moolenbroek /* if EOP flag is set -> stop processing */
8205af3c256SDavid van Moolenbroek if (flags & LAN8710A_DESC_FLAG_EOP)
8215af3c256SDavid van Moolenbroek break;
822433d6423SLionel Sambuc
823433d6423SLionel Sambuc /*
8245af3c256SDavid van Moolenbroek * TODO: the upper 16 bits of buffer_length_off are used *only*
8255af3c256SDavid van Moolenbroek * for descriptors *after* the first one; I'm retaining this
8265af3c256SDavid van Moolenbroek * behavior because I don't have the chip's spec, but it may be
8275af3c256SDavid van Moolenbroek * better to simplify/correct this behavior. --David
828433d6423SLionel Sambuc */
8295af3c256SDavid van Moolenbroek off = p_rx_desc->buffer_length_off >> 16;
830433d6423SLionel Sambuc }
8315af3c256SDavid van Moolenbroek
8325af3c256SDavid van Moolenbroek return size;
833433d6423SLionel Sambuc }
834433d6423SLionel Sambuc
835433d6423SLionel Sambuc /*============================================================================*
836433d6423SLionel Sambuc * lan8710a_phy_write *
837433d6423SLionel Sambuc *============================================================================*/
838433d6423SLionel Sambuc static void
lan8710a_phy_write(u32_t reg,u32_t value)8395af3c256SDavid van Moolenbroek lan8710a_phy_write(u32_t reg, u32_t value)
840433d6423SLionel Sambuc {
841433d6423SLionel Sambuc if (!(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)) {
842433d6423SLionel Sambuc /* Clearing MDIOUSERACCESS0 register */
843433d6423SLionel Sambuc lan8710a_reg_write(MDIOUSERACCESS0, 0);
844433d6423SLionel Sambuc /* Setting proper values in MDIOUSERACCESS0 */
845433d6423SLionel Sambuc lan8710a_reg_set(MDIOUSERACCESS0, MDIO_WRITE);
846433d6423SLionel Sambuc lan8710a_reg_set(MDIOUSERACCESS0, reg << MDIO_REGADR);
847433d6423SLionel Sambuc lan8710a_reg_set(MDIOUSERACCESS0,
848433d6423SLionel Sambuc lan8710a_state.phy_address << MDIO_PHYADR);
849433d6423SLionel Sambuc /* Data written only 16 bits. */
8505af3c256SDavid van Moolenbroek lan8710a_reg_set(MDIOUSERACCESS0,
8515af3c256SDavid van Moolenbroek (value & 0xFFFF) << MDIO_DATA);
852433d6423SLionel Sambuc lan8710a_reg_set(MDIOUSERACCESS0, MDIO_GO);
853433d6423SLionel Sambuc
854433d6423SLionel Sambuc /* Waiting for writing completion */
855433d6423SLionel Sambuc while (lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO);
856433d6423SLionel Sambuc }
857433d6423SLionel Sambuc }
858433d6423SLionel Sambuc
859433d6423SLionel Sambuc /*============================================================================*
860433d6423SLionel Sambuc * lan8710a_phy_read *
861433d6423SLionel Sambuc *============================================================================*/
862433d6423SLionel Sambuc static u32_t
lan8710a_phy_read(u32_t reg)8635af3c256SDavid van Moolenbroek lan8710a_phy_read(u32_t reg)
864433d6423SLionel Sambuc {
865433d6423SLionel Sambuc u32_t value = 0xFFFFFFFF;
866433d6423SLionel Sambuc
867433d6423SLionel Sambuc if (!(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)) {
868433d6423SLionel Sambuc /* Clearing MDIOUSERACCESS0 register */
869433d6423SLionel Sambuc lan8710a_reg_write(MDIOUSERACCESS0, 0);
870433d6423SLionel Sambuc /* Setting proper values in MDIOUSERACCESS0 */
871433d6423SLionel Sambuc lan8710a_reg_unset(MDIOUSERACCESS0, MDIO_WRITE);
872433d6423SLionel Sambuc /* Reg number must be 5 bit long */
873433d6423SLionel Sambuc lan8710a_reg_set(MDIOUSERACCESS0, (reg & 0x1F) << MDIO_REGADR);
874433d6423SLionel Sambuc /* Addr must be 5 bit long */
875433d6423SLionel Sambuc lan8710a_reg_set(MDIOUSERACCESS0,
876433d6423SLionel Sambuc (lan8710a_state.phy_address & 0x1F) << MDIO_PHYADR);
877433d6423SLionel Sambuc lan8710a_reg_set(MDIOUSERACCESS0, MDIO_GO);
878433d6423SLionel Sambuc
879433d6423SLionel Sambuc /* Waiting for reading completion */
880433d6423SLionel Sambuc while ((lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_GO)
881433d6423SLionel Sambuc && !(lan8710a_reg_read(MDIOUSERACCESS0) & MDIO_ACK));
882433d6423SLionel Sambuc
883433d6423SLionel Sambuc /* Reading data */
884433d6423SLionel Sambuc value = lan8710a_reg_read(MDIOUSERACCESS0) & 0xFFFF;
885433d6423SLionel Sambuc }
886433d6423SLionel Sambuc return value;
887433d6423SLionel Sambuc }
888433d6423SLionel Sambuc
889433d6423SLionel Sambuc /*============================================================================*
890433d6423SLionel Sambuc * lan8710a_reset_hw *
891433d6423SLionel Sambuc *============================================================================*/
892433d6423SLionel Sambuc static void
lan8710a_reset_hw(void)8935af3c256SDavid van Moolenbroek lan8710a_reset_hw(void)
894433d6423SLionel Sambuc {
895433d6423SLionel Sambuc /* Assert a Device Reset signal. */
896433d6423SLionel Sambuc lan8710a_phy_write(LAN8710A_CTRL_REG, LAN8710A_SOFT_RESET);
897433d6423SLionel Sambuc
898433d6423SLionel Sambuc /* Waiting for reset completion. */
899433d6423SLionel Sambuc while (lan8710a_phy_read(LAN8710A_CTRL_REG) & LAN8710A_SOFT_RESET);
900433d6423SLionel Sambuc }
901433d6423SLionel Sambuc
902433d6423SLionel Sambuc /*============================================================================*
903433d6423SLionel Sambuc * lan8710a_reg_read *
904433d6423SLionel Sambuc *============================================================================*/
905433d6423SLionel Sambuc static u32_t
lan8710a_reg_read(volatile u32_t * reg)9065af3c256SDavid van Moolenbroek lan8710a_reg_read(volatile u32_t *reg)
907433d6423SLionel Sambuc {
908433d6423SLionel Sambuc u32_t value;
909433d6423SLionel Sambuc
910433d6423SLionel Sambuc /* Read from memory mapped register. */
911433d6423SLionel Sambuc value = *reg;
912433d6423SLionel Sambuc
913433d6423SLionel Sambuc /* Return the result. */
914433d6423SLionel Sambuc return value;
915433d6423SLionel Sambuc }
916433d6423SLionel Sambuc
917433d6423SLionel Sambuc /*============================================================================*
918433d6423SLionel Sambuc * lan8710a_reg_write *
919433d6423SLionel Sambuc *============================================================================*/
920433d6423SLionel Sambuc static void
lan8710a_reg_write(volatile u32_t * reg,u32_t value)9215af3c256SDavid van Moolenbroek lan8710a_reg_write(volatile u32_t *reg, u32_t value)
922433d6423SLionel Sambuc {
923433d6423SLionel Sambuc /* Write to memory mapped register. */
924433d6423SLionel Sambuc *reg = value;
925433d6423SLionel Sambuc }
926433d6423SLionel Sambuc
927433d6423SLionel Sambuc /*============================================================================*
928433d6423SLionel Sambuc * lan8710a_reg_set *
929433d6423SLionel Sambuc *============================================================================*/
930433d6423SLionel Sambuc static void
lan8710a_reg_set(volatile u32_t * reg,u32_t value)9315af3c256SDavid van Moolenbroek lan8710a_reg_set(volatile u32_t *reg, u32_t value)
932433d6423SLionel Sambuc {
933433d6423SLionel Sambuc u32_t data;
934433d6423SLionel Sambuc
935433d6423SLionel Sambuc /* First read the current value. */
936433d6423SLionel Sambuc data = lan8710a_reg_read(reg);
937433d6423SLionel Sambuc
938433d6423SLionel Sambuc /* Set value, and write back. */
939433d6423SLionel Sambuc lan8710a_reg_write(reg, data | value);
940433d6423SLionel Sambuc }
941433d6423SLionel Sambuc
942433d6423SLionel Sambuc /*============================================================================*
943433d6423SLionel Sambuc * lan8710a_reg_unset *
944433d6423SLionel Sambuc *============================================================================*/
945433d6423SLionel Sambuc static void
lan8710a_reg_unset(volatile u32_t * reg,u32_t value)9465af3c256SDavid van Moolenbroek lan8710a_reg_unset(volatile u32_t *reg, u32_t value)
947433d6423SLionel Sambuc {
948433d6423SLionel Sambuc u32_t data;
949433d6423SLionel Sambuc
950433d6423SLionel Sambuc /* First read the current value. */
951433d6423SLionel Sambuc data = lan8710a_reg_read(reg);
952433d6423SLionel Sambuc
953433d6423SLionel Sambuc /* Unset value, and write back. */
954433d6423SLionel Sambuc lan8710a_reg_write(reg, data & ~value);
955433d6423SLionel Sambuc }
956