1 /* Driver for ATMEL DataFlash support
2  * Author : Hamid Ikdoumi (Atmel)
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17  * MA 02111-1307 USA
18  *
19  */
20 
21 #include <config.h>
22 #include <common.h>
23 #include <asm/hardware.h>
24 
25 #ifdef CONFIG_HAS_DATAFLASH
26 #include <dataflash.h>
27 
28 #define AT91C_SPI_CLK	10000000	/* Max Value = 10MHz to be compliant to
29 					the Continuous Array Read function */
30 
31 /* AC Characteristics */
32 /* DLYBS = tCSS = 250ns min and DLYBCT = tCSH = 250ns */
33 #define DATAFLASH_TCSS	(0xC << 16)
34 #define DATAFLASH_TCHS	(0x1 << 24)
35 
36 #define AT91C_TIMEOUT_WRDY		200000
37 #define AT91C_SPI_PCS0_SERIAL_DATAFLASH	0xE	/* Chip Select 0: NPCS0%1110 */
38 #define AT91C_SPI_PCS3_DATAFLASH_CARD	0x7	/* Chip Select 3: NPCS3%0111 */
39 
40 /*-------------------------------------------------------------------*/
41 /*	SPI DataFlash Init					     */
42 /*-------------------------------------------------------------------*/
AT91F_SpiInit(void)43 void AT91F_SpiInit(void)
44 {
45 	/* Configure PIOs */
46 	AT91C_BASE_PIOA->PIO_ASR =
47 		AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 | AT91C_PA1_MOSI |
48 		AT91C_PA5_NPCS2 | AT91C_PA6_NPCS3 | AT91C_PA0_MISO |
49 		AT91C_PA2_SPCK;
50 	AT91C_BASE_PIOA->PIO_PDR =
51 		AT91C_PA3_NPCS0 | AT91C_PA4_NPCS1 | AT91C_PA1_MOSI |
52 		AT91C_PA5_NPCS2 | AT91C_PA6_NPCS3 | AT91C_PA0_MISO |
53 		AT91C_PA2_SPCK;
54 	/* Enable CLock */
55 	AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_SPI;
56 
57 	/* Reset the SPI */
58 	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
59 
60 	/* Configure SPI in Master Mode with No CS selected !!! */
61 	AT91C_BASE_SPI->SPI_MR =
62 		AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS;
63 
64 	/* Configure CS0 and CS3 */
65 	*(AT91C_SPI_CSR + 0) =
66 		AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) |
67 		(AT91C_SPI_DLYBCT & DATAFLASH_TCHS) |
68 		((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8);
69 
70 	*(AT91C_SPI_CSR + 3) =
71 		AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) |
72 		(AT91C_SPI_DLYBCT & DATAFLASH_TCHS) |
73 		((AT91C_MASTER_CLOCK / (2*AT91C_SPI_CLK)) << 8);
74 }
75 
AT91F_SpiEnable(int cs)76 void AT91F_SpiEnable(int cs)
77 {
78 	switch(cs) {
79 	case 0:	/* Configure SPI CS0 for Serial DataFlash AT45DBxx */
80 		AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
81 		AT91C_BASE_SPI->SPI_MR |=
82 			((AT91C_SPI_PCS0_SERIAL_DATAFLASH<<16) &
83 				AT91C_SPI_PCS);
84 		break;
85 	case 3:	/* Configure SPI CS3 for Serial DataFlash Card */
86 		/* Set up PIO SDC_TYPE to switch on DataFlash Card */
87 		/* and not MMC/SDCard */
88 		AT91C_BASE_PIOB->PIO_PER =
89 			AT91C_PIO_PB7;	/* Set in PIO mode */
90 		AT91C_BASE_PIOB->PIO_OER =
91 			AT91C_PIO_PB7;	/* Configure in output */
92 		/* Clear Output */
93 		AT91C_BASE_PIOB->PIO_CODR = AT91C_PIO_PB7;
94 		/* Configure PCS */
95 		AT91C_BASE_SPI->SPI_MR &= 0xFFF0FFFF;
96 		AT91C_BASE_SPI->SPI_MR |=
97 			((AT91C_SPI_PCS3_DATAFLASH_CARD<<16) & AT91C_SPI_PCS);
98 		break;
99 	}
100 
101 	/* SPI_Enable */
102 	AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; }
103 
104 /*---------------------------------------------------------------------------*/
105 /* \fn    AT91F_SpiWrite						     */
106 /* \brief Set the PDC registers for a transfert				     */
107 /*---------------------------------------------------------------------------*/
AT91F_SpiWrite(AT91PS_DataflashDesc pDesc)108 unsigned int AT91F_SpiWrite ( AT91PS_DataflashDesc pDesc )
109 {
110 	unsigned int timeout;
111 
112 	pDesc->state = BUSY;
113 
114 	AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
115 
116 	/* Initialize the Transmit and Receive Pointer */
117 	AT91C_BASE_SPI->SPI_RPR = (unsigned int)pDesc->rx_cmd_pt ;
118 	AT91C_BASE_SPI->SPI_TPR = (unsigned int)pDesc->tx_cmd_pt ;
119 
120 	/* Intialize the Transmit and Receive Counters */
121 	AT91C_BASE_SPI->SPI_RCR = pDesc->rx_cmd_size;
122 	AT91C_BASE_SPI->SPI_TCR = pDesc->tx_cmd_size;
123 
124 	if ( pDesc->tx_data_size != 0 ) {
125 		/* Initialize the Next Transmit and Next Receive Pointer */
126 		AT91C_BASE_SPI->SPI_RNPR = (unsigned int)pDesc->rx_data_pt ;
127 		AT91C_BASE_SPI->SPI_TNPR = (unsigned int)pDesc->tx_data_pt ;
128 
129 		/* Intialize the Next Transmit and Next Receive Counters */
130 		AT91C_BASE_SPI->SPI_RNCR = pDesc->rx_data_size ;
131 		AT91C_BASE_SPI->SPI_TNCR = pDesc->tx_data_size ;
132 	}
133 
134 	/* arm simple, non interrupt dependent timer */
135 	reset_timer_masked();
136 	timeout = 0;
137 
138 	AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN;
139 	while(!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RXBUFF) &&
140 		((timeout = get_timer_masked() ) < CONFIG_SYS_SPI_WRITE_TOUT));
141 	AT91C_BASE_SPI->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS;
142 	pDesc->state = IDLE;
143 
144 	if (timeout >= CONFIG_SYS_SPI_WRITE_TOUT){
145 		printf("Error Timeout\n\r");
146 		return DATAFLASH_ERROR;
147 	}
148 
149 	return DATAFLASH_OK;
150 }
151 #endif
152