Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | /* * SPI flash interface * * Copyright (C) 2008 Atmel Corporation */ #define DEBUG #include <common.h> #include <malloc.h> #include <spi.h> #include <spi_flash.h> #include "spi_flash_internal.h" int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len) { unsigned long flags = SPI_XFER_BEGIN; int ret; if (len == 0) flags |= SPI_XFER_END; ret = spi_xfer(spi, 8, &cmd, NULL, flags); if (ret) { debug("SF: Failed to send command %02x: %d\n", cmd, ret); return ret; } if (len) { ret = spi_xfer(spi, len * 8, NULL, response, SPI_XFER_END); if (ret) debug("SF: Failed to read response (%zu bytes): %d\n", len, ret); } return ret; } int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, void *data, size_t data_len) { unsigned long flags = SPI_XFER_BEGIN; int ret; if (data_len == 0) flags |= SPI_XFER_END; ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags); if (ret) { debug("SF: Failed to send read command (%zu bytes): %d\n", cmd_len, ret); } else if (data_len != 0) { ret = spi_xfer(spi, data_len * 8, NULL, data, SPI_XFER_END); if (ret) debug("SF: Failed to read %zu bytes of data: %d\n", data_len, ret); } return ret; } int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, const void *data, size_t data_len) { unsigned long flags = SPI_XFER_BEGIN; int ret; if (data_len == 0) flags |= SPI_XFER_END; ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags); if (ret) { debug("SF: Failed to send read command (%zu bytes): %d\n", cmd_len, ret); } else if (data_len != 0) { ret = spi_xfer(spi, data_len * 8, data, NULL, SPI_XFER_END); if (ret) debug("SF: Failed to read %zu bytes of data: %d\n", data_len, ret); } return ret; } int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, void *data, size_t data_len) { struct spi_slave *spi = flash->spi; int ret; spi_claim_bus(spi); ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); spi_release_bus(spi); return ret; } struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int spi_mode) { struct spi_slave *spi; struct spi_flash *flash; int ret; u8 idcode[3]; spi = spi_setup_slave(bus, cs, max_hz, spi_mode); if (!spi) { debug("SF: Failed to set up slave\n"); return NULL; } ret = spi_claim_bus(spi); if (ret) { debug("SF: Failed to claim SPI bus: %d\n", ret); goto err_claim_bus; } /* Read the ID codes */ ret = spi_flash_cmd(spi, CMD_READ_ID, &idcode, sizeof(idcode)); if (ret) goto err_read_id; debug("SF: Got idcode %02x %02x %02x\n", idcode[0], idcode[1], idcode[2]); switch (idcode[0]) { #ifdef CONFIG_SPI_FLASH_SPANSION case 0x01: flash = spi_flash_probe_spansion(spi, idcode); break; #endif #ifdef CONFIG_SPI_FLASH_ATMEL case 0x1F: flash = spi_flash_probe_atmel(spi, idcode); break; #endif default: debug("SF: Unsupported manufacturer %02X\n", idcode[0]); flash = NULL; break; } if (!flash) goto err_manufacturer_probe; spi_release_bus(spi); return flash; err_manufacturer_probe: err_read_id: spi_release_bus(spi); err_claim_bus: spi_free_slave(spi); return NULL; } void spi_flash_free(struct spi_flash *flash) { spi_free_slave(flash->spi); free(flash); } |