aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/flash.c35
-rw-r--r--external/pflash/pflash.c31
-rw-r--r--external/pflash/rules.mk2
-rw-r--r--include/skiboot.h4
-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
-rw-r--r--platforms/astbmc/pnor.c12
-rw-r--r--platforms/rhesus/rhesus.c11
11 files changed, 153 insertions, 128 deletions
diff --git a/core/flash.c b/core/flash.c
index 601a9ab..7cd9153 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -22,12 +22,13 @@
#include <device.h>
#include <libflash/libflash.h>
#include <libflash/libffs.h>
+#include <libflash/blocklevel.h>
#include <ecc.h>
struct flash {
bool registered;
bool busy;
- struct flash_chip *chip;
+ struct blocklevel_device *bl;
uint32_t size;
uint32_t block_size;
};
@@ -108,7 +109,7 @@ static int flash_nvram_start_read(void *dst, uint32_t src, uint32_t len)
goto out;
}
- rc = flash_read(nvram_flash->chip, nvram_offset + src, dst, len);
+ rc = blocklevel_read(nvram_flash->bl, nvram_offset + src, dst, len);
out:
unlock(&flash_lock);
@@ -137,7 +138,7 @@ static int flash_nvram_write(uint32_t dst, void *src, uint32_t len)
rc = OPAL_PARAMETER;
goto out;
}
- rc = flash_smart_write(nvram_flash->chip, nvram_offset + dst, src, len);
+ rc = blocklevel_write(nvram_flash->bl, nvram_offset + dst, src, len);
out:
unlock(&flash_lock);
@@ -222,7 +223,7 @@ static void setup_system_flash(struct flash *flash, struct dt_node *node,
flash_nvram_probe(flash, ffs);
}
-int flash_register(struct flash_chip *chip, bool is_system_flash)
+int flash_register(struct blocklevel_device *bl, bool is_system_flash)
{
uint32_t size, block_size;
struct ffs_handle *ffs;
@@ -232,7 +233,7 @@ int flash_register(struct flash_chip *chip, bool is_system_flash)
unsigned int i;
int rc;
- rc = flash_get_info(chip, &name, &size, &block_size);
+ rc = blocklevel_get_info(bl, &name, &size, &block_size);
if (rc)
return rc;
@@ -248,7 +249,7 @@ int flash_register(struct flash_chip *chip, bool is_system_flash)
flash = &flashes[i];
flash->registered = true;
flash->busy = false;
- flash->chip = chip;
+ flash->bl = bl;
flash->size = size;
flash->block_size = block_size;
break;
@@ -260,7 +261,7 @@ int flash_register(struct flash_chip *chip, bool is_system_flash)
return OPAL_RESOURCE;
}
- rc = ffs_open_flash(chip, 0, flash->size, &ffs);
+ rc = ffs_init(0, flash->size, bl, &ffs);
if (rc) {
prlog(PR_WARNING, "FLASH: No ffs info; "
"using raw device only\n");
@@ -318,13 +319,17 @@ static int64_t opal_flash_op(enum flash_op op, uint64_t id, uint64_t offset,
switch (op) {
case FLASH_OP_READ:
- rc = flash_read(flash->chip, offset, (void *)buf, size);
+ rc = blocklevel_read(flash->bl, offset, (void *)buf, size);
break;
case FLASH_OP_WRITE:
- rc = flash_write(flash->chip, offset, (void *)buf, size, false);
+ /*
+ * Note: blocklevel_write() uses flash_smart_write(), this call used to
+ * be flash_write()
+ */
+ rc = blocklevel_write(flash->bl, offset, (void *)buf, size);
break;
case FLASH_OP_ERASE:
- rc = flash_erase(flash->chip, offset, size);
+ rc = blocklevel_erase(flash->bl, offset, size);
break;
default:
assert(0);
@@ -397,7 +402,7 @@ struct flash_hostboot_header {
};
/* start and total size include ECC */
-static int flash_find_subpartition(struct flash_chip *chip, uint32_t subid,
+static int flash_find_subpartition(struct blocklevel_device *bl, uint32_t subid,
uint32_t *start, uint32_t *total_size,
bool *ecc)
{
@@ -416,7 +421,7 @@ static int flash_find_subpartition(struct flash_chip *chip, uint32_t subid,
partsize = BUFFER_SIZE_MINUS_ECC(*total_size);
/* Get the TOC */
- rc = flash_read_corrected(chip, *start, header,
+ rc = flash_read_corrected(bl, *start, header,
FLASH_SUBPART_HEADER_SIZE, ecc);
if (rc) {
prerror("FLASH: flash subpartition TOC read failed %i\n", rc);
@@ -536,7 +541,7 @@ static int flash_load_resource(enum resource_id id, uint32_t subid,
goto out_unlock;
}
- rc = ffs_open_flash(flash->chip, 0, flash->size, &ffs);
+ rc = ffs_init(0, flash->size, flash->bl, &ffs);
if (rc) {
prerror("FLASH: Can't open ffs handle\n");
goto out_unlock;
@@ -563,7 +568,7 @@ static int flash_load_resource(enum resource_id id, uint32_t subid,
/* Find the sub partition if required */
if (subid != RESOURCE_SUBID_NONE) {
- rc = flash_find_subpartition(flash->chip, subid, &part_start,
+ rc = flash_find_subpartition(flash->bl, subid, &part_start,
&part_size, &ecc);
if (rc)
goto out_free_ffs;
@@ -586,7 +591,7 @@ static int flash_load_resource(enum resource_id id, uint32_t subid,
goto out_free_ffs;
}
- rc = flash_read_corrected(flash->chip, part_start, buf, size, ecc);
+ rc = flash_read_corrected(flash->bl, part_start, buf, size, ecc);
if (rc) {
prerror("FLASH: failed to read %s partition\n", name);
goto out_free_ffs;
diff --git a/external/pflash/pflash.c b/external/pflash/pflash.c
index 0722bc6..9244570 100644
--- a/external/pflash/pflash.c
+++ b/external/pflash/pflash.c
@@ -16,6 +16,7 @@
#include <libflash/libflash.h>
#include <libflash/libffs.h>
+#include <libflash/blocklevel.h>
#include "progress.h"
#include "io.h"
#include "ast.h"
@@ -39,8 +40,8 @@ static bool using_sfc;
#define FILE_BUF_SIZE 0x10000
static uint8_t file_buf[FILE_BUF_SIZE] __aligned(0x1000);
+static struct blocklevel_device *bl;
static struct spi_flash_ctrl *fl_ctrl;
-static struct flash_chip *fl_chip;
static struct ffs_handle *ffsh;
static uint32_t fl_total_size, fl_erase_granule;
static const char *fl_name;
@@ -79,7 +80,7 @@ static void print_ffs_info(uint32_t toc_offset)
int rc;
uint32_t i;
- rc = ffs_open_flash(fl_chip, toc_offset, 0, &ffs_handle);
+ rc = ffs_init(toc_offset, fl_total_size, bl, &ffs_handle);
if (rc) {
fprintf(stderr, "Error %d opening ffs !\n", rc);
return;
@@ -139,7 +140,7 @@ static int open_partition(const char *name)
/* Open libffs if needed */
if (!ffsh) {
- rc = ffs_open_flash(fl_chip, ffs_toc, 0, &ffsh);
+ rc = ffs_init(ffs_toc, fl_total_size, bl, &ffsh);
if (rc) {
fprintf(stderr, "Error %d opening ffs !\n", rc);
if (ffs_toc)
@@ -210,7 +211,7 @@ static void erase_chip(void)
return;
}
- rc = flash_erase_chip(fl_chip);
+ rc = flash_erase_chip(bl);
if (rc) {
fprintf(stderr, "Error %d erasing chip\n", rc);
exit(1);
@@ -237,7 +238,7 @@ static void erase_range(uint32_t start, uint32_t size, bool will_program)
while(size) {
/* If aligned to 64k and at least 64k, use 64k erase */
if ((start & 0xffff) == 0 && size >= 0x10000) {
- rc = flash_erase(fl_chip, start, 0x10000);
+ rc = blocklevel_erase(bl, start, 0x10000);
if (rc) {
fprintf(stderr, "Error %d erasing 0x%08x\n",
rc, start);
@@ -247,7 +248,7 @@ static void erase_range(uint32_t start, uint32_t size, bool will_program)
size -= 0x10000;
done += 0x10000;
} else {
- rc = flash_erase(fl_chip, start, 0x1000);
+ rc = blocklevel_erase(bl, start, 0x1000);
if (rc) {
fprintf(stderr, "Error %d erasing 0x%08x\n",
rc, start);
@@ -304,7 +305,7 @@ static void program_file(const char *file, uint32_t start, uint32_t size)
len = size;
size -= len;
actual_size += len;
- rc = flash_write(fl_chip, start, file_buf, len, true);
+ rc = blocklevel_write(bl, start, file_buf, len);
if (rc) {
if (rc == FLASH_ERR_VERIFY_FAILURE)
fprintf(stderr, "Verification failed for"
@@ -344,7 +345,7 @@ static void do_read_file(const char *file, uint32_t start, uint32_t size)
progress_init(size >> 8);
while(size) {
len = size > FILE_BUF_SIZE ? FILE_BUF_SIZE : size;
- rc = flash_read(fl_chip, start, file_buf, len);
+ rc = blocklevel_read(bl, start, file_buf, len);
if (rc) {
fprintf(stderr, "Flash read error %d for"
" chunk at 0x%08x\n", rc, start);
@@ -370,7 +371,7 @@ static void enable_4B_addresses(void)
printf("Switching to 4-bytes address mode\n");
- rc = flash_force_4b_mode(fl_chip, true);
+ rc = flash_force_4b_mode(bl, true);
if (rc) {
fprintf(stderr, "Error %d enabling 4b mode\n", rc);
exit(1);
@@ -383,7 +384,7 @@ static void disable_4B_addresses(void)
printf("Switching to 3-bytes address mode\n");
- rc = flash_force_4b_mode(fl_chip, false);
+ rc = flash_force_4b_mode(bl, false);
if (rc) {
fprintf(stderr, "Error %d disabling 4b mode\n", rc);
exit(1);
@@ -394,7 +395,7 @@ static void flash_access_cleanup_bmc(void)
{
if (ffsh)
ffs_close(ffsh);
- flash_exit(fl_chip);
+ flash_exit(bl);
ast_sf_close(fl_ctrl);
close_devs();
}
@@ -414,7 +415,7 @@ static void flash_access_setup_bmc(bool use_lpc, bool need_write)
}
/* Open flash chip */
- rc = flash_init(fl_ctrl, &fl_chip);
+ rc = flash_init(fl_ctrl, &bl);
if (rc) {
fprintf(stderr, "Failed to open flash chip\n");
exit(1);
@@ -432,7 +433,7 @@ static void flash_access_cleanup_pnor(void)
if (ffsh)
ffs_close(ffsh);
- flash_exit(fl_chip);
+ flash_exit(bl);
#ifdef __powerpc__
if (using_sfc)
sfc_close(fl_ctrl);
@@ -473,7 +474,7 @@ static void flash_access_setup_pnor(bool use_lpc, bool use_sfc, bool need_write)
#endif
/* Open flash chip */
- rc = flash_init(fl_ctrl, &fl_chip);
+ rc = flash_init(fl_ctrl, &bl);
if (rc) {
fprintf(stderr, "Failed to open flash chip\n");
exit(1);
@@ -776,7 +777,7 @@ int main(int argc, char *argv[])
flash_access_setup_pnor(use_lpc, has_sfc, erase || program);
}
- rc = flash_get_info(fl_chip, &fl_name,
+ rc = blocklevel_get_info(bl, &fl_name,
&fl_total_size, &fl_erase_granule);
if (rc) {
fprintf(stderr, "Error %d getting flash info\n", rc);
diff --git a/external/pflash/rules.mk b/external/pflash/rules.mk
index 0c396a2..f59e2ee 100644
--- a/external/pflash/rules.mk
+++ b/external/pflash/rules.mk
@@ -15,7 +15,7 @@ endif
CFLAGS = -O2 -Wall -I.
LDFLAGS = -lrt
OBJS = pflash.o progress.o ast-sf-ctrl.o version.o
-OBJS += libflash/libflash.o libflash/libffs.o libflash/ecc.o
+OBJS += libflash/libflash.o libflash/libffs.o libflash/ecc.o libflash/blocklevel.o
OBJS += $(ARCH_OBJS)
EXE = pflash
diff --git a/include/skiboot.h b/include/skiboot.h
index 5aa0c85..790f3db 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -36,6 +36,8 @@
#include <ccan/endian/endian.h>
#include <ccan/str/str.h>
+#include <libflash/blocklevel.h>
+
#include <mem-map.h>
#include <op-panel.h>
#include <platform.h>
@@ -217,7 +219,7 @@ extern void occ_fsp_init(void);
/* flash support */
struct flash_chip;
-extern int flash_register(struct flash_chip *chip, bool is_system_flash);
+extern int flash_register(struct blocklevel_device *bl, bool is_system_flash);
extern int flash_start_preload_resource(enum resource_id id, uint32_t subid,
void *buf, size_t *len);
extern int flash_resource_loaded(enum resource_id id, uint32_t idx);
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;
}
diff --git a/platforms/astbmc/pnor.c b/platforms/astbmc/pnor.c
index d294c1f..634cb86 100644
--- a/platforms/astbmc/pnor.c
+++ b/platforms/astbmc/pnor.c
@@ -20,6 +20,7 @@
#include <opal.h>
#include <libflash/libflash.h>
#include <libflash/libffs.h>
+#include <libflash/blocklevel.h>
#include <ast.h>
#include "astbmc.h"
@@ -27,7 +28,7 @@
int pnor_init(void)
{
struct spi_flash_ctrl *pnor_ctrl;
- struct flash_chip *pnor_chip = NULL;
+ struct blocklevel_device *bl;
int rc;
/* Open controller and flash. If the LPC->AHB doesn't point to
@@ -44,19 +45,20 @@ int pnor_init(void)
prerror("PLAT: Failed to open PNOR flash controller\n");
goto fail;
}
- rc = flash_init(pnor_ctrl, &pnor_chip);
+
+ rc = flash_init(pnor_ctrl, &bl);
if (rc) {
prerror("PLAT: Failed to open init PNOR driver\n");
goto fail;
}
- rc = flash_register(pnor_chip, true);
+ rc = flash_register(bl, true);
if (!rc)
return 0;
fail:
- if (pnor_chip)
- flash_exit(pnor_chip);
+ if (bl)
+ flash_exit(bl);
if (pnor_ctrl)
ast_sf_close(pnor_ctrl);
diff --git a/platforms/rhesus/rhesus.c b/platforms/rhesus/rhesus.c
index 27e1c91..855d0e4 100644
--- a/platforms/rhesus/rhesus.c
+++ b/platforms/rhesus/rhesus.c
@@ -22,6 +22,7 @@
#include <opal.h>
#include <libflash/libflash.h>
#include <libflash/libffs.h>
+#include <libflash/blocklevel.h>
#include <sfc-ctrl.h>
#include <ec/config.h>
#include <ec/gpio.h>
@@ -118,7 +119,7 @@ static int64_t rhesus_power_down(uint64_t request __unused)
static int rhesus_pnor_init(void)
{
struct spi_flash_ctrl *pnor_ctrl;
- struct flash_chip *pnor_chip = NULL;
+ struct blocklevel_device *bl;
int rc;
/* Open controller, flash and ffs */
@@ -127,19 +128,19 @@ static int rhesus_pnor_init(void)
prerror("PLAT: Failed to open PNOR flash controller\n");
goto fail;
}
- rc = flash_init(pnor_ctrl, &pnor_chip);
+ rc = flash_init(pnor_ctrl, &bl);
if (rc) {
prerror("PLAT: Failed to open init PNOR driver\n");
goto fail;
}
- rc = flash_register(pnor_chip, true);
+ rc = flash_register(bl, true);
if (!rc)
return 0;
fail:
- if (pnor_chip)
- flash_exit(pnor_chip);
+ if (bl)
+ flash_exit(bl);
if (pnor_ctrl)
sfc_close(pnor_ctrl);