spi


#ifndef _SPI_H_
#define _SPI_H_

#include "tistdtypes.h"

// Prevent C++ name mangling
#ifdef __cplusplus
extern far "c" {
#endif

/************************************************************
* Global Macro Declarations                                 *
************************************************************/

#define SPI_RXINTFLAG     (0x00000100u)
#define SPI_OVRNINTFLG    (0x00000040u)
#define SPI_BITERRFLG     (0x00000010u)
#define SPI_DESELECTFLG   (0x00000004u)            // SPI_PARERRFLG

#define SPI_CS_NUM        (0)


/***********************************************************
* Global Typedef declarations                              *
***********************************************************/

// SPI Module Roles
typedef enum _SPI_ROLE_
{
  SPI_ROLE_MASTER = 0x01,
  SPI_ROLE_SLAVE = 0x02
}
SPI_Role;

// SPI Module Modes of Operation
typedef enum _SPI_MODE_
{
  SPI_MODE_3PIN       = 0x01,
  SPI_MODE_4PIN_CS    = 0x02,
  SPI_MODE_4PIN_ENA   = 0x04,
  SPI_MODE_5PIN       = 0x08
}
SPI_Mode;

typedef struct _SPI_CONFIG_
{
  Uint8 polarity;
  Uint8 phase;
  Uint8 prescalar;
  Uint8 charLen;
}
SPI_Config;

// SPI driver structure
typedef struct _SPI_INFO_
{
  Uint32      peripheralNum;
  Uint32      csNum;
  void        *regs;
  SPI_Role    role;
  SPI_Mode    mode;
  SPI_Config  *config;
}
SPI_InfoObj, *SPI_InfoHandle;


/************************************************************
* Global Function Declarations                              *
************************************************************/

extern SPI_InfoHandle SPI_open(Uint32 spiPeripheralNum, SPI_Role role, SPI_Mode mode, SPI_Config *config);
extern Uint32 SPI_reset(SPI_InfoHandle hSPIInfo);
extern Uint32 SPI_readBytes(SPI_InfoHandle hSPIInfo, Uint32 byteCnt, Uint8 *dest);
extern Uint32 SPI_writeBytes(SPI_InfoHandle hSPIInfo, Uint32 byteCnt, Uint8 *src);
extern Uint32 SPI_xferOneChar(SPI_InfoHandle hSPIInfo, Uint32 dataOut);
extern void SPI_enableCS(SPI_InfoHandle hSPIInfo);
extern void SPI_disableCS(SPI_InfoHandle hSPIInfo);
extern Uint32 SPIBOOT_copy(Uint32 spiInstanceNum);


/***********************************************************
* End file                                                 *
***********************************************************/

#ifdef __cplusplus
}
#endif

#endif //_SPI_H_

 

// General type include
#include "tistdtypes.h"

// Device specific CSL
#include "device.h"

// Util functions
#include "util.h"

// This module's header file
#include "spi.h"


/************************************************************
* Explicit External Declarations                            *
************************************************************/


/************************************************************
* Local Macro Declarations                                  *
************************************************************/

#define DELAY_AFTER_CS_DN     (4700)
#define DELAY_BEFORE_CS_UP    (3800)
#define DELAY_AFTER_CS_UP     (9400)

/************************************************************
* Local Function Declarations                               *
************************************************************/

static Uint32 LOCAL_setupMode(SPI_InfoHandle hSPIInfo);

/************************************************************
* Local Variable Definitions                                *
************************************************************/


/************************************************************
* Global Variable Definitions                               *
************************************************************/

#ifdef USE_IN_ROM
SPI_InfoObj gSPIInfo;
#endif


/************************************************************
* Global Function Definitions                               *
************************************************************/

