tizen 2.4 release
[profile/mobile/platform/kernel/u-boot-tm1.git] / drivers / spi / sc8825_spi.c
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
8 \r
9 #include <asm/arch/sprd_spi.h>\r
10 \r
11 #ifdef CONFIG_FB_SC7710\r
12 #define SPI2_BASE 0x8e008000\r
13 #else\r
14 #define SPI2_BASE 0x4e006000\r
15 #endif\r
16 #define SPI_USED_BASE SPI2_BASE\r
17 \r
18 \r
19 /**---------------------------------------------------------------------------*\r
20  **                         Globle Variable                                  *\r
21  **---------------------------------------------------------------------------*/\r
22 \r
23 //endian switch mode\r
24 typedef enum\r
25 {\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
30         ENDIAN_SWITCH_MAX\r
31 } DMA_ENDIANSWITCH_E ;  //should be added to dma_hal_new.h\r
32 //data width\r
33 typedef enum DMA_DATAWIDTH\r
34 {\r
35         DMA_DATAWIDTH_BYTE = 0,\r
36         DMA_DATAWIDTH_HALFWORD,\r
37         DMA_DATAWIDTH_WORD,\r
38         DMA_DATAWIDTH_MAX\r
39 }  DMA_DATAWIDTH_E;\r
40 //request mode\r
41 typedef enum DMA_CHN_REQMODE\r
42 {\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
47         DMA_CHN_REQMODE_MAX\r
48 } DMA_CHN_REQMODE_E;\r
49 \r
50 \r
51 typedef enum LCM_DMA_RETURN_E\r
52 {\r
53         LCM_ERR_ID    = 0,\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
56         LCM_ERR_ENDIAN\r
57 } LCM_DMA_RETURN_E;       //SHOULD define in lcd.h\r
58 \r
59 #define GEN0_SPI2_EN    1\r
60 \r
61 \r
62 /**---------------------------------------------------------------------------*\r
63  **                         Function Define                                    *\r
64  **---------------------------------------------------------------------------*/\r
65 PUBLIC void SPI_Enable( uint32 spi_id, BOOLEAN is_en)\r
66 {\r
67         if(is_en)\r
68         {\r
69                 switch(spi_id){\r
70                         case 0:\r
71                                 *(volatile uint32 *)GR_GEN0 |= ( 1 << GEN0_SPI0_EN);\r
72                                 break;\r
73                         case 1:\r
74                                 *(volatile uint32 *)GR_GEN0 |= ( 1 << GEN0_SPI1_EN);\r
75                                 break;\r
76                         case 2: \r
77 #ifdef CONFIG_FB_SC7710\r
78                                 *(volatile uint32 *)0x8b0000a4 |= ( 1 << 19);\r
79 #else\r
80                                 *(volatile uint32 *)GR_GEN0 |= ( 1 << GEN0_SPI2_EN);\r
81 #endif\r
82                                 break;\r
83                         default:\r
84                                 break;\r
85 \r
86                 }\r
87         }\r
88         else\r
89         {\r
90 \r
91         }\r
92 \r
93 }\r
94 \r
95 PUBLIC void SPI_Reset( uint32 spi_id, uint32 ms)\r
96 {\r
97         uint32 i = 0;\r
98 \r
99         if(spi_id == 0)\r
100         {\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
104         }\r
105         else if(spi_id == 1)\r
106         {\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
110         }\r
111         else if(spi_id == 2)\r
112         {\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
116         }\r
117 \r
118 \r
119 }\r
120 \r
121 \r
122 LOCAL void SPI_PinConfig(void)\r
123 {\r
124 #ifndef FPGA_TEST\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
130 #endif\r
131 }\r
132 \r
133 \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
136 {\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
139 \r
140         if(spi_id == 0)\r
141         {\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
150         }\r
151 }\r
152 \r
153 \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
157 {\r
158         volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T*)(SPI_USED_BASE);\r
159         uint32 temp;\r
160 \r
161         if(is_low)     {\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
165         }\r
166         else\r
167         {\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
170         }\r
171 }\r
172 \r
173 #define SPI_CD_MASK  BIT_15\r
174 PUBLIC void SPI_SetCd( uint32 cd)\r
175 {\r
176         volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T*)(SPI_USED_BASE);\r
177 \r
178         //0-command;1-data\r
179         if(cd == 0)\r
180                 spi_ctr_ptr->ctl8 &= ~(SPI_CD_MASK);  \r
181         else\r
182                 spi_ctr_ptr->ctl8 |= (SPI_CD_MASK);  \r
183 }\r
184 \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
188 {\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
195 }  SPI_DATA_WIDTH;\r
196 \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
201 {\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
204 \r
205         temp &= ~SPI_MODE_MASK;\r
206         temp |= (spi_mode<<SPI_MODE_SHIFT);\r
207 \r
208         spi_ctr_ptr->ctl7 = temp;\r
209 }\r
210 \r
211 // Transmit data bit number:spi_ctl0[6:2] \r
212 PUBLIC void  SPI_SetDatawidth(uint32 datawidth)\r
213 {\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
216 \r
217         if( 32 == datawidth )\r
218         {\r
219                 spi_ctr_ptr->ctl0 &= ~0x7C;  //  [6:2]\r
220                 return;\r
221         }\r
222 \r
223         temp &= ~0x0000007C;  //mask\r
224         temp |= (datawidth<<2);\r
225 \r
226         spi_ctr_ptr->ctl0 = temp;\r
227 }\r
228 \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
235 //  Author     :  lichd\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
239 {\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
243 \r
244         data_len &= TX_MAX_LEN_MASK;\r
245 \r
246         ctl8 &= ~((TX_DUMY_LEN_MASK<<4) | TX_DATA_LEN_H_MASK);\r
247         ctl9 &= ~( TX_DATA_LEN_L_MASK );\r
248 \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
253 }\r
254 \r
255 \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
262 //  Author     :  lichd\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
266 {\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
270 \r
271         data_len &= RX_MAX_LEN_MASK;\r
272 \r
273         ctl10 &= ~((RX_DUMY_LEN_MASK<<4) | RX_DATA_LEN_H_MASK);\r
274         ctl11 &= ~( RX_DATA_LEN_L_MASK );\r
275 \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
280 \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
286                 }\r
287 }\r
288 \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
293 {\r
294         volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);\r
295 \r
296         spi_ctr_ptr->ctl12 |= SW_TX_REQ_MASK;\r
297 }\r
298 \r
299 PUBLIC void SPI_RxReq( void )\r
300 {\r
301         volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);\r
302 \r
303         spi_ctr_ptr->ctl12 |= SW_RX_REQ_MASK;\r
304 }\r
305 \r
306 /*****************************************************************************/\r
307 //  Description:      To enable or disable DMA depending on parameter(is_enable)\r
308 //  Author:         @Vine.Yuan 2010.5.10\r
309 //    Note:\r
310 /*****************************************************************************/ \r
311 PUBLIC BOOLEAN SPI_EnableDMA(uint32 spi_index,BOOLEAN is_enable)\r
312 {\r
313         volatile SPI_CTL_REG_T* spi_ctl;\r
314 \r
315         spi_ctl = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE+0x3000*spi_index); \r
316 \r
317         if (is_enable)\r
318         {\r
319                 spi_ctl->ctl2 |= BIT_6;\r
320         }\r
321         else\r
322         {\r
323                 spi_ctl->ctl2 &= ~BIT_6;\r
324         }\r
325 \r
326         //spi_ctl->ctl7 |= (BIT_7 | BIT_8);\r
327         spi_ctl->ctl7 |= (BIT_7);\r
328 \r
329         return SCI_TRUE;\r
330 }\r
331 \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
336 \r
337 PUBLIC void SPI_Init(SPI_INIT_PARM *spi_parm)\r
338 {\r
339         volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);\r
340         uint32 temp;\r
341         uint32 ctl0, ctl1, ctl2, ctl3;\r
342 \r
343         /*default clk is 500k 192M /(0xc0 * 2)*/\r
344         spi_ctr_ptr->clkd =0xc0;\r
345 \r
346         temp  = 0;\r
347         temp |= (spi_parm->tx_edge << 1)    |\r
348                 (spi_parm->rx_edge << 0)    |\r
349                 (0x1 << 13) |\r
350                 (spi_parm->msb_lsb_sel<< 7) ;\r
351         spi_ctr_ptr->ctl0 = temp;\r
352 \r
353         spi_ctr_ptr->ctl1 |= BIT_12 | BIT_13;     // set rx/tx mode\r
354 \r
355         /*rx fifo full watermark is 16*/\r
356         spi_ctr_ptr->ctl3 = 0x10;\r
357 \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
361         \r
362 #if 0\r
363         // set water mark of reveive FIFO\r
364         spi_ctr_ptr->ctl3  = (ctl3 & ~0xFFFF) | \r
365                 ((BURST_SIZE >>2) <<8) | \r
366                 (BURST_SIZE >>2);\r
367 #endif\r
368 }\r
369 \r
370 PUBLIC void SPI_WaitTxFinish()\r
371 {\r
372         volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);\r
373 \r
374         while( !((spi_ctr_ptr->iraw)&BIT_8) ) // IS tx finish\r
375         {\r
376         }  \r
377         spi_ctr_ptr->iclr |= BIT_8;\r
378 \r
379         // Wait for spi bus idle\r
380         while((spi_ctr_ptr->sts2)&BIT_8) \r
381         {\r
382         }\r
383         // Wait for tx real empty\r
384         while( !((spi_ctr_ptr->sts2)&BIT_7) ) \r
385         {\r
386         }      \r
387 }\r
388 \r
389 PUBLIC void SPI_WriteData(uint32 data, uint32 data_len, uint32 dummy_bitlen)\r
390 {\r
391         uint32 command;\r
392         volatile SPI_CTL_REG_T *spi_ctr_ptr = (volatile SPI_CTL_REG_T *)(SPI_USED_BASE);\r
393 \r
394         // The unit of data_len is identical with buswidth\r
395         SPI_SetTxLen(data_len, dummy_bitlen);\r
396         SPI_TxReq( );\r
397 \r
398         spi_ctr_ptr->data = data;\r
399 \r
400         SPI_WaitTxFinish();\r
401 }\r
402 \r
403 PUBLIC uint32 SPI_ReadData( uint32 data_len, uint32 dummy_bitlen )\r
404 {\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
407 \r
408         // The unit of data_len is identical with buswidth\r
409         SPI_SetRxLen(data_len, dummy_bitlen);\r
410         SPI_RxReq( );\r
411 \r
412         //Wait for spi receive finish\r
413         while( !((spi_ctr_ptr->iraw)&BIT_9) )\r
414         {\r
415                 //wait rxt fifo full\r
416                 if((spi_ctr_ptr->iraw)&BIT_6)\r
417                 {\r
418                         rxt_cnt = (spi_ctr_ptr->ctl3)&0x1F;\r
419                         //SCI_TraceLow("---FIFOFULL:rxt_cnt=0x%x", rxt_cnt);\r
420                         while(rxt_cnt--)\r
421                         {\r
422                                 read_data = spi_ctr_ptr->data;   \r
423                                 //SCI_TraceLow("---FIFOFULL: SPI_ReadData =0x%x", read_data);\r
424                         }\r
425                 }\r
426         }\r
427 \r
428         // Wait for spi bus idle\r
429         while((spi_ctr_ptr->sts2)&BIT_8) \r
430         {\r
431         }\r
432 \r
433         //\r
434         while(data_len--)\r
435         {\r
436                 read_data = spi_ctr_ptr->data;   \r
437                 //SCI_TraceLow("---Finish: SPI_ReadData =0x%x", read_data);\r
438         }\r
439 \r
440         return (read_data);\r
441 }\r