1 #include <asm/arch/sci_types.h>
\r
2 #include <asm/arch/os_api.h>
\r
3 #include <asm/arch/arm_reg.h>
\r
4 #include <asm/arch/sprd_reg_base.h>
\r
5 #include <asm/arch/sprd_reg_ahb.h>
\r
6 #include <asm/arch/sprd_reg_global.h>
\r
7 #include <asm/arch/sprd_spi.h>
\r
8 #if defined(CONFIG_SC8830) || defined(CONFIG_SC9630)
\r
9 #define SPI2_BASE CTL_BASE_SPI2
\r
11 #define SPI2_BASE 0x4e006000
\r
13 #define SPI_USED_BASE SPI2_BASE
\r
16 /**---------------------------------------------------------------------------*
\r
17 ** Globle Variable *
\r
18 **---------------------------------------------------------------------------*/
\r
20 //endian switch mode
\r
23 ENDIAN_SWITCH_NONE = 0x00, // 2'b00: 0xABCD => 0xABCD
\r
24 ENDIAN_SWITCH_ALL =0x01, // 2'b01: 0xABCD => 0xDCBA
\r
25 ENDIAN_SWITCH_MODE0 =0x02 , // 2'b01: 0xABCD => 0xBADC
\r
26 ENDIAN_SWITCH_MODE1 = 0x03 , // 2'b01: 0xABCD => 0xCDAB
\r
28 } DMA_ENDIANSWITCH_E ; //should be added to dma_hal_new.h
\r
30 typedef enum DMA_DATAWIDTH
\r
32 DMA_DATAWIDTH_BYTE = 0,
\r
33 DMA_DATAWIDTH_HALFWORD,
\r
38 typedef enum DMA_CHN_REQMODE
\r
40 DMA_CHN_REQMODE_NORMAL = 0,
\r
41 DMA_CHN_REQMODE_TRASACTION,
\r
42 DMA_CHN_REQMODE_LIST,
\r
43 DMA_CHN_REQMODE_INFINITE,
\r
45 } DMA_CHN_REQMODE_E;
\r
48 typedef enum LCM_DMA_RETURN_E
\r
51 LCM_ERR_BUSWIDTH =1, //only support:8-bit,16-bit 80_sys_bus
\r
52 LCM_ERR_SRCADDR =2, //not HalfWORD_align
\r
54 } LCM_DMA_RETURN_E; //SHOULD define in lcd.h
\r
56 #define GEN0_SPI2_EN 1
\r
59 /**---------------------------------------------------------------------------*
\r
60 ** Function Define *
\r
61 **---------------------------------------------------------------------------*/
\r
62 PUBLIC void SPI_Enable( uint32 spi_id, BOOLEAN is_en)
\r
68 #if defined(CONFIG_SC8830) || defined(CONFIG_SC9630)
\r
72 *(volatile uint32 *)GR_GEN0 |= ( 1 << GEN0_SPI0_EN);
\r
75 *(volatile uint32 *)GR_GEN0 |= ( 1 << GEN0_SPI1_EN);
\r
78 *(volatile uint32 *)GR_GEN0 |= ( 1 << GEN0_SPI2_EN);
\r
92 PUBLIC void SPI_Reset( uint32 spi_id, uint32 ms)
\r
95 #if defined(CONFIG_SC8830) || defined(CONFIG_SC9630)
\r
100 *(volatile uint32 *)GR_SOFT_RST |= (1 << 14);
\r
101 for (i=0; i<0x100; i++);
\r
102 *(volatile uint32 *)GR_SOFT_RST &=~(1 << 14);
\r
104 else if(spi_id == 1)
\r
106 *(volatile uint32 *)GR_SOFT_RST |= (1 << 15);
\r
107 for (i=0; i<0x100; i++);
\r
108 *(volatile uint32 *)GR_SOFT_RST &=~(1 << 15);
\r
110 else if(spi_id == 2)
\r
112 *(volatile uint32 *)GR_SOFT_RST |= (1 << 31);
\r
113 for (i=0; i<0x100; i++);
\r
114 *(volatile uint32 *)GR_SOFT_RST &=~(1 << 31);
\r
120 LOCAL void SPI_PinConfig(void)
\r
125 // The dividend is clk_spiX_div[1:0] + 1
\r
126 PUBLIC void SPI_ClkSetting(uint32 spi_id, uint32 clk_src, uint32 clk_div)
\r
128 //clk_spi0_sel: [3:2]---->2'b:00-78M 01-26M,01-104M,11-48M,
\r
129 //clk_spi0_div: [5:4]---->div, clk/(div+1)
\r
130 #if defined(CONFIG_SC8830) || defined(CONFIG_SC9630)
\r
135 *(volatile uint32 *) GR_CLK_DLY |= (clk_src&3)<<26;
\r
136 *(volatile uint32 *) GR_GEN2 |= (clk_div&7)<<21;
\r
137 } else if(spi_id == 1){
\r
138 *(volatile uint32 *) GR_CLK_DLY |= (clk_src&3)<<30;
\r
139 *(volatile uint32 *) GR_GEN2 |= (clk_div&7)<<11;
\r
140 } else if(spi_id == 2){
\r
141 *(volatile uint32 *) GR_GEN3 |= (clk_src&3)<<3;
\r
142 *(volatile uint32 *) GR_GEN3 |= (clk_div&7)<<5;
\r
148 #define SPI_SEL_CS_SHIFT 8
\r
149 #define SPI_SEL_CS_MASK (0x0F<<SPI_SEL_CS_SHIFT)
\r
150 PUBLIC void SPI_SetCsLow( uint32 spi_sel_csx , BOOLEAN is_low)
\r
152 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T*)(SPI_USED_BASE);
\r
156 //spi_ctl0[11:8]:cs3<->cs0 chip select, 0-selected;1-none
\r
157 spi_ctr_ptr->ctl0 &= ~(SPI_SEL_CS_MASK);
\r
158 spi_ctr_ptr->ctl0 &= ~((1<<spi_sel_csx)<<SPI_SEL_CS_SHIFT);
\r
162 //spi_ctl0[11:8]:cs3<->cs0 chip select, 0-selected;1-none
\r
163 spi_ctr_ptr->ctl0 |= ((1<<spi_sel_csx)<<SPI_SEL_CS_SHIFT);
\r
167 #define SPI_CD_MASK BIT_15
\r
168 PUBLIC void SPI_SetCd( uint32 cd)
\r
170 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T*)(SPI_USED_BASE);
\r
174 spi_ctr_ptr->ctl8 &= ~(SPI_CD_MASK);
\r
176 spi_ctr_ptr->ctl8 |= (SPI_CD_MASK);
\r
179 // USE spi interface to write cmd/data to the lcm
\r
180 // pay attention to the data_format
\r
181 typedef enum data_width
\r
183 DATA_WIDTH_7bit =7,
\r
184 DATA_WIDTH_8bit =8,
\r
185 DATA_WIDTH_9bit =9,
\r
186 DATA_WIDTH_10bit=10,
\r
187 DATA_WIDTH_11bit=11,
\r
188 DATA_WIDTH_12bit=12,
\r
191 // Set spi work mode for LCM with spi interface
\r
192 #define SPI_MODE_SHIFT 3 //[5:3]
\r
193 #define SPI_MODE_MASK (0x07<<SPI_MODE_SHIFT)
\r
194 PUBLIC void SPI_SetSpiMode(uint32 spi_mode)
\r
196 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
197 uint32 temp = spi_ctr_ptr->ctl7;
\r
199 temp &= ~SPI_MODE_MASK;
\r
200 temp |= (spi_mode<<SPI_MODE_SHIFT);
\r
202 spi_ctr_ptr->ctl7 = temp;
\r
205 // Transmit data bit number:spi_ctl0[6:2]
\r
206 PUBLIC void SPI_SetDatawidth(uint32 datawidth)
\r
208 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
209 uint32 temp = spi_ctr_ptr->ctl0;
\r
211 if( 32 == datawidth )
\r
213 spi_ctr_ptr->ctl0 &= ~0x7C; // [6:2]
\r
217 temp &= ~0x0000007C; //mask
\r
218 temp |= (datawidth<<2);
\r
220 spi_ctr_ptr->ctl0 = temp;
\r
223 #define TX_MAX_LEN_MASK 0xFFFFF
\r
224 #define TX_DUMY_LEN_MASK 0x3F //[09:04]
\r
225 #define TX_DATA_LEN_H_MASK 0x0F //[03:00]
\r
226 #define TX_DATA_LEN_L_MASK 0xFFFF //[15:00]
\r
227 /*****************************************************************************/
\r
228 // Description: Set rxt data length with dummy_len
\r
230 // Note : the unit is identical with datawidth you set
\r
231 /*****************************************************************************/
\r
232 PUBLIC void SPI_SetTxLen(uint32 data_len, uint32 dummy_bitlen)
\r
234 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
235 uint32 ctl8 = spi_ctr_ptr->ctl8;
\r
236 uint32 ctl9 = spi_ctr_ptr->ctl9;
\r
238 data_len &= TX_MAX_LEN_MASK;
\r
240 ctl8 &= ~((TX_DUMY_LEN_MASK<<4) | TX_DATA_LEN_H_MASK);
\r
241 ctl9 &= ~( TX_DATA_LEN_L_MASK );
\r
243 // set dummy_bitlen in bit[9:4] and data_len[19:16] in bit[3:0]
\r
244 spi_ctr_ptr->ctl8 = (ctl8 | (dummy_bitlen<<4) | (data_len>>16));
\r
245 // set data_len[15:00]
\r
246 spi_ctr_ptr->ctl9 = (ctl9 | (data_len&0xFFFF));
\r
250 #define RX_MAX_LEN_MASK 0xFFFFFF
\r
251 #define RX_DUMY_LEN_MASK 0x3F //[09:04]
\r
252 #define RX_DATA_LEN_H_MASK 0x0F //[03:00]
\r
253 #define RX_DATA_LEN_L_MASK 0xFFFF //[15:00]
\r
254 /*****************************************************************************/
\r
255 // Description: Set rxt data length with dummy_len
\r
257 // Note : the unit is identical with datawidth you set
\r
258 /*****************************************************************************/
\r
259 PUBLIC void SPI_SetRxLen(uint32 data_len, uint32 dummy_bitlen)
\r
261 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
262 uint32 ctl10 = spi_ctr_ptr->ctl10;
\r
263 uint32 ctl11 = spi_ctr_ptr->ctl11;
\r
265 data_len &= RX_MAX_LEN_MASK;
\r
267 ctl10 &= ~((RX_DUMY_LEN_MASK<<4) | RX_DATA_LEN_H_MASK);
\r
268 ctl11 &= ~( RX_DATA_LEN_L_MASK );
\r
270 // set dummy_bitlen in bit[9:4] and data_len[19:16] in bit[3:0]
\r
271 spi_ctr_ptr->ctl10 = (ctl10 | (dummy_bitlen<<4) | (data_len>>16));
\r
272 // set data_len[15:00]
\r
273 spi_ctr_ptr->ctl11 = (ctl11 | (data_len&0xFFFF));
\r
275 /* in SPIMODE_3WIRE_9BIT_SDI ,DO
\r
276 the tx len has to set 0 to generate 8 clk, or generate 9clk */
\r
277 if(0x10==(spi_ctr_ptr->ctl7&(0x7 << 3))){
\r
278 spi_ctr_ptr->ctl8 &= 0xfff0;
\r
279 spi_ctr_ptr->ctl9 &= 0x0;
\r
283 // Request txt trans before send data
\r
284 #define SW_RX_REQ_MASK BIT_0
\r
285 #define SW_TX_REQ_MASK BIT_1
\r
286 PUBLIC void SPI_TxReq( void )
\r
288 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
290 spi_ctr_ptr->ctl12 |= SW_TX_REQ_MASK;
\r
293 PUBLIC void SPI_RxReq( void )
\r
295 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
297 spi_ctr_ptr->ctl12 |= SW_RX_REQ_MASK;
\r
300 /*****************************************************************************/
\r
301 // Description: To enable or disable DMA depending on parameter(is_enable)
\r
302 // Author: @Vine.Yuan 2010.5.10
\r
304 /*****************************************************************************/
\r
305 PUBLIC BOOLEAN SPI_EnableDMA(uint32 spi_index,BOOLEAN is_enable)
\r
307 volatile SPI_CTL_REG_T* spi_ctl;
\r
309 spi_ctl = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE+0x3000*spi_index);
\r
313 spi_ctl->ctl2 |= BIT_6;
\r
317 spi_ctl->ctl2 &= ~BIT_6;
\r
320 //spi_ctl->ctl7 |= (BIT_7 | BIT_8);
\r
321 spi_ctl->ctl7 |= (BIT_7);
\r
326 #define SPI_DMA_TIME_OUT 0x80000
\r
327 #define BURST_SIZE 16
\r
328 #define BURST_SIZE_MARK 0xF
\r
329 #define LENGTH_4_DIVIDE 4
\r
331 PUBLIC void SPI_Init(SPI_INIT_PARM *spi_parm)
\r
333 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
335 uint32 ctl0, ctl1, ctl2, ctl3;
\r
337 /*default clk is 500k 192M /(0xc0 * 2)*/
\r
338 spi_ctr_ptr->clkd =0xc0;
\r
341 temp |= (spi_parm->tx_edge << 1) |
\r
342 (spi_parm->rx_edge << 0) |
\r
344 (spi_parm->msb_lsb_sel<< 7) ;
\r
345 spi_ctr_ptr->ctl0 = temp;
\r
347 spi_ctr_ptr->ctl1 |= BIT_12 | BIT_13; // set rx/tx mode
\r
349 /*rx fifo full watermark is 16*/
\r
350 spi_ctr_ptr->ctl3 = 0x10;
\r
352 /*set SPIMODE_3WIRE_9BIT_SDIO mode*/
\r
353 spi_ctr_ptr->ctl7 &= ~(0x7 << 3);
\r
354 spi_ctr_ptr->ctl7 |= SPIMODE_3WIRE_9BIT_SDIO << 3;
\r
359 // set water mark of reveive FIFO
\r
360 spi_ctr_ptr->ctl3 = (ctl3 & ~0xFFFF) |
\r
361 ((BURST_SIZE >>2) <<8) |
\r
366 PUBLIC void SPI_WaitTxFinish()
\r
368 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
370 while( !(spi_ctr_ptr->iraw)&BIT_8 ) // IS tx finish
\r
373 spi_ctr_ptr->iclr |= BIT_8;
\r
375 // Wait for spi bus idle
\r
376 while((spi_ctr_ptr->sts2)&BIT_8)
\r
379 // Wait for tx real empty
\r
380 while( !((spi_ctr_ptr->sts2)&BIT_7) )
\r
385 PUBLIC void SPI_WriteData(uint32 data, uint32 data_len, uint32 dummy_bitlen)
\r
388 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
390 // The unit of data_len is identical with buswidth
\r
391 SPI_SetTxLen(data_len, dummy_bitlen);
\r
394 spi_ctr_ptr->data = data;
\r
396 SPI_WaitTxFinish();
\r
399 PUBLIC uint32 SPI_ReadData( uint32 data_len, uint32 dummy_bitlen )
\r
401 uint32 read_data=0, rxt_cnt=0;
\r
402 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
404 // The unit of data_len is identical with buswidth
\r
405 SPI_SetRxLen(data_len, dummy_bitlen);
\r
408 //Wait for spi receive finish
\r
409 while( !((spi_ctr_ptr->iraw)&BIT_9) )
\r
411 //wait rxt fifo full
\r
412 if((spi_ctr_ptr->iraw)&BIT_6)
\r
414 rxt_cnt = (spi_ctr_ptr->ctl3)&0x1F;
\r
415 //SCI_TraceLow("---FIFOFULL:rxt_cnt=0x%x", rxt_cnt);
\r
418 read_data = spi_ctr_ptr->data;
\r
419 //SCI_TraceLow("---FIFOFULL: SPI_ReadData =0x%x", read_data);
\r
424 // Wait for spi bus idle
\r
425 while((spi_ctr_ptr->sts2)&BIT_8)
\r
432 read_data = spi_ctr_ptr->data;
\r
433 //SCI_TraceLow("---Finish: SPI_ReadData =0x%x", read_data);
\r
436 return (read_data);
\r