No subject
Thu Oct 11 07:38:59 CEST 2012
are able to access
only up to 16MB--> means 0 to 0x FFFFFF
If the flash has 32MB, if the user is giving an offset 0x1000000 it will ag=
ain pointing to 0x0.
Because we have 3-byte addressing able to access only first 16MB of flash b=
ut the actual flash size is 32MB.
So, from my implementation if user is giving an offset of 0x1000000 then we=
have enable the bank register
for pointing to second 16MB area on 32 MB flash and we must subtract the of=
fset from 16MB as we are using 3-byte
addressing. Means we are accessing 4-byte addressing in 3-byte address mode=
. Ie is the reason I am subtracting it from16MB.
Please comment and let me know if you're not clear.
>
> > + } else {
> > + ret =3D spi_flash_extaddr_access(flash,
> STATUS_EXTADDR_DISABLE);
> > + if (ret) {
> > + debug("SF: fail to %s ext addr bit\n",
> > + STATUS_EXTADDR_DISABLE ? "set" : "reset");
> > + return ret;
> > + }
> > + }
> > +
> > + return ret;
> > +}
> > +
> > static int spi_flash_read_write(struct spi_slave *spi,
> > const u8 *cmd, size_t cmd_len,
> > const u8 *data_out, u8 *data_in, @@ -73,6
> +97,14 @@ int
> > spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
> > int ret;
> > u8 cmd[4];
> >
> > + if (flash->size > 0x1000000) {
>
> As already said in my comments to patch 1/4, this check (and the check fo=
r
> manufacturer ID) should be done only once once during probing of the flas=
h.
> Then, if necessary, adapted functions for read, write and erase should be=
> assigned to the function-pointers.
> Or use an additional function-pointer, which can be set to this or a simi=
lar
> function.
> Then the call of this function should be included in the loops, which all=
these
> functions have.
> Otherwise, as with your current code, you have a problem if the current
> accessed block crosses the boundary at 16M. Have you ever tried this?
Means this check should be in probe call, by adding one member in spi_flash=
structure, is it?.
I am not understanding extra function pointers concept, will you please exp=
lain.
>
> > + ret =3D spi_flash_check_extaddr_access(flash, &offset);
> > + if (ret) {
> > + debug("SF: fail to acess ext_addr\n");
> > + return ret;
> > + }
> > + }
> > +
> > page_size =3D flash->page_size;
> > page_addr =3D offset / page_size;
> > byte_addr =3D offset % page_size;
> > @@ -139,6 +171,15 @@ int spi_flash_cmd_read_fast(struct spi_flash
> *flash, u32 offset,
> > size_t len, void *data)
> > {
> > u8 cmd[5];
> > + int ret;
> > +
> > + if (flash->size > 0x1000000) {
> > + ret =3D spi_flash_check_extaddr_access(flash, &offset);
> > + if (ret) {
> > + debug("SF: fail to acess ext_addr\n");
> > + return ret;
> > + }
> > + }
> >
> > cmd[0] =3D CMD_READ_ARRAY_FAST;
> > spi_flash_addr(offset, cmd);
> > @@ -196,6 +237,14 @@ int spi_flash_cmd_erase(struct spi_flash *flash,
> u32 offset, size_t len)
> > int ret;
> > u8 cmd[4];
> >
> > + if (flash->size > 0x1000000) {
> > + ret =3D spi_flash_check_extaddr_access(flash, &offset);
> > + if (ret) {
> > + debug("SF: fail to acess ext_addr\n");
> > + return ret;
> > + }
> > + }
> > +
> > erase_size =3D flash->sector_size;
> > if (offset % erase_size || len % erase_size) {
> > debug("SF: Erase offset/length not multiple of erase size\n=
");
> @@
> > -333,6 +382,38 @@ int spi_flash_cmd_extaddr_read(struct spi_flash *flas=
h,
> void *data)
> > return spi_flash_read_common(flash, &cmd, 1, data, 1);
> > }
> >
> > +int spi_flash_extaddr_access(struct spi_flash *flash, u8 status) {
> > + int ret, pass;
> > + u8 data =3D 0, write_done =3D 0;
> > +
> > + for (pass =3D 0; pass < 2; pass++) {
> Why this is required??
>
> > + ret =3D spi_flash_cmd_extaddr_read(flash, (void *)&data);
> > + if (ret < 0) {
> > + debug("SF: fail to read ext addr register\n");
> > + return ret;
> > + }
> > +
> > + if ((data !=3D status) & !write_done) {
> > + debug("SF: need to %s ext addr bit\n",
> > + status ? "set" : "reset");
> > +
> > + write_done =3D 1;
> > + ret =3D spi_flash_cmd_extaddr_write(flash, status);=
> > + if (ret < 0) {
> > + debug("SF: fail to write ext addr bit\n");
> > + return ret;
> > + }
> > + } else {
> > + debug("SF: ext addr bit is %s.\n",
> > + status ? "set" : "reset");
> Instead of reading and writing this register each time (which will happen=
> often, if this function is called in the loops as suggested above), plea=
se
> cache the actual value inside struct spi_flash.
> Initial read should be done during probing and then writing only if the v=
alue
> needs to change.
> This is something depending on this design rule:
> http://www.denx.de/wiki/U-Boot/DesignPrinciples#2_Keep_it_Fast
But reading is also required a/f writing, whether the particular write is h=
appened properly or not?
The reason for 2 times loop is for code reduction.
The actual flow is first need to read the value and then write and finally =
read back whether the written
value is fine or not. So this entire flow requires 2 reads and 1 write.
I am adding loop for reduce the extra read code.
Any suggestions.
Thanks,
Jagan.
>
>
> > + return ret;
> > + }
> > + }
> > +
> > + return -1;
> > +}
> > +
> > /*
> > * The following table holds all device probe functions
> > *
> > diff --git a/drivers/mtd/spi/spi_flash_internal.h
> > b/drivers/mtd/spi/spi_flash_internal.h
> > index 65960ad..a6b04d7 100644
> > --- a/drivers/mtd/spi/spi_flash_internal.h
> > +++ b/drivers/mtd/spi/spi_flash_internal.h
> > @@ -34,6 +34,8 @@
> >
> > /* Common status */
> > #define STATUS_WIP 0x01
> > +#define STATUS_EXTADDR_ENABLE 0x01
> > +#define STATUS_EXTADDR_DISABLE 0x00
> As said above, don't restrict to a single bit!
>
> >
> > /* Send a single-byte command to the device and read the response */
> > int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response,
> > size_t len); @@ -86,6 +88,12 @@ int spi_flash_cmd_extaddr_write(struct
> > spi_flash *flash, u8 ear);
> >
> > /* Read the extended address register */
> > int spi_flash_cmd_extaddr_read(struct spi_flash *flash, void *data);
> > +/*
> > + * Extended address access
> > + * access 4th byte address in 3-byte addessing mode for flashes
> > + * which has an actual size of > 16MB.
> > + */
> > +int spi_flash_extaddr_access(struct spi_flash *flash, u8 status);
> >
> > /*
> > * Same as spi_flash_cmd_read() except it also claims/releases the
> > SPI
> >
>
> Best Regards,
> Thomas
This email and any attachments are intended for the sole use of the named r=
ecipient(s) and contain(s) confidential information that may be proprietary=
, privileged or copyrighted under applicable law. If you are not the intend=
ed recipient, do not read, copy, or forward this email message or any attac=
hments. Delete this email message and any attachments immediately.
More information about the U-Boot
mailing list