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_nor_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 struct mtd_info *mtd = &flash->mtd; 100 size_t retlen; 101 102 return log_ret(mtd->_read(mtd, offset, len, &retlen, buf)); 103 } 104 105 static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, 106 const void *buf) 107 { 108 struct spi_flash *flash = dev_get_uclass_priv(dev); 109 struct mtd_info *mtd = &flash->mtd; 110 size_t retlen; 111 112 return mtd->_write(mtd, offset, len, &retlen, buf); 113 } 114 115 static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) 116 { 117 struct spi_flash *flash = dev_get_uclass_priv(dev); 118 struct mtd_info *mtd = &flash->mtd; 119 struct erase_info instr; 120 121 if (offset % mtd->erasesize || len % mtd->erasesize) { 122 printf("SF: Erase offset/length not multiple of erase size\n"); 123 return -EINVAL; 124 } 125 126 memset(&instr, 0, sizeof(instr)); 127 instr.addr = offset; 128 instr.len = len; 129 130 return mtd->_erase(mtd, &instr); 131 } 132 133 static int spi_flash_std_get_sw_write_prot(struct udevice *dev) 134 { 135 struct spi_flash *flash = dev_get_uclass_priv(dev); 136 137 return spi_flash_cmd_get_sw_write_prot(flash); 138 } 139 140 static int spi_flash_std_probe(struct udevice *dev) 141 { 142 struct spi_slave *slave = dev_get_parent_priv(dev); 143 struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); 144 struct spi_flash *flash; 145 146 flash = dev_get_uclass_priv(dev); 147 flash->dev = dev; 148 flash->spi = slave; 149 debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); 150 return spi_flash_probe_slave(flash); 151 } 152 153 static int spi_flash_std_remove(struct udevice *dev) 154 { 155 #ifdef CONFIG_SPI_FLASH_MTD 156 spi_flash_mtd_unregister(); 157 #endif 158 return 0; 159 } 160 161 static const struct dm_spi_flash_ops spi_flash_std_ops = { 162 .read = spi_flash_std_read, 163 .write = spi_flash_std_write, 164 .erase = spi_flash_std_erase, 165 .get_sw_write_prot = spi_flash_std_get_sw_write_prot, 166 }; 167 168 static const struct udevice_id spi_flash_std_ids[] = { 169 { .compatible = "spi-flash" }, 170 { .compatible = "jedec,spi-nor" }, 171 { } 172 }; 173 174 U_BOOT_DRIVER(spi_flash_std) = { 175 .name = "spi_flash_std", 176 .id = UCLASS_SPI_FLASH, 177 .of_match = spi_flash_std_ids, 178 .probe = spi_flash_std_probe, 179 .remove = spi_flash_std_remove, 180 .priv_auto_alloc_size = sizeof(struct spi_flash), 181 .ops = &spi_flash_std_ops, 182 }; 183 184 #endif /* CONFIG_DM_SPI_FLASH */ 185