blob: e7d3ff0ac5c96eb12af1c2a0522f077a05ee21c5 [file] [log] [blame]
Stelian Popfefb6c12008-01-30 21:15:54 +00001/*
2 * Driver for ATMEL DataFlash support
3 * Author : Hamid Ikdoumi (Atmel)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 * MA 02111-1307 USA
19 *
20 */
21
Stelian Popfefb6c12008-01-30 21:15:54 +000022#include <common.h>
Jens Scharsig0cf0b932010-02-03 22:46:58 +010023#ifndef CONFIG_AT91_LEGACY
Reinhard Meyer576e7a12011-06-06 00:05:56 +000024# define CONFIG_AT91_LEGACY
Reinhard Meyera0cfd182010-11-09 17:06:20 +010025# warning Please update to use C structure SoC access !
Jens Scharsig0cf0b932010-02-03 22:46:58 +010026#endif
Reinhard Meyera0cfd182010-11-09 17:06:20 +010027#include <spi.h>
28#include <malloc.h>
29
30#include <asm/io.h>
31
Jean-Christophe PLAGNIOL-VILLARDdc39ae92009-04-16 21:30:44 +020032#include <asm/arch/clk.h>
Reinhard Meyera0cfd182010-11-09 17:06:20 +010033#include <asm/arch/hardware.h>
34
35#include "atmel_spi.h"
36
Stelian Pop983c1db2008-03-26 20:52:32 +010037#include <asm/arch/gpio.h>
Stelian Pop983c1db2008-03-26 20:52:32 +010038#include <asm/arch/at91_pio.h>
39#include <asm/arch/at91_spi.h>
Stelian Popfefb6c12008-01-30 21:15:54 +000040
Stelian Popfefb6c12008-01-30 21:15:54 +000041#include <dataflash.h>
42
Stelian Pop983c1db2008-03-26 20:52:32 +010043#define AT91_SPI_PCS0_DATAFLASH_CARD 0xE /* Chip Select 0: NPCS0%1110 */
Remy Bohmer41dfd8a2009-10-28 22:13:37 +010044#define AT91_SPI_PCS1_DATAFLASH_CARD 0xD /* Chip Select 1: NPCS1%1101 */
45#define AT91_SPI_PCS2_DATAFLASH_CARD 0xB /* Chip Select 2: NPCS2%1011 */
Stelian Pop983c1db2008-03-26 20:52:32 +010046#define AT91_SPI_PCS3_DATAFLASH_CARD 0x7 /* Chip Select 3: NPCS3%0111 */
Stelian Popfefb6c12008-01-30 21:15:54 +000047
48void AT91F_SpiInit(void)
49{
50 /* Reset the SPI */
Reinhard Meyera0cfd182010-11-09 17:06:20 +010051 writel(AT91_SPI_SWRST, ATMEL_BASE_SPI0 + AT91_SPI_CR);
Stelian Popfefb6c12008-01-30 21:15:54 +000052
53 /* Configure SPI in Master Mode with No CS selected !!! */
Stelian Pop983c1db2008-03-26 20:52:32 +010054 writel(AT91_SPI_MSTR | AT91_SPI_MODFDIS | AT91_SPI_PCS,
Reinhard Meyera0cfd182010-11-09 17:06:20 +010055 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popfefb6c12008-01-30 21:15:54 +000056
57 /* Configure CS0 */
Stelian Pop983c1db2008-03-26 20:52:32 +010058 writel(AT91_SPI_NCPHA |
59 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
60 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
Jean-Christophe PLAGNIOL-VILLARDdc39ae92009-04-16 21:30:44 +020061 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyera0cfd182010-11-09 17:06:20 +010062 ATMEL_BASE_SPI0 + AT91_SPI_CSR(0));
Stelian Pop983c1db2008-03-26 20:52:32 +010063
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020064#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS1
Stelian Pop983c1db2008-03-26 20:52:32 +010065 /* Configure CS1 */
66 writel(AT91_SPI_NCPHA |
67 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
68 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
Jean-Christophe PLAGNIOL-VILLARDdc39ae92009-04-16 21:30:44 +020069 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyera0cfd182010-11-09 17:06:20 +010070 ATMEL_BASE_SPI0 + AT91_SPI_CSR(1));
Stelian Pop983c1db2008-03-26 20:52:32 +010071#endif
Remy Bohmer41dfd8a2009-10-28 22:13:37 +010072#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS2
73 /* Configure CS2 */
74 writel(AT91_SPI_NCPHA |
75 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
76 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
77 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyera0cfd182010-11-09 17:06:20 +010078 ATMEL_BASE_SPI0 + AT91_SPI_CSR(2));
Remy Bohmer41dfd8a2009-10-28 22:13:37 +010079#endif
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020080#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS3
Stelian Pop983c1db2008-03-26 20:52:32 +010081 /* Configure CS3 */
82 writel(AT91_SPI_NCPHA |
83 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
84 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
Jean-Christophe PLAGNIOL-VILLARDdc39ae92009-04-16 21:30:44 +020085 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyera0cfd182010-11-09 17:06:20 +010086 ATMEL_BASE_SPI0 + AT91_SPI_CSR(3));
Stelian Pop983c1db2008-03-26 20:52:32 +010087#endif
88
89 /* SPI_Enable */
Reinhard Meyera0cfd182010-11-09 17:06:20 +010090 writel(AT91_SPI_SPIEN, ATMEL_BASE_SPI0 + AT91_SPI_CR);
Stelian Pop983c1db2008-03-26 20:52:32 +010091
Reinhard Meyera0cfd182010-11-09 17:06:20 +010092 while (!(readl(ATMEL_BASE_SPI0 + AT91_SPI_SR) & AT91_SPI_SPIENS))
93 ;
Stelian Pop983c1db2008-03-26 20:52:32 +010094
95 /*
96 * Add tempo to get SPI in a safe state.
97 * Should not be needed for new silicon (Rev B)
98 */
99 udelay(500000);
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100100 readl(ATMEL_BASE_SPI0 + AT91_SPI_SR);
101 readl(ATMEL_BASE_SPI0 + AT91_SPI_RDR);
Stelian Pop983c1db2008-03-26 20:52:32 +0100102
Stelian Popfefb6c12008-01-30 21:15:54 +0000103}
104
105void AT91F_SpiEnable(int cs)
106{
Stelian Pop983c1db2008-03-26 20:52:32 +0100107 unsigned long mode;
Jean-Christophe PLAGNIOL-VILLARD1762f132008-03-31 21:20:49 +0200108
Stelian Popfefb6c12008-01-30 21:15:54 +0000109 switch (cs) {
110 case 0: /* Configure SPI CS0 for Serial DataFlash AT45DBxx */
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100111 mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Pop983c1db2008-03-26 20:52:32 +0100112 mode &= 0xFFF0FFFF;
113 writel(mode | ((AT91_SPI_PCS0_DATAFLASH_CARD<<16) & AT91_SPI_PCS),
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100114 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Pop983c1db2008-03-26 20:52:32 +0100115 break;
116 case 1: /* Configure SPI CS1 for Serial DataFlash AT45DBxx */
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100117 mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Pop983c1db2008-03-26 20:52:32 +0100118 mode &= 0xFFF0FFFF;
119 writel(mode | ((AT91_SPI_PCS1_DATAFLASH_CARD<<16) & AT91_SPI_PCS),
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100120 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popfefb6c12008-01-30 21:15:54 +0000121 break;
Remy Bohmer41dfd8a2009-10-28 22:13:37 +0100122 case 2: /* Configure SPI CS2 for Serial DataFlash AT45DBxx */
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100123 mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
Remy Bohmer41dfd8a2009-10-28 22:13:37 +0100124 mode &= 0xFFF0FFFF;
125 writel(mode | ((AT91_SPI_PCS2_DATAFLASH_CARD<<16) & AT91_SPI_PCS),
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100126 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Remy Bohmer41dfd8a2009-10-28 22:13:37 +0100127 break;
Stelian Popfefb6c12008-01-30 21:15:54 +0000128 case 3:
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100129 mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Pop983c1db2008-03-26 20:52:32 +0100130 mode &= 0xFFF0FFFF;
131 writel(mode | ((AT91_SPI_PCS3_DATAFLASH_CARD<<16) & AT91_SPI_PCS),
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100132 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popfefb6c12008-01-30 21:15:54 +0000133 break;
134 }
135
136 /* SPI_Enable */
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100137 writel(AT91_SPI_SPIEN, ATMEL_BASE_SPI0 + AT91_SPI_CR);
Stelian Popfefb6c12008-01-30 21:15:54 +0000138}
139
Stelian Pop983c1db2008-03-26 20:52:32 +0100140unsigned int AT91F_SpiWrite1(AT91PS_DataflashDesc pDesc);
141
Stelian Popfefb6c12008-01-30 21:15:54 +0000142unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc)
143{
144 unsigned int timeout;
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100145 unsigned int timebase;
Stelian Popfefb6c12008-01-30 21:15:54 +0000146
147 pDesc->state = BUSY;
148
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100149 writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS,
150 ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
Stelian Pop983c1db2008-03-26 20:52:32 +0100151
Stelian Popfefb6c12008-01-30 21:15:54 +0000152 /* Initialize the Transmit and Receive Pointer */
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100153 writel((unsigned int)pDesc->rx_cmd_pt,
154 ATMEL_BASE_SPI0 + AT91_SPI_RPR);
155 writel((unsigned int)pDesc->tx_cmd_pt,
156 ATMEL_BASE_SPI0 + AT91_SPI_TPR);
Stelian Popfefb6c12008-01-30 21:15:54 +0000157
158 /* Intialize the Transmit and Receive Counters */
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100159 writel(pDesc->rx_cmd_size, ATMEL_BASE_SPI0 + AT91_SPI_RCR);
160 writel(pDesc->tx_cmd_size, ATMEL_BASE_SPI0 + AT91_SPI_TCR);
Stelian Popfefb6c12008-01-30 21:15:54 +0000161
162 if (pDesc->tx_data_size != 0) {
163 /* Initialize the Next Transmit and Next Receive Pointer */
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100164 writel((unsigned int)pDesc->rx_data_pt,
165 ATMEL_BASE_SPI0 + AT91_SPI_RNPR);
166 writel((unsigned int)pDesc->tx_data_pt,
167 ATMEL_BASE_SPI0 + AT91_SPI_TNPR);
Stelian Popfefb6c12008-01-30 21:15:54 +0000168
169 /* Intialize the Next Transmit and Next Receive Counters */
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100170 writel(pDesc->rx_data_size,
171 ATMEL_BASE_SPI0 + AT91_SPI_RNCR);
172 writel(pDesc->tx_data_size,
173 ATMEL_BASE_SPI0 + AT91_SPI_TNCR);
Stelian Popfefb6c12008-01-30 21:15:54 +0000174 }
175
176 /* arm simple, non interrupt dependent timer */
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100177 timebase = get_timer(0);
Stelian Popfefb6c12008-01-30 21:15:54 +0000178 timeout = 0;
179
Reinhard Meyera0cfd182010-11-09 17:06:20 +0100180 writel(AT91_SPI_TXTEN + AT91_SPI_RXTEN,
181 ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
182 while (!(readl(ATMEL_BASE_SPI0 + AT91_SPI_SR) & AT91_SPI_RXBUFF) &&
183 ((timeout = get_timer(timebase)) < CONFIG_SYS_SPI_WRITE_TOUT))
184 ;
185 writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS,
186 ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
Stelian Popfefb6c12008-01-30 21:15:54 +0000187 pDesc->state = IDLE;
188
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200189 if (timeout >= CONFIG_SYS_SPI_WRITE_TOUT) {
Stelian Popfefb6c12008-01-30 21:15:54 +0000190 printf("Error Timeout\n\r");
191 return DATAFLASH_ERROR;
192 }
193
194 return DATAFLASH_OK;
195}