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> 12fbb09918SSimon Glass #include <dm.h> 13ae242cbfSSimon Glass #include <errno.h> 14898e76c9SJagannadha Sutradharudu Teki #include <malloc.h> 15898e76c9SJagannadha Sutradharudu Teki #include <spi.h> 16898e76c9SJagannadha Sutradharudu Teki #include <spi_flash.h> 17898e76c9SJagannadha Sutradharudu Teki 18898e76c9SJagannadha Sutradharudu Teki #include "sf_internal.h" 19898e76c9SJagannadha Sutradharudu Teki 20ae242cbfSSimon Glass /** 21ae242cbfSSimon Glass * spi_flash_probe_slave() - Probe for a SPI flash device on a bus 22ae242cbfSSimon Glass * 23ae242cbfSSimon Glass * @flashp: Pointer to place to put flash info, which may be NULL if the 24ae242cbfSSimon Glass * space should be allocated 25ae242cbfSSimon Glass */ 26339fd6dcSJagan Teki static int spi_flash_probe_slave(struct spi_flash *flash) 27898e76c9SJagannadha Sutradharudu Teki { 28bfdb07ebSJagan Teki struct spi_slave *spi = flash->spi; 29898e76c9SJagannadha Sutradharudu Teki int ret; 30898e76c9SJagannadha Sutradharudu Teki 31898e76c9SJagannadha Sutradharudu Teki /* Setup spi_slave */ 32898e76c9SJagannadha Sutradharudu Teki if (!spi) { 33898e76c9SJagannadha Sutradharudu Teki printf("SF: Failed to set up slave\n"); 34ae242cbfSSimon Glass return -ENODEV; 35898e76c9SJagannadha Sutradharudu Teki } 36898e76c9SJagannadha Sutradharudu Teki 37898e76c9SJagannadha Sutradharudu Teki /* Claim spi bus */ 38898e76c9SJagannadha Sutradharudu Teki ret = spi_claim_bus(spi); 39898e76c9SJagannadha Sutradharudu Teki if (ret) { 40898e76c9SJagannadha Sutradharudu Teki debug("SF: Failed to claim SPI bus: %d\n", ret); 41ae242cbfSSimon Glass return ret; 42898e76c9SJagannadha Sutradharudu Teki } 43898e76c9SJagannadha Sutradharudu Teki 44bfdb07ebSJagan Teki ret = spi_flash_scan(flash); 450badb23dSSimon Glass if (ret) 46898e76c9SJagannadha Sutradharudu Teki goto err_read_id; 47898e76c9SJagannadha Sutradharudu Teki 489fe6d871SDaniel Schwierzeck #ifdef CONFIG_SPI_FLASH_MTD 499fe6d871SDaniel Schwierzeck ret = spi_flash_mtd_register(flash); 509fe6d871SDaniel Schwierzeck #endif 51898e76c9SJagannadha Sutradharudu Teki 52898e76c9SJagannadha Sutradharudu Teki err_read_id: 53898e76c9SJagannadha Sutradharudu Teki spi_release_bus(spi); 54ae242cbfSSimon Glass return ret; 55ae242cbfSSimon Glass } 56ae242cbfSSimon Glass 57fbb09918SSimon Glass #ifndef CONFIG_DM_SPI_FLASH 58*8a91194bSMario Six struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, 59*8a91194bSMario Six unsigned int max_hz, unsigned int spi_mode) 60ae242cbfSSimon Glass { 61*8a91194bSMario Six struct spi_slave *bus; 62ae242cbfSSimon Glass struct spi_flash *flash; 63ae242cbfSSimon Glass 64*8a91194bSMario Six bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); 65*8a91194bSMario Six if (!bus) 66*8a91194bSMario Six return NULL; 67*8a91194bSMario Six 68ae242cbfSSimon Glass /* Allocate space if needed (not used by sf-uclass */ 69ae242cbfSSimon Glass flash = calloc(1, sizeof(*flash)); 70ae242cbfSSimon Glass if (!flash) { 71ae242cbfSSimon Glass debug("SF: Failed to allocate spi_flash\n"); 72898e76c9SJagannadha Sutradharudu Teki return NULL; 73898e76c9SJagannadha Sutradharudu Teki } 74898e76c9SJagannadha Sutradharudu Teki 75bfdb07ebSJagan Teki flash->spi = bus; 76bfdb07ebSJagan Teki if (spi_flash_probe_slave(flash)) { 77ae242cbfSSimon Glass spi_free_slave(bus); 78ae242cbfSSimon Glass free(flash); 79ae242cbfSSimon Glass return NULL; 80ae242cbfSSimon Glass } 81ae242cbfSSimon Glass 82ae242cbfSSimon Glass return flash; 83ae242cbfSSimon Glass } 84ae242cbfSSimon Glass 85898e76c9SJagannadha Sutradharudu Teki void spi_flash_free(struct spi_flash *flash) 86898e76c9SJagannadha Sutradharudu Teki { 879fe6d871SDaniel Schwierzeck #ifdef CONFIG_SPI_FLASH_MTD 889fe6d871SDaniel Schwierzeck spi_flash_mtd_unregister(); 899fe6d871SDaniel Schwierzeck #endif 90898e76c9SJagannadha Sutradharudu Teki spi_free_slave(flash->spi); 91898e76c9SJagannadha Sutradharudu Teki free(flash); 92898e76c9SJagannadha Sutradharudu Teki } 93fbb09918SSimon Glass 94fbb09918SSimon Glass #else /* defined CONFIG_DM_SPI_FLASH */ 95fbb09918SSimon Glass 96fbb09918SSimon Glass static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, 97fbb09918SSimon Glass void *buf) 98fbb09918SSimon Glass { 99e564f054SSimon Glass struct spi_flash *flash = dev_get_uclass_priv(dev); 100fbb09918SSimon Glass 101fbb09918SSimon Glass return spi_flash_cmd_read_ops(flash, offset, len, buf); 102fbb09918SSimon Glass } 103fbb09918SSimon Glass 104339fd6dcSJagan Teki static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, 105fbb09918SSimon Glass const void *buf) 106fbb09918SSimon Glass { 107e564f054SSimon Glass struct spi_flash *flash = dev_get_uclass_priv(dev); 108fbb09918SSimon Glass 109074eed51SBin Meng #if defined(CONFIG_SPI_FLASH_SST) 1101fabefddSJagan Teki if (flash->flags & SNOR_F_SST_WR) { 111cdf33938SJagan Teki if (flash->spi->mode & SPI_TX_BYTE) 112074eed51SBin Meng return sst_write_bp(flash, offset, len, buf); 113074eed51SBin Meng else 114074eed51SBin Meng return sst_write_wp(flash, offset, len, buf); 115074eed51SBin Meng } 116074eed51SBin Meng #endif 117074eed51SBin Meng 118fbb09918SSimon Glass return spi_flash_cmd_write_ops(flash, offset, len, buf); 119fbb09918SSimon Glass } 120fbb09918SSimon Glass 121339fd6dcSJagan Teki static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) 122fbb09918SSimon Glass { 123e564f054SSimon Glass struct spi_flash *flash = dev_get_uclass_priv(dev); 124fbb09918SSimon Glass 125fbb09918SSimon Glass return spi_flash_cmd_erase_ops(flash, offset, len); 126fbb09918SSimon Glass } 127fbb09918SSimon Glass 128339fd6dcSJagan Teki static int spi_flash_std_probe(struct udevice *dev) 129fbb09918SSimon Glass { 130bcbe3d15SSimon Glass struct spi_slave *slave = dev_get_parent_priv(dev); 131d0cff03eSSimon Glass struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); 132fbb09918SSimon Glass struct spi_flash *flash; 133fbb09918SSimon Glass 134e564f054SSimon Glass flash = dev_get_uclass_priv(dev); 135fbb09918SSimon Glass flash->dev = dev; 136bfdb07ebSJagan Teki flash->spi = slave; 137d0cff03eSSimon Glass debug("%s: slave=%p, cs=%d\n", __func__, slave, plat->cs); 138bfdb07ebSJagan Teki return spi_flash_probe_slave(flash); 139fbb09918SSimon Glass } 140fbb09918SSimon Glass 141fbb09918SSimon Glass static const struct dm_spi_flash_ops spi_flash_std_ops = { 142fbb09918SSimon Glass .read = spi_flash_std_read, 143fbb09918SSimon Glass .write = spi_flash_std_write, 144fbb09918SSimon Glass .erase = spi_flash_std_erase, 145fbb09918SSimon Glass }; 146fbb09918SSimon Glass 147fbb09918SSimon Glass static const struct udevice_id spi_flash_std_ids[] = { 148fbb09918SSimon Glass { .compatible = "spi-flash" }, 149fbb09918SSimon Glass { } 150fbb09918SSimon Glass }; 151fbb09918SSimon Glass 152fbb09918SSimon Glass U_BOOT_DRIVER(spi_flash_std) = { 153fbb09918SSimon Glass .name = "spi_flash_std", 154fbb09918SSimon Glass .id = UCLASS_SPI_FLASH, 155fbb09918SSimon Glass .of_match = spi_flash_std_ids, 156fbb09918SSimon Glass .probe = spi_flash_std_probe, 157fbb09918SSimon Glass .priv_auto_alloc_size = sizeof(struct spi_flash), 158fbb09918SSimon Glass .ops = &spi_flash_std_ops, 159fbb09918SSimon Glass }; 160fbb09918SSimon Glass 161fbb09918SSimon Glass #endif /* CONFIG_DM_SPI_FLASH */ 162