blob: ad0d4f9cf173630dcc12c1fc9a4c9c48680b8c2d [file] [log] [blame]
/*
|| ADD SPI DRVER FOR LCD DISPLAY
*/
#include <common.h>
#include <drvs_gpio.h>
#include <ssp.h>
#include <config.h>
#define REG32(x) (*(volatile u32*)(x))
#define ZX29_SSP0_BASE 0x0140a000
#define LSP_CRPM_SPI0_CLKREG (0x01400000 + 0x30)
#define ZX29_SSP1_BASE 0x01410000
#define LSP_CRPM_SPI1_CLKREG (0x01400000 + 0x48)
#define SSP_COM_CTRL 0x04
#define SSP_COM_CTRL_SSPEN (1 << 1)
#define SSP_COM_CTRL_SSPEN_POS 1
#define SSP_COM_CTRL_MASTER (1 << 2)
#define SSP_COM_CTRL_MASTER_POS 2
#define SSP_FMT_CTRL 0x08
#define SSP_FMT_CTRL_POL (0x3 << 2)
#define SSP_FMT_CTRL_POL_POS 2
#define SSP_FMT_CTRL_DSS (0x1f << 4)
#define SSP_FMT_CTRL_DSS_POS 4
#define SSP_DATA_DR 0x0c
#define SSP_FIFO_CTRL 0x10
#define SSP_FIFO_CTRL_TXTHRES (0xf << 8)
#define SSP_FIFO_CTRL_TXTHRES_POS 8
#define SSP_FIFO_SR 0x14
#define SSP_INT_EN 0x18
#define SSP_INT_SC 0x1c
#define SSP_TRANS_TIMEING 0x20
//define ssp mode
typedef enum _E_SspXferWidth
{
SSP_WIDTH_BIT_8 = 7,
SSP_WIDTH_BIT_16 = 15,
SSP_WIDTH_BIT_32 = 31
}E_SspXferWidth;
//define ssp mode
typedef enum _E_SspPolarity
{
SPH_SPO_00 = 0x0,
SPH_SPO_01 = 0x1,
SPH_SPO_10 = 0x2,
SPH_SPO_11 = 0x3
}E_SspPolarity;
typedef struct
{
u8 devNum; //indicate the ssp device num
u32 regBase;
E_SspPolarity polarity;
E_SspXferWidth xferWidth;
unsigned char master;
unsigned int fifoTxThres;
}T_SspDev;
static T_SspDev g_SspDev[SSP_DEV_NUM]=
{
[0]={
.devNum = SSP_DEV_0,
.regBase = ZX29_SSP0_BASE,
.polarity =SPH_SPO_00,
.xferWidth = SSP_WIDTH_BIT_8,
.master = 0,
.fifoTxThres = 3,
},
[1]={
.devNum =SSP_DEV_1,
.regBase =ZX29_SSP1_BASE,
.polarity =SPH_SPO_00,
.xferWidth =SSP_WIDTH_BIT_8,
.master = 0, // 0:master; 1: slave
.fifoTxThres = 3, //thres 8
},
};
static void usdelay(u32 us)
{
u32 count;
for(count = 0 ; count < us* 1000; count++);
}
static void sspClk_enable(T_SspDev* sspDev)
{
if(sspDev->devNum == SSP_DEV_0)
{
REG32(LSP_CRPM_SPI0_CLKREG) &= ~(0x3 << 8);
usdelay(20);
REG32(LSP_CRPM_SPI0_CLKREG) = (0x3 << 8);
usdelay(20);
// CLK SEL 26M
REG32(LSP_CRPM_SPI0_CLKREG) |= (0x0 << 4); //(0x2 << 4);
#if defined(CONFIG_ZX297520V3E_FWP)
REG32(LSP_CRPM_SPI0_CLKREG) |= (0x3 << 12); // max 0xf
#else
REG32(LSP_CRPM_SPI0_CLKREG) |= (0x0 << 12); // max 0xf
#endif
// enable ssp1 pclk wclk
REG32(LSP_CRPM_SPI0_CLKREG) |= (0x3);
usdelay(20);
// auto ssp1 wclk
REG32(LSP_CRPM_SPI0_CLKREG) |= (0x3 << 10); //(0x1 << 10);
return;
}
else if(sspDev->devNum == SSP_DEV_1)
{
REG32(LSP_CRPM_SPI1_CLKREG) &= ~(0x3 << 8);
usdelay(20);
REG32(LSP_CRPM_SPI1_CLKREG) = (0x3 << 8);
usdelay(20);
// enable ssp1 pclk wclk
REG32(LSP_CRPM_SPI1_CLKREG) |= (0x3);
// CLK SEL 26M
REG32(LSP_CRPM_SPI1_CLKREG) |= (0x0 << 4);
REG32(LSP_CRPM_SPI1_CLKREG) |= (0x0 << 12); // max 0xf
usdelay(20);
// auto ssp1 wclk
REG32(LSP_CRPM_SPI1_CLKREG) |= (0x3 << 10);
return;
}
}
static void sspClk_disable(T_SspDev* sspDev)
{
if(sspDev->devNum == SSP_DEV_0)
{
REG32(LSP_CRPM_SPI0_CLKREG) &= ~(0x3);
}
else if(sspDev->devNum == SSP_DEV_1)
{
REG32(LSP_CRPM_SPI1_CLKREG) &= ~(0x3);
}
}
static void sspGpio_config(T_SspDev* sspDev)
{
if(sspDev->devNum == SSP_DEV_0)
{
zDrvGpio_SetFunc(GPIO25, GPIO25_SSP0_CS);
zDrvGpio_SetFunc(GPIO26, GPIO26_SSP0_CLK);
zDrvGpio_SetFunc(GPIO28, GPIO28_SSP0_TXD);
}
else if(sspDev->devNum == SSP_DEV_1)
{
//zDrvGpio_SetFunc(GPIO87, GPIO87_CAM_SPI_CS);
//zDrvGpio_SetFunc(GPIO88, GPIO88_CAM_SPI_CLK);
//(GPIO90, GPIO90_CAM_SPI_TXD);
}
}
static void sspConfig_init(T_SspDev* sspDev)
{
//config M/S
REG32(sspDev->regBase + SSP_COM_CTRL) &= ~SSP_COM_CTRL_MASTER;
REG32(sspDev->regBase + SSP_COM_CTRL) |= (sspDev->master << SSP_COM_CTRL_MASTER_POS);
//config ssp mode :default
REG32(sspDev->regBase + SSP_FMT_CTRL) &= ~(SSP_FMT_CTRL_POL | SSP_FMT_CTRL_DSS);
//config POL
REG32(sspDev->regBase + SSP_FMT_CTRL) |= (sspDev->polarity << SSP_FMT_CTRL_POL_POS);
//config bus width
REG32(sspDev->regBase + SSP_FMT_CTRL) |= (sspDev->xferWidth << SSP_FMT_CTRL_DSS_POS);
//config fifo
REG32(sspDev->regBase + SSP_FIFO_CTRL) &= ~SSP_FIFO_CTRL_TXTHRES;
REG32(sspDev->regBase + SSP_FIFO_CTRL) |= (sspDev->fifoTxThres << SSP_FIFO_CTRL_TXTHRES_POS);
//config fifo
REG32(sspDev->regBase + SSP_TRANS_TIMEING) = (0xe);
// close all int
REG32(sspDev->regBase + SSP_INT_EN) = 0x0;
//enable SSP
usdelay(80);
while(REG32(sspDev->regBase + SSP_COM_CTRL) & (0x1 << 4));
REG32(sspDev->regBase + SSP_COM_CTRL) |= (0x1 << 1 );
usdelay(80);
while ((REG32(sspDev->regBase + SSP_COM_CTRL) & (0x1 << 4)) == 0);
}
static void ssp_init(T_SspDev* sspDev)
{
sspGpio_config(sspDev);
sspClk_enable(sspDev);
sspConfig_init(sspDev);
}
static void ssp_uninit(T_SspDev* sspDev)
{
sspClk_disable(sspDev);
}
void* ssp_open(u8 num)
{
if(num >= SSP_DEV_NUM)
return NULL;
ssp_init(&g_SspDev[num]);
return (void*)&g_SspDev[num];
}
void ssp_close(void* handler)
{
T_SspDev* sspDev = (T_SspDev*)handler;
ssp_uninit(sspDev);
}
int ssp_transfer(void* handler, u8* buf, u32 length)
{
T_SspDev* sspDev = (T_SspDev*)handler;
u32 count = 0;
u32 data;
if(!sspDev || !buf)
return 0;
//add chip select
if(sspDev->xferWidth == SSP_WIDTH_BIT_8){
u8* pbuf = (u8*)buf;
do{
REG32(sspDev->regBase + SSP_DATA_DR) = pbuf[count];
while(REG32(sspDev->regBase + SSP_FIFO_SR)& (1 << 4));
count++;
}while(count < length);
}else if(sspDev->xferWidth == SSP_WIDTH_BIT_16){
u16* pbuf = (u16*)buf;
do{
REG32(sspDev->regBase + SSP_DATA_DR) = pbuf[count];
while(REG32(sspDev->regBase + SSP_FIFO_SR)& (1 << 4));
count += 2;
}while(count < length);
}else if(sspDev->xferWidth == SSP_WIDTH_BIT_32){
do{
u32* pbuf = (u32*)buf;
REG32(sspDev->regBase + SSP_DATA_DR) = pbuf[count];
while(REG32(sspDev->regBase + SSP_FIFO_SR)& (1 << 4));
count += 4;
}while(count < length);
}
return count;
}