ksz8851snl_spi.c

Go to the documentation of this file.
00001 /**************************************************************************/
00015 #include <stdio.h>
00016 #include <stdint.h>
00017 
00018 #include "ksz8851snl_spi.h"
00019 #include "em_assert.h"
00020 #include "em_common.h"
00021 #include "em_gpio.h"
00022 #include "spidrv.h"
00023 
00024 #define BOGUS_BYTE           0xFF               
00025 #define REG_MASK             0x03               
00026 #define OPCODE_REG_READ      0x00               
00027 #define OPCODE_REG_WRITE     0x40               
00028 #define OPCODE_FIFO_READ     0x80               
00029 #define OPCODE_FIFO_WRITE    0xC0               
00030 #define ADDRESS_MS2B_POS     0x06               
00031 #define ADDRESS_SHIFT        0x02               
00032 #define BYTE_ENABLE          0x03               
00033 #define BYTE_ENABLE_SHIFT    0x02               
00035 /* GPIO pins used for SPI communication. */
00036 /*(USART 1, Location #1) */
00037 #define ETH_CS_PIN       3                      
00038 #define ETH_CS_PORT      gpioPortD              
00042 static SPIDRV_HandleData_t spiHandleData;
00043 static SPIDRV_Handle_t spiHandle = &spiHandleData;
00044 
00048 /**************************************************************************/
00057 void KSZ8851SNL_SPI_Init(void)
00058 {
00059   Ecode_t result;
00060   SPIDRV_Init_t initData = SPIDRV_MASTER_USART1;
00061   initData.bitRate = 8000000; // 8 MHz max safe speed
00062   initData.frameLength = 8;
00063   initData.dummyTxValue = BOGUS_BYTE;
00064   initData.bitOrder = spidrvBitOrderMsbFirst;
00065   initData.clockMode = spidrvClockMode0;
00066   initData.csControl = spidrvCsControlApplication;
00067 
00068   result = SPIDRV_Init(spiHandle, &initData);
00069   EFM_ASSERT(result == ECODE_EMDRV_SPIDRV_OK);
00070 
00071   GPIO_PinModeSet(ETH_CS_PORT, ETH_CS_PIN, gpioModePushPull, 1);
00072 }
00073 
00074 
00075 /**************************************************************************/
00085 static void KSZ8851SNL_SPI_Transmit(int numBytes, const uint8_t * data)
00086 {
00087   Ecode_t result;
00088   int remaining = numBytes;
00089 
00090   /* The spidrv is using dma to transfer bytes to the USART (spi)
00091    * this is why we must transmit bytes in chunks of at most
00092    * DMADRV_MAX_XFER_COUNT (1024 on EFM32GG990F1024)
00093    */
00094   do {
00095     int count  = EFM32_MIN(remaining, DMADRV_MAX_XFER_COUNT);
00096     result     = SPIDRV_MTransmitB(spiHandle, data, count);
00097     remaining -= count;
00098     data      += count;
00099   } while (result == ECODE_EMDRV_SPIDRV_OK && remaining > 0);
00100 
00101   EFM_ASSERT(result == ECODE_EMDRV_SPIDRV_OK);
00102 }
00103 
00104 
00105 /**************************************************************************/
00115 static void KSZ8851SNL_SPI_Receive(int numBytes, uint8_t * buffer)
00116 {
00117   Ecode_t result;
00118   int remaining = numBytes;
00119 
00120   /* The spidrv is using dma to receive bytes from the USART (spi)
00121    * this is why we must receive bytes in chunks of at most
00122    * DMADRV_MAX_XFER_COUNT (1024 on EFM32GG990F1024)
00123    */
00124   do {
00125     int count  = EFM32_MIN(remaining, DMADRV_MAX_XFER_COUNT);
00126     result     = SPIDRV_MReceiveB(spiHandle, buffer, count);
00127     remaining -= count;
00128     buffer    += count;
00129   } while (result == ECODE_EMDRV_SPIDRV_OK && remaining > 0);
00130 
00131   EFM_ASSERT(result == ECODE_EMDRV_SPIDRV_OK);
00132 }
00133 
00134 
00135 /**************************************************************************/
00144 static void KSZ8851SNL_SPI_SetChipSelect(bool enable)
00145 {
00146   if (enable)
00147   {
00148     GPIO_PinOutClear(ETH_CS_PORT, ETH_CS_PIN);
00149   }
00150   else
00151   {
00152     GPIO_PinOutSet(ETH_CS_PORT, ETH_CS_PIN);
00153   }
00154 }
00155 
00156 
00157 /**************************************************************************/
00167 uint16_t KSZ8851SNL_SPI_ReadRegister(uint8_t reg)
00168 {
00169   uint16_t value = 0x0000;
00170   uint8_t txBuffer[4];
00171   uint8_t rxBuffer[4];
00172 
00185   txBuffer[0]  = OPCODE_REG_READ;
00186   txBuffer[0] |= BYTE_ENABLE << (BYTE_ENABLE_SHIFT + (reg & REG_MASK));
00187   txBuffer[0] |= (reg >> ADDRESS_MS2B_POS);
00188   txBuffer[1]  = (reg << ADDRESS_SHIFT) & 0xf0;
00189 
00190   KSZ8851SNL_SPI_SetChipSelect(true);
00191   SPIDRV_MTransferB(spiHandle, txBuffer, rxBuffer, 4);
00192   KSZ8851SNL_SPI_SetChipSelect(false);
00193 
00194   value = (rxBuffer[3] << 8) | rxBuffer[2];
00195   return value;
00196 }
00197 
00198 
00199 /**************************************************************************/
00209 void KSZ8851SNL_SPI_WriteRegister(uint8_t reg, uint16_t value)
00210 {
00211   uint8_t txBuffer[4];
00212 
00225   txBuffer[0]  = OPCODE_REG_WRITE | (BYTE_ENABLE << (BYTE_ENABLE_SHIFT + (reg & REG_MASK)));
00226   txBuffer[0] |= reg >> ADDRESS_MS2B_POS;
00227   txBuffer[1]  = (reg << ADDRESS_SHIFT) & 0xf0;
00228   txBuffer[2]  = value & 0xff;
00229   txBuffer[3]  = (value >> 8) & 0xff;
00230 
00231   KSZ8851SNL_SPI_SetChipSelect(true);
00232   KSZ8851SNL_SPI_Transmit(4, txBuffer);
00233   KSZ8851SNL_SPI_SetChipSelect(false);
00234 }
00235 
00236 
00237 /*************************************************************************/
00257 void KSZ8851SNL_SPI_ReadFifo(int numBytes, uint8_t *data)
00258 {
00259   EFM_ASSERT(numBytes >= 0 && numBytes < 12000);
00260   EFM_ASSERT(data != NULL);
00261 
00262   uint8_t cmd = OPCODE_FIFO_READ;
00263   uint8_t dummy[4];
00264 
00265   KSZ8851SNL_SPI_SetChipSelect(true);
00266   KSZ8851SNL_SPI_Transmit(1, &cmd);
00267   KSZ8851SNL_SPI_Receive(4, dummy);
00268   KSZ8851SNL_SPI_Receive(numBytes, data);
00269   KSZ8851SNL_SPI_SetChipSelect(false);
00270 }
00271 
00272 /*************************************************************************/
00275 void KSZ8851SNL_SPI_WriteFifoBegin(void)
00276 {
00277   uint8_t cmd = OPCODE_FIFO_WRITE;
00278   /* Enable chip select */
00279   KSZ8851SNL_SPI_SetChipSelect(true);
00280   /* Send Write command */
00281   KSZ8851SNL_SPI_Transmit(1, &cmd);
00282 }
00283 
00284 /*************************************************************************/
00289 void KSZ8851SNL_SPI_WriteFifo(int numBytes, const uint8_t *data)
00290 {
00291   EFM_ASSERT(numBytes >= 0 && numBytes < 12000);
00292   EFM_ASSERT(data != NULL);
00293 
00294   KSZ8851SNL_SPI_Transmit(numBytes, data);
00295 }
00296 
00297 
00298 /*************************************************************************/
00301 void KSZ8851SNL_SPI_WriteFifoEnd(void)
00302 {
00303   KSZ8851SNL_SPI_SetChipSelect(false);
00304 }