1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2012-2014 Daniel Schwierzeck, daniel.schwierzeck@gmail.com
9 #include <linux/errno.h>
10 #include <linux/mtd/mtd.h>
11 #include <spi_flash.h>
13 static struct mtd_info sf_mtd_info
;
14 static bool sf_mtd_registered
;
15 static char sf_mtd_name
[8];
17 static int spi_flash_mtd_erase(struct mtd_info
*mtd
, struct erase_info
*instr
)
19 struct spi_flash
*flash
= mtd
->priv
;
25 instr
->state
= MTD_ERASING
;
27 err
= spi_flash_erase(flash
, instr
->addr
, instr
->len
);
29 instr
->state
= MTD_ERASE_FAILED
;
30 instr
->fail_addr
= MTD_FAIL_ADDR_UNKNOWN
;
34 instr
->state
= MTD_ERASE_DONE
;
35 mtd_erase_callback(instr
);
40 static int spi_flash_mtd_read(struct mtd_info
*mtd
, loff_t from
, size_t len
,
41 size_t *retlen
, u_char
*buf
)
43 struct spi_flash
*flash
= mtd
->priv
;
49 err
= spi_flash_read(flash
, from
, len
, buf
);
56 static int spi_flash_mtd_write(struct mtd_info
*mtd
, loff_t to
, size_t len
,
57 size_t *retlen
, const u_char
*buf
)
59 struct spi_flash
*flash
= mtd
->priv
;
65 err
= spi_flash_write(flash
, to
, len
, buf
);
72 static void spi_flash_mtd_sync(struct mtd_info
*mtd
)
76 static int spi_flash_mtd_number(void)
78 #ifdef CONFIG_SYS_MAX_FLASH_BANKS
79 return CONFIG_SYS_MAX_FLASH_BANKS
;
85 int spi_flash_mtd_register(struct spi_flash
*flash
)
89 if (sf_mtd_registered
) {
90 ret
= del_mtd_device(&sf_mtd_info
);
94 sf_mtd_registered
= false;
97 sf_mtd_registered
= false;
98 memset(&sf_mtd_info
, 0, sizeof(sf_mtd_info
));
99 sprintf(sf_mtd_name
, "nor%d", spi_flash_mtd_number());
101 sf_mtd_info
.name
= sf_mtd_name
;
102 sf_mtd_info
.type
= MTD_NORFLASH
;
103 sf_mtd_info
.flags
= MTD_CAP_NORFLASH
;
104 sf_mtd_info
.writesize
= 1;
105 sf_mtd_info
.writebufsize
= flash
->page_size
;
107 sf_mtd_info
._erase
= spi_flash_mtd_erase
;
108 sf_mtd_info
._read
= spi_flash_mtd_read
;
109 sf_mtd_info
._write
= spi_flash_mtd_write
;
110 sf_mtd_info
._sync
= spi_flash_mtd_sync
;
112 sf_mtd_info
.size
= flash
->size
;
113 sf_mtd_info
.priv
= flash
;
115 /* Only uniform flash devices for now */
116 sf_mtd_info
.numeraseregions
= 0;
117 sf_mtd_info
.erasesize
= flash
->sector_size
;
119 ret
= add_mtd_device(&sf_mtd_info
);
121 sf_mtd_registered
= true;
126 void spi_flash_mtd_unregister(void)
130 if (!sf_mtd_registered
)
133 ret
= del_mtd_device(&sf_mtd_info
);
135 sf_mtd_registered
= false;
140 * Setting mtd->priv to NULL is the best we can do. Thanks to that,
141 * the MTD layer can still call mtd hooks without risking a
142 * use-after-free bug. Still, things should be fixed to prevent the
143 * spi_flash object from being destroyed when del_mtd_device() fails.
145 sf_mtd_info
.priv
= NULL
;
146 printf("Failed to unregister MTD %s and the spi_flash object is going away: you're in deep trouble!",