blob: a2e9c00ea660733758f8f5d768932b1ad50a655d [file] [log] [blame]
Stelian Popd1aea1c2008-01-30 21:15:54 +00001/*
2 * Driver for ATMEL DataFlash support
3 * Author : Hamid Ikdoumi (Atmel)
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Stelian Popd1aea1c2008-01-30 21:15:54 +00006 */
7
Reinhard Meyerc163d3d2011-08-02 15:09:55 +00008/*
9 * This driver desperately needs rework:
10 *
11 * - use structure SoC access
12 * - get rid of including asm/arch/at91_spi.h
13 * - remove asm/arch/at91_spi.h
14 * - get rid of all CONFIG_ATMEL_LEGACY defines and uses
15 *
16 * 02-Aug-2010 Reinhard Meyer <uboot@emk-elektronik.de>
17 */
18
Stelian Popd1aea1c2008-01-30 21:15:54 +000019#include <common.h>
Reinhard Meyerc163d3d2011-08-02 15:09:55 +000020#ifndef CONFIG_ATMEL_LEGACY
21# define CONFIG_ATMEL_LEGACY
Jens Scharsiga4db1ca2010-02-03 22:46:58 +010022#endif
Reinhard Meyer324914a2010-11-09 17:06:20 +010023#include <spi.h>
24#include <malloc.h>
25
26#include <asm/io.h>
27
Jean-Christophe PLAGNIOL-VILLARD23164f12009-04-16 21:30:44 +020028#include <asm/arch/clk.h>
Reinhard Meyer324914a2010-11-09 17:06:20 +010029#include <asm/arch/hardware.h>
30
31#include "atmel_spi.h"
32
Stelian Popd4bfbc52008-03-26 20:52:32 +010033#include <asm/arch/gpio.h>
Stelian Popd4bfbc52008-03-26 20:52:32 +010034#include <asm/arch/at91_pio.h>
35#include <asm/arch/at91_spi.h>
Stelian Popd1aea1c2008-01-30 21:15:54 +000036
Stelian Popd1aea1c2008-01-30 21:15:54 +000037#include <dataflash.h>
38
Stelian Popd4bfbc52008-03-26 20:52:32 +010039#define AT91_SPI_PCS0_DATAFLASH_CARD 0xE /* Chip Select 0: NPCS0%1110 */
Remy Bohmer7b2b5d32009-10-28 22:13:37 +010040#define AT91_SPI_PCS1_DATAFLASH_CARD 0xD /* Chip Select 1: NPCS1%1101 */
41#define AT91_SPI_PCS2_DATAFLASH_CARD 0xB /* Chip Select 2: NPCS2%1011 */
Stelian Popd4bfbc52008-03-26 20:52:32 +010042#define AT91_SPI_PCS3_DATAFLASH_CARD 0x7 /* Chip Select 3: NPCS3%0111 */
Stelian Popd1aea1c2008-01-30 21:15:54 +000043
44void AT91F_SpiInit(void)
45{
46 /* Reset the SPI */
Reinhard Meyer324914a2010-11-09 17:06:20 +010047 writel(AT91_SPI_SWRST, ATMEL_BASE_SPI0 + AT91_SPI_CR);
Stelian Popd1aea1c2008-01-30 21:15:54 +000048
49 /* Configure SPI in Master Mode with No CS selected !!! */
Stelian Popd4bfbc52008-03-26 20:52:32 +010050 writel(AT91_SPI_MSTR | AT91_SPI_MODFDIS | AT91_SPI_PCS,
Reinhard Meyer324914a2010-11-09 17:06:20 +010051 ATMEL_BASE_SPI0 + AT91_SPI_MR);
Stelian Popd1aea1c2008-01-30 21:15:54 +000052
53 /* Configure CS0 */
Stelian Popd4bfbc52008-03-26 20:52:32 +010054 writel(AT91_SPI_NCPHA |
55 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
56 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
Jean-Christophe PLAGNIOL-VILLARD23164f12009-04-16 21:30:44 +020057 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyer324914a2010-11-09 17:06:20 +010058 ATMEL_BASE_SPI0 + AT91_SPI_CSR(0));
Stelian Popd4bfbc52008-03-26 20:52:32 +010059
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020060#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS1
Stelian Popd4bfbc52008-03-26 20:52:32 +010061 /* Configure CS1 */
62 writel(AT91_SPI_NCPHA |
63 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
64 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
Jean-Christophe PLAGNIOL-VILLARD23164f12009-04-16 21:30:44 +020065 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyer324914a2010-11-09 17:06:20 +010066 ATMEL_BASE_SPI0 + AT91_SPI_CSR(1));
Stelian Popd4bfbc52008-03-26 20:52:32 +010067#endif
Remy Bohmer7b2b5d32009-10-28 22:13:37 +010068#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS2
69 /* Configure CS2 */
70 writel(AT91_SPI_NCPHA |
71 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
72 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
73 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyer324914a2010-11-09 17:06:20 +010074 ATMEL_BASE_SPI0 + AT91_SPI_CSR(2));
Remy Bohmer7b2b5d32009-10-28 22:13:37 +010075#endif
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020076#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS3
Stelian Popd4bfbc52008-03-26 20:52:32 +010077 /* Configure CS3 */
78 writel(AT91_SPI_NCPHA |
79 (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
80 (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
Jean-Christophe PLAGNIOL-VILLARD23164f12009-04-16 21:30:44 +020081 ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
Reinhard Meyer324914a2010-11-09 17:06:20 +010082 ATMEL_BASE_SPI0 + AT91_SPI_CSR(3));
Stelian Popd4bfbc52008-03-26 20:52:32 +010083#endif
84
85 /* SPI_Enable */
Reinhard Meyer324914a2010-11-09 17:06:20 +010086 writel(AT91_SPI_SPIEN, ATMEL_BASE_SPI0 + AT91_SPI_CR);
Stelian Popd4bfbc52008-03-26 20:52:32 +010087
Reinhard Meyer324914a2010-11-09 17:06:20 +010088 while (!(readl(ATMEL_BASE_SPI0 + AT91_SPI_SR) & AT91_SPI_SPIENS))
89 ;
Stelian Popd4bfbc52008-03-26 20:52:32 +010090
91 /*
92 * Add tempo to get SPI in a safe state.
93 * Should not be needed for new silicon (Rev B)
94 */
95 udelay(500000);
Reinhard Meyer324914a2010-11-09 17:06:20 +010096 readl(ATMEL_BASE_SPI0 + AT91_SPI_SR);
97 readl(ATMEL_BASE_SPI0 + AT91_SPI_RDR);
Stelian Popd4bfbc52008-03-26 20:52:32 +010098
Stelian Popd1aea1c2008-01-30 21:15:54 +000099}
100
101void AT91F_SpiEnable(int cs)
102{
Stelian Popd4bfbc52008-03-26 20:52:32 +0100103 unsigned long mode;
Jean-Christophe PLAGNIOL-VILLARD4c2b4652008-03-31 21:20:49 +0200104
Axel Lin73071572014-02-21 08:55:47 +0800105 mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
106 mode &= ~AT91_SPI_PCS;
107
Stelian Popd1aea1c2008-01-30 21:15:54 +0000108 switch (cs) {
Axel Lin73071572014-02-21 08:55:47 +0800109 case 0:
110 mode |= AT91_SPI_PCS0_DATAFLASH_CARD << 16;
Stelian Popd4bfbc52008-03-26 20:52:32 +0100111 break;
Axel Lin73071572014-02-21 08:55:47 +0800112 case 1:
113 mode |= AT91_SPI_PCS1_DATAFLASH_CARD << 16;
Stelian Popd1aea1c2008-01-30 21:15:54 +0000114 break;
Axel Lin73071572014-02-21 08:55:47 +0800115 case 2:
116 mode |= AT91_SPI_PCS2_DATAFLASH_CARD << 16;
Remy Bohmer7b2b5d32009-10-28 22:13:37 +0100117 break;
Stelian Popd1aea1c2008-01-30 21:15:54 +0000118 case 3:
Axel Lin73071572014-02-21 08:55:47 +0800119 mode |= AT91_SPI_PCS3_DATAFLASH_CARD << 16;
Stelian Popd1aea1c2008-01-30 21:15:54 +0000120 break;
121 }
122
Axel Lin73071572014-02-21 08:55:47 +0800123 writel(mode, ATMEL_BASE_SPI0 + AT91_SPI_MR);
124
Stelian Popd1aea1c2008-01-30 21:15:54 +0000125 /* SPI_Enable */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100126 writel(AT91_SPI_SPIEN, ATMEL_BASE_SPI0 + AT91_SPI_CR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000127}
128
Stelian Popd4bfbc52008-03-26 20:52:32 +0100129unsigned int AT91F_SpiWrite1(AT91PS_DataflashDesc pDesc);
130
Stelian Popd1aea1c2008-01-30 21:15:54 +0000131unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc)
132{
133 unsigned int timeout;
Reinhard Meyer324914a2010-11-09 17:06:20 +0100134 unsigned int timebase;
Stelian Popd1aea1c2008-01-30 21:15:54 +0000135
136 pDesc->state = BUSY;
137
Reinhard Meyer324914a2010-11-09 17:06:20 +0100138 writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS,
139 ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
Stelian Popd4bfbc52008-03-26 20:52:32 +0100140
Stelian Popd1aea1c2008-01-30 21:15:54 +0000141 /* Initialize the Transmit and Receive Pointer */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100142 writel((unsigned int)pDesc->rx_cmd_pt,
143 ATMEL_BASE_SPI0 + AT91_SPI_RPR);
144 writel((unsigned int)pDesc->tx_cmd_pt,
145 ATMEL_BASE_SPI0 + AT91_SPI_TPR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000146
147 /* Intialize the Transmit and Receive Counters */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100148 writel(pDesc->rx_cmd_size, ATMEL_BASE_SPI0 + AT91_SPI_RCR);
149 writel(pDesc->tx_cmd_size, ATMEL_BASE_SPI0 + AT91_SPI_TCR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000150
151 if (pDesc->tx_data_size != 0) {
152 /* Initialize the Next Transmit and Next Receive Pointer */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100153 writel((unsigned int)pDesc->rx_data_pt,
154 ATMEL_BASE_SPI0 + AT91_SPI_RNPR);
155 writel((unsigned int)pDesc->tx_data_pt,
156 ATMEL_BASE_SPI0 + AT91_SPI_TNPR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000157
158 /* Intialize the Next Transmit and Next Receive Counters */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100159 writel(pDesc->rx_data_size,
160 ATMEL_BASE_SPI0 + AT91_SPI_RNCR);
161 writel(pDesc->tx_data_size,
162 ATMEL_BASE_SPI0 + AT91_SPI_TNCR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000163 }
164
165 /* arm simple, non interrupt dependent timer */
Reinhard Meyer324914a2010-11-09 17:06:20 +0100166 timebase = get_timer(0);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000167 timeout = 0;
168
Reinhard Meyer324914a2010-11-09 17:06:20 +0100169 writel(AT91_SPI_TXTEN + AT91_SPI_RXTEN,
170 ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
171 while (!(readl(ATMEL_BASE_SPI0 + AT91_SPI_SR) & AT91_SPI_RXBUFF) &&
172 ((timeout = get_timer(timebase)) < CONFIG_SYS_SPI_WRITE_TOUT))
173 ;
174 writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS,
175 ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
Stelian Popd1aea1c2008-01-30 21:15:54 +0000176 pDesc->state = IDLE;
177
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200178 if (timeout >= CONFIG_SYS_SPI_WRITE_TOUT) {
Stelian Popd1aea1c2008-01-30 21:15:54 +0000179 printf("Error Timeout\n\r");
180 return DATAFLASH_ERROR;
181 }
182
183 return DATAFLASH_OK;
184}