// Initialze NAND interface and find the details of the NAND used
SPI_InfoHandle SPI_open(Uint32 spiPeripheralNum, SPI_Role role, SPI_Mode mode, SPI_Config *config)
{
  DEVICE_SPIRegs *SPI;
  SPI_InfoHandle hSPIInfo;
 
  if (spiPeripheralNum >= SPI_PERIPHERAL_CNT)
    return NULL;
   
#ifdef USE_IN_ROM
  hSPIInfo = (SPI_InfoHandle) &gSPIInfo;
#else
  hSPIInfo = (SPI_InfoHandle) UTIL_allocMem(sizeof(SPI_InfoObj));
#endif

  // Assign the correct register base
  hSPIInfo->peripheralNum = spiPeripheralNum; 
  hSPIInfo->csNum = SPI_CS_NUM;
  hSPIInfo->regs = (void *) (((Uint32)SPI0) + (SPI_MEMORYMAP_SPACING *spiPeripheralNum) );
  SPI = (DEVICE_SPIRegs *) hSPIInfo->regs;
 
  // Assign mode and role
  hSPIInfo->role = role;
  hSPIInfo->mode = mode;
  hSPIInfo->config = config;
 
  // Reset the SPI
  SPI_reset(hSPIInfo);

  LOCAL_setupMode(hSPIInfo);

  // Disable CS if in 3-pin mode
  SPI_disableCS(hSPIInfo);
 
  // Enable SPI
  SPI->SPIGCR1 |= ( 1 << 24 );
 
  return hSPIInfo;
}

// Routine to reset the SPI device
Uint32 SPI_reset(SPI_InfoHandle hSPIInfo)
{
  DEVICE_SPIRegs *SPI = (DEVICE_SPIRegs *) hSPIInfo->regs;

  // Put the SPI in reset
  SPI->SPIGCR0 = 0x00;
  UTIL_waitLoop( 1000 );

  // Release SPI from reset
  SPI->SPIGCR0 = 0x01;

  return E_PASS;
}

Uint32 SPI_readBytes(SPI_InfoHandle hSPIInfo, Uint32 byteCnt, Uint8 *dest)
{
  Uint32 i;

  if (hSPIInfo->config->charLen == 16)
  {
    Uint16 *tempDest = (Uint16 *) dest;
    for (i=0; i< (byteCnt>>1); i++)
    {
      tempDest[i] = SPI_xferOneChar(hSPIInfo,0x0000);
    }
  }
  else if (hSPIInfo->config->charLen == 8)
  {
    for (i=0; i< byteCnt; i++)
    {
      dest[i] = SPI_xferOneChar(hSPIInfo,0x00);
    }
  }

  return E_PASS;
}

Uint32 SPI_writeBytes(SPI_InfoHandle hSPIInfo, Uint32 byteCnt, Uint8 *src)
{
  Uint32 i;

  if (hSPIInfo->config->charLen == 16)
  {
    Uint16 *tempSrc = (Uint16 *) src;
    for (i=0; i< (byteCnt>>1); i++)
    {
      SPI_xferOneChar(hSPIInfo,tempSrc[i]);
    }
  }
  else if (hSPIInfo->config->charLen == 8)
  {
    for (i=0; i< byteCnt; i++)
    {
      SPI_xferOneChar(hSPIInfo,src[i]);
    }
  }

  return E_PASS;
}

Uint32 SPI_xferOneChar(SPI_InfoHandle hSPIInfo, Uint32 dataOut)
{
  Uint32 spiflg, spibuf;
  DEVICE_SPIRegs *SPI = (DEVICE_SPIRegs *) hSPIInfo->regs;

  Uint32 mask = (0x1 << hSPIInfo->config->charLen) - 1;

  // Write output data
  SPI->SPIDAT0 = dataOut & mask;

  do
  {
    spiflg = SPI->SPIFLG;
    if (spiflg & SPI_RXINTFLAG)
    {
      spibuf = (SPI->SPIBUF);
      break;
    }
    if (spiflg & SPI_OVRNINTFLG)
    {
      spibuf = (SPI->SPIBUF);
      SPI->SPIFLG &= SPI_OVRNINTFLG;
      continue;
    }
    if (spiflg & SPI_BITERRFLG)
    {                     
      spibuf = 0x0;
      break;
    }
  }
  while (TRUE);

  return (spibuf & mask);
}

