aboutsummaryrefslogtreecommitdiff
path: root/libflash/libflash.c
diff options
context:
space:
mode:
Diffstat (limited to 'libflash/libflash.c')
-rw-r--r--libflash/libflash.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/libflash/libflash.c b/libflash/libflash.c
index e43be4f..2af0c79 100644
--- a/libflash/libflash.c
+++ b/libflash/libflash.c
@@ -20,6 +20,7 @@
#include "libflash.h"
#include "libflash-priv.h"
#include "ecc.h"
+#include "blocklevel.h"
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
@@ -45,6 +46,7 @@ struct flash_chip {
bool mode_4b; /* Flash currently in 4b mode */
struct flash_req *cur_req; /* Current request */
void *smart_buf; /* Buffer for smart writes */
+ struct blocklevel_device bl;
};
#ifndef __SKIBOOT__
@@ -112,8 +114,9 @@ int fl_wren(struct spi_flash_ctrl *ct)
return FLASH_ERR_WREN_TIMEOUT;
}
-int flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len)
+static int flash_read(struct blocklevel_device *bl, uint32_t pos, void *buf, uint32_t len)
{
+ struct flash_chip *c = container_of(bl, struct flash_chip, bl);
struct spi_flash_ctrl *ct = c->ctrl;
/* XXX Add sanity/bound checking */
@@ -138,7 +141,7 @@ int flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len)
* This provides a wrapper around flash_read on ECCed data
* len is length of data without ECC attached
*/
-int flash_read_corrected(struct flash_chip *c, uint32_t pos, void *buf,
+int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf,
uint32_t len, bool ecc)
{
struct ecc64 *bufecc;
@@ -147,7 +150,7 @@ int flash_read_corrected(struct flash_chip *c, uint32_t pos, void *buf,
uint8_t ret;
if (!ecc)
- return flash_read(c, pos, buf, len);
+ return flash_read(bl, pos, buf, len);
/* Copy the buffer in chunks */
bufecc = malloc(ECC_BUFFER_SIZE(COPY_BUFFER_LENGTH));
@@ -159,7 +162,7 @@ int flash_read_corrected(struct flash_chip *c, uint32_t pos, void *buf,
copylen = MIN(len, COPY_BUFFER_LENGTH);
/* Read ECCed data from flash */
- rc = flash_read(c, pos, bufecc, ECC_BUFFER_SIZE(copylen));
+ rc = flash_read(bl, pos, bufecc, ECC_BUFFER_SIZE(copylen));
if (rc)
goto err;
@@ -215,8 +218,9 @@ static void fl_get_best_erase(struct flash_chip *c, uint32_t dst, uint32_t size,
*cmd = CMD_BE;
}
-int flash_erase(struct flash_chip *c, uint32_t dst, uint32_t size)
+static int flash_erase(struct blocklevel_device *bl, uint32_t dst, uint32_t size)
{
+ struct flash_chip *c = container_of(bl, struct flash_chip, bl);
struct spi_flash_ctrl *ct = c->ctrl;
uint32_t chunk;
uint8_t cmd;
@@ -262,8 +266,9 @@ int flash_erase(struct flash_chip *c, uint32_t dst, uint32_t size)
return 0;
}
-int flash_erase_chip(struct flash_chip *c)
+int flash_erase_chip(struct blocklevel_device *bl)
{
+ struct flash_chip *c = container_of(bl, struct flash_chip, bl);
struct spi_flash_ctrl *ct = c->ctrl;
int rc;
@@ -311,9 +316,10 @@ static int fl_wpage(struct flash_chip *c, uint32_t dst, const void *src,
return fl_sync_wait_idle(ct);
}
-int flash_write(struct flash_chip *c, uint32_t dst, const void *src,
+static int flash_write(struct blocklevel_device *bl, uint32_t dst, const void *src,
uint32_t size, bool verify)
{
+ struct flash_chip *c = container_of(bl, struct flash_chip, bl);
struct spi_flash_ctrl *ct = c->ctrl;
uint32_t todo = size;
uint32_t d = dst;
@@ -374,7 +380,7 @@ int flash_write(struct flash_chip *c, uint32_t dst, const void *src,
chunk = sizeof(vbuf);
if (chunk > size)
chunk = size;
- rc = flash_read(c, dst, vbuf, chunk);
+ rc = flash_read(bl, dst, vbuf, chunk);
if (rc) return rc;
if (memcmp(vbuf, src, chunk)) {
FL_ERR("LIBFLASH: Miscompare at 0x%08x\n", dst);
@@ -387,7 +393,7 @@ int flash_write(struct flash_chip *c, uint32_t dst, const void *src,
return 0;
}
-int flash_write_corrected(struct flash_chip *c, uint32_t pos, const void *buf,
+int flash_write_corrected(struct blocklevel_device *bl, uint32_t pos, const void *buf,
uint32_t len, bool verify, bool ecc)
{
struct ecc64 *bufecc;
@@ -396,7 +402,7 @@ int flash_write_corrected(struct flash_chip *c, uint32_t pos, const void *buf,
uint8_t ret;
if (!ecc)
- return flash_write(c, pos, buf, len, verify);
+ return flash_write(bl, pos, buf, len, verify);
/* Copy the buffer in chunks */
bufecc = malloc(ECC_BUFFER_SIZE(COPY_BUFFER_LENGTH));
@@ -415,7 +421,7 @@ int flash_write_corrected(struct flash_chip *c, uint32_t pos, const void *buf,
}
/* Write ECCed data to the flash */
- rc = flash_write(c, pos, bufecc, copylen, verify);
+ rc = flash_write(bl, pos, bufecc, copylen, verify);
if (rc)
goto err;
@@ -463,12 +469,12 @@ static enum sm_comp_res flash_smart_comp(struct flash_chip *c,
return is_same ? sm_no_change : sm_need_write;
}
-int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src,
- uint32_t size)
+static int flash_smart_write(struct blocklevel_device *bl, uint32_t dst, const void *src, uint32_t size)
{
+ struct flash_chip *c = container_of(bl, struct flash_chip, bl);
uint32_t er_size = c->min_erase_mask + 1;
uint32_t end = dst + size;
- int rc;
+ int rc;
/* Some sanity checking */
if (end <= dst || !size || end > c->tsize) {
@@ -489,7 +495,7 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src,
off = dst & c->min_erase_mask;
FL_DBG("LIBFLASH: reading page 0x%08x..0x%08x...",
page, page + er_size);
- rc = flash_read(c, page, c->smart_buf, er_size);
+ rc = flash_read(bl, page, c->smart_buf, er_size);
if (rc) {
FL_DBG(" error %d!\n", rc);
return rc;
@@ -510,7 +516,7 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src,
case sm_need_write:
/* Just needs writing over */
FL_DBG(" need write !\n");
- rc = flash_write(c, dst, src, chunk, true);
+ rc = flash_write(bl, dst, src, chunk, true);
if (rc) {
FL_DBG("LIBFLASH: Write error %d !\n", rc);
return rc;
@@ -518,14 +524,14 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src,
break;
case sm_need_erase:
FL_DBG(" need erase !\n");
- rc = flash_erase(c, page, er_size);
+ rc = flash_erase(bl, page, er_size);
if (rc) {
FL_DBG("LIBFLASH: erase error %d !\n", rc);
return rc;
}
/* Then update the portion of the buffer and write the block */
memcpy(c->smart_buf + off, src, chunk);
- rc = flash_write(c, page, c->smart_buf, er_size, true);
+ rc = flash_write(bl, page, c->smart_buf, er_size, true);
if (rc) {
FL_DBG("LIBFLASH: write error %d !\n", rc);
return rc;
@@ -539,14 +545,14 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src,
return 0;
}
-int flash_smart_write_corrected(struct flash_chip *c, uint32_t dst, const void *src,
+int flash_smart_write_corrected(struct blocklevel_device *bl, uint32_t dst, const void *src,
uint32_t size, bool ecc)
{
struct ecc64 *buf;
int rc;
if (!ecc)
- return flash_smart_write(c, dst, src, size);
+ return flash_smart_write(bl, dst, src, size);
buf = malloc(ECC_BUFFER_SIZE(size));
if (!buf)
@@ -558,7 +564,7 @@ int flash_smart_write_corrected(struct flash_chip *c, uint32_t dst, const void *
goto out;
}
- rc = flash_smart_write(c, dst, buf, ECC_BUFFER_SIZE(size));
+ rc = flash_smart_write(bl, dst, buf, ECC_BUFFER_SIZE(size));
out:
free(buf);
@@ -684,8 +690,9 @@ static int flash_set_4b(struct flash_chip *c, bool enable)
return ct->cmd_wr(ct, enable ? CMD_EN4B : CMD_EX4B, false, 0, NULL, 0);
}
-int flash_force_4b_mode(struct flash_chip *c, bool enable_4b)
+int flash_force_4b_mode(struct blocklevel_device *bl, bool enable_4b)
{
+ struct flash_chip *c = container_of(bl, struct flash_chip, bl);
struct spi_flash_ctrl *ct = c->ctrl;
int rc;
@@ -776,24 +783,29 @@ static int flash_configure(struct flash_chip *c)
return 0;
}
-int flash_get_info(struct flash_chip *chip, const char **name,
+static int flash_get_info(struct blocklevel_device *bl, const char **name,
uint32_t *total_size, uint32_t *erase_granule)
{
+ struct flash_chip *c = container_of(bl, struct flash_chip, bl);
if (name)
- *name = chip->info.name;
+ *name = c->info.name;
if (total_size)
- *total_size = chip->tsize;
+ *total_size = c->tsize;
if (erase_granule)
- *erase_granule = chip->min_erase_mask + 1;
+ *erase_granule = c->min_erase_mask + 1;
return 0;
}
-int flash_init(struct spi_flash_ctrl *ctrl, struct flash_chip **flash)
+int flash_init(struct spi_flash_ctrl *ctrl, struct blocklevel_device **bl)
{
struct flash_chip *c;
int rc;
- *flash = NULL;
+ if (!bl)
+ return FLASH_ERR_PARM_ERROR;
+
+ *bl = NULL;
+
c = malloc(sizeof(struct flash_chip));
if (!c)
return FLASH_ERR_MALLOC_FAILED;
@@ -814,18 +826,25 @@ int flash_init(struct spi_flash_ctrl *ctrl, struct flash_chip **flash)
rc = flash_configure(c);
if (rc)
FL_ERR("LIBFLASH: Flash configuration failed\n");
- bail:
+bail:
if (rc) {
free(c);
return rc;
}
- *flash = c;
+
+ c->bl.read = &flash_read;
+ c->bl.write = &flash_smart_write;
+ c->bl.erase = &flash_erase;
+ c->bl.get_info = &flash_get_info;
+
+ *bl = &(c->bl);
return 0;
}
-void flash_exit(struct flash_chip *chip)
+void flash_exit(struct blocklevel_device *bl)
{
/* XXX Make sure we are idle etc... */
- free(chip);
+ if (bl)
+ free(container_of(bl, struct flash_chip, bl));
}