[Skiboot] [PATCH 2/2] libflash: start using the blocklevel interface.

Cyril Bur cyril.bur at au1.ibm.com
Thu May 21 17:49:34 AEST 2015


On Thu, 2015-05-21 at 17:31 +1000, Cyril Bur wrote:
> On Thu, 2015-05-21 at 11:53 +1000, Alistair Popple wrote:
> > This looks ok, my only concern is that changing flash_write -> 
> > flash_smart_write in pflash is likely to reduce pflash performance. Is there a 
> > way we could not make that change in pflash for the moment? I have an idea for 
> > how we could fix it properly, but that change would be easier to do if we had 
> > these patches applied.
> > 
> 
> Agreed, however this all depends on if it is actually slower. I'll
> confirm that tomorrow, if it is, we'll leave flash_write() exposed for
> pflash.
> 

So, to my surprise (top one is new pflash):

# time /tmp/pflash -E -p /tmp/palmetto.pnor 
About to erase chip !
WARNING ! This will modify your HOST flash chip content !
Enter "yes" to confirm:yes
Erasing... (may take a while !) done !
About to program "/tmp/palmetto.pnor" at 0x00000000..0x02000000 !
Programming & Verifying...
[==================================================] 100% ETA:0s     
real	3m 1.11s
user	2m 54.24s
sys	0m 0.82s

# time pflash -E -p /tmp/palmetto.pnor      
About to erase chip !
WARNING ! This will modify your HOST flash chip content !
Enter "yes" to confirm:yes
Erasing... (may take a while !) done !
About to program "/tmp/palmetto.pnor" at 0x00000000..0x02000000 !
Programming & Verifying...
[==================================================] 100% ETA:0s     
real	2m 59.80s
user	2m 50.82s
sys	0m 0.93s


Makes 'no' difference.

> The solution from there would be to make flash_smart_write() smarter and
> ultimately wind up in blocklevel.
> 
> > Signed-off-by: Alistair Popple <alistair at popple.id.au>
> > Reviewed-by: Alistair Popple <alistair at popple.id.au>
> > 
> > On Thu, 14 May 2015 17:06:39 Cyril Bur wrote:
> > > 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 at au1.ibm.com>
> > > ---
> > >  core/flash.c               | 35 ++++++++++---------
> > >  external/pflash/Makefile   |  2 +-
> > >  external/pflash/pflash.c   | 33 +++++++++---------
> > >  include/skiboot.h          |  4 ++-
> > >  libflash/libffs.c          | 52 ++++++++++++++---------------
> > >  libflash/libffs.h          |  7 ++--
> > >  libflash/libflash.c        | 83
> > > ++++++++++++++++++++++++++++------------------ libflash/libflash.h        |
> > > 25 +++++---------
> > >  libflash/test/test-flash.c | 20 +++++------
> > >  platforms/astbmc/pnor.c    | 12 ++++---
> > >  platforms/rhesus/rhesus.c  | 11 +++---
> > >  11 files changed, 153 insertions(+), 131 deletions(-)
> > > 
> > > diff --git a/core/flash.c b/core/flash.c
> > > index 9018ecd..90dbac7 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);
> > > @@ -250,7 +251,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;
> > > @@ -260,7 +261,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;
> > > 
> > > @@ -276,7 +277,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;
> > > @@ -288,7 +289,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");
> > > @@ -346,13 +347,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);
> > > @@ -425,7 +430,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)
> > >  {
> > > @@ -444,7 +449,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);
> > > @@ -564,7 +569,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;
> > > @@ -591,7 +596,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;
> > > @@ -614,7 +619,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/Makefile b/external/pflash/Makefile
> > > index c28e359..7771343 100644
> > > --- a/external/pflash/Makefile
> > > +++ b/external/pflash/Makefile
> > > @@ -14,7 +14,7 @@ endif
> > >  CFLAGS  = -O2 -Wall -I.
> > >  LDFLAGS	= -lrt
> > >  OBJS    = pflash.o progress.o ast-sf-ctrl.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/external/pflash/pflash.c b/external/pflash/pflash.c
> > > index fb783a2..0958691 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"
> > > @@ -23,7 +24,7 @@
> > > 
> > >  #define __aligned(x)			__attribute__((aligned(x)))
> > > 
> > > -#define PFLASH_VERSION	"0.8.6"
> > > +#define PFLASH_VERSION	"0.8.7"
> > > 
> > >  static bool must_confirm = true;
> > >  static bool dummy_run;
> > > @@ -36,8 +37,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;
> > > @@ -84,7 +85,7 @@ static void print_flash_info(void)
> > >  		return;
> > > 
> > >  	if (!ffsh) {
> > > -		rc = ffs_open_flash(fl_chip, 0, 0, &ffsh);
> > > +		rc = ffs_init(0, fl_total_size, bl, &ffsh);
> > >  		if (rc) {
> > >  			fprintf(stderr, "Error %d opening ffs !\n", rc);
> > >  			ffsh = NULL;
> > > @@ -122,7 +123,7 @@ static void lookup_partition(const char *name)
> > > 
> > >  	/* Open libffs if needed */
> > >  	if (!ffsh) {
> > > -		rc = ffs_open_flash(fl_chip, 0, 0, &ffsh);
> > > +		rc = ffs_init(0, fl_total_size, bl, &ffsh);
> > >  		if (rc) {
> > >  			fprintf(stderr, "Error %d opening ffs !\n", rc);
> > >  			exit(1);
> > > @@ -158,7 +159,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);
> > > @@ -185,7 +186,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);
> > > @@ -195,7 +196,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);
> > > @@ -252,7 +253,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"
> > > @@ -292,7 +293,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);
> > > @@ -318,7 +319,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);
> > > @@ -331,7 +332,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);
> > > @@ -342,7 +343,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();
> > >  }
> > > @@ -362,7 +363,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);
> > > @@ -380,7 +381,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);
> > > @@ -421,7 +422,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);
> > > @@ -698,7 +699,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/include/skiboot.h b/include/skiboot.h
> > > index 9751a31..aa92f68 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>
> > > @@ -214,7 +216,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 2d05cc9..8a60bee 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,29 @@ 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 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 ((offset + max_size) < offset)
> > > +		FL_ERR("FFS: Error %d getting device total size", rc);
> > >  		return FLASH_ERR_PARM_ERROR;
> > > -	if ((offset + max_size) > fl_size)
> > > +	}
> > > +
> > > +	if ((offset + max_size) < offset || (offset + max_size) > total_size)
> > >  		return FLASH_ERR_PARM_ERROR;
> > > 
> > >  	/* Read flash header */
> > > -	rc = flash_read(chip, 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 +105,15 @@ int ffs_open_flash(struct flash_chip *chip, uint32_t
> > > offset, if (!f)
> > >  		return FLASH_ERR_MALLOC_FAILED;
> > >  	memset(f, 0, sizeof(*f));
> > > -	f->type = ffs_type_flash;
> > >  	f->flash_offset = offset;
> > > -	f->max_size = max_size ? max_size : (fl_size - offset);
> > > -	f->chip = chip;
> > > +	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 +123,26 @@ int ffs_open_flash(struct flash_chip *chip, uint32_t
> > > 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, 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 +358,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 dd58d28..a310172 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 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);
> > 
> 




More information about the Skiboot mailing list