1/* 2 * sst25l.c 3 * 4 * Driver for SST25L SPI Flash chips 5 * 6 * Copyright �� 2009 Bluewater Systems Ltd 7 * Author: Andre Renaud <andre@bluewatersys.com> 8 * Author: Ryan Mallon 9 * 10 * Based on m25p80.c 11 * 12 * This code is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 * 16 */ 17 18#include <linux/module.h> 19#include <linux/device.h> 20#include <linux/mutex.h> 21#include <linux/interrupt.h> 22#include <linux/slab.h> 23#include <linux/sched.h> 24 25#include <linux/mtd/mtd.h> 26#include <linux/mtd/partitions.h> 27 28#include <linux/spi/spi.h> 29#include <linux/spi/flash.h> 30 31/* Erases can take up to 3 seconds! */ 32#define MAX_READY_WAIT_JIFFIES msecs_to_jiffies(3000) 33 34#define SST25L_CMD_WRSR 0x01 /* Write status register */ 35#define SST25L_CMD_WRDI 0x04 /* Write disable */ 36#define SST25L_CMD_RDSR 0x05 /* Read status register */ 37#define SST25L_CMD_WREN 0x06 /* Write enable */ 38#define SST25L_CMD_READ 0x03 /* High speed read */ 39 40#define SST25L_CMD_EWSR 0x50 /* Enable write status register */ 41#define SST25L_CMD_SECTOR_ERASE 0x20 /* Erase sector */ 42#define SST25L_CMD_READ_ID 0x90 /* Read device ID */ 43#define SST25L_CMD_AAI_PROGRAM 0xaf /* Auto address increment */ 44 45#define SST25L_STATUS_BUSY (1 << 0) /* Chip is busy */ 46#define SST25L_STATUS_WREN (1 << 1) /* Write enabled */ 47#define SST25L_STATUS_BP0 (1 << 2) /* Block protection 0 */ 48#define SST25L_STATUS_BP1 (1 << 3) /* Block protection 1 */ 49 50struct sst25l_flash { 51 struct spi_device *spi; 52 struct mutex lock; 53 struct mtd_info mtd; 54}; 55 56struct flash_info { 57 const char *name; 58 uint16_t device_id; 59 unsigned page_size; 60 unsigned nr_pages; 61 unsigned erase_size; 62}; 63 64#define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd) 65 66static struct flash_info sst25l_flash_info[] = { 67 {"sst25lf020a", 0xbf43, 256, 1024, 4096}, 68 {"sst25lf040a", 0xbf44, 256, 2048, 4096}, 69}; 70 71static int sst25l_status(struct sst25l_flash *flash, int *status) 72{ 73 struct spi_message m; 74 struct spi_transfer t; 75 unsigned char cmd_resp[2]; 76 int err; 77 78 spi_message_init(&m); 79 memset(&t, 0, sizeof(struct spi_transfer)); 80 81 cmd_resp[0] = SST25L_CMD_RDSR; 82 cmd_resp[1] = 0xff; 83 t.tx_buf = cmd_resp; 84 t.rx_buf = cmd_resp; 85 t.len = sizeof(cmd_resp); 86 spi_message_add_tail(&t, &m); 87 err = spi_sync(flash->spi, &m); 88 if (err < 0) 89 return err; 90 91 *status = cmd_resp[1]; 92 return 0; 93} 94 95static int sst25l_write_enable(struct sst25l_flash *flash, int enable) 96{ 97 unsigned char command[2]; 98 int status, err; 99 100 command[0] = enable ? SST25L_CMD_WREN : SST25L_CMD_WRDI; 101 err = spi_write(flash->spi, command, 1); 102 if (err) 103 return err; 104 105 command[0] = SST25L_CMD_EWSR; 106 err = spi_write(flash->spi, command, 1); 107 if (err) 108 return err; 109 110 command[0] = SST25L_CMD_WRSR; 111 command[1] = enable ? 0 : SST25L_STATUS_BP0 | SST25L_STATUS_BP1; 112 err = spi_write(flash->spi, command, 2); 113 if (err) 114 return err; 115 116 if (enable) { 117 err = sst25l_status(flash, &status); 118 if (err) 119 return err; 120 if (!(status & SST25L_STATUS_WREN)) 121 return -EROFS; 122 } 123 124 return 0; 125} 126 127static int sst25l_wait_till_ready(struct sst25l_flash *flash) 128{ 129 unsigned long deadline; 130 int status, err; 131 132 deadline = jiffies + MAX_READY_WAIT_JIFFIES; 133 do { 134 err = sst25l_status(flash, &status); 135 if (err) 136 return err; 137 if (!(status & SST25L_STATUS_BUSY)) 138 return 0; 139 140 cond_resched(); 141 } while (!time_after_eq(jiffies, deadline)); 142 143 return -ETIMEDOUT; 144} 145 146static int sst25l_erase_sector(struct sst25l_flash *flash, uint32_t offset) 147{ 148 unsigned char command[4]; 149 int err; 150 151 err = sst25l_write_enable(flash, 1); 152 if (err) 153 return err; 154 155 command[0] = SST25L_CMD_SECTOR_ERASE; 156 command[1] = offset >> 16; 157 command[2] = offset >> 8; 158 command[3] = offset; 159 err = spi_write(flash->spi, command, 4); 160 if (err) 161 return err; 162 163 err = sst25l_wait_till_ready(flash); 164 if (err) 165 return err; 166 167 return sst25l_write_enable(flash, 0); 168} 169 170static int sst25l_erase(struct mtd_info *mtd, struct erase_info *instr) 171{ 172 struct sst25l_flash *flash = to_sst25l_flash(mtd); 173 uint32_t addr, end; 174 int err; 175 176 /* Sanity checks */ 177 if ((uint32_t)instr->len % mtd->erasesize) 178 return -EINVAL; 179 180 if ((uint32_t)instr->addr % mtd->erasesize) 181 return -EINVAL; 182 183 addr = instr->addr; 184 end = addr + instr->len; 185 186 mutex_lock(&flash->lock); 187 188 err = sst25l_wait_till_ready(flash); 189 if (err) { 190 mutex_unlock(&flash->lock); 191 return err; 192 } 193 194 while (addr < end) { 195 err = sst25l_erase_sector(flash, addr); 196 if (err) { 197 mutex_unlock(&flash->lock); 198 instr->state = MTD_ERASE_FAILED; 199 dev_err(&flash->spi->dev, "Erase failed\n"); 200 return err; 201 } 202 203 addr += mtd->erasesize; 204 } 205 206 mutex_unlock(&flash->lock); 207 208 instr->state = MTD_ERASE_DONE; 209 mtd_erase_callback(instr); 210 return 0; 211} 212 213static int sst25l_read(struct mtd_info *mtd, loff_t from, size_t len, 214 size_t *retlen, unsigned char *buf) 215{ 216 struct sst25l_flash *flash = to_sst25l_flash(mtd); 217 struct spi_transfer transfer[2]; 218 struct spi_message message; 219 unsigned char command[4]; 220 int ret; 221 222 spi_message_init(&message); 223 memset(&transfer, 0, sizeof(transfer)); 224 225 command[0] = SST25L_CMD_READ; 226 command[1] = from >> 16; 227 command[2] = from >> 8; 228 command[3] = from; 229 230 transfer[0].tx_buf = command; 231 transfer[0].len = sizeof(command); 232 spi_message_add_tail(&transfer[0], &message); 233 234 transfer[1].rx_buf = buf; 235 transfer[1].len = len; 236 spi_message_add_tail(&transfer[1], &message); 237 238 mutex_lock(&flash->lock); 239 240 /* Wait for previous write/erase to complete */ 241 ret = sst25l_wait_till_ready(flash); 242 if (ret) { 243 mutex_unlock(&flash->lock); 244 return ret; 245 } 246 247 spi_sync(flash->spi, &message); 248 249 if (retlen && message.actual_length > sizeof(command)) 250 *retlen += message.actual_length - sizeof(command); 251 252 mutex_unlock(&flash->lock); 253 return 0; 254} 255 256static int sst25l_write(struct mtd_info *mtd, loff_t to, size_t len, 257 size_t *retlen, const unsigned char *buf) 258{ 259 struct sst25l_flash *flash = to_sst25l_flash(mtd); 260 int i, j, ret, bytes, copied = 0; 261 unsigned char command[5]; 262 263 if ((uint32_t)to % mtd->writesize) 264 return -EINVAL; 265 266 mutex_lock(&flash->lock); 267 268 ret = sst25l_write_enable(flash, 1); 269 if (ret) 270 goto out; 271 272 for (i = 0; i < len; i += mtd->writesize) { 273 ret = sst25l_wait_till_ready(flash); 274 if (ret) 275 goto out; 276 277 /* Write the first byte of the page */ 278 command[0] = SST25L_CMD_AAI_PROGRAM; 279 command[1] = (to + i) >> 16; 280 command[2] = (to + i) >> 8; 281 command[3] = (to + i); 282 command[4] = buf[i]; 283 ret = spi_write(flash->spi, command, 5); 284 if (ret < 0) 285 goto out; 286 copied++; 287 288 /* 289 * Write the remaining bytes using auto address 290 * increment mode 291 */ 292 bytes = min_t(uint32_t, mtd->writesize, len - i); 293 for (j = 1; j < bytes; j++, copied++) { 294 ret = sst25l_wait_till_ready(flash); 295 if (ret) 296 goto out; 297 298 command[1] = buf[i + j]; 299 ret = spi_write(flash->spi, command, 2); 300 if (ret) 301 goto out; 302 } 303 } 304 305out: 306 ret = sst25l_write_enable(flash, 0); 307 308 if (retlen) 309 *retlen = copied; 310 311 mutex_unlock(&flash->lock); 312 return ret; 313} 314 315static struct flash_info *sst25l_match_device(struct spi_device *spi) 316{ 317 struct flash_info *flash_info = NULL; 318 struct spi_message m; 319 struct spi_transfer t; 320 unsigned char cmd_resp[6]; 321 int i, err; 322 uint16_t id; 323 324 spi_message_init(&m); 325 memset(&t, 0, sizeof(struct spi_transfer)); 326 327 cmd_resp[0] = SST25L_CMD_READ_ID; 328 cmd_resp[1] = 0; 329 cmd_resp[2] = 0; 330 cmd_resp[3] = 0; 331 cmd_resp[4] = 0xff; 332 cmd_resp[5] = 0xff; 333 t.tx_buf = cmd_resp; 334 t.rx_buf = cmd_resp; 335 t.len = sizeof(cmd_resp); 336 spi_message_add_tail(&t, &m); 337 err = spi_sync(spi, &m); 338 if (err < 0) { 339 dev_err(&spi->dev, "error reading device id\n"); 340 return NULL; 341 } 342 343 id = (cmd_resp[4] << 8) | cmd_resp[5]; 344 345 for (i = 0; i < ARRAY_SIZE(sst25l_flash_info); i++) 346 if (sst25l_flash_info[i].device_id == id) 347 flash_info = &sst25l_flash_info[i]; 348 349 if (!flash_info) 350 dev_err(&spi->dev, "unknown id %.4x\n", id); 351 352 return flash_info; 353} 354 355static int sst25l_probe(struct spi_device *spi) 356{ 357 struct flash_info *flash_info; 358 struct sst25l_flash *flash; 359 struct flash_platform_data *data; 360 int ret; 361 362 flash_info = sst25l_match_device(spi); 363 if (!flash_info) 364 return -ENODEV; 365 366 flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL); 367 if (!flash) 368 return -ENOMEM; 369 370 flash->spi = spi; 371 mutex_init(&flash->lock); 372 spi_set_drvdata(spi, flash); 373 374 data = dev_get_platdata(&spi->dev); 375 if (data && data->name) 376 flash->mtd.name = data->name; 377 378 flash->mtd.dev.parent = &spi->dev; 379 flash->mtd.type = MTD_NORFLASH; 380 flash->mtd.flags = MTD_CAP_NORFLASH; 381 flash->mtd.erasesize = flash_info->erase_size; 382 flash->mtd.writesize = flash_info->page_size; 383 flash->mtd.writebufsize = flash_info->page_size; 384 flash->mtd.size = flash_info->page_size * flash_info->nr_pages; 385 flash->mtd._erase = sst25l_erase; 386 flash->mtd._read = sst25l_read; 387 flash->mtd._write = sst25l_write; 388 389 dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name, 390 (long long)flash->mtd.size >> 10); 391 392 pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) " 393 ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", 394 flash->mtd.name, 395 (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20), 396 flash->mtd.erasesize, flash->mtd.erasesize / 1024, 397 flash->mtd.numeraseregions); 398 399 400 ret = mtd_device_parse_register(&flash->mtd, NULL, NULL, 401 data ? data->parts : NULL, 402 data ? data->nr_parts : 0); 403 if (ret) 404 return -ENODEV; 405 406 return 0; 407} 408 409static int sst25l_remove(struct spi_device *spi) 410{ 411 struct sst25l_flash *flash = spi_get_drvdata(spi); 412 413 return mtd_device_unregister(&flash->mtd); 414} 415 416static struct spi_driver sst25l_driver = { 417 .driver = { 418 .name = "sst25l", 419 }, 420 .probe = sst25l_probe, 421 .remove = sst25l_remove, 422}; 423 424module_spi_driver(sst25l_driver); 425 426MODULE_DESCRIPTION("MTD SPI driver for SST25L Flash chips"); 427MODULE_AUTHOR("Andre Renaud <andre@bluewatersys.com>, " 428 "Ryan Mallon"); 429MODULE_LICENSE("GPL"); 430