1 /* 2 * Copyright (C) 2012-2014 Daniel Schwierzeck, daniel.schwierzeck@gmail.com 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <malloc.h> 9 #include <asm/errno.h> 10 #include <linux/mtd/mtd.h> 11 #include <spi_flash.h> 12 13 static struct mtd_info sf_mtd_info; 14 static char sf_mtd_name[8]; 15 16 static int spi_flash_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) 17 { 18 struct spi_flash *flash = mtd->priv; 19 int err; 20 21 instr->state = MTD_ERASING; 22 23 err = spi_flash_erase(flash, instr->addr, instr->len); 24 if (err) { 25 instr->state = MTD_ERASE_FAILED; 26 instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; 27 return -EIO; 28 } 29 30 instr->state = MTD_ERASE_DONE; 31 mtd_erase_callback(instr); 32 33 return 0; 34 } 35 36 static int spi_flash_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, 37 size_t *retlen, u_char *buf) 38 { 39 struct spi_flash *flash = mtd->priv; 40 int err; 41 42 err = spi_flash_read(flash, from, len, buf); 43 if (!err) 44 *retlen = len; 45 46 return err; 47 } 48 49 static int spi_flash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, 50 size_t *retlen, const u_char *buf) 51 { 52 struct spi_flash *flash = mtd->priv; 53 int err; 54 55 err = spi_flash_write(flash, to, len, buf); 56 if (!err) 57 *retlen = len; 58 59 return err; 60 } 61 62 static void spi_flash_mtd_sync(struct mtd_info *mtd) 63 { 64 } 65 66 static int spi_flash_mtd_number(void) 67 { 68 #ifdef CONFIG_SYS_MAX_FLASH_BANKS 69 return CONFIG_SYS_MAX_FLASH_BANKS; 70 #else 71 return 0; 72 #endif 73 } 74 75 int spi_flash_mtd_register(struct spi_flash *flash) 76 { 77 memset(&sf_mtd_info, 0, sizeof(sf_mtd_info)); 78 sprintf(sf_mtd_name, "nor%d", spi_flash_mtd_number()); 79 80 sf_mtd_info.name = sf_mtd_name; 81 sf_mtd_info.type = MTD_NORFLASH; 82 sf_mtd_info.flags = MTD_CAP_NORFLASH; 83 sf_mtd_info.writesize = 1; 84 sf_mtd_info.writebufsize = flash->page_size; 85 86 sf_mtd_info._erase = spi_flash_mtd_erase; 87 sf_mtd_info._read = spi_flash_mtd_read; 88 sf_mtd_info._write = spi_flash_mtd_write; 89 sf_mtd_info._sync = spi_flash_mtd_sync; 90 91 sf_mtd_info.size = flash->size; 92 sf_mtd_info.priv = flash; 93 94 /* Only uniform flash devices for now */ 95 sf_mtd_info.numeraseregions = 0; 96 sf_mtd_info.erasesize = flash->sector_size; 97 98 return add_mtd_device(&sf_mtd_info); 99 } 100 101 void spi_flash_mtd_unregister(void) 102 { 103 del_mtd_device(&sf_mtd_info); 104 } 105