blob: 26364269be1a5e823efc99bd498262bd1a9d3393 [file] [log] [blame]
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +05301/*
2 * SPI flash probing
3 *
4 * Copyright (C) 2008 Atmel Corporation
5 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
6 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
7 *
Jagannadha Sutradharudu Tekid1452702013-10-10 22:32:55 +05308 * SPDX-License-Identifier: GPL-2.0+
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +05309 */
10
11#include <common.h>
Simon Glass6f7d2592014-10-13 23:42:07 -060012#include <dm.h>
Simon Glassc10c3d42014-10-13 23:42:05 -060013#include <errno.h>
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +053014#include <fdtdec.h>
15#include <malloc.h>
16#include <spi.h>
17#include <spi_flash.h>
Mike Frysingerb375ad92013-12-03 16:43:27 -070018#include <asm/io.h>
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +053019
Jagannadha Sutradharudu Tekiac8242d2013-09-26 16:00:15 +053020#include "sf_internal.h"
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +053021
22DECLARE_GLOBAL_DATA_PTR;
23
Jagannadha Sutradharudu Teki02eee9a2014-01-11 15:10:28 +053024/* Read commands array */
25static u8 spi_read_cmds_array[] = {
26 CMD_READ_ARRAY_SLOW,
27 CMD_READ_DUAL_OUTPUT_FAST,
28 CMD_READ_DUAL_IO_FAST,
Jagannadha Sutradharudu Tekie0ebabc2014-01-11 15:13:11 +053029 CMD_READ_QUAD_OUTPUT_FAST,
Jagannadha Sutradharudu Teki45462302013-12-24 15:24:31 +053030 CMD_READ_QUAD_IO_FAST,
Jagannadha Sutradharudu Teki02eee9a2014-01-11 15:10:28 +053031};
32
Jagannadha Sutradharudu Teki564a1262013-12-30 22:16:23 +053033#ifdef CONFIG_SPI_FLASH_MACRONIX
34static int spi_flash_set_qeb_mxic(struct spi_flash *flash)
35{
36 u8 qeb_status;
37 int ret;
38
39 ret = spi_flash_cmd_read_status(flash, &qeb_status);
40 if (ret < 0)
41 return ret;
42
43 if (qeb_status & STATUS_QEB_MXIC) {
44 debug("SF: mxic: QEB is already set\n");
45 } else {
46 ret = spi_flash_cmd_write_status(flash, STATUS_QEB_MXIC);
47 if (ret < 0)
48 return ret;
49 }
50
51 return ret;
52}
53#endif
54
55#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
56static int spi_flash_set_qeb_winspan(struct spi_flash *flash)
57{
58 u8 qeb_status;
59 int ret;
60
61 ret = spi_flash_cmd_read_config(flash, &qeb_status);
62 if (ret < 0)
63 return ret;
64
65 if (qeb_status & STATUS_QEB_WINSPAN) {
66 debug("SF: winspan: QEB is already set\n");
67 } else {
68 ret = spi_flash_cmd_write_config(flash, STATUS_QEB_WINSPAN);
69 if (ret < 0)
70 return ret;
71 }
72
73 return ret;
74}
75#endif
76
Jagannadha Sutradharudu Teki725c64e2013-12-26 13:54:57 +053077static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0)
78{
79 switch (idcode0) {
Jagannadha Sutradharudu Teki754c73c2013-12-26 14:13:36 +053080#ifdef CONFIG_SPI_FLASH_MACRONIX
81 case SPI_FLASH_CFI_MFR_MACRONIX:
82 return spi_flash_set_qeb_mxic(flash);
83#endif
Jagannadha Sutradharudu Teki725c64e2013-12-26 13:54:57 +053084#if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND)
85 case SPI_FLASH_CFI_MFR_SPANSION:
86 case SPI_FLASH_CFI_MFR_WINBOND:
87 return spi_flash_set_qeb_winspan(flash);
88#endif
89#ifdef CONFIG_SPI_FLASH_STMICRO
90 case SPI_FLASH_CFI_MFR_STMICRO:
91 debug("SF: QEB is volatile for %02x flash\n", idcode0);
92 return 0;
93#endif
94 default:
95 printf("SF: Need set QEB func for %02x flash\n", idcode0);
96 return -1;
97 }
98}
99
Simon Glassc10c3d42014-10-13 23:42:05 -0600100static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode,
101 struct spi_flash *flash)
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530102{
103 const struct spi_flash_params *params;
Jagannadha Sutradharudu Teki02eee9a2014-01-11 15:10:28 +0530104 u8 cmd;
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530105 u16 jedec = idcode[1] << 8 | idcode[2];
Jagannadha Sutradharudu Teki25315532013-09-28 16:49:37 +0530106 u16 ext_jedec = idcode[3] << 8 | idcode[4];
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530107
Simon Glassc10c3d42014-10-13 23:42:05 -0600108 /* Validate params from spi_flash_params table */
Jagannadha Sutradharudu Teki20e45bc2013-12-23 23:34:42 +0530109 params = spi_flash_params_table;
110 for (; params->name != NULL; params++) {
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530111 if ((params->jedec >> 16) == idcode[0]) {
Jagannadha Sutradharudu Teki25315532013-09-28 16:49:37 +0530112 if ((params->jedec & 0xFFFF) == jedec) {
113 if (params->ext_jedec == 0)
114 break;
115 else if (params->ext_jedec == ext_jedec)
116 break;
117 }
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530118 }
119 }
120
Jagannadha Sutradharudu Teki20e45bc2013-12-23 23:34:42 +0530121 if (!params->name) {
Jagannadha Sutradharudu Teki25315532013-09-28 16:49:37 +0530122 printf("SF: Unsupported flash IDs: ");
123 printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
124 idcode[0], jedec, ext_jedec);
Simon Glassc10c3d42014-10-13 23:42:05 -0600125 return -EPROTONOSUPPORT;
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530126 }
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530127
Jagannadha Sutradharudu Teki84fb8632013-10-10 22:14:09 +0530128 /* Assign spi data */
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530129 flash->spi = spi;
130 flash->name = params->name;
Jagannadha Sutradharudu Tekif3b2dd82013-10-07 19:34:56 +0530131 flash->memory_map = spi->memory_map;
Jagannadha Sutradharudu Tekie84b4f62014-01-12 21:40:11 +0530132 flash->dual_flash = flash->spi->option;
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530133
134 /* Assign spi_flash ops */
Simon Glass6f7d2592014-10-13 23:42:07 -0600135#ifndef CONFIG_DM_SPI_FLASH
Jagannadha Sutradharudu Teki25dc86a2013-10-02 19:38:49 +0530136 flash->write = spi_flash_cmd_write_ops;
Simon Glass6f7d2592014-10-13 23:42:07 -0600137#if defined(CONFIG_SPI_FLASH_SST)
Jagannadha Sutradharudu Teki08032422013-10-02 19:34:53 +0530138 if (params->flags & SST_WP)
139 flash->write = sst_write_wp;
140#endif
Jagannadha Sutradharudu Teki25dc86a2013-10-02 19:38:49 +0530141 flash->erase = spi_flash_cmd_erase_ops;
142 flash->read = spi_flash_cmd_read_ops;
Simon Glass6f7d2592014-10-13 23:42:07 -0600143#endif
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530144
145 /* Compute the flash size */
Jagannadha Sutradharudu Tekib47b7412014-01-07 00:11:35 +0530146 flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0;
Marek Vasut52fa1ff2014-02-21 18:13:26 +0100147 /*
148 * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the
149 * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with
150 * the 0x4d00 Extended JEDEC code have 512b pages. All of the others
151 * have 256b pages.
152 */
153 if (ext_jedec == 0x4d00) {
154 if ((jedec == 0x0215) || (jedec == 0x216))
155 flash->page_size = 256;
156 else
157 flash->page_size = 512;
158 } else {
159 flash->page_size = 256;
160 }
161 flash->page_size <<= flash->shift;
Jagannadha Sutradharudu Tekib47b7412014-01-07 00:11:35 +0530162 flash->sector_size = params->sector_size << flash->shift;
163 flash->size = flash->sector_size * params->nr_sectors << flash->shift;
Jagannadha Sutradharudu Tekid7f253b2014-01-11 15:25:04 +0530164#ifdef CONFIG_SF_DUAL_FLASH
Jagannadha Sutradharudu Tekie84b4f62014-01-12 21:40:11 +0530165 if (flash->dual_flash & SF_DUAL_STACKED_FLASH)
166 flash->size <<= 1;
Jagannadha Sutradharudu Tekid7f253b2014-01-11 15:25:04 +0530167#endif
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530168
Jagannadha Sutradharudu Tekibc0f8792013-10-02 19:36:58 +0530169 /* Compute erase sector and command */
170 if (params->flags & SECT_4K) {
171 flash->erase_cmd = CMD_ERASE_4K;
Jagannadha Sutradharudu Tekib47b7412014-01-07 00:11:35 +0530172 flash->erase_size = 4096 << flash->shift;
Jagannadha Sutradharudu Tekibc0f8792013-10-02 19:36:58 +0530173 } else if (params->flags & SECT_32K) {
174 flash->erase_cmd = CMD_ERASE_32K;
Jagannadha Sutradharudu Tekib47b7412014-01-07 00:11:35 +0530175 flash->erase_size = 32768 << flash->shift;
Jagannadha Sutradharudu Tekibc0f8792013-10-02 19:36:58 +0530176 } else {
177 flash->erase_cmd = CMD_ERASE_64K;
178 flash->erase_size = flash->sector_size;
179 }
180
Jagannadha Sutradharudu Teki02eee9a2014-01-11 15:10:28 +0530181 /* Look for the fastest read cmd */
182 cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx);
183 if (cmd) {
184 cmd = spi_read_cmds_array[cmd - 1];
185 flash->read_cmd = cmd;
186 } else {
Jagannadha Sutradharudu Teki243ced02014-01-12 21:38:21 +0530187 /* Go for default supported read cmd */
Jagannadha Sutradharudu Teki02eee9a2014-01-11 15:10:28 +0530188 flash->read_cmd = CMD_READ_ARRAY_FAST;
189 }
190
Jagannadha Sutradharudu Tekie0ebabc2014-01-11 15:13:11 +0530191 /* Not require to look for fastest only two write cmds yet */
192 if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP)
193 flash->write_cmd = CMD_QUAD_PAGE_PROGRAM;
194 else
195 /* Go for default supported write cmd */
196 flash->write_cmd = CMD_PAGE_PROGRAM;
197
Jagannadha Sutradharudu Tekica799862014-01-11 16:50:45 +0530198 /* Read dummy_byte: dummy byte is determined based on the
199 * dummy cycles of a particular command.
200 * Fast commands - dummy_byte = dummy_cycles/8
201 * I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8
202 * For I/O commands except cmd[0] everything goes on no.of lines
203 * based on particular command but incase of fast commands except
204 * data all go on single line irrespective of command.
205 */
206 switch (flash->read_cmd) {
207 case CMD_READ_QUAD_IO_FAST:
208 flash->dummy_byte = 2;
209 break;
210 case CMD_READ_ARRAY_SLOW:
211 flash->dummy_byte = 0;
212 break;
213 default:
214 flash->dummy_byte = 1;
215 }
216
Jagannadha Sutradharudu Teki243ced02014-01-12 21:38:21 +0530217 /* Poll cmd selection */
Jagannadha Sutradharudu Tekif41fcca2013-10-02 19:37:43 +0530218 flash->poll_cmd = CMD_READ_STATUS;
219#ifdef CONFIG_SPI_FLASH_STMICRO
220 if (params->flags & E_FSR)
221 flash->poll_cmd = CMD_FLAG_STATUS;
222#endif
223
Jagannadha Sutradharudu Tekif3b2dd82013-10-07 19:34:56 +0530224 /* Configure the BAR - discover bank cmds and read current bank */
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530225#ifdef CONFIG_SPI_FLASH_BAR
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530226 u8 curr_bank = 0;
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530227 if (flash->size > SPI_FLASH_16MB_BOUN) {
Simon Glassc10c3d42014-10-13 23:42:05 -0600228 int ret;
229
Jagannadha Sutradharudu Teki748bd4d2013-09-26 14:24:58 +0530230 flash->bank_read_cmd = (idcode[0] == 0x01) ?
231 CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR;
232 flash->bank_write_cmd = (idcode[0] == 0x01) ?
233 CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR;
234
Simon Glassc10c3d42014-10-13 23:42:05 -0600235 ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1,
236 &curr_bank, 1);
237 if (ret) {
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530238 debug("SF: fail to read bank addr register\n");
Simon Glassc10c3d42014-10-13 23:42:05 -0600239 return ret;
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530240 }
241 flash->bank_curr = curr_bank;
242 } else {
243 flash->bank_curr = curr_bank;
244 }
Jagannadha Sutradharudu Teki748bd4d2013-09-26 14:24:58 +0530245#endif
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530246
Jagannadha Sutradharudu Teki748bd4d2013-09-26 14:24:58 +0530247 /* Flash powers up read-only, so clear BP# bits */
248#if defined(CONFIG_SPI_FLASH_ATMEL) || \
249 defined(CONFIG_SPI_FLASH_MACRONIX) || \
250 defined(CONFIG_SPI_FLASH_SST)
251 spi_flash_cmd_write_status(flash, 0);
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530252#endif
253
Simon Glassc10c3d42014-10-13 23:42:05 -0600254 return 0;
Jagannadha Sutradharudu Teki748bd4d2013-09-26 14:24:58 +0530255}
256
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530257#ifdef CONFIG_OF_CONTROL
258int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
259{
260 fdt_addr_t addr;
261 fdt_size_t size;
262 int node;
263
264 /* If there is no node, do nothing */
265 node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH);
266 if (node < 0)
267 return 0;
268
269 addr = fdtdec_get_addr_size(blob, node, "memory-map", &size);
270 if (addr == FDT_ADDR_T_NONE) {
271 debug("%s: Cannot decode address\n", __func__);
272 return 0;
273 }
274
275 if (flash->size != size) {
276 debug("%s: Memory map must cover entire device\n", __func__);
277 return -1;
278 }
Mike Frysingerb375ad92013-12-03 16:43:27 -0700279 flash->memory_map = map_sysmem(addr, size);
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530280
281 return 0;
282}
283#endif /* CONFIG_OF_CONTROL */
284
Heiko Schocherd73b7ec2014-07-18 06:07:21 +0200285#ifdef CONFIG_SYS_SPI_ST_ENABLE_WP_PIN
286/* enable the W#/Vpp signal to disable writing to the status register */
287static int spi_enable_wp_pin(struct spi_flash *flash)
288{
289 u8 status;
290 int ret;
291
292 ret = spi_flash_cmd_read_status(flash, &status);
293 if (ret < 0)
294 return ret;
295
296 ret = spi_flash_cmd_write_status(flash, STATUS_SRWD);
297 if (ret < 0)
298 return ret;
299
300 ret = spi_flash_cmd_write_disable(flash);
301 if (ret < 0)
302 return ret;
303
304 return 0;
305}
306#else
307static int spi_enable_wp_pin(struct spi_flash *flash)
308{
309 return 0;
310}
311#endif
312
Simon Glassc10c3d42014-10-13 23:42:05 -0600313/**
314 * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
315 *
316 * @spi: Bus to probe
317 * @flashp: Pointer to place to put flash info, which may be NULL if the
318 * space should be allocated
319 */
320int spi_flash_probe_slave(struct spi_slave *spi, struct spi_flash *flash)
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530321{
Jagannadha Sutradharudu Teki748bd4d2013-09-26 14:24:58 +0530322 u8 idcode[5];
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530323 int ret;
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530324
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530325 /* Setup spi_slave */
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530326 if (!spi) {
327 printf("SF: Failed to set up slave\n");
Simon Glassc10c3d42014-10-13 23:42:05 -0600328 return -ENODEV;
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530329 }
330
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530331 /* Claim spi bus */
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530332 ret = spi_claim_bus(spi);
333 if (ret) {
334 debug("SF: Failed to claim SPI bus: %d\n", ret);
Simon Glassc10c3d42014-10-13 23:42:05 -0600335 return ret;
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530336 }
337
338 /* Read the ID codes */
339 ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530340 if (ret) {
341 printf("SF: Failed to get idcodes\n");
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530342 goto err_read_id;
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530343 }
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530344
345#ifdef DEBUG
346 printf("SF: Got idcodes\n");
347 print_buffer(0, idcode, 1, sizeof(idcode), 0);
348#endif
349
Simon Glassc10c3d42014-10-13 23:42:05 -0600350 if (spi_flash_validate_params(spi, idcode, flash)) {
351 ret = -EINVAL;
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530352 goto err_read_id;
Simon Glassc10c3d42014-10-13 23:42:05 -0600353 }
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530354
Poddar, Sourav39a5ebc2014-04-23 18:57:03 +0530355 /* Set the quad enable bit - only for quad commands */
356 if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
357 (flash->read_cmd == CMD_READ_QUAD_IO_FAST) ||
358 (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) {
359 if (spi_flash_set_qeb(flash, idcode[0])) {
360 debug("SF: Fail to set QEB for %02x\n", idcode[0]);
Simon Glassc10c3d42014-10-13 23:42:05 -0600361 ret = -EINVAL;
362 goto err_read_id;
Poddar, Sourav39a5ebc2014-04-23 18:57:03 +0530363 }
364 }
365
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530366#ifdef CONFIG_OF_CONTROL
367 if (spi_flash_decode_fdt(gd->fdt_blob, flash)) {
368 debug("SF: FDT decode error\n");
Simon Glassc10c3d42014-10-13 23:42:05 -0600369 ret = -EINVAL;
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530370 goto err_read_id;
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530371 }
372#endif
373#ifndef CONFIG_SPL_BUILD
374 printf("SF: Detected %s with page size ", flash->name);
Jagannadha Sutradharudu Teki918d6ac2013-09-15 23:06:12 +0530375 print_size(flash->page_size, ", erase size ");
376 print_size(flash->erase_size, ", total ");
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530377 print_size(flash->size, "");
378 if (flash->memory_map)
379 printf(", mapped at %p", flash->memory_map);
380 puts("\n");
381#endif
382#ifndef CONFIG_SPI_FLASH_BAR
Jagannadha Sutradharudu Tekie84b4f62014-01-12 21:40:11 +0530383 if (((flash->dual_flash == SF_SINGLE_FLASH) &&
384 (flash->size > SPI_FLASH_16MB_BOUN)) ||
385 ((flash->dual_flash > SF_SINGLE_FLASH) &&
386 (flash->size > SPI_FLASH_16MB_BOUN << 1))) {
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530387 puts("SF: Warning - Only lower 16MiB accessible,");
388 puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
389 }
390#endif
Heiko Schocherd73b7ec2014-07-18 06:07:21 +0200391 if (spi_enable_wp_pin(flash))
392 puts("Enable WP pin failed\n");
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530393
Jagannadha Sutradharudu Tekibb302202013-09-24 16:01:23 +0530394 /* Release spi bus */
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530395 spi_release_bus(spi);
396
Simon Glassc10c3d42014-10-13 23:42:05 -0600397 return 0;
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530398
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530399err_read_id:
400 spi_release_bus(spi);
Simon Glassc10c3d42014-10-13 23:42:05 -0600401 return ret;
402}
403
Simon Glass6f7d2592014-10-13 23:42:07 -0600404#ifndef CONFIG_DM_SPI_FLASH
405struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus)
Simon Glassc10c3d42014-10-13 23:42:05 -0600406{
407 struct spi_flash *flash;
408
409 /* Allocate space if needed (not used by sf-uclass */
410 flash = calloc(1, sizeof(*flash));
411 if (!flash) {
412 debug("SF: Failed to allocate spi_flash\n");
413 return NULL;
414 }
415
416 if (spi_flash_probe_slave(bus, flash)) {
417 spi_free_slave(bus);
418 free(flash);
419 return NULL;
420 }
421
422 return flash;
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530423}
424
Simon Glassc10c3d42014-10-13 23:42:05 -0600425struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
Simon Glass49e9d2c2013-12-03 16:43:24 -0700426 unsigned int max_hz, unsigned int spi_mode)
427{
Simon Glassc10c3d42014-10-13 23:42:05 -0600428 struct spi_slave *bus;
Simon Glass49e9d2c2013-12-03 16:43:24 -0700429
Simon Glassc10c3d42014-10-13 23:42:05 -0600430 bus = spi_setup_slave(busnum, cs, max_hz, spi_mode);
431 return spi_flash_probe_tail(bus);
Simon Glass49e9d2c2013-12-03 16:43:24 -0700432}
433
434#ifdef CONFIG_OF_SPI_FLASH
435struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node,
436 int spi_node)
437{
Simon Glassc10c3d42014-10-13 23:42:05 -0600438 struct spi_slave *bus;
Simon Glass49e9d2c2013-12-03 16:43:24 -0700439
Simon Glassc10c3d42014-10-13 23:42:05 -0600440 bus = spi_setup_slave_fdt(blob, slave_node, spi_node);
441 return spi_flash_probe_tail(bus);
Simon Glass49e9d2c2013-12-03 16:43:24 -0700442}
443#endif
444
Jagannadha Sutradharudu Tekie9a8b822013-08-29 19:01:56 +0530445void spi_flash_free(struct spi_flash *flash)
446{
447 spi_free_slave(flash->spi);
448 free(flash);
449}
Simon Glass6f7d2592014-10-13 23:42:07 -0600450
451#else /* defined CONFIG_DM_SPI_FLASH */
452
453static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len,
454 void *buf)
455{
456 struct spi_flash *flash = dev->uclass_priv;
457
458 return spi_flash_cmd_read_ops(flash, offset, len, buf);
459}
460
461int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len,
462 const void *buf)
463{
464 struct spi_flash *flash = dev->uclass_priv;
465
466 return spi_flash_cmd_write_ops(flash, offset, len, buf);
467}
468
469int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len)
470{
471 struct spi_flash *flash = dev->uclass_priv;
472
473 return spi_flash_cmd_erase_ops(flash, offset, len);
474}
475
476int spi_flash_std_probe(struct udevice *dev)
477{
478 struct spi_slave *slave = dev_get_parentdata(dev);
479 struct spi_flash *flash;
480
481 flash = dev->uclass_priv;
482 flash->dev = dev;
483 debug("%s: slave=%p, cs=%d\n", __func__, slave, slave->cs);
484 return spi_flash_probe_slave(slave, flash);
485}
486
487static const struct dm_spi_flash_ops spi_flash_std_ops = {
488 .read = spi_flash_std_read,
489 .write = spi_flash_std_write,
490 .erase = spi_flash_std_erase,
491};
492
493static const struct udevice_id spi_flash_std_ids[] = {
494 { .compatible = "spi-flash" },
495 { }
496};
497
498U_BOOT_DRIVER(spi_flash_std) = {
499 .name = "spi_flash_std",
500 .id = UCLASS_SPI_FLASH,
501 .of_match = spi_flash_std_ids,
502 .probe = spi_flash_std_probe,
503 .priv_auto_alloc_size = sizeof(struct spi_flash),
504 .ops = &spi_flash_std_ops,
505};
506
507#endif /* CONFIG_DM_SPI_FLASH */