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_get_sw_write_prot(struct udevice *dev) 128 { 129 struct spi_flash *flash = dev_get_uclass_priv(dev); 130 131 return spi_flash_cmd_get_sw_write_prot(flash); 132 } 133 134 static int spi_flash_std_probe(struct udevice *dev) 135 { 136 struct spi_slave *slave = dev_get_parent_priv(dev); 137 struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); 138 struct spi_flash *flash; 139 140 flash = dev_get_uclass_priv(dev); 141 flash->dev = dev; 142 flash->spi = slave; 143 debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); 144 return spi_flash_probe_slave(flash); 145 } 146 147 static int spi_flash_std_remove(struct udevice *dev) 148 { 149 #ifdef CONFIG_SPI_FLASH_MTD 150 spi_flash_mtd_unregister(); 151 #endif 152 return 0; 153 } 154 155 static const struct dm_spi_flash_ops spi_flash_std_ops = { 156 .read = spi_flash_std_read, 157 .write = spi_flash_std_write, 158 .erase = spi_flash_std_erase, 159 .get_sw_write_prot = spi_flash_std_get_sw_write_prot, 160 }; 161 162 static const struct udevice_id spi_flash_std_ids[] = { 163 { .compatible = "spi-flash" }, 164 { .compatible = "jedec,spi-nor" }, 165 { } 166 }; 167 168 U_BOOT_DRIVER(spi_flash_std) = { 169 .name = "spi_flash_std", 170 .id = UCLASS_SPI_FLASH, 171 .of_match = spi_flash_std_ids, 172 .probe = spi_flash_std_probe, 173 .remove = spi_flash_std_remove, 174 .priv_auto_alloc_size = sizeof(struct spi_flash), 175 .ops = &spi_flash_std_ops, 176 }; 177 178 #endif /* CONFIG_DM_SPI_FLASH */ 179