📄 spi_simulate.c
字号:
/************************************************************************/
/* */
/* Copyright 2005 - 2008, Baud Data Communication Ltd. */
/* ALL RIGHTS RESERVED */
/* */
/* Permission is hereby granted to licensees of Baud Data */
/* Communication Ltd. products to use or abstract this computer */
/* program for the sole purpose of implementing a product based */
/* on Baud Data Communication Ltd. products. No other rights to */
/* reproduce, use, or disseminate this computer program, whether */
/* in part or in whole, are granted. */
/* */
/* Baud Data Communication, Ltd. makes no representation or warranties*/
/* with respect to the performance of this computer program, and */
/* specifically disclaims any responsibility for any damages, */
/* special or consequential, connected with the use of this program. */
/* */
/*----------------------------------------------------------------------*/
/* */
/* MODULE NAME : SPI Simulate Module */
/* FILE NAME : spi_simulate.c */
/* AUTHOR : zhu zhangming */
/* DATE : 05/09/27 */
/* PURPOSE: : software simulate spi manage port */
/* : Useful When some PowerPCs have no spi port, */
/* : but switch chip need one */
/* */
/************************************************************************/
#include "IxTypes.h"
#include "vxWorks.h"
#include "ixp425Gpio.h"
/*#define SPI_SIM_DEBUG*/
/*#define FAST_READ*/
#ifdef SPI_SIM_DEBUG
#define SPI_SIM_LOG(x1, x2) printf(x1, x2)
#else
#define SPI_SIM_LOG(x1, x2)
#endif
#define SPI_MAX_BUF 0x10
#define RETRY_LOOP 2
#define COMMAND_HEAD_LEN 2 /*command byte+ register address byte*/
#if 0
#define BCM_OK 0
#define BCM_ERROR -1
#else
#define BCM_OK IX_SUCCESS
#define BCM_ERROR IX_FAIL
#endif
#define SPI_BASE_ADDR (0xc8004000)
#define SPI_INPUT_ADDR (0xc8004008)
#define SPI_FLAG (*(volatile unsigned int*)SPI_BASE_ADDR)
#define SPI_INPUT_VALUE (*(volatile unsigned int*)SPI_INPUT_ADDR)
#define SPIMISO 0x0080
#define SPIMOSI 0x0100
#define SCLK 0x0200
/*#define SPCS 0x0800*/
#define SPCS(x) (0x0400<<(x))
#define DISABLE_SPISEL(x) SPI_FLAG |= SPCS(x)
#define ENABLE_SPISEL(x) do{SPI_FLAG &= ~SPCS(x); DISABLE_SPISEL(1-x);}while(0)
#define LOW_SPICLK SPI_FLAG &= ~SCLK
#define HIGH_SPICLK SPI_FLAG |= SCLK
#define LOW_SPIMOSI SPI_FLAG &= ~SPIMOSI
#define HIGH_SPIMOSI SPI_FLAG |= SPIMOSI
/*#define IS_HIGH_SPIMISO (SPI_FLAG & SPIMISO) */
#define IS_HIGH_SPIMISO (SPI_INPUT_VALUE & SPIMISO)
/*| 0 | 1 | 1 | mode=0 | chip id 2 | chip id 1 | chip id 0 | r/w |*/
#define NORMAL_SPI_CMD 0x60
#define SPI_READ 0x00
#define SPI_WRITE 0x01
/*#define SPI_CHIP(chip) (chip << 1)*/
#define SPI_CHIP(chip) 0x0
/*| x | x | x | mode=1 | chip id 2 | chip id 1 | chip id 0 | r/w |*/
#define FAST_SPI_CMD 0x10
#define OFFSET_BYTE(byte) (byte << 5)
/*register address */
#define PAGE_REG 0xff
#define STAT_REG 0xfe
#define DATA_REG 0xf0 /*0xf0~~~0xf7*/
/*SPI status register */
#define SPIF 0x80
#define WCOL 0x40
#define RACK 0x20
#define READ_READY_ACK RACK
#define RXRDY 0x02
#define TXRDY 0x01
#if 0
/* This value MUST match the Sandpoint system 60x bus speed */
#define DEC_CLOCK_FREQ (dec_get_clock_freq()) /*66000000*/ /* 66MHz default */
/* PPC Decrementer - used as vxWorks system clock */
#define DELTA(a,b) (abs((int)a - (int)b))
#endif
/* external functions */
int spi8xx_read_bcm53x8_register(int chip, UINT8 page, UINT8 reg, char *pbuf, int reg_len);
int spi8xx_write_bcm53x8_register(int chip, UINT8 page, UINT8 reg, char* pbuf, int len);
void spi8xx_init(void);
#ifdef FAST_READ
int spi_simulate_fast_read_bcm_register(int chip, UINT8 page, UINT8 reg, char *pbuf, int reg_len);
#endif
static UINT8 txbuf[SPI_MAX_BUF];
static UINT8 rxbuf;
/*internal functions*/
static int spi_simulate_send_bytes(UINT8* buf, UINT8 nbyte);
static int spi_simulate_recv_bytes(UINT8* buf, UINT8 nbyte);
static void spi_simulate_read_bytes_cont(int chip, char* pbuf, int reg_len);
static void setup_page_address(int chip, UINT8 page);
static void write_page_address(int chip, UINT8 page);
static void setup_reg_address(int chip, UINT8 reg);
static UINT8 read_spi_status(int chip);
static void spi_delay(void);
/****************************************************************/
/* */
/* FUNCTION NAME: spi_simulate_init */
/* */
/* INPUTS : void */
/* : */
/* */
/* RETURN : void */
/* */
/* NOTE : initial the spi simulate module */
/* : disable slave-select, serial clock, */
/* : set MISO, MOSI to high */
/* */
/****************************************************************/
void spiSimulate_init(void)
{
SPI_SIM_LOG("before spi_init SPI_FLAG = 0x%4x\n", SPI_FLAG);
/*spi gpio init*/
ixp425GPIOLineConfig(IXP425_GPIO_PIN_7, IXP425_GPIO_IN);
ixp425GPIOLineConfig(IXP425_GPIO_PIN_8, IXP425_GPIO_OUT);
ixp425GPIOLineConfig(IXP425_GPIO_PIN_9, IXP425_GPIO_OUT);
ixp425GPIOLineConfig(IXP425_GPIO_PIN_10, IXP425_GPIO_OUT);
ixp425GPIOLineConfig(IXP425_GPIO_PIN_11, IXP425_GPIO_OUT);
/**/
DISABLE_SPISEL(0);
DISABLE_SPISEL(1);
HIGH_SPICLK;
HIGH_SPIMOSI;
read_spi_status(0);
read_spi_status(1);
SPI_SIM_LOG("after spi_init SPI_FLAG = 0x%4x\n", SPI_FLAG);
}
/****************************************************************/
/* */
/* FUNCTION NAME: spi_simulate_read_bcm_register */
/* */
/* INPUTS : chip - the chip ID */
/* : page - page address */
/* : reg - register address */
/* : reg_len - register length to be read */
/* */
/* OUTPUTS : pbuf - pointer to the buffer of read data */
/* */
/* RETURN : the status of broadcom SPI */
/* */
/* NOTE : read data from the broadcom chip to pbuf[]. */
/* : using CHIP ID, PAGE address, Register address */
/* : the data length is reg_len */
/* */
/****************************************************************/
extern unsigned long Print(char *format, ...);
int spi8xx_read_bcm53x8_register(int chip, UINT8 page, UINT8 reg, char *pbuf, int reg_len)
{
#ifdef FAST_READ
return spi_simulate_fast_read_bcm_register(chip, page, reg, pbuf, reg_len);
#else
UINT8 spi_status=0;
ULONG i = 0;
// SPI_SIM_LOG("spi_simulate_read_bcm_register.....\n", 1);
// Print("chip:%d, page:%d, reg:%d, pbuf:0x%x, reg_len:%d\n",
// chip, page, reg, pbuf, reg_len);
setup_page_address(chip, page);
setup_reg_address(chip, reg);
/*test RACK==1*/
for (i=0; i<RETRY_LOOP; ++i)
{
spi_status = read_spi_status(chip);
SPI_SIM_LOG("new spi_status = 0x%x\n", spi_status);
//Print("new spi_status = 0x%x\n", spi_status);
if (spi_status & RACK)
break;
spi_delay();
}
if (i == RETRY_LOOP)
{
return BCM_ERROR;
}
spi_simulate_read_bytes_cont(chip, pbuf, reg_len);
//Print("pbuf:0x%x 0x%x \n", pbuf[0], pbuf[1]);
return BCM_OK;
#endif
}
/****************************************************************/
/* */
/* FUNCTION NAME: spi_simulate_write_bcm_register */
/* */
/* INPUTS : chip - the chip ID */
/* : page - page address */
/* : reg - register address */
/* : len - length of data to write */
/* */
/* OUTPUTS : pbuf - pointer to the buffer of write data */
/* */
/* RETURN : the status of broadcom SPI */
/* */
/* NOTE : write data in pbuf[] to the broadcom chip . */
/* : using CHIP ID, PAGE address, Register address */
/* : the data length is len */
/* */
/****************************************************************/
int spi8xx_write_bcm53x8_register(int chip, UINT8 page, UINT8 reg, char *pbuf, int len)
{
int i = 0;
SPI_SIM_LOG("spi_simulate_write_bcm_registser......\n", 1);
setup_page_address(chip, page);
/*write pbuf[0:len-1] to register address*/
txbuf[0] = NORMAL_SPI_CMD | SPI_WRITE | SPI_CHIP(chip);
txbuf[1] = reg;
for (i=0; i<len; ++i)
{
txbuf[COMMAND_HEAD_LEN+i] = pbuf[i];
}
ENABLE_SPISEL(chip);
spi_simulate_send_bytes(txbuf, len+COMMAND_HEAD_LEN);
DISABLE_SPISEL(chip);
return BCM_OK;
}
/****************************************************************/
/* */
/* FUNCTION NAME: spi_simulate_fast_read_bcm_register */
/* */
/* INPUTS : chip - the chip ID */
/* : page - page address */
/* : reg - register address */
/* : reg_len - register length to be read */
/* */
/* OUTPUTS : pbuf - pointer to the buffer of read data */
/* */
/* RETURN : the status of broadcom SPI */
/* */
/* NOTE : fast read data from the broadcom chip to pbuf[]. */
/* : using CHIP ID, PAGE address, Register address */
/* : the data length is reg_len */
/* */
/****************************************************************/
#ifdef FAST_READ
int spi_simulate_fast_read_bcm_register(int chip, UINT8 page, UINT8 reg, char *pbuf, int reg_len)
{
#define S_SEND 0
#define S_POLL 2
#define S_RECV 3
UINT8 state = S_SEND;
UINT8 loop = 0xFF;
UINT8 send;
UINT8 mask;
UINT8 rcvd=0;
UINT8 buf[SPI_MAX_BUF];
int i=0;
int byte = 0;
buf[0] = FAST_SPI_CMD | SPI_READ |SPI_CHIP(chip) | OFFSET_BYTE(byte); /* cmd */
buf[1] = reg; /* reg address */
for (i=COMMAND_HEAD_LEN; i<SPI_MAX_BUF; ++i)
buf[i] = 0;
setup_page_address(chip, page);
ENABLE_SPISEL(chip);
for (i=0; i<reg_len+byte+COMMAND_HEAD_LEN; ++i)
{
send = (state==S_POLL) ? 0 : buf[i];
for( mask=0x80, rcvd=0; mask!=0; mask=mask>>1 )
{
LOW_SPICLK;
if( mask & send ) HIGH_SPIMOSI;
else LOW_SPIMOSI;
HIGH_SPICLK;
spi_delay();
if( IS_HIGH_SPIMISO ) rcvd |= mask;
}
/*Print("i = %d \t send = 0x%x \t recv = 0x%x\n", i, send, rcvd);*/
if( state == S_POLL )
{
if( rcvd & 0x02 )
state = S_RECV;
else if( --loop == 0 )
{
DISABLE_SPISEL(chip);
return BCM_ERROR;
}
--i;
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -