blob: 0c832311c0402958a7d601f69b873489490291af [file] [log] [blame]
Haavard Skinnemoend25ce7d2008-05-16 11:10:33 +02001/*
2 * SPI flash interface
3 *
4 * Copyright (C) 2008 Atmel Corporation
5 */
Mike Frysingerf773a1b2009-03-23 23:03:58 -04006
Haavard Skinnemoend25ce7d2008-05-16 11:10:33 +02007#include <common.h>
8#include <malloc.h>
9#include <spi.h>
10#include <spi_flash.h>
11
12#include "spi_flash_internal.h"
13
14int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
15{
16 unsigned long flags = SPI_XFER_BEGIN;
17 int ret;
18
19 if (len == 0)
20 flags |= SPI_XFER_END;
21
22 ret = spi_xfer(spi, 8, &cmd, NULL, flags);
23 if (ret) {
24 debug("SF: Failed to send command %02x: %d\n", cmd, ret);
25 return ret;
26 }
27
28 if (len) {
29 ret = spi_xfer(spi, len * 8, NULL, response, SPI_XFER_END);
30 if (ret)
31 debug("SF: Failed to read response (%zu bytes): %d\n",
32 len, ret);
33 }
34
35 return ret;
36}
37
38int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
39 size_t cmd_len, void *data, size_t data_len)
40{
41 unsigned long flags = SPI_XFER_BEGIN;
42 int ret;
43
44 if (data_len == 0)
45 flags |= SPI_XFER_END;
46
47 ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
48 if (ret) {
49 debug("SF: Failed to send read command (%zu bytes): %d\n",
50 cmd_len, ret);
51 } else if (data_len != 0) {
52 ret = spi_xfer(spi, data_len * 8, NULL, data, SPI_XFER_END);
53 if (ret)
54 debug("SF: Failed to read %zu bytes of data: %d\n",
55 data_len, ret);
56 }
57
58 return ret;
59}
60
61int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
62 const void *data, size_t data_len)
63{
64 unsigned long flags = SPI_XFER_BEGIN;
65 int ret;
66
67 if (data_len == 0)
68 flags |= SPI_XFER_END;
69
70 ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags);
71 if (ret) {
72 debug("SF: Failed to send read command (%zu bytes): %d\n",
73 cmd_len, ret);
74 } else if (data_len != 0) {
75 ret = spi_xfer(spi, data_len * 8, data, NULL, SPI_XFER_END);
76 if (ret)
77 debug("SF: Failed to read %zu bytes of data: %d\n",
78 data_len, ret);
79 }
80
81 return ret;
82}
83
84
85int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
86 size_t cmd_len, void *data, size_t data_len)
87{
88 struct spi_slave *spi = flash->spi;
89 int ret;
90
91 spi_claim_bus(spi);
92 ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len);
93 spi_release_bus(spi);
94
95 return ret;
96}
97
98struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
99 unsigned int max_hz, unsigned int spi_mode)
100{
101 struct spi_slave *spi;
102 struct spi_flash *flash;
103 int ret;
Mike Frysinger0dcdbb12009-03-28 06:41:09 -0400104 u8 idcode[5];
Haavard Skinnemoend25ce7d2008-05-16 11:10:33 +0200105
106 spi = spi_setup_slave(bus, cs, max_hz, spi_mode);
107 if (!spi) {
108 debug("SF: Failed to set up slave\n");
109 return NULL;
110 }
111
112 ret = spi_claim_bus(spi);
113 if (ret) {
114 debug("SF: Failed to claim SPI bus: %d\n", ret);
115 goto err_claim_bus;
116 }
117
118 /* Read the ID codes */
119 ret = spi_flash_cmd(spi, CMD_READ_ID, &idcode, sizeof(idcode));
120 if (ret)
121 goto err_read_id;
122
Mike Frysinger0dcdbb12009-03-28 06:41:09 -0400123 debug("SF: Got idcode %02x %02x %02x %02x %02x\n", idcode[0],
124 idcode[1], idcode[2], idcode[3], idcode[4]);
Haavard Skinnemoend25ce7d2008-05-16 11:10:33 +0200125
126 switch (idcode[0]) {
127#ifdef CONFIG_SPI_FLASH_SPANSION
128 case 0x01:
129 flash = spi_flash_probe_spansion(spi, idcode);
130 break;
131#endif
132#ifdef CONFIG_SPI_FLASH_ATMEL
133 case 0x1F:
134 flash = spi_flash_probe_atmel(spi, idcode);
135 break;
136#endif
Prafulla Wadaskar7ce60312009-04-06 21:24:43 +0530137#ifdef CONFIG_SPI_FLASH_MACRONIX
138 case 0xc2:
139 flash = spi_flash_probe_macronix(spi, idcode);
140 break;
141#endif
TsiChung Liew7b7a8692008-08-06 16:08:41 -0500142#ifdef CONFIG_SPI_FLASH_STMICRO
143 case 0x20:
144 flash = spi_flash_probe_stmicro(spi, idcode);
145 break;
146#endif
Mike Frysinger1c587432009-03-27 19:27:58 -0400147#ifdef CONFIG_SPI_FLASH_SST
148 case 0xBF:
149 flash = spi_flash_probe_sst(spi, idcode);
150 break;
151#endif
Haavard Skinnemoend25ce7d2008-05-16 11:10:33 +0200152 default:
153 debug("SF: Unsupported manufacturer %02X\n", idcode[0]);
154 flash = NULL;
155 break;
156 }
157
158 if (!flash)
159 goto err_manufacturer_probe;
160
161 spi_release_bus(spi);
162
163 return flash;
164
165err_manufacturer_probe:
166err_read_id:
167 spi_release_bus(spi);
168err_claim_bus:
169 spi_free_slave(spi);
170 return NULL;
171}
172
173void spi_flash_free(struct spi_flash *flash)
174{
175 spi_free_slave(flash->spi);
176 free(flash);
177}