1898e76c9SJagannadha Sutradharudu Teki /* 2898e76c9SJagannadha Sutradharudu Teki * SPI flash probing 3898e76c9SJagannadha Sutradharudu Teki * 4898e76c9SJagannadha Sutradharudu Teki * Copyright (C) 2008 Atmel Corporation 5898e76c9SJagannadha Sutradharudu Teki * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik 6898e76c9SJagannadha Sutradharudu Teki * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. 7898e76c9SJagannadha Sutradharudu Teki * 80c88a84aSJagannadha Sutradharudu Teki * SPDX-License-Identifier: GPL-2.0+ 9898e76c9SJagannadha Sutradharudu Teki */ 10898e76c9SJagannadha Sutradharudu Teki 11898e76c9SJagannadha Sutradharudu Teki #include <common.h> 12898e76c9SJagannadha Sutradharudu Teki #include <fdtdec.h> 13898e76c9SJagannadha Sutradharudu Teki #include <malloc.h> 14898e76c9SJagannadha Sutradharudu Teki #include <spi.h> 15898e76c9SJagannadha Sutradharudu Teki #include <spi_flash.h> 16ffdb20beSMike Frysinger #include <asm/io.h> 17898e76c9SJagannadha Sutradharudu Teki 18898e76c9SJagannadha Sutradharudu Teki #include "sf_internal.h" 19898e76c9SJagannadha Sutradharudu Teki 20898e76c9SJagannadha Sutradharudu Teki DECLARE_GLOBAL_DATA_PTR; 21898e76c9SJagannadha Sutradharudu Teki 224e09cc1eSJagannadha Sutradharudu Teki /* Read commands array */ 234e09cc1eSJagannadha Sutradharudu Teki static u8 spi_read_cmds_array[] = { 244e09cc1eSJagannadha Sutradharudu Teki CMD_READ_ARRAY_SLOW, 254e09cc1eSJagannadha Sutradharudu Teki CMD_READ_DUAL_OUTPUT_FAST, 264e09cc1eSJagannadha Sutradharudu Teki CMD_READ_DUAL_IO_FAST, 273163aaa6SJagannadha Sutradharudu Teki CMD_READ_QUAD_OUTPUT_FAST, 28c4ba0d82SJagannadha Sutradharudu Teki CMD_READ_QUAD_IO_FAST, 294e09cc1eSJagannadha Sutradharudu Teki }; 304e09cc1eSJagannadha Sutradharudu Teki 31d08a1bafSJagannadha Sutradharudu Teki static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0) 32d08a1bafSJagannadha Sutradharudu Teki { 33d08a1bafSJagannadha Sutradharudu Teki switch (idcode0) { 34d08a1bafSJagannadha Sutradharudu Teki #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) 35d08a1bafSJagannadha Sutradharudu Teki case SPI_FLASH_CFI_MFR_SPANSION: 36d08a1bafSJagannadha Sutradharudu Teki case SPI_FLASH_CFI_MFR_WINBOND: 37d08a1bafSJagannadha Sutradharudu Teki return spi_flash_set_qeb_winspan(flash); 38d08a1bafSJagannadha Sutradharudu Teki #endif 39d08a1bafSJagannadha Sutradharudu Teki #ifdef CONFIG_SPI_FLASH_STMICRO 40d08a1bafSJagannadha Sutradharudu Teki case SPI_FLASH_CFI_MFR_STMICRO: 41d08a1bafSJagannadha Sutradharudu Teki debug("SF: QEB is volatile for %02x flash\n", idcode0); 42d08a1bafSJagannadha Sutradharudu Teki return 0; 43d08a1bafSJagannadha Sutradharudu Teki #endif 44d08a1bafSJagannadha Sutradharudu Teki default: 45d08a1bafSJagannadha Sutradharudu Teki printf("SF: Need set QEB func for %02x flash\n", idcode0); 46d08a1bafSJagannadha Sutradharudu Teki return -1; 47d08a1bafSJagannadha Sutradharudu Teki } 48d08a1bafSJagannadha Sutradharudu Teki } 49d08a1bafSJagannadha Sutradharudu Teki 50ce22b922SJagannadha Sutradharudu Teki static struct spi_flash *spi_flash_validate_params(struct spi_slave *spi, 51ce22b922SJagannadha Sutradharudu Teki u8 *idcode) 52898e76c9SJagannadha Sutradharudu Teki { 53898e76c9SJagannadha Sutradharudu Teki const struct spi_flash_params *params; 54898e76c9SJagannadha Sutradharudu Teki struct spi_flash *flash; 554e09cc1eSJagannadha Sutradharudu Teki u8 cmd; 56898e76c9SJagannadha Sutradharudu Teki u16 jedec = idcode[1] << 8 | idcode[2]; 57898e76c9SJagannadha Sutradharudu Teki u16 ext_jedec = idcode[3] << 8 | idcode[4]; 58898e76c9SJagannadha Sutradharudu Teki 5933adfb5fSJagannadha Sutradharudu Teki params = spi_flash_params_table; 6033adfb5fSJagannadha Sutradharudu Teki for (; params->name != NULL; params++) { 61898e76c9SJagannadha Sutradharudu Teki if ((params->jedec >> 16) == idcode[0]) { 62898e76c9SJagannadha Sutradharudu Teki if ((params->jedec & 0xFFFF) == jedec) { 63898e76c9SJagannadha Sutradharudu Teki if (params->ext_jedec == 0) 64898e76c9SJagannadha Sutradharudu Teki break; 65898e76c9SJagannadha Sutradharudu Teki else if (params->ext_jedec == ext_jedec) 66898e76c9SJagannadha Sutradharudu Teki break; 67898e76c9SJagannadha Sutradharudu Teki } 68898e76c9SJagannadha Sutradharudu Teki } 69898e76c9SJagannadha Sutradharudu Teki } 70898e76c9SJagannadha Sutradharudu Teki 7133adfb5fSJagannadha Sutradharudu Teki if (!params->name) { 72898e76c9SJagannadha Sutradharudu Teki printf("SF: Unsupported flash IDs: "); 73898e76c9SJagannadha Sutradharudu Teki printf("manuf %02x, jedec %04x, ext_jedec %04x\n", 74898e76c9SJagannadha Sutradharudu Teki idcode[0], jedec, ext_jedec); 75898e76c9SJagannadha Sutradharudu Teki return NULL; 76898e76c9SJagannadha Sutradharudu Teki } 77898e76c9SJagannadha Sutradharudu Teki 78898e76c9SJagannadha Sutradharudu Teki flash = malloc(sizeof(*flash)); 79898e76c9SJagannadha Sutradharudu Teki if (!flash) { 80898e76c9SJagannadha Sutradharudu Teki debug("SF: Failed to allocate spi_flash\n"); 81898e76c9SJagannadha Sutradharudu Teki return NULL; 82898e76c9SJagannadha Sutradharudu Teki } 83898e76c9SJagannadha Sutradharudu Teki memset(flash, '\0', sizeof(*flash)); 84898e76c9SJagannadha Sutradharudu Teki 85469146c0SJagannadha Sutradharudu Teki /* Assign spi data */ 86898e76c9SJagannadha Sutradharudu Teki flash->spi = spi; 87898e76c9SJagannadha Sutradharudu Teki flash->name = params->name; 88ce22b922SJagannadha Sutradharudu Teki flash->memory_map = spi->memory_map; 89898e76c9SJagannadha Sutradharudu Teki 90898e76c9SJagannadha Sutradharudu Teki /* Assign spi_flash ops */ 91898e76c9SJagannadha Sutradharudu Teki flash->write = spi_flash_cmd_write_ops; 92898e76c9SJagannadha Sutradharudu Teki #ifdef CONFIG_SPI_FLASH_SST 93898e76c9SJagannadha Sutradharudu Teki if (params->flags & SST_WP) 94898e76c9SJagannadha Sutradharudu Teki flash->write = sst_write_wp; 95898e76c9SJagannadha Sutradharudu Teki #endif 96898e76c9SJagannadha Sutradharudu Teki flash->erase = spi_flash_cmd_erase_ops; 97898e76c9SJagannadha Sutradharudu Teki flash->read = spi_flash_cmd_read_ops; 98898e76c9SJagannadha Sutradharudu Teki 99898e76c9SJagannadha Sutradharudu Teki /* Compute the flash size */ 100898e76c9SJagannadha Sutradharudu Teki flash->page_size = (ext_jedec == 0x4d00) ? 512 : 256; 101898e76c9SJagannadha Sutradharudu Teki flash->sector_size = params->sector_size; 102898e76c9SJagannadha Sutradharudu Teki flash->size = flash->sector_size * params->nr_sectors; 103898e76c9SJagannadha Sutradharudu Teki 104898e76c9SJagannadha Sutradharudu Teki /* Compute erase sector and command */ 105898e76c9SJagannadha Sutradharudu Teki if (params->flags & SECT_4K) { 106898e76c9SJagannadha Sutradharudu Teki flash->erase_cmd = CMD_ERASE_4K; 107898e76c9SJagannadha Sutradharudu Teki flash->erase_size = 4096; 108898e76c9SJagannadha Sutradharudu Teki } else if (params->flags & SECT_32K) { 109898e76c9SJagannadha Sutradharudu Teki flash->erase_cmd = CMD_ERASE_32K; 110898e76c9SJagannadha Sutradharudu Teki flash->erase_size = 32768; 111898e76c9SJagannadha Sutradharudu Teki } else { 112898e76c9SJagannadha Sutradharudu Teki flash->erase_cmd = CMD_ERASE_64K; 113898e76c9SJagannadha Sutradharudu Teki flash->erase_size = flash->sector_size; 114898e76c9SJagannadha Sutradharudu Teki } 115898e76c9SJagannadha Sutradharudu Teki 1164e09cc1eSJagannadha Sutradharudu Teki /* Look for the fastest read cmd */ 1174e09cc1eSJagannadha Sutradharudu Teki cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); 1184e09cc1eSJagannadha Sutradharudu Teki if (cmd) { 1194e09cc1eSJagannadha Sutradharudu Teki cmd = spi_read_cmds_array[cmd - 1]; 1204e09cc1eSJagannadha Sutradharudu Teki flash->read_cmd = cmd; 1214e09cc1eSJagannadha Sutradharudu Teki } else { 1224e09cc1eSJagannadha Sutradharudu Teki /* Go for for default supported read cmd */ 1234e09cc1eSJagannadha Sutradharudu Teki flash->read_cmd = CMD_READ_ARRAY_FAST; 1244e09cc1eSJagannadha Sutradharudu Teki } 1254e09cc1eSJagannadha Sutradharudu Teki 1263163aaa6SJagannadha Sutradharudu Teki /* Not require to look for fastest only two write cmds yet */ 1273163aaa6SJagannadha Sutradharudu Teki if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP) 1283163aaa6SJagannadha Sutradharudu Teki flash->write_cmd = CMD_QUAD_PAGE_PROGRAM; 1293163aaa6SJagannadha Sutradharudu Teki else 1303163aaa6SJagannadha Sutradharudu Teki /* Go for default supported write cmd */ 1313163aaa6SJagannadha Sutradharudu Teki flash->write_cmd = CMD_PAGE_PROGRAM; 1323163aaa6SJagannadha Sutradharudu Teki 133d08a1bafSJagannadha Sutradharudu Teki /* Set the quad enable bit - only for quad commands */ 134d08a1bafSJagannadha Sutradharudu Teki if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || 135c4ba0d82SJagannadha Sutradharudu Teki (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || 136d08a1bafSJagannadha Sutradharudu Teki (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { 137d08a1bafSJagannadha Sutradharudu Teki if (spi_flash_set_qeb(flash, idcode[0])) { 138d08a1bafSJagannadha Sutradharudu Teki debug("SF: Fail to set QEB for %02x\n", idcode[0]); 139d08a1bafSJagannadha Sutradharudu Teki return NULL; 140d08a1bafSJagannadha Sutradharudu Teki } 141d08a1bafSJagannadha Sutradharudu Teki } 142d08a1bafSJagannadha Sutradharudu Teki 143*ff063ed4SJagannadha Sutradharudu Teki /* Read dummy_byte: dummy byte is determined based on the 144*ff063ed4SJagannadha Sutradharudu Teki * dummy cycles of a particular command. 145*ff063ed4SJagannadha Sutradharudu Teki * Fast commands - dummy_byte = dummy_cycles/8 146*ff063ed4SJagannadha Sutradharudu Teki * I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8 147*ff063ed4SJagannadha Sutradharudu Teki * For I/O commands except cmd[0] everything goes on no.of lines 148*ff063ed4SJagannadha Sutradharudu Teki * based on particular command but incase of fast commands except 149*ff063ed4SJagannadha Sutradharudu Teki * data all go on single line irrespective of command. 150*ff063ed4SJagannadha Sutradharudu Teki */ 151*ff063ed4SJagannadha Sutradharudu Teki switch (flash->read_cmd) { 152*ff063ed4SJagannadha Sutradharudu Teki case CMD_READ_QUAD_IO_FAST: 153*ff063ed4SJagannadha Sutradharudu Teki flash->dummy_byte = 2; 154*ff063ed4SJagannadha Sutradharudu Teki break; 155*ff063ed4SJagannadha Sutradharudu Teki case CMD_READ_ARRAY_SLOW: 156*ff063ed4SJagannadha Sutradharudu Teki flash->dummy_byte = 0; 157*ff063ed4SJagannadha Sutradharudu Teki break; 158*ff063ed4SJagannadha Sutradharudu Teki default: 159*ff063ed4SJagannadha Sutradharudu Teki flash->dummy_byte = 1; 160*ff063ed4SJagannadha Sutradharudu Teki } 161*ff063ed4SJagannadha Sutradharudu Teki 162898e76c9SJagannadha Sutradharudu Teki /* Poll cmd seclection */ 163898e76c9SJagannadha Sutradharudu Teki flash->poll_cmd = CMD_READ_STATUS; 164898e76c9SJagannadha Sutradharudu Teki #ifdef CONFIG_SPI_FLASH_STMICRO 165898e76c9SJagannadha Sutradharudu Teki if (params->flags & E_FSR) 166898e76c9SJagannadha Sutradharudu Teki flash->poll_cmd = CMD_FLAG_STATUS; 167898e76c9SJagannadha Sutradharudu Teki #endif 168898e76c9SJagannadha Sutradharudu Teki 169898e76c9SJagannadha Sutradharudu Teki /* Configure the BAR - discover bank cmds and read current bank */ 170ce22b922SJagannadha Sutradharudu Teki #ifdef CONFIG_SPI_FLASH_BAR 171898e76c9SJagannadha Sutradharudu Teki u8 curr_bank = 0; 172898e76c9SJagannadha Sutradharudu Teki if (flash->size > SPI_FLASH_16MB_BOUN) { 173898e76c9SJagannadha Sutradharudu Teki flash->bank_read_cmd = (idcode[0] == 0x01) ? 174898e76c9SJagannadha Sutradharudu Teki CMD_BANKADDR_BRRD : CMD_EXTNADDR_RDEAR; 175898e76c9SJagannadha Sutradharudu Teki flash->bank_write_cmd = (idcode[0] == 0x01) ? 176898e76c9SJagannadha Sutradharudu Teki CMD_BANKADDR_BRWR : CMD_EXTNADDR_WREAR; 177898e76c9SJagannadha Sutradharudu Teki 178898e76c9SJagannadha Sutradharudu Teki if (spi_flash_read_common(flash, &flash->bank_read_cmd, 1, 179898e76c9SJagannadha Sutradharudu Teki &curr_bank, 1)) { 180898e76c9SJagannadha Sutradharudu Teki debug("SF: fail to read bank addr register\n"); 181898e76c9SJagannadha Sutradharudu Teki return NULL; 182898e76c9SJagannadha Sutradharudu Teki } 183898e76c9SJagannadha Sutradharudu Teki flash->bank_curr = curr_bank; 184898e76c9SJagannadha Sutradharudu Teki } else { 185898e76c9SJagannadha Sutradharudu Teki flash->bank_curr = curr_bank; 186898e76c9SJagannadha Sutradharudu Teki } 187898e76c9SJagannadha Sutradharudu Teki #endif 188898e76c9SJagannadha Sutradharudu Teki 189898e76c9SJagannadha Sutradharudu Teki /* Flash powers up read-only, so clear BP# bits */ 190898e76c9SJagannadha Sutradharudu Teki #if defined(CONFIG_SPI_FLASH_ATMEL) || \ 191898e76c9SJagannadha Sutradharudu Teki defined(CONFIG_SPI_FLASH_MACRONIX) || \ 192898e76c9SJagannadha Sutradharudu Teki defined(CONFIG_SPI_FLASH_SST) 193898e76c9SJagannadha Sutradharudu Teki spi_flash_cmd_write_status(flash, 0); 194898e76c9SJagannadha Sutradharudu Teki #endif 195898e76c9SJagannadha Sutradharudu Teki 196898e76c9SJagannadha Sutradharudu Teki return flash; 197898e76c9SJagannadha Sutradharudu Teki } 198898e76c9SJagannadha Sutradharudu Teki 199898e76c9SJagannadha Sutradharudu Teki #ifdef CONFIG_OF_CONTROL 200898e76c9SJagannadha Sutradharudu Teki int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) 201898e76c9SJagannadha Sutradharudu Teki { 202898e76c9SJagannadha Sutradharudu Teki fdt_addr_t addr; 203898e76c9SJagannadha Sutradharudu Teki fdt_size_t size; 204898e76c9SJagannadha Sutradharudu Teki int node; 205898e76c9SJagannadha Sutradharudu Teki 206898e76c9SJagannadha Sutradharudu Teki /* If there is no node, do nothing */ 207898e76c9SJagannadha Sutradharudu Teki node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); 208898e76c9SJagannadha Sutradharudu Teki if (node < 0) 209898e76c9SJagannadha Sutradharudu Teki return 0; 210898e76c9SJagannadha Sutradharudu Teki 211898e76c9SJagannadha Sutradharudu Teki addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); 212898e76c9SJagannadha Sutradharudu Teki if (addr == FDT_ADDR_T_NONE) { 213898e76c9SJagannadha Sutradharudu Teki debug("%s: Cannot decode address\n", __func__); 214898e76c9SJagannadha Sutradharudu Teki return 0; 215898e76c9SJagannadha Sutradharudu Teki } 216898e76c9SJagannadha Sutradharudu Teki 217898e76c9SJagannadha Sutradharudu Teki if (flash->size != size) { 218898e76c9SJagannadha Sutradharudu Teki debug("%s: Memory map must cover entire device\n", __func__); 219898e76c9SJagannadha Sutradharudu Teki return -1; 220898e76c9SJagannadha Sutradharudu Teki } 221ffdb20beSMike Frysinger flash->memory_map = map_sysmem(addr, size); 222898e76c9SJagannadha Sutradharudu Teki 223898e76c9SJagannadha Sutradharudu Teki return 0; 224898e76c9SJagannadha Sutradharudu Teki } 225898e76c9SJagannadha Sutradharudu Teki #endif /* CONFIG_OF_CONTROL */ 226898e76c9SJagannadha Sutradharudu Teki 2270efc0249SSimon Glass static struct spi_flash *spi_flash_probe_slave(struct spi_slave *spi) 228898e76c9SJagannadha Sutradharudu Teki { 229898e76c9SJagannadha Sutradharudu Teki struct spi_flash *flash = NULL; 230898e76c9SJagannadha Sutradharudu Teki u8 idcode[5]; 231898e76c9SJagannadha Sutradharudu Teki int ret; 232898e76c9SJagannadha Sutradharudu Teki 233898e76c9SJagannadha Sutradharudu Teki /* Setup spi_slave */ 234898e76c9SJagannadha Sutradharudu Teki if (!spi) { 235898e76c9SJagannadha Sutradharudu Teki printf("SF: Failed to set up slave\n"); 236898e76c9SJagannadha Sutradharudu Teki return NULL; 237898e76c9SJagannadha Sutradharudu Teki } 238898e76c9SJagannadha Sutradharudu Teki 239898e76c9SJagannadha Sutradharudu Teki /* Claim spi bus */ 240898e76c9SJagannadha Sutradharudu Teki ret = spi_claim_bus(spi); 241898e76c9SJagannadha Sutradharudu Teki if (ret) { 242898e76c9SJagannadha Sutradharudu Teki debug("SF: Failed to claim SPI bus: %d\n", ret); 243898e76c9SJagannadha Sutradharudu Teki goto err_claim_bus; 244898e76c9SJagannadha Sutradharudu Teki } 245898e76c9SJagannadha Sutradharudu Teki 246898e76c9SJagannadha Sutradharudu Teki /* Read the ID codes */ 247898e76c9SJagannadha Sutradharudu Teki ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); 248898e76c9SJagannadha Sutradharudu Teki if (ret) { 249898e76c9SJagannadha Sutradharudu Teki printf("SF: Failed to get idcodes\n"); 250898e76c9SJagannadha Sutradharudu Teki goto err_read_id; 251898e76c9SJagannadha Sutradharudu Teki } 252898e76c9SJagannadha Sutradharudu Teki 253898e76c9SJagannadha Sutradharudu Teki #ifdef DEBUG 254898e76c9SJagannadha Sutradharudu Teki printf("SF: Got idcodes\n"); 255898e76c9SJagannadha Sutradharudu Teki print_buffer(0, idcode, 1, sizeof(idcode), 0); 256898e76c9SJagannadha Sutradharudu Teki #endif 257898e76c9SJagannadha Sutradharudu Teki 258898e76c9SJagannadha Sutradharudu Teki /* Validate params from spi_flash_params table */ 259898e76c9SJagannadha Sutradharudu Teki flash = spi_flash_validate_params(spi, idcode); 260898e76c9SJagannadha Sutradharudu Teki if (!flash) 261898e76c9SJagannadha Sutradharudu Teki goto err_read_id; 262898e76c9SJagannadha Sutradharudu Teki 263898e76c9SJagannadha Sutradharudu Teki #ifdef CONFIG_OF_CONTROL 264898e76c9SJagannadha Sutradharudu Teki if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { 265898e76c9SJagannadha Sutradharudu Teki debug("SF: FDT decode error\n"); 266898e76c9SJagannadha Sutradharudu Teki goto err_read_id; 267898e76c9SJagannadha Sutradharudu Teki } 268898e76c9SJagannadha Sutradharudu Teki #endif 269898e76c9SJagannadha Sutradharudu Teki #ifndef CONFIG_SPL_BUILD 270898e76c9SJagannadha Sutradharudu Teki printf("SF: Detected %s with page size ", flash->name); 271898e76c9SJagannadha Sutradharudu Teki print_size(flash->page_size, ", erase size "); 272898e76c9SJagannadha Sutradharudu Teki print_size(flash->erase_size, ", total "); 273898e76c9SJagannadha Sutradharudu Teki print_size(flash->size, ""); 274898e76c9SJagannadha Sutradharudu Teki if (flash->memory_map) 275898e76c9SJagannadha Sutradharudu Teki printf(", mapped at %p", flash->memory_map); 276898e76c9SJagannadha Sutradharudu Teki puts("\n"); 277898e76c9SJagannadha Sutradharudu Teki #endif 278898e76c9SJagannadha Sutradharudu Teki #ifndef CONFIG_SPI_FLASH_BAR 279898e76c9SJagannadha Sutradharudu Teki if (flash->size > SPI_FLASH_16MB_BOUN) { 280898e76c9SJagannadha Sutradharudu Teki puts("SF: Warning - Only lower 16MiB accessible,"); 281898e76c9SJagannadha Sutradharudu Teki puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); 282898e76c9SJagannadha Sutradharudu Teki } 283898e76c9SJagannadha Sutradharudu Teki #endif 284898e76c9SJagannadha Sutradharudu Teki 285898e76c9SJagannadha Sutradharudu Teki /* Release spi bus */ 286898e76c9SJagannadha Sutradharudu Teki spi_release_bus(spi); 287898e76c9SJagannadha Sutradharudu Teki 288898e76c9SJagannadha Sutradharudu Teki return flash; 289898e76c9SJagannadha Sutradharudu Teki 290898e76c9SJagannadha Sutradharudu Teki err_read_id: 291898e76c9SJagannadha Sutradharudu Teki spi_release_bus(spi); 292898e76c9SJagannadha Sutradharudu Teki err_claim_bus: 293898e76c9SJagannadha Sutradharudu Teki spi_free_slave(spi); 294898e76c9SJagannadha Sutradharudu Teki return NULL; 295898e76c9SJagannadha Sutradharudu Teki } 296898e76c9SJagannadha Sutradharudu Teki 2970efc0249SSimon Glass struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, 2980efc0249SSimon Glass unsigned int max_hz, unsigned int spi_mode) 2990efc0249SSimon Glass { 3000efc0249SSimon Glass struct spi_slave *spi; 3010efc0249SSimon Glass 3020efc0249SSimon Glass spi = spi_setup_slave(bus, cs, max_hz, spi_mode); 3030efc0249SSimon Glass return spi_flash_probe_slave(spi); 3040efc0249SSimon Glass } 3050efc0249SSimon Glass 3060efc0249SSimon Glass #ifdef CONFIG_OF_SPI_FLASH 3070efc0249SSimon Glass struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, 3080efc0249SSimon Glass int spi_node) 3090efc0249SSimon Glass { 3100efc0249SSimon Glass struct spi_slave *spi; 3110efc0249SSimon Glass 3120efc0249SSimon Glass spi = spi_setup_slave_fdt(blob, slave_node, spi_node); 3130efc0249SSimon Glass return spi_flash_probe_slave(spi); 3140efc0249SSimon Glass } 3150efc0249SSimon Glass #endif 3160efc0249SSimon Glass 317898e76c9SJagannadha Sutradharudu Teki void spi_flash_free(struct spi_flash *flash) 318898e76c9SJagannadha Sutradharudu Teki { 319898e76c9SJagannadha Sutradharudu Teki spi_free_slave(flash->spi); 320898e76c9SJagannadha Sutradharudu Teki free(flash); 321898e76c9SJagannadha Sutradharudu Teki } 322