/* | |
|| 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; | |
} | |