1 #include <asm/arch/sci_types.h>
\r
2 //#include <asm/arch/sys_init.h>
\r
3 #include <asm/arch/os_api.h>
\r
4 #include <asm/arch/arm_reg.h>
\r
5 #include <asm/arch/sc8810_reg_base.h>
\r
6 #include <asm/arch/sc8810_reg_ahb.h>
\r
7 #include <asm/arch/sc8810_reg_global.h>
\r
9 #include <asm/arch/sprd_spi.h>
\r
11 #ifdef CONFIG_FB_SC7710
\r
12 #define SPI2_BASE 0x8e008000
\r
14 #define SPI2_BASE 0x4e006000
\r
16 #define SPI_USED_BASE SPI2_BASE
\r
19 /**---------------------------------------------------------------------------*
\r
20 ** Globle Variable *
\r
21 **---------------------------------------------------------------------------*/
\r
23 //endian switch mode
\r
26 ENDIAN_SWITCH_NONE = 0x00, // 2'b00: 0xABCD => 0xABCD
\r
27 ENDIAN_SWITCH_ALL =0x01, // 2'b01: 0xABCD => 0xDCBA
\r
28 ENDIAN_SWITCH_MODE0 =0x02 , // 2'b01: 0xABCD => 0xBADC
\r
29 ENDIAN_SWITCH_MODE1 = 0x03 , // 2'b01: 0xABCD => 0xCDAB
\r
31 } DMA_ENDIANSWITCH_E ; //should be added to dma_hal_new.h
\r
33 typedef enum DMA_DATAWIDTH
\r
35 DMA_DATAWIDTH_BYTE = 0,
\r
36 DMA_DATAWIDTH_HALFWORD,
\r
41 typedef enum DMA_CHN_REQMODE
\r
43 DMA_CHN_REQMODE_NORMAL = 0,
\r
44 DMA_CHN_REQMODE_TRASACTION,
\r
45 DMA_CHN_REQMODE_LIST,
\r
46 DMA_CHN_REQMODE_INFINITE,
\r
48 } DMA_CHN_REQMODE_E;
\r
51 typedef enum LCM_DMA_RETURN_E
\r
54 LCM_ERR_BUSWIDTH =1, //only support:8-bit,16-bit 80_sys_bus
\r
55 LCM_ERR_SRCADDR =2, //not HalfWORD_align
\r
57 } LCM_DMA_RETURN_E; //SHOULD define in lcd.h
\r
59 #define GEN0_SPI2_EN 1
\r
62 /**---------------------------------------------------------------------------*
\r
63 ** Function Define *
\r
64 **---------------------------------------------------------------------------*/
\r
65 PUBLIC void SPI_Enable( uint32 spi_id, BOOLEAN is_en)
\r
71 *(volatile uint32 *)GR_GEN0 |= ( 1 << GEN0_SPI0_EN);
\r
74 *(volatile uint32 *)GR_GEN0 |= ( 1 << GEN0_SPI1_EN);
\r
77 #ifdef CONFIG_FB_SC7710
\r
78 *(volatile uint32 *)0x8b0000a4 |= ( 1 << 19);
\r
80 *(volatile uint32 *)GR_GEN0 |= ( 1 << GEN0_SPI2_EN);
\r
95 PUBLIC void SPI_Reset( uint32 spi_id, uint32 ms)
\r
101 *(volatile uint32 *)GR_SOFT_RST |= (1 << 14);
\r
102 for (i=0; i<0x100; i++);
\r
103 *(volatile uint32 *)GR_SOFT_RST &=~(1 << 14);
\r
105 else if(spi_id == 1)
\r
107 *(volatile uint32 *)GR_SOFT_RST |= (1 << 15);
\r
108 for (i=0; i<0x100; i++);
\r
109 *(volatile uint32 *)GR_SOFT_RST &=~(1 << 15);
\r
111 else if(spi_id == 2)
\r
113 *(volatile uint32 *)GR_SOFT_RST |= (1 << 31);
\r
114 for (i=0; i<0x100; i++);
\r
115 *(volatile uint32 *)GR_SOFT_RST &=~(1 << 31);
\r
122 LOCAL void SPI_PinConfig(void)
\r
125 *(volatile uint32 *)(0x8C000100) = 0x18A;
\r
126 *(volatile uint32 *)(0x8C000104) = 0x107;
\r
127 *(volatile uint32 *)(0x8C000108) = 0x109;
\r
128 *(volatile uint32 *)(0x8C00010C) = 0x109;
\r
129 *(volatile uint32 *)(0x8C000110) = 0x109;
\r
134 // The dividend is clk_spiX_div[1:0] + 1
\r
135 PUBLIC void SPI_ClkSetting(uint32 spi_id, uint32 clk_src, uint32 clk_div)
\r
137 //clk_spi0_sel: [3:2]---->2'b:00-78M 01-26M,01-104M,11-48M,
\r
138 //clk_spi0_div: [5:4]---->div, clk/(div+1)
\r
142 *(volatile uint32 *) GR_CLK_DLY |= (clk_src&3)<<26;
\r
143 *(volatile uint32 *) GR_GEN2 |= (clk_div&7)<<21;
\r
144 } else if(spi_id == 1){
\r
145 *(volatile uint32 *) GR_CLK_DLY |= (clk_src&3)<<30;
\r
146 *(volatile uint32 *) GR_GEN2 |= (clk_div&7)<<11;
\r
147 } else if(spi_id == 2){
\r
148 *(volatile uint32 *) GR_GEN3 |= (clk_src&3)<<3;
\r
149 *(volatile uint32 *) GR_GEN3 |= (clk_div&7)<<5;
\r
154 #define SPI_SEL_CS_SHIFT 8
\r
155 #define SPI_SEL_CS_MASK (0x0F<<SPI_SEL_CS_SHIFT)
\r
156 PUBLIC void SPI_SetCsLow( uint32 spi_sel_csx , BOOLEAN is_low)
\r
158 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T*)(SPI_USED_BASE);
\r
162 //spi_ctl0[11:8]:cs3<->cs0 chip select, 0-selected;1-none
\r
163 spi_ctr_ptr->ctl0 &= ~(SPI_SEL_CS_MASK);
\r
164 spi_ctr_ptr->ctl0 &= ~((1<<spi_sel_csx)<<SPI_SEL_CS_SHIFT);
\r
168 //spi_ctl0[11:8]:cs3<->cs0 chip select, 0-selected;1-none
\r
169 spi_ctr_ptr->ctl0 |= ((1<<spi_sel_csx)<<SPI_SEL_CS_SHIFT);
\r
173 #define SPI_CD_MASK BIT_15
\r
174 PUBLIC void SPI_SetCd( uint32 cd)
\r
176 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T*)(SPI_USED_BASE);
\r
180 spi_ctr_ptr->ctl8 &= ~(SPI_CD_MASK);
\r
182 spi_ctr_ptr->ctl8 |= (SPI_CD_MASK);
\r
185 // USE spi interface to write cmd/data to the lcm
\r
186 // pay attention to the data_format
\r
187 typedef enum data_width
\r
189 DATA_WIDTH_7bit =7,
\r
190 DATA_WIDTH_8bit =8,
\r
191 DATA_WIDTH_9bit =9,
\r
192 DATA_WIDTH_10bit=10,
\r
193 DATA_WIDTH_11bit=11,
\r
194 DATA_WIDTH_12bit=12,
\r
197 // Set spi work mode for LCM with spi interface
\r
198 #define SPI_MODE_SHIFT 3 //[5:3]
\r
199 #define SPI_MODE_MASK (0x07<<SPI_MODE_SHIFT)
\r
200 PUBLIC void SPI_SetSpiMode(uint32 spi_mode)
\r
202 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
203 uint32 temp = spi_ctr_ptr->ctl7;
\r
205 temp &= ~SPI_MODE_MASK;
\r
206 temp |= (spi_mode<<SPI_MODE_SHIFT);
\r
208 spi_ctr_ptr->ctl7 = temp;
\r
211 // Transmit data bit number:spi_ctl0[6:2]
\r
212 PUBLIC void SPI_SetDatawidth(uint32 datawidth)
\r
214 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
215 uint32 temp = spi_ctr_ptr->ctl0;
\r
217 if( 32 == datawidth )
\r
219 spi_ctr_ptr->ctl0 &= ~0x7C; // [6:2]
\r
223 temp &= ~0x0000007C; //mask
\r
224 temp |= (datawidth<<2);
\r
226 spi_ctr_ptr->ctl0 = temp;
\r
229 #define TX_MAX_LEN_MASK 0xFFFFF
\r
230 #define TX_DUMY_LEN_MASK 0x3F //[09:04]
\r
231 #define TX_DATA_LEN_H_MASK 0x0F //[03:00]
\r
232 #define TX_DATA_LEN_L_MASK 0xFFFF //[15:00]
\r
233 /*****************************************************************************/
\r
234 // Description: Set rxt data length with dummy_len
\r
236 // Note : the unit is identical with datawidth you set
\r
237 /*****************************************************************************/
\r
238 PUBLIC void SPI_SetTxLen(uint32 data_len, uint32 dummy_bitlen)
\r
240 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
241 uint32 ctl8 = spi_ctr_ptr->ctl8;
\r
242 uint32 ctl9 = spi_ctr_ptr->ctl9;
\r
244 data_len &= TX_MAX_LEN_MASK;
\r
246 ctl8 &= ~((TX_DUMY_LEN_MASK<<4) | TX_DATA_LEN_H_MASK);
\r
247 ctl9 &= ~( TX_DATA_LEN_L_MASK );
\r
249 // set dummy_bitlen in bit[9:4] and data_len[19:16] in bit[3:0]
\r
250 spi_ctr_ptr->ctl8 = (ctl8 | (dummy_bitlen<<4) | (data_len>>16));
\r
251 // set data_len[15:00]
\r
252 spi_ctr_ptr->ctl9 = (ctl9 | (data_len&0xFFFF));
\r
256 #define RX_MAX_LEN_MASK 0xFFFFFF
\r
257 #define RX_DUMY_LEN_MASK 0x3F //[09:04]
\r
258 #define RX_DATA_LEN_H_MASK 0x0F //[03:00]
\r
259 #define RX_DATA_LEN_L_MASK 0xFFFF //[15:00]
\r
260 /*****************************************************************************/
\r
261 // Description: Set rxt data length with dummy_len
\r
263 // Note : the unit is identical with datawidth you set
\r
264 /*****************************************************************************/
\r
265 PUBLIC void SPI_SetRxLen(uint32 data_len, uint32 dummy_bitlen)
\r
267 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
268 uint32 ctl10 = spi_ctr_ptr->ctl10;
\r
269 uint32 ctl11 = spi_ctr_ptr->ctl11;
\r
271 data_len &= RX_MAX_LEN_MASK;
\r
273 ctl10 &= ~((RX_DUMY_LEN_MASK<<4) | RX_DATA_LEN_H_MASK);
\r
274 ctl11 &= ~( RX_DATA_LEN_L_MASK );
\r
276 // set dummy_bitlen in bit[9:4] and data_len[19:16] in bit[3:0]
\r
277 spi_ctr_ptr->ctl10 = (ctl10 | (dummy_bitlen<<4) | (data_len>>16));
\r
278 // set data_len[15:00]
\r
279 spi_ctr_ptr->ctl11 = (ctl11 | (data_len&0xFFFF));
\r
281 /* in SPIMODE_3WIRE_9BIT_SDI ,DO
\r
282 the tx len has to set 0 to generate 8 clk, or generate 9clk */
\r
283 if(0x10==(spi_ctr_ptr->ctl7&(0x7 << 3))){
\r
284 spi_ctr_ptr->ctl8 &= 0xfff0;
\r
285 spi_ctr_ptr->ctl9 &= 0x0;
\r
289 // Request txt trans before send data
\r
290 #define SW_RX_REQ_MASK BIT_0
\r
291 #define SW_TX_REQ_MASK BIT_1
\r
292 PUBLIC void SPI_TxReq( void )
\r
294 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
296 spi_ctr_ptr->ctl12 |= SW_TX_REQ_MASK;
\r
299 PUBLIC void SPI_RxReq( void )
\r
301 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
303 spi_ctr_ptr->ctl12 |= SW_RX_REQ_MASK;
\r
306 /*****************************************************************************/
\r
307 // Description: To enable or disable DMA depending on parameter(is_enable)
\r
308 // Author: @Vine.Yuan 2010.5.10
\r
310 /*****************************************************************************/
\r
311 PUBLIC BOOLEAN SPI_EnableDMA(uint32 spi_index,BOOLEAN is_enable)
\r
313 volatile SPI_CTL_REG_T* spi_ctl;
\r
315 spi_ctl = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE+0x3000*spi_index);
\r
319 spi_ctl->ctl2 |= BIT_6;
\r
323 spi_ctl->ctl2 &= ~BIT_6;
\r
326 //spi_ctl->ctl7 |= (BIT_7 | BIT_8);
\r
327 spi_ctl->ctl7 |= (BIT_7);
\r
332 #define SPI_DMA_TIME_OUT 0x80000
\r
333 #define BURST_SIZE 16
\r
334 #define BURST_SIZE_MARK 0xF
\r
335 #define LENGTH_4_DIVIDE 4
\r
337 PUBLIC void SPI_Init(SPI_INIT_PARM *spi_parm)
\r
339 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
341 uint32 ctl0, ctl1, ctl2, ctl3;
\r
343 /*default clk is 500k 192M /(0xc0 * 2)*/
\r
344 spi_ctr_ptr->clkd =0xc0;
\r
347 temp |= (spi_parm->tx_edge << 1) |
\r
348 (spi_parm->rx_edge << 0) |
\r
350 (spi_parm->msb_lsb_sel<< 7) ;
\r
351 spi_ctr_ptr->ctl0 = temp;
\r
353 spi_ctr_ptr->ctl1 |= BIT_12 | BIT_13; // set rx/tx mode
\r
355 /*rx fifo full watermark is 16*/
\r
356 spi_ctr_ptr->ctl3 = 0x10;
\r
358 /*set SPIMODE_3WIRE_9BIT_SDIO mode*/
\r
359 spi_ctr_ptr->ctl7 &= ~(0x7 << 3);
\r
360 spi_ctr_ptr->ctl7 |= SPIMODE_3WIRE_9BIT_SDIO << 3;
\r
363 // set water mark of reveive FIFO
\r
364 spi_ctr_ptr->ctl3 = (ctl3 & ~0xFFFF) |
\r
365 ((BURST_SIZE >>2) <<8) |
\r
370 PUBLIC void SPI_WaitTxFinish()
\r
372 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
374 while( !((spi_ctr_ptr->iraw)&BIT_8) ) // IS tx finish
\r
377 spi_ctr_ptr->iclr |= BIT_8;
\r
379 // Wait for spi bus idle
\r
380 while((spi_ctr_ptr->sts2)&BIT_8)
\r
383 // Wait for tx real empty
\r
384 while( !((spi_ctr_ptr->sts2)&BIT_7) )
\r
389 PUBLIC void SPI_WriteData(uint32 data, uint32 data_len, uint32 dummy_bitlen)
\r
392 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
394 // The unit of data_len is identical with buswidth
\r
395 SPI_SetTxLen(data_len, dummy_bitlen);
\r
398 spi_ctr_ptr->data = data;
\r
400 SPI_WaitTxFinish();
\r
403 PUBLIC uint32 SPI_ReadData( uint32 data_len, uint32 dummy_bitlen )
\r
405 uint32 read_data=0, rxt_cnt=0;
\r
406 volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);
\r
408 // The unit of data_len is identical with buswidth
\r
409 SPI_SetRxLen(data_len, dummy_bitlen);
\r
412 //Wait for spi receive finish
\r
413 while( !((spi_ctr_ptr->iraw)&BIT_9) )
\r
415 //wait rxt fifo full
\r
416 if((spi_ctr_ptr->iraw)&BIT_6)
\r
418 rxt_cnt = (spi_ctr_ptr->ctl3)&0x1F;
\r
419 //SCI_TraceLow("---FIFOFULL:rxt_cnt=0x%x", rxt_cnt);
\r
422 read_data = spi_ctr_ptr->data;
\r
423 //SCI_TraceLow("---FIFOFULL: SPI_ReadData =0x%x", read_data);
\r
428 // Wait for spi bus idle
\r
429 while((spi_ctr_ptr->sts2)&BIT_8)
\r
436 read_data = spi_ctr_ptr->data;
\r
437 //SCI_TraceLow("---Finish: SPI_ReadData =0x%x", read_data);
\r
440 return (read_data);
\r