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