blob: 21ba5f9009359e888e90f96aefac7f76bf7a35d2 [file] [log] [blame]
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +02001/*
2 * SPI flash interface
3 *
4 * Copyright (C) 2008 Atmel Corporation
5 */
Mike Frysingerc5431ac2009-03-23 23:03:58 -04006
Haavard Skinnemoen2f5bfb72008-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;
104 u8 idcode[3];
105
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
123 debug("SF: Got idcode %02x %02x %02x\n", idcode[0],
124 idcode[1], idcode[2]);
125
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
TsiChung Liew8dd593a2008-08-06 16:08:41 -0500137#ifdef CONFIG_SPI_FLASH_STMICRO
138 case 0x20:
139 flash = spi_flash_probe_stmicro(spi, idcode);
140 break;
141#endif
Mike Frysingerf1cb7c82009-03-27 19:27:58 -0400142#ifdef CONFIG_SPI_FLASH_SST
143 case 0xBF:
144 flash = spi_flash_probe_sst(spi, idcode);
145 break;
146#endif
Haavard Skinnemoen2f5bfb72008-05-16 11:10:33 +0200147 default:
148 debug("SF: Unsupported manufacturer %02X\n", idcode[0]);
149 flash = NULL;
150 break;
151 }
152
153 if (!flash)
154 goto err_manufacturer_probe;
155
156 spi_release_bus(spi);
157
158 return flash;
159
160err_manufacturer_probe:
161err_read_id:
162 spi_release_bus(spi);
163err_claim_bus:
164 spi_free_slave(spi);
165 return NULL;
166}
167
168void spi_flash_free(struct spi_flash *flash)
169{
170 spi_free_slave(flash->spi);
171 free(flash);
172}