5 * \brief KS8851SNL driver for SAM.
\r
7 * Copyright (c) 2013-2015 Atmel Corporation. All rights reserved.
\r
13 * Redistribution and use in source and binary forms, with or without
\r
14 * modification, are permitted provided that the following conditions are met:
\r
16 * 1. Redistributions of source code must retain the above copyright notice,
\r
17 * this list of conditions and the following disclaimer.
\r
19 * 2. Redistributions in binary form must reproduce the above copyright notice,
\r
20 * this list of conditions and the following disclaimer in the documentation
\r
21 * and/or other materials provided with the distribution.
\r
23 * 3. The name of Atmel may not be used to endorse or promote products derived
\r
24 * from this software without specific prior written permission.
\r
26 * 4. This software may only be redistributed and used in connection with an
\r
27 * Atmel microcontroller product.
\r
29 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
\r
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
31 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
32 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
\r
33 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
\r
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
\r
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
\r
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
\r
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
\r
38 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
\r
39 * POSSIBILITY OF SUCH DAMAGE.
\r
45 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
\r
48 /* FreeRTOS includes. */
\r
49 #include "FreeRTOS.h"
\r
52 #include "spi_master.h"
\r
53 #include "ksz8851snl.h"
\r
54 #include "ksz8851snl_reg.h"
\r
57 #include "pio_handler.h"
\r
59 #include "conf_eth.h"
\r
61 /* Clock polarity. */
\r
62 #define SPI_CLK_POLARITY 0
\r
65 #define SPI_CLK_PHASE 1
\r
67 /* SPI PDC register base. */
\r
68 Pdc *g_p_spi_pdc = 0;
\r
70 int lUDPLoggingPrintf( const char *pcFormatString, ... );
\r
72 /* Temporary buffer for PDC reception. */
\r
73 uint8_t tmpbuf[1536] __attribute__ ((aligned (16)));
\r
80 void dbg_add_line( const char *pcFormat, ... );
\r
82 static void spi_clear_ovres( void );
\r
85 * \brief Read register content, set bitmask and write back to register.
\r
87 * \param reg the register address to modify.
\r
88 * \param bits_to_set bitmask to apply.
\r
90 void ksz8851_reg_setbits(uint16_t reg, uint16_t bits_to_set)
\r
94 temp = ksz8851_reg_read(reg);
\r
95 temp |= bits_to_set;
\r
96 ksz8851_reg_write(reg, temp);
\r
100 * \brief Read register content, clear bitmask and write back to register.
\r
102 * \param reg the register address to modify.
\r
103 * \param bits_to_set bitmask to apply.
\r
105 void ksz8851_reg_clrbits(uint16_t reg, uint16_t bits_to_clr)
\r
109 temp = ksz8851_reg_read(reg);
\r
110 temp &= ~(uint32_t) bits_to_clr;
\r
111 ksz8851_reg_write(reg, temp);
\r
115 * \brief Configure the INTN interrupt.
\r
117 void configure_intn(void (*p_handler) (uint32_t, uint32_t))
\r
119 // gpio_configure_pin(KSZ8851SNL_INTN_GPIO, PIO_INPUT);
\r
120 // pio_set_input(PIOA, PIO_PA11_IDX, PIO_PULLUP);
\r
122 /* Configure PIO clock. */
\r
123 pmc_enable_periph_clk(INTN_ID);
\r
125 /* Adjust PIO debounce filter parameters, uses 10 Hz filter. */
\r
126 pio_set_debounce_filter(INTN_PIO, INTN_PIN_MSK, 10);
\r
128 /* Initialize PIO interrupt handlers, see PIO definition in board.h. */
\r
129 pio_handler_set(INTN_PIO, INTN_ID, INTN_PIN_MSK,
\r
130 INTN_ATTR, p_handler);
\r
132 /* Enable NVIC interrupts. */
\r
133 NVIC_SetPriority(INTN_IRQn, INT_PRIORITY_PIO);
\r
134 NVIC_EnableIRQ((IRQn_Type)INTN_ID);
\r
136 /* Enable PIO interrupts. */
\r
137 pio_enable_interrupt(INTN_PIO, INTN_PIN_MSK);
\r
141 * \brief Read a register value.
\r
143 * \param reg the register address to modify.
\r
145 * \return the register value.
\r
147 uint16_t ksz8851_reg_read(uint16_t reg)
\r
149 pdc_packet_t g_pdc_spi_tx_packet;
\r
150 pdc_packet_t g_pdc_spi_rx_packet;
\r
155 while( iTryCount-- > 0 )
\r
160 /* Move register address to cmd bits 9-2, make 32-bit address. */
\r
161 cmd = (reg << 2) & REG_ADDR_MASK;
\r
163 /* Last 2 bits still under "don't care bits" handled with byte enable. */
\r
164 /* Select byte enable for command. */
\r
166 /* Odd word address writes bytes 2 and 3 */
\r
167 cmd |= (0xc << 10);
\r
169 /* Even word address write bytes 0 and 1 */
\r
170 cmd |= (0x3 << 10);
\r
173 /* Add command read code. */
\r
175 cmdBuf.uc[0] = cmd >> 8;
\r
176 cmdBuf.uc[1] = cmd & 0xff;
\r
177 cmdBuf.uc[2] = CONFIG_SPI_MASTER_DUMMY;
\r
178 cmdBuf.uc[3] = CONFIG_SPI_MASTER_DUMMY;
\r
180 /* Prepare PDC transfer. */
\r
181 g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
\r
182 g_pdc_spi_tx_packet.ul_size = 4;
\r
183 g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
\r
184 g_pdc_spi_rx_packet.ul_size = 4;
\r
185 pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
\r
186 pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, NULL);
\r
187 pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, NULL);
\r
188 gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);
\r
190 spi_disable_interrupt( KSZ8851SNL_SPI, ~0ul );
\r
191 pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
\r
194 ulStatus = spi_read_status( KSZ8851SNL_SPI );
\r
195 if( ( ulStatus & ( SPI_SR_OVRES | SPI_SR_ENDRX ) ) != 0 )
\r
200 gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
\r
201 if( ( ulStatus & SPI_SR_OVRES ) == 0 )
\r
205 pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
\r
206 lUDPLoggingPrintf( "ksz8851_reg_read: SPI_SR_OVRES\n" );
\r
209 res = (tmpbuf[3] << 8) | tmpbuf[2];
\r
214 * \brief Write a register value.
\r
216 * \param reg the register address to modify.
\r
217 * \param wrdata the new register value.
\r
219 void ksz8851_reg_write(uint16_t reg, uint16_t wrdata)
\r
221 pdc_packet_t g_pdc_spi_tx_packet;
\r
222 pdc_packet_t g_pdc_spi_rx_packet;
\r
226 while( iTryCount-- > 0 )
\r
232 /* Move register address to cmd bits 9-2, make 32-bit address. */
\r
233 cmd = (reg << 2) & REG_ADDR_MASK;
\r
235 /* Last 2 bits still under "don't care bits" handled with byte enable. */
\r
236 /* Select byte enable for command. */
\r
238 /* Odd word address writes bytes 2 and 3 */
\r
239 cmd |= (0xc << 10);
\r
241 /* Even word address write bytes 0 and 1 */
\r
242 cmd |= (0x3 << 10);
\r
245 /* Add command write code. */
\r
247 cmdBuf.uc[0] = cmd >> 8;
\r
248 cmdBuf.uc[1] = cmd & 0xff;
\r
249 cmdBuf.uc[2] = wrdata & 0xff;
\r
250 cmdBuf.uc[3] = wrdata >> 8;
\r
252 /* Prepare PDC transfer. */
\r
253 g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
\r
254 g_pdc_spi_tx_packet.ul_size = 4;
\r
255 g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
\r
256 g_pdc_spi_rx_packet.ul_size = 4;
\r
257 pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
\r
258 pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, NULL);
\r
259 pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, NULL);
\r
260 gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);
\r
262 spi_disable_interrupt( KSZ8851SNL_SPI, ~0ul );
\r
264 pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
\r
267 ulStatus = spi_read_status( KSZ8851SNL_SPI );
\r
268 if( ( ulStatus & ( SPI_SR_OVRES | SPI_SR_ENDRX ) ) != 0 )
\r
273 gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
\r
274 if( ( ulStatus & SPI_SR_OVRES ) == 0 )
\r
278 pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
\r
279 lUDPLoggingPrintf( "ksz8851_reg_write: SPI_SR_OVRES\n" );
\r
283 static void spi_clear_ovres( void )
\r
285 volatile uint32_t rc;
\r
286 rc = KSZ8851SNL_SPI->SPI_RDR;
\r
288 spi_read_status( KSZ8851SNL_SPI );
\r
292 * \brief Read internal fifo buffer.
\r
294 * \param buf the buffer to store the data from the fifo buffer.
\r
295 * \param len the amount of data to read.
\r
297 void ksz8851_fifo_read(uint8_t *buf, uint32_t len)
\r
299 pdc_packet_t g_pdc_spi_tx_packet;
\r
300 pdc_packet_t g_pdc_spi_rx_packet;
\r
301 pdc_packet_t g_pdc_spi_tx_npacket;
\r
302 pdc_packet_t g_pdc_spi_rx_npacket;
\r
304 memset( cmdBuf.uc, '\0', sizeof cmdBuf );
\r
305 cmdBuf.uc[0] = FIFO_READ;
\r
308 /* Prepare PDC transfer. */
\r
309 g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
\r
310 g_pdc_spi_tx_packet.ul_size = 9;
\r
311 g_pdc_spi_rx_packet.ul_addr = (uint32_t) respBuf.uc;
\r
312 g_pdc_spi_rx_packet.ul_size = 9;
\r
314 g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
\r
315 g_pdc_spi_tx_npacket.ul_size = len;
\r
316 g_pdc_spi_rx_npacket.ul_addr = (uint32_t) buf;
\r
317 g_pdc_spi_rx_npacket.ul_size = len;
\r
318 pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
\r
319 pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
\r
320 pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);
\r
322 spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_RXBUFF | SPI_IER_OVRES);
\r
324 pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
\r
328 * \brief Write internal fifo buffer.
\r
330 * \param buf the buffer to send to the fifo buffer.
\r
331 * \param ulActualLength the total amount of data to write.
\r
332 * \param ulFIFOLength the size of the first pbuf to write from the pbuf chain.
\r
334 void ksz8851_fifo_write(uint8_t *buf, uint32_t ulActualLength, uint32_t ulFIFOLength)
\r
336 static uint8_t frameID = 0;
\r
338 pdc_packet_t g_pdc_spi_tx_packet;
\r
339 pdc_packet_t g_pdc_spi_rx_packet;
\r
340 pdc_packet_t g_pdc_spi_tx_npacket;
\r
341 pdc_packet_t g_pdc_spi_rx_npacket;
\r
343 /* Prepare control word and byte count. */
\r
344 cmdBuf.uc[0] = FIFO_WRITE;
\r
345 cmdBuf.uc[1] = frameID++ & 0x3f;
\r
347 cmdBuf.uc[3] = ulActualLength & 0xff;
\r
348 cmdBuf.uc[4] = ulActualLength >> 8;
\r
352 /* Prepare PDC transfer. */
\r
353 g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
\r
354 g_pdc_spi_tx_packet.ul_size = 5;
\r
356 g_pdc_spi_rx_packet.ul_addr = (uint32_t) respBuf.uc;
\r
357 g_pdc_spi_rx_packet.ul_size = 5;
\r
359 g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
\r
360 g_pdc_spi_tx_npacket.ul_size = ulFIFOLength;
\r
362 g_pdc_spi_rx_npacket.ul_addr = (uint32_t) tmpbuf;
\r
363 g_pdc_spi_rx_npacket.ul_size = ulFIFOLength;
\r
365 pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
\r
366 pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
\r
367 #if( TX_USES_RECV == 1 )
\r
368 pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);
\r
369 spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_ENDRX | SPI_IER_OVRES);
\r
370 pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
\r
372 spi_enable_interrupt(KSZ8851SNL_SPI, SPI_SR_TXBUFE | SPI_IER_OVRES);
\r
373 pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_TXTEN);
\r
378 * \brief Write dummy data to the internal fifo buffer.
\r
380 * \param len the amount of dummy data to write.
\r
382 void ksz8851_fifo_dummy(uint32_t len)
\r
384 pdc_packet_t g_pdc_spi_tx_packet;
\r
385 pdc_packet_t g_pdc_spi_rx_packet;
\r
387 /* Prepare PDC transfer. */
\r
388 g_pdc_spi_tx_packet.ul_addr = (uint32_t) tmpbuf;
\r
389 g_pdc_spi_tx_packet.ul_size = len;
\r
390 g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
\r
391 g_pdc_spi_rx_packet.ul_size = len;
\r
392 pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
\r
393 pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, NULL);
\r
394 pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, NULL);
\r
395 pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
\r
397 while (!(spi_read_status(KSZ8851SNL_SPI) & SPI_SR_ENDRX))
\r
401 void ksz8851snl_set_registers(void)
\r
403 /* Init step2-4: write QMU MAC address (low, middle then high). */
\r
404 ksz8851_reg_write(REG_MAC_ADDR_0, (ETHERNET_CONF_ETHADDR4 << 8) | ETHERNET_CONF_ETHADDR5);
\r
405 ksz8851_reg_write(REG_MAC_ADDR_2, (ETHERNET_CONF_ETHADDR2 << 8) | ETHERNET_CONF_ETHADDR3);
\r
406 ksz8851_reg_write(REG_MAC_ADDR_4, (ETHERNET_CONF_ETHADDR0 << 8) | ETHERNET_CONF_ETHADDR1);
\r
408 /* Init step5: enable QMU Transmit Frame Data Pointer Auto Increment. */
\r
409 ksz8851_reg_write(REG_TX_ADDR_PTR, ADDR_PTR_AUTO_INC);
\r
411 /* Init step6: configure QMU transmit control register. */
\r
412 ksz8851_reg_write(REG_TX_CTRL,
\r
413 TX_CTRL_ICMP_CHECKSUM |
\r
414 TX_CTRL_UDP_CHECKSUM |
\r
415 TX_CTRL_TCP_CHECKSUM |
\r
416 TX_CTRL_IP_CHECKSUM |
\r
417 TX_CTRL_FLOW_ENABLE |
\r
418 TX_CTRL_PAD_ENABLE |
\r
422 /* Init step7: enable QMU Receive Frame Data Pointer Auto Increment. */
\r
423 ksz8851_reg_write(REG_RX_ADDR_PTR, ADDR_PTR_AUTO_INC);
\r
425 /* Init step8: configure QMU Receive Frame Threshold for one frame. */
\r
426 ksz8851_reg_write(REG_RX_FRAME_CNT_THRES, 1);
\r
428 /* Init step9: configure QMU receive control register1. */
\r
429 ksz8851_reg_write(REG_RX_CTRL1,
\r
430 RX_CTRL_UDP_CHECKSUM |
\r
431 RX_CTRL_TCP_CHECKSUM |
\r
432 RX_CTRL_IP_CHECKSUM |
\r
433 RX_CTRL_MAC_FILTER |
\r
434 RX_CTRL_FLOW_ENABLE |
\r
435 RX_CTRL_BROADCAST |
\r
436 RX_CTRL_ALL_MULTICAST|
\r
438 // ksz8851_reg_write(REG_RX_CTRL1,
\r
439 // RX_CTRL_UDP_CHECKSUM |
\r
440 // RX_CTRL_TCP_CHECKSUM |
\r
441 // RX_CTRL_IP_CHECKSUM |
\r
442 // RX_CTRL_FLOW_ENABLE |
\r
443 // RX_CTRL_PROMISCUOUS);
\r
445 ksz8851_reg_write(REG_RX_CTRL2,
\r
446 RX_CTRL_IPV6_UDP_NOCHECKSUM |
\r
447 RX_CTRL_UDP_LITE_CHECKSUM |
\r
448 RX_CTRL_ICMP_CHECKSUM |
\r
449 RX_CTRL_BURST_LEN_FRAME);
\r
452 //#define RXQ_TWOBYTE_OFFSET (0x0200) /* Enable adding 2-byte before frame header for IP aligned with DWORD */
\r
453 #warning Remember to try the above option to get a 2-byte offset
\r
455 /* Init step11: configure QMU receive queue: trigger INT and auto-dequeue frame. */
\r
456 ksz8851_reg_write( REG_RXQ_CMD, RXQ_CMD_CNTL | RXQ_TWOBYTE_OFFSET );
\r
458 /* Init step12: adjust SPI data output delay. */
\r
459 ksz8851_reg_write(REG_BUS_CLOCK_CTRL, BUS_CLOCK_166 | BUS_CLOCK_DIVIDEDBY_1);
\r
461 /* Init step13: restart auto-negotiation. */
\r
462 ksz8851_reg_setbits(REG_PORT_CTRL, PORT_AUTO_NEG_RESTART);
\r
464 /* Init step13.1: force link in half duplex if auto-negotiation failed. */
\r
465 if ((ksz8851_reg_read(REG_PORT_CTRL) & PORT_AUTO_NEG_RESTART) != PORT_AUTO_NEG_RESTART)
\r
467 ksz8851_reg_clrbits(REG_PORT_CTRL, PORT_FORCE_FULL_DUPLEX);
\r
470 /* Init step14: clear interrupt status. */
\r
471 ksz8851_reg_write(REG_INT_STATUS, 0xFFFF);
\r
473 /* Init step15: set interrupt mask. */
\r
474 ksz8851_reg_write(REG_INT_MASK, INT_RX);
\r
476 /* Init step16: enable QMU Transmit. */
\r
477 ksz8851_reg_setbits(REG_TX_CTRL, TX_CTRL_ENABLE);
\r
479 /* Init step17: enable QMU Receive. */
\r
480 ksz8851_reg_setbits(REG_RX_CTRL1, RX_CTRL_ENABLE);
\r
483 * \brief KSZ8851SNL initialization function.
\r
485 * \return 0 on success, 1 on communication error.
\r
487 uint32_t ksz8851snl_init(void)
\r
489 uint32_t count = 10;
\r
490 uint16_t dev_id = 0;
\r
493 /* Configure the SPI peripheral. */
\r
494 spi_enable_clock(KSZ8851SNL_SPI);
\r
495 spi_disable(KSZ8851SNL_SPI);
\r
496 spi_reset(KSZ8851SNL_SPI);
\r
497 spi_set_master_mode(KSZ8851SNL_SPI);
\r
498 spi_disable_mode_fault_detect(KSZ8851SNL_SPI);
\r
499 spi_set_peripheral_chip_select_value(KSZ8851SNL_SPI, ~(uint32_t)(1UL << KSZ8851SNL_CS_PIN));
\r
500 spi_set_fixed_peripheral_select(KSZ8851SNL_SPI);
\r
501 //spi_disable_peripheral_select_decode(KSZ8851SNL_SPI);
\r
503 spi_set_clock_polarity(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, SPI_CLK_POLARITY);
\r
504 spi_set_clock_phase(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, SPI_CLK_PHASE);
\r
505 spi_set_bits_per_transfer(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN,
\r
506 SPI_CSR_BITS_8_BIT);
\r
507 spi_set_baudrate_div(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, (sysclk_get_cpu_hz() / KSZ8851SNL_CLOCK_SPEED));
\r
508 // spi_set_transfer_delay(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, CONFIG_SPI_MASTER_DELAY_BS,
\r
509 // CONFIG_SPI_MASTER_DELAY_BCT);
\r
512 spi_set_transfer_delay(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, 0, 0);
\r
514 spi_enable(KSZ8851SNL_SPI);
\r
516 /* Get pointer to UART PDC register base. */
\r
517 g_p_spi_pdc = spi_get_pdc_base(KSZ8851SNL_SPI);
\r
518 pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
\r
520 /* Control RSTN and CSN pin from the driver. */
\r
521 gpio_configure_pin(KSZ8851SNL_CSN_GPIO, KSZ8851SNL_CSN_FLAGS);
\r
522 gpio_set_pin_high(KSZ8851SNL_CSN_GPIO);
\r
523 gpio_configure_pin(KSZ8851SNL_RSTN_GPIO, KSZ8851SNL_RSTN_FLAGS);
\r
525 /* Reset the Micrel in a proper state. */
\r
528 /* Perform hardware reset with respect to the reset timing from the datasheet. */
\r
529 gpio_set_pin_low(KSZ8851SNL_RSTN_GPIO);
\r
531 gpio_set_pin_high(KSZ8851SNL_RSTN_GPIO);
\r
534 /* Init step1: read chip ID. */
\r
535 dev_id = ksz8851_reg_read(REG_CHIP_ID);
\r
536 if( ( dev_id & 0xFFF0 ) == CHIP_ID_8851_16 )
\r
544 ksz8851snl_set_registers();
\r
547 return id_ok ? 1 : -1;
\r
550 uint32_t ksz8851snl_reinit(void)
\r
552 uint32_t count = 10;
\r
553 uint16_t dev_id = 0;
\r
555 /* Reset the Micrel in a proper state. */
\r
558 /* Perform hardware reset with respect to the reset timing from the datasheet. */
\r
559 gpio_set_pin_low(KSZ8851SNL_RSTN_GPIO);
\r
561 gpio_set_pin_high(KSZ8851SNL_RSTN_GPIO);
\r
564 /* Init step1: read chip ID. */
\r
565 dev_id = ksz8851_reg_read(REG_CHIP_ID);
\r
566 if( ( dev_id & 0xFFF0 ) == CHIP_ID_8851_16 )
\r
574 ksz8851snl_set_registers();
\r
577 return id_ok ? 1 : -1;
\r
580 uint32_t ksz8851snl_reset_rx( void )
\r
584 usValue = ksz8851_reg_read(REG_RX_CTRL1);
\r
586 usValue &= ~( ( uint16_t ) RX_CTRL_ENABLE | RX_CTRL_FLUSH_QUEUE );
\r
588 ksz8851_reg_write( REG_RX_CTRL1, usValue ); vTaskDelay( 2 );
\r
589 ksz8851_reg_write( REG_RX_CTRL1, usValue | RX_CTRL_FLUSH_QUEUE ); vTaskDelay( 1 );
\r
590 ksz8851_reg_write( REG_RX_CTRL1, usValue ); vTaskDelay( 1 );
\r
591 ksz8851_reg_write( REG_RX_CTRL1, usValue | RX_CTRL_ENABLE ); vTaskDelay( 1 );
\r
593 return ( uint32_t )usValue;
\r
596 uint32_t ksz8851snl_reset_tx( void )
\r
600 usValue = ksz8851_reg_read( REG_TX_CTRL );
\r
602 usValue &= ~( ( uint16_t ) TX_CTRL_ENABLE | TX_CTRL_FLUSH_QUEUE );
\r
604 ksz8851_reg_write( REG_TX_CTRL, usValue ); vTaskDelay( 2 );
\r
605 ksz8851_reg_write( REG_TX_CTRL, usValue | TX_CTRL_FLUSH_QUEUE ); vTaskDelay( 1 );
\r
606 ksz8851_reg_write( REG_TX_CTRL, usValue ); vTaskDelay( 1 );
\r
607 ksz8851_reg_write( REG_TX_CTRL, usValue | TX_CTRL_ENABLE ); vTaskDelay( 1 );
\r
609 return ( uint32_t )usValue;
\r