1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * SPI flash probing 4 * 5 * Copyright (C) 2008 Atmel Corporation 6 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik 7 * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. 8 */ 9 10 #include <common.h> 11 #include <dm.h> 12 #include <errno.h> 13 #include <malloc.h> 14 #include <spi.h> 15 #include <spi_flash.h> 16 17 #include "sf_internal.h" 18 19 /** 20 * spi_flash_probe_slave() - Probe for a SPI flash device on a bus 21 * 22 * @flashp: Pointer to place to put flash info, which may be NULL if the 23 * space should be allocated 24 */ 25 static int spi_flash_probe_slave(struct spi_flash *flash) 26 { 27 struct spi_slave *spi = flash->spi; 28 int ret; 29 30 /* Setup spi_slave */ 31 if (!spi) { 32 printf("SF: Failed to set up slave\n"); 33 return -ENODEV; 34 } 35 36 /* Claim spi bus */ 37 ret = spi_claim_bus(spi); 38 if (ret) { 39 debug("SF: Failed to claim SPI bus: %d\n", ret); 40 return ret; 41 } 42 43 ret = spi_flash_scan(flash); 44 if (ret) 45 goto err_read_id; 46 47 #ifdef CONFIG_SPI_FLASH_MTD 48 ret = spi_flash_mtd_register(flash); 49 #endif 50 51 err_read_id: 52 spi_release_bus(spi); 53 return ret; 54 } 55 56 #ifndef CONFIG_DM_SPI_FLASH 57 struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, 58 unsigned int max_hz, unsigned int spi_mode) 59 { 60 struct spi_slave *bus; 61 struct spi_flash *flash; 62 63 bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); 64 if (!bus) 65 return NULL; 66 67 /* Allocate space if needed (not used by sf-uclass */ 68 flash = calloc(1, sizeof(*flash)); 69 if (!flash) { 70 debug("SF: Failed to allocate spi_flash\n"); 71 return NULL; 72 } 73 74 flash->spi = bus; 75 if (spi_flash_probe_slave(flash)) { 76 spi_free_slave(bus); 77 free(flash); 78 return NULL; 79 } 80 81 return flash; 82 } 83 84 void spi_flash_free(struct spi_flash *flash) 85 { 86 #ifdef CONFIG_SPI_FLASH_MTD 87 spi_flash_mtd_unregister(); 88 #endif 89 spi_free_slave(flash->spi); 90 free(flash); 91 } 92 93 #else /* defined CONFIG_DM_SPI_FLASH */ 94 95 static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, 96 void *buf) 97 { 98 struct spi_flash *flash = dev_get_uclass_priv(dev); 99 100 return log_ret(spi_flash_cmd_read_ops(flash, offset, len, buf)); 101 } 102 103 static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, 104 const void *buf) 105 { 106 struct spi_flash *flash = dev_get_uclass_priv(dev); 107 108 #if defined(CONFIG_SPI_FLASH_SST) 109 if (flash->flags & SNOR_F_SST_WR) { 110 if (flash->spi->mode & SPI_TX_BYTE) 111 return sst_write_bp(flash, offset, len, buf); 112 else 113 return sst_write_wp(flash, offset, len, buf); 114 } 115 #endif 116 117 return spi_flash_cmd_write_ops(flash, offset, len, buf); 118 } 119 120 static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) 121 { 122 struct spi_flash *flash = dev_get_uclass_priv(dev); 123 124 return spi_flash_cmd_erase_ops(flash, offset, len); 125 } 126 127 static int spi_flash_std_probe(struct udevice *dev) 128 { 129 struct spi_slave *slave = dev_get_parent_priv(dev); 130 struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); 131 struct spi_flash *flash; 132 133 flash = dev_get_uclass_priv(dev); 134 flash->dev = dev; 135 flash->spi = slave; 136 debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); 137 return spi_flash_probe_slave(flash); 138 } 139 140 static const struct dm_spi_flash_ops spi_flash_std_ops = { 141 .read = spi_flash_std_read, 142 .write = spi_flash_std_write, 143 .erase = spi_flash_std_erase, 144 }; 145 146 static const struct udevice_id spi_flash_std_ids[] = { 147 { .compatible = "spi-flash" }, 148 { } 149 }; 150 151 U_BOOT_DRIVER(spi_flash_std) = { 152 .name = "spi_flash_std", 153 .id = UCLASS_SPI_FLASH, 154 .of_match = spi_flash_std_ids, 155 .probe = spi_flash_std_probe, 156 .priv_auto_alloc_size = sizeof(struct spi_flash), 157 .ops = &spi_flash_std_ops, 158 }; 159 160 #endif /* CONFIG_DM_SPI_FLASH */ 161