blob: 363e07a53f978ec9641b02559f3b87bfb6bc892c [file] [log] [blame]
Stelian Popd1aea1c2008-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
Reinhard Meyerc163d3d2011-08-02 15:09:55 +000022/*
23 * This driver desperately needs rework:
24 *
25 * - use structure SoC access
26 * - get rid of including asm/arch/at91_spi.h
27 * - remove asm/arch/at91_spi.h
28 * - get rid of all CONFIG_ATMEL_LEGACY defines and uses
29 *
30 * 02-Aug-2010 Reinhard Meyer <uboot@emk-elektronik.de>
31 */
32
Stelian Popd1aea1c2008-01-30 21:15:54 +000033#include <common.h>
Reinhard Meyerc163d3d2011-08-02 15:09:55 +000034#ifndef CONFIG_ATMEL_LEGACY
35# define CONFIG_ATMEL_LEGACY
Jens Scharsiga4db1ca2010-02-03 22:46:58 +010036#endif
Reinhard Meyer324914a2010-11-09 17:06:20 +010037#include <spi.h>
38#include <malloc.h>
39
40#include <asm/io.h>
41
Jean-Christophe PLAGNIOL-VILLARD23164f12009-04-16 21:30:44 +020042#include <asm/arch/clk.h>
Reinhard Meyer324914a2010-11-09 17:06:20 +010043#include <asm/arch/hardware.h>
44
45#include "atmel_spi.h"
46
Stelian Popd4bfbc52008-03-26 20:52:32 +010047#include <asm/arch/gpio.h>
Stelian Popd4bfbc52008-03-26 20:52:32 +010048#include <asm/arch/at91_pio.h>
49#include <asm/arch/at91_spi.h>
Stelian Popd1aea1c2008-01-30 21:15:54 +000050
Stelian Popd1aea1c2008-01-30 21:15:54 +000051#include <dataflash.h>
52
Stelian Popd4bfbc52008-03-26 20:52:32 +010053#define AT91_SPI_PCS0_DATAFLASH_CARD 0xE /* Chip Select 0: NPCS0%1110 */
Remy Bohmer7b2b5d32009-10-28 22:13:37 +010054#define AT91_SPI_PCS1_DATAFLASH_CARD 0xD /* Chip Select 1: NPCS1%1101 */
55#define AT91_SPI_PCS2_DATAFLASH_CARD 0xB /* Chip Select 2: NPCS2%1011 */
Stelian Popd4bfbc52008-03-26 20:52:32 +010056#define AT91_SPI_PCS3_DATAFLASH_CARD 0x7 /* Chip Select 3: NPCS3%0111 */
Stelian Popd1aea1c2008-01-30 21:15:54 +000057
58void AT91F_SpiInit(void)
59{
60 /* Reset the SPI */
Reinhard Meyer324914a2010-11-09 17:06:20 +010061 writel(AT91_SPI_SWRST, ATMEL_BASE_SPI0 + AT91_SPI_CR);
Stelian Popd1aea1c2008-01-30 21:15:54 +000062
63 /* Configure SPI in Master Mode with No CS selected !!! */
Stelian Popd4bfbc52008-03-26 20:52:32 +010064 writel(AT91_SPI_MSTR | AT91_SPI_MODFDIS | AT91_SPI_PCS,
Reinhard Meyer324914a2010-11-09 17:06:20 +010065 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popd1aea1c2008-01-30 21:15:54 +000066
67 /* Configure CS0 */
Stelian Popd4bfbc52008-03-26 20:52:32 +010068 writel(AT91_SPI_NCPHA |
69 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
70 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
Jean-Christophe PLAGNIOL-VILLARD23164f12009-04-16 21:30:44 +020071 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyer324914a2010-11-09 17:06:20 +010072 ATMEL_BASE_SPI0 + AT91_SPI_CSR(0));
Stelian Popd4bfbc52008-03-26 20:52:32 +010073
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020074#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS1
Stelian Popd4bfbc52008-03-26 20:52:32 +010075 /* Configure CS1 */
76 writel(AT91_SPI_NCPHA |
77 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
78 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
Jean-Christophe PLAGNIOL-VILLARD23164f12009-04-16 21:30:44 +020079 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyer324914a2010-11-09 17:06:20 +010080 ATMEL_BASE_SPI0 + AT91_SPI_CSR(1));
Stelian Popd4bfbc52008-03-26 20:52:32 +010081#endif
Remy Bohmer7b2b5d32009-10-28 22:13:37 +010082#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS2
83 /* Configure CS2 */
84 writel(AT91_SPI_NCPHA |
85 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
86 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
87 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyer324914a2010-11-09 17:06:20 +010088 ATMEL_BASE_SPI0 + AT91_SPI_CSR(2));
Remy Bohmer7b2b5d32009-10-28 22:13:37 +010089#endif
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020090#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS3
Stelian Popd4bfbc52008-03-26 20:52:32 +010091 /* Configure CS3 */
92 writel(AT91_SPI_NCPHA |
93 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
94 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
Jean-Christophe PLAGNIOL-VILLARD23164f12009-04-16 21:30:44 +020095 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyer324914a2010-11-09 17:06:20 +010096 ATMEL_BASE_SPI0 + AT91_SPI_CSR(3));
Stelian Popd4bfbc52008-03-26 20:52:32 +010097#endif
98
99 /* SPI_Enable */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100100 writel(AT91_SPI_SPIEN, ATMEL_BASE_SPI0 + AT91_SPI_CR);
Stelian Popd4bfbc52008-03-26 20:52:32 +0100101
Reinhard Meyer324914a2010-11-09 17:06:20 +0100102 while (!(readl(ATMEL_BASE_SPI0 + AT91_SPI_SR) & AT91_SPI_SPIENS))
103 ;
Stelian Popd4bfbc52008-03-26 20:52:32 +0100104
105 /*
106 * Add tempo to get SPI in a safe state.
107 * Should not be needed for new silicon (Rev B)
108 */
109 udelay(500000);
Reinhard Meyer324914a2010-11-09 17:06:20 +0100110 readl(ATMEL_BASE_SPI0 + AT91_SPI_SR);
111 readl(ATMEL_BASE_SPI0 + AT91_SPI_RDR);
Stelian Popd4bfbc52008-03-26 20:52:32 +0100112
Stelian Popd1aea1c2008-01-30 21:15:54 +0000113}
114
115void AT91F_SpiEnable(int cs)
116{
Stelian Popd4bfbc52008-03-26 20:52:32 +0100117 unsigned long mode;
Jean-Christophe PLAGNIOL-VILLARD4c2b4652008-03-31 21:20:49 +0200118
Stelian Popd1aea1c2008-01-30 21:15:54 +0000119 switch (cs) {
120 case 0: /* Configure SPI CS0 for Serial DataFlash AT45DBxx */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100121 mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popd4bfbc52008-03-26 20:52:32 +0100122 mode &= 0xFFF0FFFF;
123 writel(mode | ((AT91_SPI_PCS0_DATAFLASH_CARD<<16) & AT91_SPI_PCS),
Reinhard Meyer324914a2010-11-09 17:06:20 +0100124 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popd4bfbc52008-03-26 20:52:32 +0100125 break;
126 case 1: /* Configure SPI CS1 for Serial DataFlash AT45DBxx */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100127 mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popd4bfbc52008-03-26 20:52:32 +0100128 mode &= 0xFFF0FFFF;
129 writel(mode | ((AT91_SPI_PCS1_DATAFLASH_CARD<<16) & AT91_SPI_PCS),
Reinhard Meyer324914a2010-11-09 17:06:20 +0100130 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000131 break;
Remy Bohmer7b2b5d32009-10-28 22:13:37 +0100132 case 2: /* Configure SPI CS2 for Serial DataFlash AT45DBxx */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100133 mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
Remy Bohmer7b2b5d32009-10-28 22:13:37 +0100134 mode &= 0xFFF0FFFF;
135 writel(mode | ((AT91_SPI_PCS2_DATAFLASH_CARD<<16) & AT91_SPI_PCS),
Reinhard Meyer324914a2010-11-09 17:06:20 +0100136 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Remy Bohmer7b2b5d32009-10-28 22:13:37 +0100137 break;
Stelian Popd1aea1c2008-01-30 21:15:54 +0000138 case 3:
Reinhard Meyer324914a2010-11-09 17:06:20 +0100139 mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popd4bfbc52008-03-26 20:52:32 +0100140 mode &= 0xFFF0FFFF;
141 writel(mode | ((AT91_SPI_PCS3_DATAFLASH_CARD<<16) & AT91_SPI_PCS),
Reinhard Meyer324914a2010-11-09 17:06:20 +0100142 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000143 break;
144 }
145
146 /* SPI_Enable */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100147 writel(AT91_SPI_SPIEN, ATMEL_BASE_SPI0 + AT91_SPI_CR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000148}
149
Stelian Popd4bfbc52008-03-26 20:52:32 +0100150unsigned int AT91F_SpiWrite1(AT91PS_DataflashDesc pDesc);
151
Stelian Popd1aea1c2008-01-30 21:15:54 +0000152unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc)
153{
154 unsigned int timeout;
Reinhard Meyer324914a2010-11-09 17:06:20 +0100155 unsigned int timebase;
Stelian Popd1aea1c2008-01-30 21:15:54 +0000156
157 pDesc->state = BUSY;
158
Reinhard Meyer324914a2010-11-09 17:06:20 +0100159 writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS,
160 ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
Stelian Popd4bfbc52008-03-26 20:52:32 +0100161
Stelian Popd1aea1c2008-01-30 21:15:54 +0000162 /* Initialize the Transmit and Receive Pointer */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100163 writel((unsigned int)pDesc->rx_cmd_pt,
164 ATMEL_BASE_SPI0 + AT91_SPI_RPR);
165 writel((unsigned int)pDesc->tx_cmd_pt,
166 ATMEL_BASE_SPI0 + AT91_SPI_TPR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000167
168 /* Intialize the Transmit and Receive Counters */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100169 writel(pDesc->rx_cmd_size, ATMEL_BASE_SPI0 + AT91_SPI_RCR);
170 writel(pDesc->tx_cmd_size, ATMEL_BASE_SPI0 + AT91_SPI_TCR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000171
172 if (pDesc->tx_data_size != 0) {
173 /* Initialize the Next Transmit and Next Receive Pointer */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100174 writel((unsigned int)pDesc->rx_data_pt,
175 ATMEL_BASE_SPI0 + AT91_SPI_RNPR);
176 writel((unsigned int)pDesc->tx_data_pt,
177 ATMEL_BASE_SPI0 + AT91_SPI_TNPR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000178
179 /* Intialize the Next Transmit and Next Receive Counters */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100180 writel(pDesc->rx_data_size,
181 ATMEL_BASE_SPI0 + AT91_SPI_RNCR);
182 writel(pDesc->tx_data_size,
183 ATMEL_BASE_SPI0 + AT91_SPI_TNCR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000184 }
185
186 /* arm simple, non interrupt dependent timer */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100187 timebase = get_timer(0);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000188 timeout = 0;
189
Reinhard Meyer324914a2010-11-09 17:06:20 +0100190 writel(AT91_SPI_TXTEN + AT91_SPI_RXTEN,
191 ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
192 while (!(readl(ATMEL_BASE_SPI0 + AT91_SPI_SR) & AT91_SPI_RXBUFF) &&
193 ((timeout = get_timer(timebase)) < CONFIG_SYS_SPI_WRITE_TOUT))
194 ;
195 writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS,
196 ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000197 pDesc->state = IDLE;
198
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200199 if (timeout >= CONFIG_SYS_SPI_WRITE_TOUT) {
Stelian Popd1aea1c2008-01-30 21:15:54 +0000200 printf("Error Timeout\n\r");
201 return DATAFLASH_ERROR;
202 }
203
204 return DATAFLASH_OK;
205}