aboutsummaryrefslogtreecommitdiff
path: root/libflash
diff options
context:
space:
mode:
authorCyril Bur <cyril.bur@au1.ibm.com>2015-06-02 10:51:02 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-06-09 16:37:33 +1000
commit39d9e14cdeef9a20e3da05d527b136de65e39904 (patch)
tree13246271b2b9fba1dbfc0a6729ca84223668e6cf /libflash
parent1fd9d5afc6aff3870695110c74a4a9daa88e5c81 (diff)
downloadskiboot-39d9e14cdeef9a20e3da05d527b136de65e39904.zip
skiboot-39d9e14cdeef9a20e3da05d527b136de65e39904.tar.gz
skiboot-39d9e14cdeef9a20e3da05d527b136de65e39904.tar.bz2
libflash: start using the blocklevel interface.
Converted all the libflash calls to use the blocklevel interface, modified all callers to libflash to use the blocklevel interface. This patch should introduce next to no functional change. Signed-off-by: Cyril Bur <cyril.bur@au1.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'libflash')
-rw-r--r--libflash/libffs.c51
-rw-r--r--libflash/libffs.h7
-rw-r--r--libflash/libflash.c83
-rw-r--r--libflash/libflash.h25
-rw-r--r--libflash/test/test-flash.c20
5 files changed, 100 insertions, 86 deletions
diff --git a/libflash/libffs.c b/libflash/libffs.c
index 55e6895..c03c56a 100644
--- a/libflash/libffs.c
+++ b/libflash/libffs.c
@@ -41,6 +41,7 @@ struct ffs_handle {
uint32_t max_size;
void *cache;
uint32_t cached_size;
+ struct blocklevel_device *bl;
};
static uint32_t ffs_checksum(void* data, size_t size)
@@ -71,31 +72,31 @@ static int ffs_check_convert_header(struct ffs_hdr *dst, struct ffs_hdr *src)
return 0;
}
-int ffs_open_flash(struct flash_chip *chip, uint32_t toc_offset,
- uint32_t max_size, struct ffs_handle **ffs)
+int ffs_init(uint32_t offset, uint32_t max_size, struct blocklevel_device *bl,
+ struct ffs_handle **ffs)
{
struct ffs_hdr hdr;
struct ffs_handle *f;
- uint32_t fl_size, erase_size;
+ uint32_t total_size;
int rc;
- if (!ffs)
+ if (!ffs || !bl)
return FLASH_ERR_PARM_ERROR;
*ffs = NULL;
- /* Grab some info about our flash chip */
- rc = flash_get_info(chip, NULL, &fl_size, &erase_size);
+ rc = blocklevel_get_info(bl, NULL, &total_size, NULL);
if (rc) {
FL_ERR("FFS: Error %d retrieving flash info\n", rc);
return rc;
}
- if ((toc_offset + max_size) < toc_offset)
+ if ((offset + max_size) < offset)
return FLASH_ERR_PARM_ERROR;
- if ((toc_offset + max_size) > fl_size)
+
+ if ((max_size > total_size))
return FLASH_ERR_PARM_ERROR;
/* Read flash header */
- rc = flash_read(chip, toc_offset, &hdr, sizeof(hdr));
+ rc = blocklevel_read(bl, offset, &hdr, sizeof(hdr));
if (rc) {
FL_ERR("FFS: Error %d reading flash header\n", rc);
return rc;
@@ -106,17 +107,16 @@ int ffs_open_flash(struct flash_chip *chip, uint32_t toc_offset,
if (!f)
return FLASH_ERR_MALLOC_FAILED;
memset(f, 0, sizeof(*f));
- f->type = ffs_type_flash;
- f->toc_offset = toc_offset;
- f->max_size = max_size ? max_size : (fl_size - toc_offset);
- f->chip = chip;
+
+ f->toc_offset = offset;
+ f->max_size = max_size;
+ f->bl = bl;
/* Convert and check flash header */
rc = ffs_check_convert_header(&f->hdr, &hdr);
if (rc) {
FL_ERR("FFS: Error %d checking flash header\n", rc);
- free(f);
- return rc;
+ goto out;
}
/*
@@ -126,26 +126,26 @@ int ffs_open_flash(struct flash_chip *chip, uint32_t toc_offset,
f->cached_size = f->hdr.block_size * f->hdr.size;
FL_DBG("FFS: Partition map size: 0x%x\n", f->cached_size);
- /* Align to erase size */
- f->cached_size |= (erase_size - 1);
- f->cached_size &= ~(erase_size - 1);
- FL_DBG("FFS: Aligned to: 0x%x\n", f->cached_size);
-
/* Allocate cache */
f->cache = malloc(f->cached_size);
if (!f->cache) {
- free(f);
- return FLASH_ERR_MALLOC_FAILED;
+ rc = FLASH_ERR_MALLOC_FAILED;
+ goto out;
}
/* Read the cached map */
- rc = flash_read(chip, toc_offset, f->cache, f->cached_size);
+ rc = blocklevel_read(bl, offset, f->cache, f->cached_size);
if (rc) {
FL_ERR("FFS: Error %d reading flash partition map\n", rc);
- free(f);
+ goto out;
}
+
+out:
if (rc == 0)
*ffs = f;
+ else
+ free(f);
+
return rc;
}
@@ -361,6 +361,7 @@ int ffs_update_act_size(struct ffs_handle *ffs, uint32_t part_idx,
ent->checksum = ffs_checksum(ent, FFS_ENTRY_SIZE_CSUM);
if (!ffs->chip)
return 0;
- return flash_smart_write(ffs->chip, offset, ent, FFS_ENTRY_SIZE);
+
+ return blocklevel_write(ffs->bl, offset, ent, FFS_ENTRY_SIZE);
}
diff --git a/libflash/libffs.h b/libflash/libffs.h
index faaa4bc..a0040e9 100644
--- a/libflash/libffs.h
+++ b/libflash/libffs.h
@@ -18,6 +18,7 @@
#include <libflash/libflash.h>
#include <libflash/ffs.h>
+#include <libflash/blocklevel.h>
/* FFS handle, opaque */
struct ffs_handle;
@@ -34,8 +35,10 @@ struct ffs_handle;
#define FFS_ERR_PART_NOT_FOUND 103
#define FFS_ERR_BAD_ECC 104
-int ffs_open_flash(struct flash_chip *chip, uint32_t toc_offset,
- uint32_t max_size, struct ffs_handle **ffs);
+/* Init */
+
+int ffs_init(uint32_t offset, uint32_t max_size,
+ struct blocklevel_device *bl, struct ffs_handle **ffs);
/* ffs_open_image is Linux only as it uses lseek, which skiboot does not
* implement */
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));
}
diff --git a/libflash/libflash.h b/libflash/libflash.h
index 7ed65d0..30f984d 100644
--- a/libflash/libflash.h
+++ b/libflash/libflash.h
@@ -18,6 +18,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include <libflash/blocklevel.h>
#ifdef __SKIBOOT__
#include <skiboot.h>
@@ -59,18 +60,13 @@ extern bool libflash_debug;
struct flash_chip;
struct spi_flash_ctrl;
-int flash_init(struct spi_flash_ctrl *ctrl, struct flash_chip **flash);
-void flash_exit(struct flash_chip *chip);
-
-int flash_get_info(struct flash_chip *chip, const char **name,
- uint32_t *total_size, uint32_t *erase_granule);
+int flash_init(struct spi_flash_ctrl *ctrl, struct blocklevel_device **bl);
+void flash_exit(struct blocklevel_device *bl);
/* libflash sets the 4b mode automatically based on the flash
* size and controller capabilities but it can be overriden
*/
-int flash_force_4b_mode(struct flash_chip *chip, bool enable_4b);
-
-int flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len);
+int flash_force_4b_mode(struct blocklevel_device *bl, bool enable_4b);
/*
* This provides a wapper around flash_read() on ECCed data. All params are
@@ -80,11 +76,8 @@ int flash_read(struct flash_chip *c, uint32_t pos, void *buf, uint32_t len);
* len is length of data without ecc attached therefore this will read beyond
* pos + len.
*/
-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);
-int flash_erase(struct flash_chip *c, uint32_t dst, uint32_t size);
-int flash_write(struct flash_chip *c, uint32_t dst, const void *src,
- uint32_t size, bool verify);
/*
* This provides a wrapper around flash_write() on ECCed data. All params are
@@ -94,10 +87,8 @@ int flash_write(struct flash_chip *c, uint32_t dst, const void *src,
* size is length of data without ECC attached therefore this will write beyond
* dst + size.
*/
-int flash_write_corrected(struct flash_chip *c, uint32_t dst, const void *src,
+int flash_write_corrected(struct blocklevel_device *bl, uint32_t dst, const void *src,
uint32_t size, bool verify, bool ecc);
-int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src,
- uint32_t size);
/*
* This provides a wrapper around flash_smart_write() on ECCed data. All
@@ -107,12 +98,12 @@ int flash_smart_write(struct flash_chip *c, uint32_t dst, const void *src,
* size is length of data without ECC attached therefore this will write beyond
* dst + size.
*/
-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);
/* chip erase may not be supported by all chips/controllers, get ready
* for FLASH_ERR_CHIP_ER_NOT_SUPPORTED
*/
-int flash_erase_chip(struct flash_chip *c);
+int flash_erase_chip(struct blocklevel_device *bl);
#endif /* __LIBFLASH_H */
diff --git a/libflash/test/test-flash.c b/libflash/test/test-flash.c
index 4479b5a..cf2b3a5 100644
--- a/libflash/test/test-flash.c
+++ b/libflash/test/test-flash.c
@@ -366,7 +366,7 @@ struct spi_flash_ctrl sim_ctrl = {
int main(void)
{
- struct flash_chip *fl;
+ struct blocklevel_device *bl;
uint32_t total_size, erase_granule;
const char *name;
uint16_t *test;
@@ -378,12 +378,12 @@ int main(void)
memset(sim_image, 0xff, sim_image_sz);
test = malloc(0x10000 * 2);
- rc = flash_init(&sim_ctrl, &fl);
+ rc = flash_init(&sim_ctrl, &bl);
if (rc) {
ERR("flash_init failed with err %d\n", rc);
exit(1);
}
- rc = flash_get_info(fl, &name, &total_size, &erase_granule);
+ rc = flash_get_info(bl, &name, &total_size, &erase_granule);
if (rc) {
ERR("flash_get_info failed with err %d\n", rc);
exit(1);
@@ -395,13 +395,13 @@ int main(void)
/* Write 64k of stuff at 0 and at 128k */
printf("Writing test patterns...\n");
- flash_smart_write(fl, 0, test, 0x10000);
- flash_smart_write(fl, 0x20000, test, 0x10000);
+ flash_smart_write(bl, 0, test, 0x10000);
+ flash_smart_write(bl, 0x20000, test, 0x10000);
/* Write "Hello world" straddling the 64k boundary */
#define HW "Hello World"
printf("Writing test string...\n");
- flash_smart_write(fl, 0xfffc, HW, sizeof(HW));
+ flash_smart_write(bl, 0xfffc, HW, sizeof(HW));
/* Check result */
if (memcmp(sim_image + 0xfffc, HW, sizeof(HW))) {
@@ -416,7 +416,7 @@ int main(void)
printf("Test pattern pass\n");
printf("Test ECC interfaces\n");
- flash_smart_write_corrected(fl, 0, test, 0x10000, 1);
+ flash_smart_write_corrected(bl, 0, test, 0x10000, 1);
ecc_test = (struct ecc64 *)sim_image;
test64 = (uint64_t *)test;
for (i = 0; i < 0x10000 / sizeof(*ecc_test); i++) {
@@ -433,7 +433,7 @@ int main(void)
printf("Test ECC interface pass\n");
printf("Test ECC erase\n");
- if (flash_erase(fl, 0, 0x10000) != 0) {
+ if (flash_erase(bl, 0, 0x10000) != 0) {
ERR("flash_erase didn't return 0\n");
exit(1);
}
@@ -444,7 +444,7 @@ int main(void)
ERR("Data not properly cleared at %d\n", i);
exit(1);
}
- rc = flash_write(fl, i * sizeof(*ecc_test) + 8, &zero, 1, 0);
+ rc = flash_write(bl, i * sizeof(*ecc_test) + 8, &zero, 1, 0);
if (rc || ecc_test[i].ecc != 0) {
ERR("Cleared data not correctly ECCed: 0x%02x (0x%016lx) expecting 0 at %d\n", ecc_test[i].ecc, ecc_test[i].data, i);
exit(1);
@@ -452,7 +452,7 @@ int main(void)
}
printf("Test ECC erase pass\n");
- flash_exit(fl);
+ flash_exit(bl);
return 0;
}