spi.c
上传用户:plenty2008
上传日期:2022-08-02
资源大小:11k
文件大小:16k
源码类别:

驱动编程

开发平台:

Unix_Linux

  1. /*
  2. Module Name: SPI.CPP
  3. Abstract: SPI Interface Routines for Samsung SC2410 CPU
  4.   
  5. Notes: Presently, only the SPI Channel 0 is supported.
  6. Environment: Samsung SC2410 CPU
  7. Date:  2004/01/28
  8. By:  Li zhongmin
  9.    
  10. */
  11. #include <asm-arm/arch-s3c2410/S3C2410.h>
  12. #include <linux/delay.h>
  13. //#include  "2410addr.h"
  14. #include  "def.h"
  15. #include  "spi.h"
  16. #include "option.h"
  17. volatile DWORD g_dwWaitCounter = 0;
  18. //----------------------------------------------------------------------------------
  19. //extern str[256];
  20. // Used to wait the specified # of clock cycles
  21. #define WAIT(x) { for(g_dwWaitCounter=0; g_dwWaitCounter<x; g_dwWaitCounter++); }
  22. void Port_Init(void)
  23. {
  24.     //CAUTION:Follow the configuration order for setting the ports. 
  25.     // 1) setting value(GPnDAT) 
  26.     // 2) setting control register  (GPnCON)
  27.     // 3) configure pull-up resistor(GPnUP)  
  28.     //32bit data bus configuration  
  29.     //=== PORT A GROUP
  30.     //Ports  : GPA22 GPA21  GPA20 GPA19 GPA18 GPA17 GPA16 GPA15 GPA14 GPA13 GPA12  
  31.     //Signal : nFCE nRSTOUT nFRE   nFWE  ALE   CLE  nGCS5 nGCS4 nGCS3 nGCS2 nGCS1 
  32.     //Binary :  1     1      1  , 1   1   1    1   ,  1     1     1     1
  33.     //Ports  : GPA11   GPA10  GPA9   GPA8   GPA7   GPA6   GPA5   GPA4   GPA3   GPA2   GPA1  GPA0
  34.     //Signal : ADDR26 ADDR25 ADDR24 ADDR23 ADDR22 ADDR21 ADDR20 ADDR19 ADDR18 ADDR17 ADDR16 ADDR0 
  35.     //Binary :  1       1      1      1   , 1       1      1      1   ,  1       1     1      1         
  36.     *(unsigned int *)rGPACON = 0x7fffff; 
  37.     //===* PORT B GROUP
  38.     //Ports  : GPB10    GPB9    GPB8    GPB7    GPB6     GPB5    GPB4   GPB3   GPB2     GPB1      GPB0
  39.     //Signal : nXDREQ0 nXDACK0 nXDREQ1 nXDACK1 nSS_KBD nDIS_OFF L3CLOCK L3DATA L3MODE nIrDATXDEN Keyboard
  40.     //Setting: INPUT  OUTPUT   INPUT  OUTPUT   INPUT   OUTPUT   OUTPUT OUTPUT OUTPUT   OUTPUT    OUTPUT 
  41.     //Binary :   00  ,  01       00  ,   01      00   ,  01       01  ,   01     01   ,  01        01  
  42.     *(unsigned int *)rGPBCON = 0x044555;
  43.     *(unsigned int *)rGPBUP  = 0x7ff;     // The pull up function is disabled GPB[10:0]
  44.     //=== PORT C GROUP
  45.     //Ports  : GPC15 GPC14 GPC13 GPC12 GPC11 GPC10 GPC9 GPC8  GPC7   GPC6   GPC5 GPC4 GPC3  GPC2  GPC1 GPC0
  46.     //Signal : VD7   VD6   VD5   VD4   VD3   VD2   VD1  VD0 LCDVF2 LCDVF1 LCDVF0 VM VFRAME VLINE VCLK LEND  
  47.     //Binary :  10   10  , 10    10  , 10    10  , 10   10  , 10     10  ,  10   10 , 10     10 , 10   10
  48.     *(unsigned int *)rGPCCON = 0xaaaaaaaa;       
  49.     *(unsigned int *)rGPCUP  = 0xffff;     // The pull up function is disabled GPC[15:0] 
  50.     //=== PORT D GROUP
  51.     //Ports  : GPD15 GPD14 GPD13 GPD12 GPD11 GPD10 GPD9 GPD8 GPD7 GPD6 GPD5 GPD4 GPD3 GPD2 GPD1 GPD0
  52.     //Signal : VD23  VD22  VD21  VD20  VD19  VD18  VD17 VD16 VD15 VD14 VD13 VD12 VD11 VD10 VD9  VD8
  53.     //Binary : 10    10  , 10    10  , 10    10  , 10   10 , 10   10 , 10   10 , 10   10 ,10   10
  54.     *(unsigned int *)rGPDCON = 0xaaaaaaaa;       
  55.     *(unsigned int *)rGPDUP  = 0xffff;     // The pull up function is disabled GPD[15:0]
  56.     //=== PORT E GROUP
  57.     //Ports  : GPE15  GPE14 GPE13   GPE12   GPE11   GPE10   GPE9    GPE8     GPE7  GPE6  GPE5   GPE4  
  58.     //Signal : IICSDA IICSCL SPICLK SPIMOSI SPIMISO SDDATA3 SDDATA2 SDDATA1 SDDATA0 SDCMD SDCLK I2SSDO 
  59.     //Binary :  10     10  ,  10      10  ,  10      10   ,  10      10   ,   10    10  , 10     10  ,     
  60.     //-------------------------------------------------------------------------------------------------------
  61.     //Ports  :  GPE3   GPE2  GPE1    GPE0    
  62.     //Signal : I2SSDI CDCLK I2SSCLK I2SLRCK     
  63.     //Binary :  10     10  ,  10      10 
  64.     *(unsigned int *)rGPECON = 0xaaaaaaaa;       
  65.     *(unsigned int *)rGPEUP  = 0xffff;     // The pull up function is disabled GPE[15:0]
  66.     //=== PORT F GROUP
  67.     //Ports  : GPF7   GPF6   GPF5   GPF4      GPF3     GPF2  GPF1   GPF0
  68.     //Signal : nLED_8 nLED_4 nLED_2 nLED_1 nIRQ_PCMCIA EINT2 KBDINT EINT0
  69.     //Setting: Output Output Output Output    EINT3    EINT2 EINT1  EINT0
  70.     //Binary :  01      01 ,  01     01  ,     10       10  , 10     10
  71. //    *(unsigned int *)rGPFCON = 0x55aa;
  72.     *(unsigned int *)rGPFCON = 0xaaaa;
  73.     *(unsigned int *)rGPFUP  = 0xff;     // The pull up function is disabled GPF[7:0]
  74. #if 0       // LIUSJ, Commented for AIJI
  75.     //*** PORT G GROUP
  76.     //Ports  : GPG15 GPG14 GPG13 GPG12 GPG11    GPG10    GPG9     GPG8     GPG7      GPG6    
  77.     //Signal : nYPON  YMON nXPON XMON  EINT19 DMAMODE1 DMAMODE0 DMASTART KBDSPICLK KBDSPIMOSI
  78.     //Setting: nYPON  YMON nXPON XMON  EINT19  Output   Output   Output   SPICLK1    SPIMOSI1
  79.     //Binary :   11    11 , 11    11  , 10      01    ,   01       01   ,    11         11
  80.     //-----------------------------------------------------------------------------------------
  81.     //Ports  :    GPG5       GPG4    GPG3    GPG2    GPG1    GPG0    
  82.     //Signal : KBDSPIMISO LCD_PWREN EINT11 nSS_SPI IRQ_LAN IRQ_PCMCIA
  83.     //Setting:  SPIMISO1  LCD_PWRDN EINT11   nSS0   EINT9    EINT8
  84.     //Binary :     11         11   ,  10      11  ,  10        10
  85.     *(unsigned int *)rGPGCON = 0xff95ffba;
  86.     *(unsigned int *)rGPGUP  = 0xffff;    // The pull up function is disabled GPG[15:0]
  87. #else     
  88. //config GPG15-12 to Touch Panel signals
  89. //config GPG11-10 to output pins
  90. //config GPG9-8   to output pins
  91. //config GPG7-5   to output pins ----Testpoints:TP6,4,2
  92. //config GPG4     to LCD Power Enable
  93. //config GPG3-2   to output pins ----Testpints:TP8,7
  94. //config GPG1-0   to output pins ----GPRS_boot and GPRS_PWR 
  95. *(unsigned int *)rGPGCON = 0xff055555;
  96. *(unsigned int *)rGPGUP  = 0xfffff;
  97. #endif
  98. /*    
  99.     //GPG4 Output Port [9:8] 01      -> LCD_PWREN Enable
  100.     rGPGCON = (rGPGCON & 0xfffffcff) | (1<<8);
  101.     rGPGDAT = (rGPGDAT & 0xffef) | (1<<4);
  102. */
  103.     //=== PORT H GROUP
  104.     //Ports  :  GPH10    GPH9  GPH8 GPH7  GPH6  GPH5 GPH4 GPH3 GPH2 GPH1  GPH0 
  105.     //Signal : CLKOUT1 CLKOUT0 UCLK nCTS1 nRTS1 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
  106.     //Binary :   10   ,  10     10 , 11    11  , 10   10 , 10   10 , 10    10
  107.     *(unsigned int *)rGPHCON = 0x2afaaa;
  108.     *(unsigned int *)rGPHUP  = 0x7ff;    // The pull up function is disabled GPH[10:0]
  109.     
  110.     //External interrupt will be falling edge triggered. 
  111.     *(unsigned int *)rEXTINT0 = 0x22222222;    // EINT[7:0]
  112.     *(unsigned int *)rEXTINT1 = 0x22222222;    // EINT[15:8]
  113.     *(unsigned int *)rEXTINT2 = 0x22222222;    // EINT[23:16]
  114. }
  115. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  116. Function: SPI_Init()
  117. Description: Initializes the Serial Peripheral Interface (SPI)
  118. Notes: This routine assumes that the control registers (see 
  119. the globals section above) have already been initialized.
  120. Returns: Boolean indicating success.
  121. -------------------------------------------------------------------*/
  122. BOOL SPI_Init(VOID)
  123. {
  124. int index;
  125. // index = *(unsigned int *)rCLKCON;
  126. // *(unsigned int *)rCLKCON = index;
  127. // index = 0;
  128. // index = *(unsigned int *)rCLKCON;
  129. // printk("rCLKCON = %dn",index);
  130. *(unsigned int *)rGPGDAT = (*(unsigned int *)rGPGDAT)|CHIP_DESELECT_nSS0;
  131. //chip select SPI1 ???
  132. //----- 1. IMPORTANT: By default, the internal clock is disabled.  To configure the controller ------
  133. //   we must first enable it.
  134. StartSPIClock();
  135.     
  136. SetSPIClockRate(CLK_RATE_SLOW);
  137. //----- 2. Configure the GPIO pins for SPI mode -----
  138. //
  139. //    nSPICS0  (chip select) = GPG2
  140. //    SPICLK0  (SPI clock) = GPE13
  141. //    SPIMOSIO (SPI output data) = GPE12
  142. /*   
  143. *(unsigned int *)rGPGCON = (*(unsigned int *)rGPGCON) & CLEAR_GPG2_MASK;
  144. *(unsigned int *)rGPGCON = (*(unsigned int *)rGPGCON) | ENABLE_GPG2_OUTPUT;
  145. *(unsigned int *)rGPGUP  = (*(unsigned int *)rGPGUP)  & ENABLE_GPG2_PULLUP;
  146. // port_outl(rGPGUP , (port_inl(rGPGUP) & 0x0));
  147. *(unsigned int *)rGPGCON = (*(unsigned int *)rGPECON) & 0xf03fffff;
  148. *(unsigned int *)rGPECON = (*(unsigned int *)rGPECON) | ENABLE_SPICLK0 | ENABLE_SPIMSIO;
  149. // *(unsigned int *)rGPEUP  = (*(unsigned int *)rGPEUP) | DISABLE_SPICLK_SPIMSIO_PULLUP; // Disable pullup-resistor for SPICLK0 and SPIMOSIO   the name is too long 
  150. // *(unsigned int *)rGPEUP  = (*(unsigned int *)rGPEUP)  | TEST;    //#define TEST 0x00003800 in spi.h
  151. *(unsigned int *)rGPEUP  = (*(unsigned int *)rGPEUP)  | 0x00003800;
  152. // port_outl(rGPEUP , (port_inl(rGPEUP)  | 0xffffffff));
  153. */
  154. Port_Init();
  155. //----- 3. Configure the SPI controller with reasonable default values -----
  156. *(unsigned int *)rSPCON0 = SPI_MODE_POLLING | SPI_SELECT_MASTER | SPI_CLOCK_ENABLE;
  157. *(unsigned int *)rSPCON1 = SPI_MODE_POLLING | SPI_SELECT_MASTER | SPI_CLOCK_ENABLE;
  158. for( index = 0; index < 20; index++)
  159. *(unsigned char *)rSPTDAT0 =  0xFF;
  160. for( index = 0; index < 20; index++)
  161. *(unsigned char *)rSPTDAT1 =  0xFF;
  162.     //StopSPIClock();
  163. return TRUE;
  164. }
  165. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  166. Function: SPI_Deinit()
  167. Description: Deinitializes the Serial Peripheral Interface (SPI)
  168. Notes: This routine DOES NOT unmap the control registers;
  169. the caller is responsible for freeing this memory.
  170. Returns: Boolean indicating success.
  171. -------------------------------------------------------------------*/
  172. BOOL SPI_Deinit(VOID)
  173. {
  174. //----- 1. Stop the SPI clocks -----
  175.     StopSPIClock();
  176. return TRUE;
  177. }
  178. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  179. Function: SPI_SendByte()
  180. Description: Sends the specified byte out onto the SPI bus.
  181. Returns: Boolean indicating success.
  182. -------------------------------------------------------------------*/
  183. BOOL SPI_SendByte(BYTE bData, BYTE* pData)
  184. {
  185.     //----- 0. Start clock
  186.     //StartSPIClock();
  187. //----- 1. Chip select the slave device (active low) -----
  188. //rGPGDAT &= CHIP_SELECT_nSS0;
  189. //----- 2. Wait until the controller is ready to transfer -----
  190. if(SPI_WaitTxRxReady()==FALSE) return FALSE;
  191. // printk("after the 1st wait in SPI_SendByte.n");
  192. //----- 3. Put the byte out onto the SPI bus -----
  193. *(unsigned char *)rSPTDAT0 =  bData;
  194. //----- 4. Delay a little bit so the byte finishes clocking out before the chip select line is deasserted -----
  195. if(SPI_WaitTxRxReady()==FALSE) return FALSE;
  196. // printk("after the 2nd wait in SPI_SendByte.n");
  197. *pData = *(unsigned char *)rSPRDAT0;
  198. //----- 5. Deselect the slave device (active low) -----
  199. //rGPGDAT |= CHIP_DESELECT_nSS0;
  200.    // StopSPIClock();
  201. return TRUE;
  202. }
  203. BOOL SPI_ReadByte(BYTE *pData)
  204. {
  205.     BOOL    bRet = TRUE;
  206.     
  207.     //----- 0. Start clock
  208.     //StartSPIClock();
  209. //----- 1. Chip select the slave device (active low) -----
  210. //rGPGDAT &= CHIP_SELECT_nSS0;
  211. //----- 2. Wait until the controller is ready to transfer -----
  212. if(SPI_WaitTxRxReady()==FALSE) return FALSE;
  213. //----- 3. Put the byte out onto the SPI bus -----
  214. *pData = *(unsigned char *)rSPRDAT0;
  215. //----- 4. Delay a little bit so the byte finishes clocking out before the chip select line is deasserted -----
  216. //if(SPI_WaitTxRxReady()==FALSE) return FALSE;
  217. //----- 5. Deselect the slave device (active low) -----
  218. //rGPGDAT |= CHIP_DESELECT_nSS0;
  219.    // StopSPIClock();
  220. return bRet;
  221. }
  222. BOOL SPI_WaitTxRxReady(VOID)
  223. {
  224. int waitCount;
  225. // int reg;
  226. //----- 1. Wait until the controller is ready to transfer -----
  227. waitCount = 1000;
  228. while(!((*(unsigned int *)rSPSTA0) & SPI_TRANSFER_READY))
  229. {
  230. if(--waitCount == 0)
  231. {
  232. // reg = *(unsigned int *)rSPSTA0;
  233. // printk("rSPSTA0 = %dn",reg);
  234. // printk("WaitTxRxReady return FALSE.n");
  235. // ssleep(1);
  236. // msleep(1);
  237. mdelay(10);
  238. // udelay(1);
  239. // ndelay(1);
  240. return FALSE;
  241. }
  242. }
  243. return TRUE;
  244. }
  245. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  246. Function: SPI_SendWord()
  247. Description: Sends the specified word out onto the SPI bus.
  248. Returns: Boolean indicating success.
  249. -------------------------------------------------------------------*/
  250. /*BOOL SPI_SendWord(WORD wData)
  251. {
  252.     BOOL    bRet = TRUE;
  253. DWORD   waitCount = 0;
  254.     StartSPIClock();
  255. //----- 1. Chip select the slave device (active low) -----
  256. rGPGDAT &= CHIP_SELECT_nSS0;
  257. //----- 2. Wait until the controller is ready to transfer -----
  258. waitCount = 1000;
  259. while(!(rSPSTA0 & SPI_TRANSFER_READY))
  260. {
  261. if(--waitCount == 0)
  262. {
  263.             bRet = FALSE;
  264. goto SEND_ERROR;
  265. }
  266. }
  267. //----- 3. Send first half of word -----
  268. rSPTDAT0 = (wData & 0xFF00) >> 8;
  269. //----- 4. Wait until the controller is ready to transfer -----
  270. waitCount = 1000;
  271. while(!(rSPSTA0 & SPI_TRANSFER_READY))
  272. {
  273. if(--waitCount == 0)
  274. {
  275. //RETAILMSG(1, (TEXT("WAVEDEV.DLL: SPI_SendWord() - timeout occurred while waiting to transfer bytern")));
  276.             bRet = FALSE;
  277. goto SEND_ERROR;
  278. }
  279. }
  280. //----- 5. Send second half of word -----
  281. rSPTDAT0 = (wData & 0x00FF);
  282. //----- 6. Delay a little bit so the byte finishes clocking out before the chip select line is deasserted -----
  283. WAIT(10000);
  284. //----- 7. Deselect the slave device (active low) -----
  285. rGPGDAT |= CHIP_DESELECT_nSS0;
  286. SEND_ERROR:
  287.     StopSPIClock();
  288. return bRet;
  289. }
  290. */
  291. //------------------------------------ Helper Routines ------------------------------------
  292. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  293. Function: StartSPIClock()
  294. Description: Enables the SPI clock.
  295. Returns: N/A
  296. -------------------------------------------------------------------*/
  297. VOID StartSPIClock(VOID)
  298. {
  299. *(unsigned int *)rCLKCON = (*(unsigned int *)rCLKCON)|SPI_INTERNAL_CLOCK_ENABLE;// Enable the CPU clock to the SPI controller
  300. *(unsigned int *)rSPCON0 = (*(unsigned int *)rSPCON0)|SPI_CLOCK_ENABLE|SPI_SELECT_MASTER;// Enable the SPI clock
  301. return;
  302. }
  303. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  304. Function: StopSPIClock()
  305. Description: Disables the SPI clock.
  306. Returns: N/A
  307. -------------------------------------------------------------------*/
  308. VOID StopSPIClock(VOID)
  309. {
  310. *(unsigned int *)rCLKCON = (*(unsigned int *)rCLKCON) & ~SPI_INTERNAL_CLOCK_ENABLE; // Disable the CPU clock to the SPI controller
  311. *(unsigned int *)rSPCON0 = (*(unsigned int *)rCLKCON) & ~SPI_CLOCK_ENABLE; // Disable the SPI clock
  312. return;
  313. }
  314. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  315. Function: SetSPIClockRate()
  316. Description: Sets the SPI clock (a.k.a. baud) rate:
  317. Params: ClockRate       0x00 =      25Mhz
  318. 0x01 = 1/2  25Mhz
  319. 0x02 = 1/4  25Mhz
  320. 0x03 = 1/8  25Mhz
  321. 0x04 = 1/16 25Mhz
  322. 0x05 = 1/32 25Mhz
  323. 0x06 = 1/64 25Mhz
  324. 0x07 = 99.121Khz
  325. Returns: N/A
  326. -------------------------------------------------------------------*/
  327. VOID SetSPIClockRate(DWORD ClockRate)
  328. {
  329. UINT16 prescale;
  330.     //----- 1. Set the clock rate  -----
  331. //    NOTE: Using the prescale value, the clock's baud rate is
  332. //  determined as follows: baud_rate = (PCLK / 2 / (prescale + 1))
  333. //
  334. //  Hence, the prescale value can be computed as follows:
  335. //  prescale = ((PCLK / 2) / baud_rate) - 1
  336. switch(ClockRate)
  337. {
  338. case CLK_RATE_FULL: // 25 Mhz
  339. prescale = (PCLK / 40000000) - 1;
  340. break;
  341. case CLK_RATE_HALF: // 1/2  25 Mhz
  342. prescale = (PCLK / 30000000) - 1;
  343. break;
  344. case CLK_RATE_FOUR: // 1/4  25 Mhz
  345. prescale = (PCLK / 10000000) - 1;
  346. break;
  347. case CLK_RATE_EIGHT: // 1/8  25 Mhz
  348. prescale = (PCLK / 500000) - 1;
  349. break;
  350. case CLK_RATE_SIXTEEN: // 1/16 25 Mhz
  351. prescale = (PCLK / 2500000) - 1;
  352. break;
  353. case CLK_RATE_THIRTY2: // 1/32 25 Mhz
  354. prescale = (PCLK / 1250000) - 1;
  355. break;
  356. case CLK_RATE_SIXTY4: // 1/64 25 Mhz
  357. prescale = (PCLK / 625000) - 1;
  358. break;
  359. case CLK_RATE_SLOW: // 99.121 kHz (i.e. ~1/256 25Mhz)
  360. prescale = 255;
  361. break;
  362. default:
  363. return;
  364. break;
  365. }
  366. *(unsigned int *)rSPPRE0 = prescale;
  367.     return;
  368. }