void SPI_enableCS(SPI_InfoHandle hSPIInfo)
{
  DEVICE_SPIRegs *SPI = (DEVICE_SPIRegs *) hSPIInfo->regs;

  if (hSPIInfo->mode != SPI_MODE_3PIN)
    return;

  // Clear GPIO
  SPI->SPIPC5 = 0x1 << hSPIInfo->csNum;
  UTIL_waitLoopAccurate ((Uint32)DELAY_AFTER_CS_DN);
}

void SPI_disableCS(SPI_InfoHandle hSPIInfo)
{
  DEVICE_SPIRegs *SPI = (DEVICE_SPIRegs *) hSPIInfo->regs;

  if (hSPIInfo->mode != SPI_MODE_3PIN)
    return;

  UTIL_waitLoopAccurate ((Uint32) DELAY_BEFORE_CS_UP);

  // Set GPIO
  SPI->SPIPC4 = 0x1 << hSPIInfo->csNum;

  UTIL_waitLoopAccurate ((Uint32) DELAY_AFTER_CS_UP);
}


// Defining this macro for the build will cause write (flash) ability to be removed
// This can be used for using this driver as read-only for ROM code
#ifndef USE_IN_ROM   


#endif

/************************************************************
* Local Function Definitions                                *
************************************************************/

static Uint32 LOCAL_setupMode(SPI_InfoHandle hSPIInfo)
{
  DEVICE_SPIRegs *SPI = (DEVICE_SPIRegs *) hSPIInfo->regs;
 
  if (hSPIInfo->role == SPI_ROLE_MASTER)
  {
    SPI->SPIGCR1 = 0
        | ( 0 << 24 )
        | ( 0 << 16 )
        | ( 1 << 1 )
        | ( 1 << 0 );
  }
  else if (hSPIInfo->role == SPI_ROLE_SLAVE)
  {
    SPI->SPIGCR1 = 0
        | ( 0 << 24 )
        | ( 0 << 16 )
        | ( 0 << 1 )
        | ( 0 << 0 );
  }
  else
  {
    return E_FAIL;
  }
  
  switch (hSPIInfo->mode)
  {
    case SPI_MODE_3PIN:
      SPI->SPIPC0 =  0
        | ( 1 << 11 )   // SOMI
        | ( 1 << 10 )   // SIMO
        | ( 1 << 9 );   // SPI_CLK
      SPI->SPIPC4 |= 0x01;
      SPI->SPIPC1 |= 0x01;  // Make CS a GPIO output
      break;
    case SPI_MODE_4PIN_CS:
      SPI->SPIPC0 =  0
        | ( 1 << 11 )   // DI
        | ( 1 << 10 )   // DO
        | ( 1 << 9 )    // CLK
        | ( 1 << 0 );   // CS0
      break;
    case SPI_MODE_4PIN_ENA:
    SPI->SPIPC0 =  0
        | ( 1 << 11 )   // DI
        | ( 1 << 10 )   // DO
        | ( 1 << 9 )    // CLK
        | ( 1 << 8 );   // ENA
      break;
    case SPI_MODE_5PIN:
      SPI->SPIPC0 =  0
        | ( 1 << 11 )   // DI
        | ( 1 << 10 )   // DO
        | ( 1 << 9 )    // CLK
        | ( 1 << 8 )    // ENA
        | ( 1 << 0 );   // CS0
      break;
    default:
      return E_FAIL;
  }
 
  SPI->SPIFMT[0] = 0x0;
  if (hSPIInfo->config->polarity)
    SPI->SPIFMT[0] |= ( 1 << 17 );   // Polarity
  if (hSPIInfo->config->phase)
    SPI->SPIFMT[0] |= ( 1 << 16 );   // Phase
  SPI->SPIFMT[0] |= (hSPIInfo->config->charLen & 0xFF);
  SPI->SPIFMT[0] |= ((hSPIInfo->config->prescalar & 0xFF) << 8);

  // CSHOLD off, FMT[0] used 
  SPI->SPIDAT1 = 0x00;

  // All chip selects go high when no transfer
  SPI->SPIDEF = 0xFF;

  // Disable interrupts
  SPI->SPIINT = 0x00;
  SPI->SPILVL = 0x00;
 
  return E_PASS;
}

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值