Merge branch 'master' of ssh://10.10.0.7/home/wd/git/u-boot/master
[platform/kernel/u-boot.git] / drivers / mtd / spi / spi_flash.c
1 /*
2  * SPI flash interface
3  *
4  * Copyright (C) 2008 Atmel Corporation
5  */
6 #define DEBUG
7 #include <common.h>
8 #include <malloc.h>
9 #include <spi.h>
10 #include <spi_flash.h>
11
12 #include "spi_flash_internal.h"
13
14 int 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
38 int 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
61 int 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
85 int 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
98 struct 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
137 #ifdef CONFIG_SPI_FLASH_STMICRO
138         case 0x20:
139                 flash = spi_flash_probe_stmicro(spi, idcode);
140                 break;
141 #endif
142         default:
143                 debug("SF: Unsupported manufacturer %02X\n", idcode[0]);
144                 flash = NULL;
145                 break;
146         }
147
148         if (!flash)
149                 goto err_manufacturer_probe;
150
151         spi_release_bus(spi);
152
153         return flash;
154
155 err_manufacturer_probe:
156 err_read_id:
157         spi_release_bus(spi);
158 err_claim_bus:
159         spi_free_slave(spi);
160         return NULL;
161 }
162
163 void spi_flash_free(struct spi_flash *flash)
164 {
165         spi_free_slave(flash->spi);
166         free(flash);
167 }