root/drivers/mtd/devices/sst25l.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sst25l_status
  2. sst25l_write_enable
  3. sst25l_wait_till_ready
  4. sst25l_erase_sector
  5. sst25l_erase
  6. sst25l_read
  7. sst25l_write
  8. sst25l_match_device
  9. sst25l_probe
  10. sst25l_remove

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

/* [<][>][^][v][top][bottom][index][help] */